跨负载平衡服务器的选择性缓存清除 (ASP.Net)
Posted
技术标签:
【中文标题】跨负载平衡服务器的选择性缓存清除 (ASP.Net)【英文标题】:Selective Cache clearing across load balanced servers (ASP.Net) 【发布时间】:2010-10-20 22:55:52 【问题描述】:我们有一个在两台负载平衡服务器上运行的网站。我们使用 ASP.Net 缓存通过缓存高使用率数据来帮助提高性能。但是,有时数据会发生变化。当它发生时,我们需要清除负载平衡服务器上的相关缓存项。是否有人对如何做到这一点有一些易于实施的建议?
我知道有一些软件可以为您管理这个问题(Microsoft Velocity 就是其中之一)。我也知道还有其他选项可以拥有单独的状态服务器等。但是,对于我们想要的,它们似乎都过大了。我们现在只需要一个清除服务器间特定缓存项的简单机制。
感谢您的任何建议。
【问题讨论】:
很高兴我的解决方案对您有用。如果您遇到任何障碍,请告诉我! 【参考方案1】:我们使用简单的网络服务方法。我们的缓存清除机制检查 Web 配置设置以查看是否存在任何其他服务器并异步调用这些服务器上的 Web 服务。
我们使用特定的命名惯例存储数据,以便轻松明确我们想要的内容。因此,我们为要删除的项目传入前缀或后缀,因为有时它可能是用户特定的(例如,用户 ID 附加到项目的名称)或应用程序特定的(例如,项目的前缀是应用程序姓名)。
下面是 ClearItem 例程的 VB 示例,可在您的任一节点上调用:
Public Shared Sub ClearItem(ByVal strPrefix As String, ByVal strPostfix As String)
If WebConfig.Caching_Enabled() Then
' Exit if no criteria specified '
If IsNothing(strPrefix) AndAlso IsNothing(strPostfix) Then
Exit Sub
End If
' At the very least we need a Postfix '
If Not IsNothing(strPostfix) AndAlso Not strPostfix.Length.Equals(0) Then
_ClearItem(strPrefix, strPostfix)
End If
If WebConfig.Caching_WebFarmEnabled() Then
' Now clear the cache across the rest of the server farm '
_ClearItem_WebFarm(strPrefix, strPostfix)
End If
End If
End Sub
Private Shared Sub _ClearItem_WebFarm(ByVal strPrefix As String, ByVal strPostfix As String)
If WebConfig.Caching_WebFarmEnabled() Then
' Use a web service on each server in the farm to clear the '
' requested item from the Cache '
' Determine which servers need to remove cache items '
Dim arrServers As String()
arrServers = Split(WebConfig.Caching_WebFarmServers(), "|")
Dim strServer As String ' Holds which server we are currently contacting '
' Loop through all the servers and call their web services '
For Each strServer In arrServers
Dim WS As New WebServiceAsyncCall
WS.StartCallBack(strServer, strPrefix, strPostfix)
Next
End If
End Sub
Private Shared Sub _ClearItem(ByVal strPrefix As String, ByVal strPostfix As String)
If WebConfig.Caching_Enabled() Then
' Determine how we are comparing keys '
Dim blnPrefix, blnPostfix As Boolean
If strPrefix.Length.Equals(0) Then
blnPrefix = False
Else
blnPrefix = True
End If
If strPostfix.Length.Equals(0) Then
blnPostfix = False
Else
blnPostfix = True
End If
' Reference the Cache collection '
Dim objCache As System.Web.Caching.Cache = HttpContext.Current.Cache
' Exit if the cache is empty '
If objCache.Count.Equals(0) Then
Exit Sub
End If
' Clear out the cache for all items matching the input(s) (on this local server) '
Dim objCacheEnum As IEnumerator = objCache.GetEnumerator()
Dim objCacheItem As Object
Dim objCurrentKey As System.Collections.DictionaryEntry
Dim strCurrentKey As String
' Enumerate through the cache '
While objCacheEnum.MoveNext()
objCurrentKey = CType(objCacheEnum.Current, DictionaryEntry)
strCurrentKey = objCurrentKey.Key.ToString()
' How are we comparing the key? '
If blnPrefix AndAlso Not (blnPostfix) Then ' Only by PREFIX '
If strCurrentKey.StartsWith(strPrefix) Then
' Remove it from the cache '
objCacheItem = objCache.Remove(strCurrentKey) ' Returns a reference to the item '
objCacheItem = Nothing ' Need to explicitly nuke this because the objCache.Remove() above doesn t destroy '
End If
ElseIf Not (blnPrefix) AndAlso blnPostfix Then ' Only by POSTFIX '
If strCurrentKey.EndsWith(strPostfix) Then
' Remove it from the cache '
objCacheItem = objCache.Remove(strCurrentKey) ' Returns a reference to the item '
objCacheItem = Nothing ' Need to explicitly nuke this because the objCache.Remove() above doesn t destroy '
End If
ElseIf blnPrefix AndAlso blnPostfix Then ' By both PREFIX and POSTFIX'
If strCurrentKey.StartsWith(strPrefix) AndAlso strCurrentKey.EndsWith(strPostfix) Then
' Remove it from the cache '
objCacheItem = objCache.Remove(strCurrentKey) ' Returns a reference to the item '
objCacheItem = Nothing ' Need to explicitly nuke this because the objCache.Remove() above doesn t destroy '
End If
Else
' Not comparing prefix OR postfix? Why bother continuing then! '
Exit Sub
End If
End While
End If
End Sub
您可以看到上面的代码使用这个帮助类调用了其他服务器:
Private Class WebServiceAsyncCall
Public Sub StartCallBack(ByVal strService As String, ByVal strPrefix As String, ByVal strPostfix As String)
ActiveWebServiceCounter += 1
Dim clearCacheProxy As New CacheClearService.CacheClear ' This is the web service which of course will exist on the other node as well '
clearCacheProxy.Url = strService
AddHandler clearCacheProxy.ClearItemCompleted, AddressOf DoneCallBack
clearCacheProxy.ClearItemAsync(strPrefix, strPostfix)
End Sub
Public Sub DoneCallBack(ByVal sender As Object, ByVal e As CacheClearService.ClearItemCompletedEventArgs)
ActiveWebServiceCounter -= 1
If e.Result.Length > 0 Then ' Something failed '
' Log the error '
End If
End Sub
End Class
然后,远程服务器上的 Web 服务调用 _ClearItem 调用的相同代码。
【讨论】:
【参考方案2】:为什么不在两个服务器都可以看到的对象上定义缓存依赖关系?您可以使用SQL 或File 缓存依赖关系。
Link to Caching Msdn Page
【讨论】:
以上是关于跨负载平衡服务器的选择性缓存清除 (ASP.Net)的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET 应用程序转到 500.21 ...直到 IIS 重置 + 清除临时 ASP.NET 缓存
Nginx+IIS+Asp.net+MySQL,MongoDB
在 Big I/p 负载平衡环境中将 ASP.NET 2.0 应用程序迁移到 IIS 7.5 时会话丢失。在 Windows Server 2000 和 2003 中运行良好