柳纲(1975-),男,湖北咸宁人,工程师,从事调度自动化系统人机界面开发、大数据分析、高并发可用集群研究工作;
0 引言
能量管理系统III区应用系统的重要性日益突出,在电力系统生产和运行中起着越来越重要的作用,III区应用系统和I区相比,有着比较鲜明的自身特点。这些系统多采用B/S架构,同时为数量众多的用户提供服务。其特点是用户数量多,有明显的用户高峰和低谷曲线,对系统的并发、可用性、可扩展性要求比较高。近年来,B/S系统高并发、高可用、可扩展性指标常常成为系统性能考核的重要指标。如何保证B/S系统的高并发、高可用,成为必须解决的问题。
文献[1]介绍了一种Web服务器集群的架构方式,在实际运行中取得了较好的实用效果。但随着系统服务规模的扩大,及用户数量的增加,这种架构模式显现出一些不足。主要表现在:高并发下负载调度器(以下简称调度器)本身成为性能瓶颈;调度器不满足高可用的要求;高并发下服务器池中各节点(以下简称服务节点)的数据一致性得不到保证;随着服务节点数量的增加,水平扩展比较困难。
1 本方案整体架构及特点
本方案采用三层结构,调度器采用基于IP层负载平衡调度技术,将浏览器的请求平均分发给后端的服务节点,服务节点之间数据完全解耦,可以方便进行水平扩展。为保证服务节点的Session同步,各服务节点均将Session缓存到Redis内存数据库中。系统架构如
1.1 调度器高并发
文献[1]设计的集群架构不足之处在于:这是一种”收费站”模式的对等网络,浏览器请求和响应数据都要经过调度器进行转发。一般而言B/S系统中的响应数据要比请求数据大一个数量级。在高并发的情况下,调度器极易成为系统的瓶颈。传统上多采用专用硬件解决对调度器的高并发需求,如使用F5作为硬件负载均衡,然而这些硬件比较昂贵,并不适用于所有用户。另外一种方案是采用更高效的软件调度器例如Nginx,但是这种方式的提升效果有限[ 2]。
传统的高并发解决方案主要是从提升调度器处理能力的角度来提高系统的并发性能,但实际上问题的关键在于这种“收费站”式的数据转发模式已不适用于高并发的应用场景,因此,本方案摈弃了这种数据转发模式。浏览器请求数据仍然由调度器中转给服务节点,但当服务节点处理完请求,生成响应数据将直接发回给浏览器端,不再经过调度器进行中转,这种方式将大大减轻调度器的负载,有助于提升系统的并发性能[ 3]。
数据传输过程如下:当用户通过Virtual IP Address(即调度器的外部地址,以下简称VIP)访问服务器时,请求报文到达调度器,调度器以负载均衡方法从服务节点池中选出一个,将请求的数据帧中目的MAC地址改为某服务节点的MAC地址,然后将数据帧发送给该服务节点。因为数据帧的MAC地址是被选出的服务节点,所以该服务节点能够收到这个数据帧,从而获得这个IP报文。该IP报文的目标地址是VIP,而服务节点事先已经在其Non-ARP网络设备上绑定了该VIP,因此它会处理这个报文,然后根据路由表将响应报文直接返回给用户[ 4]。在这一过程中,调度器并不修改IP层数据的内容,这样既方便服务节点直接返回数据给浏览器端,也有助于提高数据处理效率。
为实现服务节点能接收转发的请求数据并直接返回数据给浏览器,需要在每一服务节点上配置VIP地址,由于所有的服务节点和调度器都配置了VIP,为防止IP地址冲突,需要在所有的服务节点上做地址解析协议(Address Resolution Protocol,ARP)抑制,以不对外暴露自己的VIP地址[ 5]。
1.2 调度器高可用
文献[1]设计的集群架构第2个不足之处在于:调度器只配置了1台,存在单点故障的可能性,不满足高可用的要求。传统上为了解决单点故障问题,往往需要采用高可靠性的硬件设备,或者通过定期巡检等手段来提高可用性,这种方式投入大,效果并不理想[ 6]。
使用热备方式的配置,配合软件自动检测的方式实现高可用性是近年来较为常用的方法[ 7]。本方案也采用了这一思路,在调度器层配置2台调度器,配置“主备”值班模式。使用Keeplived软件监视
2台调度器的工作状态,控制它们的值班状态。在正常情况下由主调度器对外提供服务,备调度器进行热备。当主调度器发生故障时,Keeplived将控制备调度器接管主调度器的所有工作;一旦主调度器故障修复,Keeplived又会接管回原来处理的工作,而备调度器会释放自己接管的工作,整个切换及恢复过程完全自动实现,无需人工干预,切换过程时间短,对应用几乎无影响[ 8]。
1.3 服务节点高可用
文献[1]设计的集群架构第3个不足之处在于:调度器不具备服务节点健康检查机制。一旦某些服务节点发生异常,不能正常提供服务,调度器无法检测到这种情况并做相应处理,浏览器请求可能得不到正确响应。通常服务节点高可用的解决办法是编写特定的维护脚本,检测其服务的运行状态,发生异常时通知运维人员手动切除故障节点。这种方式故障切除时间比较长,用户体验差,对运维的要求也比较高[ 9]。
在本方案中,各服务节点对外均提供一个统一资源定位符(Uniform Resource Locator,URL),调度器周期性向各服务节点指定的URL执行Http请求,通过指定Http返回状态码来判断每个服务节点的健康状态。当返回正常状态码时,表示节点运行正常,当返回错误状态码或者异常状态码时,表示节点运行异常,此时调度器将该节点记录从自己的缓存记录中移除。当返回正常状态码时,调度器又将这个节点记录加入到自己的缓存记录中[ 10]。
采用本方案的优势在于服务节点的故障检测和切除过程完全自动实现,无需人工干预,切除过程时间短,对应用基本无影响,对运维要求也低。
1.4 服务节点Session同步
以往Session同步解决方案的通病在于没有遵循J2EE规范,不采用集中存储的方式管理Session。如文献[1]设计的集群架构使用Tomcat自带集群功能解决Session同步。这种Session同步方法存在以下不足:只支持Tomcat服务器,不支持其他动态Web容器;服务节点扩展有数量限制,超过一定数量后,服务节点水平扩展非常困难[ 11]。
本方案使用Spring Session技术,遵循J2EE规范,采用集中存储的方式解决Session同步问题。首先可以确保支持所有实现J2EE规范的动态Web容器。其次,Session数据统一保存在内存数据库中,各服务节点不再保存Session数据。这样做有以下好处:服务节点之间没有同步Session的开销,减轻了网络传输的压力;服务节点之间不再有数据耦合,水平扩展无需考虑数据同步问题,扩展节点更加简单容易[ 12]。
2 系统实现
本方案采用LVS(Linux Virtual Server)作为调度器,Keepalived作为LVS的配置工具,同时利用Keepalived保证调度器的高可用以及检测服务节点健康状态,采用Spring Session保证Session同步,其中Session保存在后端的Redis内存数据库中[ 13]。在实际中利用虚拟机搭建了一个集群演示系统,系统网络结构如
系统共7台Linux虚拟机,均安装Centos6.5_x64操作系统,通过交换机互联,其中2台用作调度器,安装Keepalived软件,另外4台用作Web服务器,安装Apache-tomcat-6.0.35,1台用作Redis服务器,安装Redis-2.19。集群系统的VIP为192.168.1.188,2台调度器的DIP分别为192.168.1.1和192.168.1.2,4台Tomcat服务器的IP分别为192.168.1.3~192.168.1.6,Redis服务器IP为192.168.1.7,Redis访问密码置空。
2.1 高并发配置
为保证系统高并发,需要配置调度器转发策略,并在所有的服务节点上配置VIP并做ARP抑制[ 14]。
2台调度器的配置文件Keepalived.conf转发策略如下:
virtual_server 192.168.1.188 8080
{
delay_loop 6
lb_algo rr //负载调度算法设置
lb_kind DR //负载均衡
nat_mask 255.255.255.0
persistence_timeout 50
protocol TCP
real_server 192.168.1.3 8080
{ //实时服务器一的地址及端口
weight 1 //权重
//服务器健康监测预留
}
...
}
上述配置在调度器上指定了一个虚拟服务器,设置了负载调度算法为Round Robin轮叫算法,设置负载方式为Direct Routing方式,并为该虚拟服务器指定了多台服务节点,指定了每个服务节点的实际IP、端口及权重,最后预留了服务节点健康监测模块的配置项。
此外在所有的服务节点上需要执行如下命令[ 4]:
1)ifconfig lo:0 192.168.1.188 netmask 255.255.255.255 broadcast 192.168.1.1 up
2)/sbin/route add -host 192.168.1.188 dev lo:0
3)echo”1”>/proc/sys/net/ipv4/conf/all/arp_ignore echo “2” >/proc/sys/net/ipv4/conf/all/arp_announce
上述命令在环回接口上配置VIP地址,添加到主机的路由,执行了网卡的ARP抑制以避免VIP地址在交换数据时发生IP地址冲突[ 15]。
2.2 高可用配置
2台调度器的配置文件Keepalived.conf中高可用配置如下:
vrrp_instance VI_1
{ state MASTER
//主机设置为MASTER,备机设置为BACKUP
interface eth0//定义设置VIP地址的网卡名
virtual_router_id 51
priority 100
//主机设为100,备机设为99
advert_int 1
…
virtual_ipaddress
{
192.168.1.188 //VIP地址
}
}
上述配置指定了调度器的主备机角色,指定了VIP地址,确定了该VIP配置的物理接口名称,设置了主备调度器的优先级。
2.3 服务节点健康检查配置
2台调度器的keepalived.conf中服务节点健康检查配置如下:
HTTP_GET {
url {
path /index.html
status_code 200
}
…
}
上述配置代码要配置在3.1节高并发配置的”服务器健康监测预留处”。该配置指定了调度器监测服务节点健康的手段是HTTP_GET,通过HTTP_GET请求获取服务节点的指定页面(index.html),当HTTP_GET请求的状态返回码为200时,调度器认为该服务节点状态正常,否则状态不正常,即从自己的缓存记录中将该节点对应的记录剔除。
2.4 Session同步配置
服务节点中使用Session同步需要Spring Session支持,因此要将Web应用配置成Spring工程,然后配置Redis连接,因此配置分为2步:
1)web.xml增加
…
<filter>
<filter-name>springSessionRepositoryFilter
</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter><filter-mapping><filter-name>
springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
上述配置代码使Spring支持本应用,并使用Spring Session拦截器拦截所有请求,以便进行处理。
2)applicationContext.xml增加
<context:component-scan base-package=”com.*”/>
…
<property name=”hostName” value=”192.168.1.7”/>
<property name=”port” value=”6379” />
<property name=”password” value=”” />
<property name=”timeout” value=”10000” />
<property name=”poolConfig” ref=”jedisPoolConfig” />
<property name=”usePool” value=”true” />
…
</bean>
上述配置代码指定了连接Redis内存数据库的bean类型、Redis内存数据库的地址及访问方式。
完成这2类配置后,在Web应用的lib目录中导入Spring项目的jar包,就完成了服务节点Web工程的Session同步配置。
3 方案测试
3.1 高并发测试
为了测试本方案的高并发性能,利用上述7台虚拟机分别构建本方案的集群系统及文献[1]的集群系统,使用LoadRunner对相同的Web应用进行压力测试。
首先测试根据文献[1]构建的集群系统(以下简称系统1),测试结果1如
使用LoadRunner对采用本方案构建的集群系统(以下简称系统2)进行压力测试,测试结果2如
进一步对系统1进行容量测试,在2 000个用户并发访问下,系统失去响应,表明在高并发的冲击下,系统已经不可用,撤除压力后系统可用性仍无法恢复。
对系统2进行容量测试,在3 500个用户并发访问下,系统有较长时延,基本不可用,但在压力撤除后,系统可用性恢复。
测试结果表明,在相同的硬件条件下,采用本方案构建集群,测试系统的并发数比原系统增加了近70%,并发性能得到了大幅度提升。
3.2 高可用测试
系统1和系统2的Web服务均为集群部署,因此Web服务的高可用性是相同的,其主要区别在于调度器的高可用性。
首先测试系统1,将系统1的调度器关闭,使用浏览器通过VIP地址访问Web系统,由于系统1只有1台调度器,因此当它宕机后,整个系统处于不可用的状态。
然后测试系统2,将系统2的值班调度器A关闭,使用浏览器通过VIP地址访问Web系统,可以看到系统仍然可以正常访问。通过查看调度器B的Keepalived日志和IP地址,可以发现VIP已经切换到调度器B上,因此调度器B升级为值班调度器,系统服务正常。
将系统2的值班调度器A恢复启动,使用浏览器通过VIP地址访问Web系统,系统可以正常访问。通过查看调度器A的Keepalived日志和IP地址,可以发现VIP重新切换到调度器A上,因此调度器A重新接管为值班调度器,系统服务正常。
测试结果表明,在相同的硬件条件下,由于本方案构建集群使用了热主备配置调度器,高可用性得到大幅度提升。
3.3 易扩展测试
易扩展即在服务器池中方便地增加节点。分为3个步骤:
1)在新增服务节点中增加Spring-Session的支持,再将该节点物理上接入局域网;
2)在该服务节点环回接口上配置VIP地址,并设置好ARP抑制;
3)在2台调度器的keepalived.conf中增加realserver的配置,然后逐一重启Keepalived服务。
从上述步骤来看,扩展过程不涉及应用代码改动,所有步骤均离线进行,由于高可用的保证,应用不会受到影响,整个扩展过程简单、快速而且对应用安全。
4 结语
针对文献[1]提出的Web服务器集群方案存在的不足,本文提出一种新的Web服务器集群架构方案。本方案满足了高并发、高可用、易扩展的要求,可望支撑中型及以上网站的并发访问需求。
不足之处在于后端Redis内存数据库使用了单例库,没有使用Redis集群做缓存存储,因此存在一定的数据丢失风险,需要在后续的研究中加以改进。
(编辑:张京娜)
参考文献
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
[10]
[11]
[12]
[13]
[14]
[15]