文章出處

回到目錄

對于目前的網站來說,為了滿足高可用,高并發,高負載,一臺WEB服務器已經遠遠不夠用了,以后的WEB應用服務器應該是一種集群的環境,它們之間使用一些工具進行數據的同步,在由1臺變成多臺服務器時,有一個問題是我們必須要考慮的,Session機制,我們都知道Session被用來存儲用戶的一些憑證信息,持久化到服務器上,這在安全性方面得到了保證(比存儲到客戶端的cookies),而當你的WEB應用服務器是多臺時(多臺之間做了負載均衡),這種Session機制就有問題了,因為你無法實現從一臺服務器到別一臺服務器的內存(緩存)共享,這也是不安全的,所以,在出現緩存中間件出現之后,就有了一種新的技術也跟著出現了,即Session中間件,比較成熟的組件是StackExchange.Redis+RedisSessionStateProvider,即使用Redis實現的Session機制,它將session數據存儲到了一臺(可以是redis集群)redis服務器上,這時,多臺WEB應用服務器之間的數據就是唯一的了,不需要進行同步了。

下面介紹實現步驟

1 使用nuget安裝redis緩存 StackExchange.Redis
2 使用nuget安裝RedisSession服務  RedisSessionStateProvider
3 從nuget添加RedisSession之后,它會在你的config文件中寫入以下內容,主要是對session進行持久化設置的
  

 <sessionState mode="Custom" customProvider="MySessionStateStore">
      <providers>
        <!-- Either use 'connectionString' and provide all parameters as string OR use 'host','port','accessKey','ssl','connectionTimeoutInMilliseconds' and 'operationTimeoutInMilliseconds'. -->
        <!-- 'throwOnError','retryTimeoutInMilliseconds','databaseId' and 'applicationName' can be used with both options. -->
        <!--
          <add name="MySessionStateStore"
            host = "127.0.0.1" [String]
            port = "" [number]
            accessKey = "" [String]
            ssl = "false" [true|false]
            throwOnError = "true" [true|false]
            retryTimeoutInMilliseconds = "5000" [number]
            databaseId = "0" [number]
            applicationName = "" [String]
            connectionTimeoutInMilliseconds = "5000" [number]
            operationTimeoutInMilliseconds = "1000" [number]
            connectionString = "<Valid StackExchange.Redis connection string>" [String]
            loggingClassName = "<Assembly qualified class name that contains logging method specified below>" [String]
            loggingMethodName = "<Logging method should be defined in loggingClass. It should be public, static, does not take any parameters and should have a return type of System.IO.TextWriter.>" [String]
          />
        -->
        <add name="MySessionStateStore" type="Microsoft.Web.Redis.RedisSessionStateProvider" host="127.0.0.1" accessKey="" ssl="false" />
      </providers>
    </sessionState>

4 下載是新版本的redis服務端,可以是windows版的,我用的是2.6.13,低版本的redis會出現Eval命令無法識別的問題
5 處理完成,可以測試你的session了,默認過期時間為1200秒

前臺使用Session時和原來沒有任何分別

     public ActionResult TestSession()
        {
            Session["username"] = "zzl";
            Session["test"] = "hello world!";
            return Content("完成..." + Session["test"]);
        }

這種不修改以有代碼就可以實現不同功能策略的方式就是我們的IoC,控制反轉技術(也是依賴注入DI的范疇),這也是編程語言發展到一定階段的必然產物,即解決復雜的業務的應對之道!

下面是網友對rediscache進行的擴展,讓它支持復雜類型,默認支持簡單類型,如果希望支持復雜類型,需要為類型添加“可序列化”的特性,因為我們在redis里存儲時,都是以二進制字節數組的形式存儲的。

  /// <summary>
    /// 對RedisCache的擴展,讓它支持復雜類型、
    /// RedisValue 類型可以直接使用字節數組,因此,
    /// 調用 Get 幫助程序方法時,它會將對象序列化為字節流,然后再緩存該對象。
    /// 檢索項目時,項目會重新序列化為對象,然后返回給調用程序。
    /// </summary>
    public static class SampleStackExchangeRedisExtensions
    {
        public static T Get<T>(this IDatabase cache, string key)
        {
            return Deserialize<T>(cache.StringGet(key));
        }

        public static object Get(this IDatabase cache, string key)
        {
            return Deserialize<object>(cache.StringGet(key));
        }

        public static void Set(this IDatabase cache, string key, object value)
        {
            cache.StringSet(key, Serialize(value));
        }

        static byte[] Serialize(object o)
        {
            if (o == null)
            {
                return null;
            }

            BinaryFormatter binaryFormatter = new BinaryFormatter();
            using (MemoryStream memoryStream = new MemoryStream())
            {
                binaryFormatter.Serialize(memoryStream, o);
                byte[] objectDataAsStream = memoryStream.ToArray();
                return objectDataAsStream;
            }
        }

        static T Deserialize<T>(byte[] stream)
        {
            if (stream == null)
            {
                return default(T);
            }

            BinaryFormatter binaryFormatter = new BinaryFormatter();
            using (MemoryStream memoryStream = new MemoryStream(stream))
            {
                T result = (T)binaryFormatter.Deserialize(memoryStream);
                return result;
            }
        }


    }

對復雜類型進行存儲和讀取的方法如下

   cache.Set("zzlList", new List<TestCache> { new TestCache { ID = 1, Name = "占占", AddTime = DateTime.Now } });
  var o = cache.Get("zzlList");

 回到目錄


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()