代码之家  ›  专栏  ›  技术社区  ›  Andiih

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

  •  4
  • Andiih  · 技术社区  · 14 年前

    我正在开发一个web服务,从第三方feed读取数据,稍加修改并存储,然后将其返回给我的客户机。它只需要从第三方网站定期更新。它将在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;            
            }
        }
    

    但我想,由于fetch可能需要1-2秒(它是一个web服务),因此多个用户将同时命中该代码。

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

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

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

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

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

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

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

    2 回复  |  直到 7 年前
        1
  •  1
  •   Greg Beech    14 年前

    从你的问题看来:

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

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

        2
  •  1
  •   Patrik Svensson Martin Ender    14 年前

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