基于HTTP协议我们可能发现我们要解决两点问题:
第一,做到负载均衡,我们需要一个负载均衡器。
可以通过DNS轮询来做,在DNS服务器上配置为每次对我们做负载均衡的同一主机名的DNS查询得到不同的IP地址。这样的好处是配置简单投入较小,缺点是浏览器访问各个服务器的机会是均等的,不能根据服务器的负载程度自动把请求路由到负载较小的服务器。
可以通过专用的负载均衡设备,通过监测后台数台服务器的负载情况,自动把HTTP请求转发到负载较轻的服务器。另外必须监测后台服务器的IIS负载情况,而不是整台服务器的CPU负载。同时可能需要在负载均衡器和后台服务应用之间建立心跳连接,以避免出现某台服务器IIS进程或者其中跑的应用已经down掉,负载均衡器反而监测到这台服务器的负载最小而把大量请求转发的这台服务器,达到相反的效果。
第二,Session状态的保持和迁移。
由于HTTP协议的无状态性,我们一般是在Session中保存客户端的一些状态数据,负载均衡之后,前后两次HTTP请求所到达的服务器可能不是同一台,这就造成可能出现这样的情况,前一此请求处理中设置的session在第二次请求中变得不可用了,造成应用程序出错。所以我们要把session跟随迁移。实现的方法就是session的统一存储和服务器间共享。
在ASP.NET中服务器保存session有五种方式,Off不说了,InProc是保存在服务器进程的内存中,显然不能满足要求。另外两种能够满足:
StateServer是把session保存在专门的状态服务器中。这样各台服务器都存取同一个StateServer,达到共享的目的。
SQLServer是把session保存在数据库中。同样能达到目的。
Custom自定制的存储方案,我们自己写当然能够实现。
比较一下,Custom这种自己实现比较麻烦一般不用,SQLServer可以利用数据库的cluster达到高性能和高可用性的目的,StateServer当然也可以通过手段达到高可用性,不过似乎不能实现集群所以性能也有所限制。
另外如果要做负载均衡在StateServer和SQLServer中配置session时,必须在web.config中重写machineKey节点:
<machineKey
validationKey="1234567890123456789012345678901234567890AAAAAAAAAA"
decryptionKey="123456789012345678901234567890123456789012345678"
validation="SHA1"
decryption="Auto"
/>
否则各个应用服务器拿到的session还是不一样的。
可能Custom方式可以自己定义存取session方式忽略machineKey,这可能就不必要了,因为没有做过,不多说。