背景
需要实现tomcat的高可用,任意一台tomcat宕机,不影响整体运行。
方案要点
- 对外需要只暴露一个地址,对内需要负载均衡的连接多个tomcat。
- tomcat宕机后,需要自动剔除连接
- 不同tomcat切换时的session共享问题
思路:使用nginx使多个tomcat联合,对外只暴露一个地址。宕机剔除由nginx功能实现。 这篇文章的应该能满足,这里尝试一下。
测试
nginx部署
只有使用nginx将多个tomcat访问地址绑定成一个nginx访问地址,外部才能感知为一个web服务,否则将不能称为tomcat高可用。
下载nginx yum源
使用yum安装nginx需要包括Nginx的库,安装Nginx的库 rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
这里注意选择与操作系统相同的版本
安装nginx
使用下面命令安装nginx yum install nginx
启动Nginx
service nginx start
centos6
systemctl start nginx.service
centos7
启动后,访问 可以查看nginx是否安装成功。
tomcat部署
这里模拟部署两台相同的tomcat,首先不考虑session的问题,进行尝试。
建立测试页面
分别在tomcat1,tomcat2上$TOMCAT_HOME/webapps 下建立 test文件夹,并向test下添加index.jsp测试页面
tomcat1的index.jsp内容
<%@ page language="java" %>Tomcat A TomcatA.san.com
Session ID | <%= session.getId() %> |
Created on | <%= session.getCreationTime() %> |
tomcat2的index.jsp内容
<%@ page language="java" %>Tomcat B TomcatB.san.com
Session ID | <%= session.getId() %> |
Created on | <%= session.getCreationTime() %> |
启动并测试访问
tomcat1
tomcat2
nginx配置
配置nginx统一访问两台tomcat,而不是上面一样分别访问两台tomcat
vim /etc/nginx/conf.d/tomcat-9333.conf
## Basic reverse proxy server #### backend for 16.32 ## ## Start 16.32 ###upstream tomcats { server 192.168.12.81:8080; # tomcat1 server 192.168.12.82:8080; # tomcat2} server { listen 9333; server_name 192.168.12.72; #root html; #index index.html index.htm index.php; access_log /var/log/nginx/reverse_proxy.access-9333.log main; error_log /var/log/nginx/debug-9333.log error; charset utf-8; ## send request back to 16.32 ## location / { #Proxy Settings proxy_pass http://tomcats; proxy_redirect off; proxy_set_header Host $host:9333; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; #proxy_max_temp_file_size 0; #proxy_connect_timeout 90; #proxy_send_timeout 90; #proxy_read_timeout 90; #proxy_buffer_size 4k; #proxy_buffers 4 32k; #proxy_busy_buffers_size 64k; #proxy_temp_file_write_size 64k; }}
测试
这次改用访问统一的nginx的地址,即 ,这个会自动跳转到tomcat1和tomcat2上。现象跟分别部署的tomcat一致,由于采用默认配置,所以分别的,一次在tomcat1上一次在tomcat2上。
PS:进行测试时,由于有缓存的存在,不是一次tomcat1一次tomcat2的轮流访问的现象,可以在地址栏按回车进行访问,或禁用缓存
这样就达到了目的1,nginx访问两台tomcat,而外部只感知到nginx的一个地址。
宕机测试
这次关闭掉tomcat,看看nginx访问的现象。
- 关闭tomcat1,此时访问 全是tomcat2的测试页面
- 关闭tomcat2,此时访问 全是tomcat1的测试页面
即nginx会自动把宕机的tomcat给剔除掉,且tomcat恢复了之后,仍然能够自动加入进来。这样也符合了预期的宕机自动下线。但是这里有一个很严重的问题,即每次访问的时候session id都会改变,而且即使同样是tomcat1的网页在切换到tomcat2再切换回来之后,其session id也会改变,这样在有登录系统保存session的时候会无法固化用户的登录状态。
nginx的ip_hash测试
这一块内容为2018-12-07补充 其实解决session id每次访问不相同有两种办法。
- 1、一次登录的所有访问都由nginx分发到同一台tomcat1上。
- 2、就是下面说的session共享,即不管访问哪台tomcat,由tomcat将其session都保持一致。
分析下这两种方案的优缺点 1的缺点是如果nginx的分发策略不好的话,会出现tomcat1上的请求比tomcat2的请求多出很多的情况。优点是配置简单。 2的缺点是配置和维护比较复杂,但是优点是负载会比较均衡,而且可以根据权重和响应时间等调整分发策略。
PS:这里网上有的文章说ip_hash无法自动剔除宕机的tomcat,需要手工标识并剔除,但是经过我的测试,发现是会自动剔除的,可能是nginx版本更新了该功能,本次测试的nginx版本为:nginx version: nginx/1.14.2
测试步骤如下: 首先修改nginx中的如下配置 vim /etc/nginx/conf.d/tomcat-9333.conf
upstream tomcats { ip_hash; #这一部分添加了根据ip hash选择合适的tomcat分发 server 192.168.12.81:8080; # tomcat1 server 192.168.12.82:8080; # tomcat2}
重新加载nginx配置文件 nginx -s reload
访问测试:
-
第一次访问nginx 显示访问的是tomcat2的网页。 以后每次访问都是tomcat2的地址,因为是根据ip地址进行hash来选择tomcat的。
-
将tomcat2停机,模拟宕机的情况。再次访问 nginx 会自动切换到tomcat1上,且以后每次都是访问tomcat1的地址。
-
将tomcat2重新恢复,模拟宕机恢复,再次访问 nginx 这里又恢复为访问tomcat2的地址了,且以后每次都是访问tomcat2的地址。 备注:这里忽略session id一致的现象,因为本来是先测试的session共享,所有这里测试的时候配置还是一样的。主要还是测试ip_hash的参数的作用。
这样其实也满足了我们当前的需求,即tomcat高可用,但是不需要考虑流量的负载均衡,有点像主备的形式。但是也起到了一部分的分流的作用。但是如果是一些大流量的网站就需要考虑使用session共享的形式了。
session共享
为了解决上面出现的session id会改变的问题,这里需要将所有tomcat服务器的session进行共享,这样tocmat1和tomcat2的session id就是一样的
Tomcat Session Replication Cluster配置
这里参考 上面的文章和 目前的配置是采用上面的文章,测试是通过的,tocmat1和tomcat2的session id 保持一致。
tomcat1
tomcat2
即使不同的页面session id也是一样的。 但是这个利用tomcat session replication cluster有一个缺点,由于是利用广播的形式在tomcat之间进行分发session,当tomcat数量较多时,就会性能的下降。这样就需要采用第三方如memcache集中式的存储session的形式来优化。
Tomcat Memcache Session Server
这个就是利用memcache来集中式的存储session的形式。这个暂时未做测试。以后有需要的时候再做测试。