如何在 C# 中构建 Web 服务缓存
我正在开发一个网络服务,从第三方源读取数据,对其进行一些修改并存储,然后将其返回给我的客户。只需定期从第三方网站更新即可。它将作为 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
从您的问题来看,它看起来像:
假设这些都是 true,那么最简单的解决方案就是使用静态变量来存储数据,并在整个检查/刷新块周围使用
lock
构造。我什至懒得尝试做任何像双重检查锁定模式这样聪明的事情;锁争用根本不会成为问题,因为与操作 Web 服务的开销相比,在关键区域花费的时间将显得微不足道,除非它阻塞并且每个人都必须阻塞。From your question, it looks like:
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.由于您从缓存中读取的内容可能多于写入的内容,因此我将使用 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.