Selective Cache clearing across load balanced servers (ASP.Net)

后端 未结 2 1501
日久生厌
日久生厌 2021-02-15 11:51

We have a website that runs on two load balanced servers. We use the ASP.Net caching to help improve performance by caching high usage data. BUT, occasionally that data change

相关标签:
2条回答
  • 2021-02-15 12:45

    We use a simple web service approach. Our cache clear mechanism checks a web config setting to see if any other servers exist and calls the web service on those server(s) asynchronously.

    We store data with specific naming convetions to make it easy to clear what we want. So we pass in either a prefix or postfix for the item to be removed as sometimes it might be user specific (ex. the userid is appended to the name of the item) or application specific (ex. the prefix of the item is the application name).

    Here is a VB example of the ClearItem routine that would be called on either one of your nodes:

    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
    

    You can see that the code above calls other server(s) by using this helper class:

    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
    

    The web service on the remote server then calls the same code that the _ClearItem called.

    0 讨论(0)
  • 2021-02-15 12:47

    Why not define a Cache Dependancy on an object both servers can see? You could use a SQL or File cache dependancy.

    Link to Caching Msdn Page

    0 讨论(0)
提交回复
热议问题