如何在 C# 中构建 Web 服务缓存

发布于 2024-10-04 12:07:37 字数 1313 浏览 1 评论 0原文

我正在开发一个网络服务,从第三方源读取数据,对其进行一些修改并存储,然后将其返回给我的客户。只需定期从第三方网站更新即可。它将作为 WCF 服务在 Azure 中的 Web 角色中运行。

起初,我以为我总是会调用我的 parsefeed 方法,但是如果上次更新太快,则让该调用返回...

   public void ParseFeed()
    {
        if (DateTime.Now > lastrun.AddMinutes(1))
        {
         //Fetch updated data into something shared here.
         //thedata is a public static in Global class 
         thedata = fetchdata();
         lastrun=DateTime.Now;            
        }
    }

但我想,由于获取可能需要 1-2 秒(它是一个 Web 服务),多个用户将同时点击该代码。

来自 http://support.microsoft.com/ default.aspx?scid=kb;en-us;Q312607 由于任何类(包括应用程序类)的静态成员都不是线程安全的,因此用户代码必须为对静态成员的访问提供适当的锁定。这适用于您添加到应用程序类的任何静态成员。

  • 我可以使用锁定(不知道如何)编辑:很多信息这里

  • 我可以避免静态变量并使用缓存,并将我的数据放入其中(但这会在到期时被删除,多个用户会尝试获取数据)

  • 我可以使用其中包含虚假数据项的缓存(基本上作为计时器)并在过期时刷新 - 但即使没有人访问该站点也会刷新。 (也可能不是线程安全的)

  • 我不能真正使用输出缓存,因为客户端查询我返回的数据的方式可能使每个请求都是唯一的:我的服务根据请求进行排序和过滤

顺便说一句,我不担心多个实例上结果的一致性天蓝色。每个服务器都可以获取自己的状态,因此我不需要在多个服务器上共享状态。

我感觉有一个简单的解决方案,但我完全错过了。想法?

I'm working on a web service to read data from a 3rd party feed, modify it a little and store it, then return it to my clients. It only needs to update from the 3rd party site periodically. It will be running as a WCF service in a web role in Azure.

At first I thought I would just always make a call to my parsefeed method, but make that call return if the last update was too soon...

   public void ParseFeed()
    {
        if (DateTime.Now > lastrun.AddMinutes(1))
        {
         //Fetch updated data into something shared here.
         //thedata is a public static in Global class 
         thedata = fetchdata();
         lastrun=DateTime.Now;            
        }
    }

But I guess that as the fetch can take 1-2s (its a web service) that multiple users will hit that code at once.

from http://support.microsoft.com/default.aspx?scid=kb;en-us;Q312607
Because static members of any class, including an application class, are not thread-safe, the user code must provide appropriate locking for access to static members. This applies to any static member that you add to the application class.

  • I could use locking (not sure how) EDIT: lots of info here

  • I could avoid the static var and use a cache, and put my data in it (but that would get removed at expiration and multiple users would try to fetch data)

  • I could use a cache with a fake item of data in it (basically as a timer) and refresh when that expired - but that would refresh even if nobody was hitting the site. (May also not be thread safe)

  • I can't really use an output cache because the clients query the data I return in a manner that probably makes each request unique: my service sorts and filters according to the request

BTW I am not worried about consistency of results over multiple instances on Azure. Each can fetch their own so I don't need to share state over multiple servers.

I get the feeling there is a simple solution, that I have totally missed. Ideas ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一场春暖 2024-10-11 12:07:37

从您的问题来看,它看起来像:

  • 提供超过一分钟过期的数据是不可接受的
  • 如果两个服务实例由于刷新时间不同步而返回不同的数据是可以接受的
  • 调用者阻止 1 是可以接受的刷新数据时 -2 秒

假设这些都是 true,那么最简单的解决方案就是使用静态变量来存储数据,并在整个检查/刷新块周围使用 lock 构造。我什至懒得尝试做任何像双重检查锁定模式这样聪明的事情;锁争用根本不会成为问题,因为与操作 Web 服务的开销相比,在关键区域花费的时间将显得微不足道,除非它阻塞并且每个人都必须阻塞。

From your question, it looks like:

  • It is not acceptable to serve data that's more than a minute out of date
  • It is acceptable if two service instances return different data due to refresh times being out of sync
  • It is acceptable for callers to block for 1-2 seconds while data is refreshed

Assuming these are all true, then the simplest solution is just to use a static variable to store the data, with a lock construct around the whole check/refresh block. I wouldn't even bother trying to do anything clever like the double-check lock pattern; lock contention simply won't be an issue as the time spent in the critical region will pale into insignificance compared to the overhead of operating a web service, except when it is blocking and everybody has to block anyway.

十年不长 2024-10-11 12:07:37

由于您从缓存中读取的内容可能多于写入的内容,因此我将使用 ReaderWriterLockSlim 确保数据可以被多个线程同时读取但不能写入。我还将确保缓存的数据是不可变的,以确保它不会被消费者更改。

Since you probably will be reading from the cache more than you will be writing, I would use a ReaderWriterLockSlim to ensure data can be read by multiple threads simultaneously but not written. I would also make sure that the cached data is immutable to make sure it's not altered by consumers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文