2016-09-16 67 views
5

我已经使用WebAPI2实现了REST服务,该服务实现了管理由正在访问服务的不同客户端创建和加入的不同会话。如何管理ASP.NET WebApi2中的缓存?

会话包含有关应用程序功能访问的信息和已加入同一会话的参与者的信息。

每个客户端都会从服务器获取会话信息和访问列表,以便每秒钟进行同步。根据访问更改,客户端功能将改变(启用/禁用)。

我正在使用MemoryCache类将会话信息存储在WebAPI服务中,如下所示。

public static class SessionManager{ 
private static object objForLock = new object(); 
public static List<Session> SessionCollection 
{ 
    get 
    { 
     lock (objForLock) 
     { 
      MemoryCache memoryCache = MemoryCache.Default; 
      return memoryCache.Get("SessionCollection") as List<Session>; 
      // return HttpContext.Current.Application["SessionCollection"] as List<Session>; 
     } 
    } 
    set 
    { 
     lock (objForLock) 
     { 
      MemoryCache memoryCache = MemoryCache.Default; 
      memoryCache.Add("SessionCollection", value, DateTimeOffset.UtcNow.AddHours(5)); 
      //HttpContext.Current.Application["SessionCollection"] = value; 
     } 
    } 
} 

}

我的问题是关于高速缓存的不一致的行为。

当客户端发送同步呼叫时,它会产生不一致的结果。对于某些请求,客户端获取正确的数据,并且对于某些请求,客户端在某些请求后获得空数据替代。

我已添加调试器并监视对象为空结果,然后“memoryCache.Get(”SessionCollection“)”也为null。经过一些连续的请求后,它会再次适当。我不明白为什么这个对象不是持久的。

另外,我试过“HttpContext.Current.Application [”SessionCollection“]”“,但同样的问题在那里。

我已阅读约“应用程序池回收”,它在微粒时间后回收所有缓存。如果我的缓存对象被应用程序池回收循环使用,那么如何再次获取此对象?

请有人可以帮助我摆脱这个问题。提前致谢。

+0

只是想仔细检查您的服务器时间是否也设置为UTC。超时值是否有可能在你期望之前达到? – ManOVision

+0

顺便说一句,MemoryCache是​​线程安全的,因此不需要锁定 –

+0

其中。你使用的是.NET版本吗? – RAM

回答

0

只需谨慎,MemoryCache将数据保存在单个服务器的内存中。因此,如果您有多个Web服务器(位于负载均衡器之前),则该缓存将无法供其他服务器使用。您还可以使用缓存名称 - “SessionCollection”。这些数据将被分享给所有客户。如果您需要将数据存储在每个客户端独有的缓存中,则需要将令牌(guid)返回给客户端,并使用该令牌在随后的请求中获取/更新缓存中的数据。

尝试引入一个类级别的变量。所以你的代码如下所示。 (某些代码删除为清楚起见)

private readonly MemoryCache _memCache = MemoryCache.Default; 

....

return _memCache.Get("SessionCollection") as List<Session>; 

...

_memCache .Add("SessionCollection", value, DateTimeOffset.UtcNow.AddHours(5)); 
+0

@alltej感谢您的回复。我正在使用单个服务器以及“Session Collection”数据为所有客户端共享。对于这种数据不一致的更多建议? –

+0

@NileshWagh更新了我的答案。你能检查一下吗? – alltej

+0

嗨@alltej,我已根据您编辑的答案添加更改,位仍然我面临同样的问题。 –

1

,可以储存在Session,而不是Cache客户的具体信息。Cache应该是为整个应用程序(共享)

但是,不建议为Web API与REST风格的建在思想和RESTful服务应该是无状态(的API不缓存状态)。无状态的应用有很多好处:

  • 减少内存使用
  • 更好的扩展性:您的应用程序更好地伸缩。如果您同时存储数百万客户端的信息,会发生什么情况。
  • 更好的负载平衡方案:每个服务器都可以处理每个客户端而不会丢失状态。
  • 会话到期问题。

如果你想存储客户端状态,你可以做任何事情。请尝试建议在以下岗位:本地ASP.NET Web API session or something?

一般来说,缓存状态在Web服务器上是不好的(包括Session和当地MemoryCache)。缓存可能会因多种原因丢失:

  • 应用程序池回收。
  • 负载均衡环境
  • 在IIS
  • 多个工作进程

关于你的要求:

每个客户端从服务器获取会话信息和访问名单上的每一秒 同步的目的。根据访问更改, 客户端功能将改变(启用/禁用)。

我不确定您是否想在客户端发送同步呼叫时立即用新的访问列表更新其他客户端。如果是这样的话,SignalR将是更好的选择。

否则,您可以将更新后的访问列表存储在某处(共享缓存或甚至数据库中),并在其他客户端与其他请求重新连接时更新其他客户端。

0

@ScottHanselman表示关于.NET 4here中的一个错误。我希望此修复程序帮助您:

临时修复

下创建禁用执行上下文的内存缓存实例流

using (ExecutionContext.SuppressFlow())  { 
      // Create memory cache instance under disabled execution context flow 
     return new YourCacheThing.GeneralMemoryCache(…); 
} 

修补程序http://support.microsoft.com/kb/2828843,你可以在此处要求:https://support.microsoft.com/contactus/emailcontact.aspx?scid=sw;%5BLN%5D;1422