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

时间:2010-11-26 09:10:18

标签: c# asp.net wcf cache-control

我正在开发一项网络服务,用于从第三方供稿中读取数据,稍微修改并存储,然后将其返回给我的客户。它只需要定期从第三方站点更新。它将作为Azure中的Web角色中的WCF服务运行。

起初我以为我会一直打电话给我的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-2s(它是一个Web服务),多个用户会立即点击该代码。

  来自http://support.microsoft.com/default.aspx?scid=kb;en-us;Q312607

  由于任何类的静态成员(包括应用程序类)都不是线程安全的,因此用户代码必须提供适当的锁定才能访问静态成员。这适用于您添加到应用程序类的任何静态成员。

  • 我可以使用锁定(不确定如何)编辑:大量信息here

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

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

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

BTW我并不担心Azure上多个实例的结果一致性。每个都可以获取自己的,所以我不需要在多个服务器上共享状态。

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

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

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

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

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