zoukankan      html  css  js  c++  java
  • 我心中的核心组件(可插拔的AOP)~分布式Session组件

    回到目录

    对于目前的网站来说,为了满足高可用,高并发,高负载,一台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");

     回到目录

  • 相关阅读:
    水晶苍蝇拍:微薄投资感悟摘录(四) (2012-04-03 14:11:01)
    水晶苍蝇拍:投资感悟(三)(手打,有删减)
    水晶苍蝇拍:投资感悟(二)(2011-12-27 08:17:54)
    leetcode -- String to Integer (atoi)
    leetcode -- Longest Palindromic Substring
    leetcode -- Longest Substring Without Repeating Characters
    leetcode -- Add Two Numbers
    QQ截图工具截取
    LUA学习笔记(第5-6章)
    Lua5.2 请求 luasocket 相关模块时的 multiple-lua-vms-detected
  • 原文地址:https://www.cnblogs.com/lori/p/4685148.html
Copyright © 2011-2022 走看看