应用层主要处理网站的业务逻辑,一个显著特点是应用的无状态性。
所谓无状态是指应用服务器不保存业务的上下文信息,而仅根据每次请求提交的数据进行相应的业务逻辑处理,多个服务实例(服务器)之间完全对等,请求提交到任意服务器,处理结果是完全一样的。
通过负载均衡进行无状态服务的失效转移
不保存状态的应用给高可用的架构设计带来了巨大便利,既然服务器不保存请求的状态,那么所有的服务器完全对等,当任意一台或多台服务器宕机,请求提交给集群中的其他任意一台可用机器处理,这样对终端用户而言,请求总是能够成功的,整个系统依然可用。对于应用服务器集群,实现这种服务器可用状态实时检测、自动转移失败任务的机制就是负载均衡。
负载均衡,顾名思义,主要使用在业务量和数据量较高的情况下,当单台服务器不足以承担所有的负载压力时,通过负载均衡手段,将流量和数据分摊到一个集群组成的多台服务器上,以提高整体的负载处理能力。目前,不管开源免费的负载均衡软件还是昂贵的负载均衡硬件,都提供失效转移功能。
当 Web 服务器集群中的服务器都可用时,负载均衡服务器会把用户发送的访问请求分发到任意一台服务器上进行处理,而当服务器 10.0.0.1 宕机时,负载均衡服务器通过心跳检测机制发现该服务器失去响应,就会把它从服务器列表中删除,而将请求发送到其他服务器上,这些服务器是完全一样的,请求在任何一台服务器中处理都不会影响最终的结果。
应用服务器的 Session 管理
应用服务器的高可用架构设计主要基于服务无状态这一特性,但是事实上,业务总是有状态的。
在交易类的电子商务网站,需要有购物车记录用户的购买信息,用户每次购买请求都是向购物车中增加商品;
在社交类的网站中,需要记录用户的当前登录状态,最新发布的消息及好友状态等,用户每次算新页面都需要更新这些信息。
Web 应用中将这些多次请求修改使用的上下文对象称作会话(Session),单机情况下,Session 可由部署在服务器上的 Web 容器(如 JBoss)管理。在使用负载均衡的集群环境中,由于负载均衡服务器可能会将请求分发到集群任何一台应用服务器上,所以保证每次请求依然能够获得正确的 Session 比单机时要复杂很多。
集群环境下,Session 管理主要有以下几种手段。
Session 复制
Session 复制是早期企业应用系统使用较多的一种服务器集群 Session 管理机制。应用服务器开启 Web 容器的 Session 复制功能,在集群中的几台服务器之间同步 Session 对象,使得每台服务器上都保存所有用户的 Session 信息,这样任何一台机器宕机都不会导致 Session 数据的丢失,而服务器使用 Session 时,也只需要在本机获取即可。
这种方案虽然简单,从本机读取 Session 信息也很快速,但只能使用在集群规模比较小的情况下。当集群规模较大时,集群服务器间需要大量的通信进行 Session 复制,占用服务器和网络的大量资源,系统不堪重负。而且由于所有用户的 Session 信息在每台服务器上都有备份,在大量用户访问的情况下,甚至会出现服务器内存不够 Session 使用的情况。
而大型网站的核心应用集群就是数千台服务器,同时在线用户可达千万,因此并不适用这种方案。
Session 绑定
Session 绑定可以利用负载均衡的源地址 Hash 算法实现,负载均衡服务器总是将来源于同一 IP 的请求分发到同一台服务器上(也可以根据 Cookie 信息将同一个用户的请求总是分发到同一台服务器上,当然这时负载均衡服务器必须工作在 HTTP 协议层上。)这样在整个会话期间,用户所有的请求都在同一台服务器上处理,即 Session 绑定在某台特定服务器上,保证 Session 总能在这台服务器上获取。这种方法也被称作会话粘滞。
但是 Session 绑定的方案显然不符合我们对于系统高可用的需求,因为一旦某台服务器宕机,那么该机器上的 Session 也就不复存在了,用户请求切换到其他机器后因为没有 Session 而无法完成业务处理。因此虽然大部分负载均衡服务器都提供源地址负载均衡算法,但很少有网站利用这个算法进行 Session 管理。
利用 Cookie 记录 Session
早期的企业应用系统使用 C/S(客户端/服务器)架构,一种管理 Session 的方式是将 Session 记录在客户端,每次请求服务器的时候,将 Session 放在请求中发送给服务器,服务器处理完请求后再将修改过的 Session 响应给客户端。网站没有客户端,但是可以利用浏览器支持的 Cookie 记录 Session。
利用 Cookie 记录 Session 也有一些缺点,比如:
受 Cookie 大小限制,能记录的信息有限;
每次请求响应都需要传输 Cookie ,影响性能;
如果用户关闭 Cookie ,访问就会不正常。
但是由于 Cookie 的简单易用,可用性高,支持应用服务器的线性伸缩,而大部分应用需要记录的 Session 信息又比较小。因此事实上,许多网站都或多或少地使用 Cookie 记录 Session。
Session 服务器
利用独立部署的 Session 服务器(集群)统一管理 Session ,应用服务器每次读写 Session 时,都访问 Session 服务器。
这种解决方案事实上是将应用服务器的状态分离,分为无状态的应用服务器和有状态的 Session 服务器,然后针对这两种服务器的不同特性分别设计其架构。
对于有状态的 Session 服务器,一种比较简单的方法是利用分布式缓存、数据库等,在这些产品的基础上进行包装,使其符合 Session 的存储和访问要求。如果业务场景对 Session 管理有比较高的要求,比如利用 Session 服务集成单点登录(SSO)、用户服务等功能,则需要开发专门的 Session 服务管理平台。
这种服务器集群 Session 管理方案可用性高、伸缩性好、性能也不错,对信息大小又没有限制。