httpd反代 + tomcat cluster + redis会话保持

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了httpd反代 + tomcat cluster + redis会话保持相关的知识,希望对你有一定的参考价值。

版本说明:

httpd版本:2.4.6

tomcat版本:7.0.69

dedis版本:3.2.3

操作系统版本:CentOS Linux release 7.3.1611


拓扑结构:

                                                           tomcat-A/192.168.1.106        

客户端------>httpd反向代理 ------->                                           ----- > redis会话保持服务器

                      192.168.1.101               tomcat-B/192.168.1.107                  192.168.1.100

 

httpd反向代理:

安装httpd服务

yum -y install  httpd

httpd实现反向代理需要三个modules的支持:

mod_proxy.so 
mod_proxy_http.so 
mod_proxy_balancer.so

编辑proxy配置

cat  /etc/httpd/conf.d/tomcat-proxy.conf
<proxy balancer://tcsrvs>
        balancermember http://192.168.1.106:8080
        balancermember http://192.168.1.107:8080
        proxyset lbmethod=byrequests   #调度方式,根据请求调度,类似于轮询
</proxy>

<virtualhost *:80>
        servername lb.tomcat.com
        proxyvia on
        proxyrequests off
        proxypreservehost on
        <proxy *>
                require all granted
        </proxy>
        proxypass / balancer://tcsrvs/
        proxypassreverse / balancer://tcsrvs/
        <location />
                require all granted
        </location>
</virtualhost>


tomcat服务器配置:

安装对应的软件包

java-1.8.0-openjdk 
tomcat  
tomcat-lib 
tomcat-admin-webapps 
tomcat-webapps
tomcat-docs-webapp

准备测试文件

mkdir /usr/share/tomcat/webapps/test/

tomcat-A:
cat /usr/share/tomcat/webapps/test/index.jsp                                                       <%@ page language="java" %>
<html>
<head><title>TomcatA</title></head>
<body>
<h1><font color="blue">TomcatA.com</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("tomcatA.com","tomcatA.com"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>

tomcat-B:
cat /usr/share/tomcat/webapps/test/index.jsp      
<%@ page language="java" %>
<html>
<head><title>TomcatB</title></head>
<body>
<h1><font color="red">TomcatB.com</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("tomcatB.com","tomcatB.com"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>

然后启动tomcat服务

systemctl  start tomcat.service

此时在浏览器测试http://192.168.1.101/test/

以上只是完成了httpd调度后端tomcat主机的需求


当客户端访问时,不希望会话信息改变,试想一下,你在电商网站下了单了,然后刷新页面调度器把你的请求调度到另一台机器上,下的单没了,你作何感受?所以,为了避免这种现象的发生,我们通过设置cookie信息,来绑定会话


httpd服务器配置:

cat tomcat-proxy.conf  
        header add set-cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED 
        #设置cookie信息
<proxy balancer://tcsrvs>
        balancermember http://192.168.1.106:8080 route=tomcatA loadfactor=1
        balancermember http://192.168.1.107:8080 route=tomcatB loadfactor=1
        proxyset lbmethod=byrequests
        proxyset stickysession=ROUTEID   #基于会话粘性来设置cookie
</proxy>
#route与后端tomcat的jvmRoute对应
<virtualhost *:80>
        servername lb.tomcat.com
        proxyvia on
        proxyrequests off
        proxypreservehost on
        <proxy *>
                require all granted
        </proxy>
        proxypass / balancer://tcsrvs/
        proxypassreverse / balancer://tcsrvs/
        <location />
                require all granted
        </location>
</virtualhost>

tomcat主机配置:

vim server.xml 
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcatA">
#修改tomcat主机,jvmRoute是支持负载均衡的

在tomcatB主机也要做类似的修改

完成上述内容就能够实现基于cookie的会话粘性了,在浏览器测试http://192.168.1.101/test/就只会调到同一台主机,当此主机故障会调度到另一台主机


上述基于cookie的会话粘性存在一个问题,即客户端基于cookie访问后端服务器A,如果A主机故障,httpd会重新调度到B主机上,但是B上没有之前的会话信息,所以客户端浏览记录、下单情况等信息就消失了。

可以使用tomcat集群加单独的缓存服务器redis解决上述问题,tomcat集群解决主机单点故障问题,将会话信息单独存放在缓存服务器上而不是tomcat主机

,不过redis为了避免单点问题也要做高可用,这里我们只要能实现会话缓存功能即可。只有高可用大家有兴趣可以自己研究


配置session server的话就不用cookie信息,把httpd配置中的cookie配置删除

 vim tomcat-proxy.conf 
 header add set-cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
 proxyset stickysession=ROUTEID
 #将上述两行删掉或者注释,然后重启服务

tomcat主机配置集群:

cat server.xml  
#在Engine字段下配置下述内容
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8">
        <Manager className="org.apache.catalina.ha.session.DeltaManager"
                expireSessionsOnShutdown="false" notifyListenersOnReplication="true"/>
        <Channel className="org.apache.catalina.tribes.group.GroupChannel">
        <Membership className="org.apache.catalina.tribes.membership.McastService"
                address="228.0.0.4" 
                port="45564" 
                frequency="500" 
                dropTime="3000"/>
        <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                address="auto" 
                port="4000" 
                autoBind="100" 
                selectorTimeout="5000" 
                maxThreads="6"/>
        <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
        <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
        </Sender>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
        </Channel>
        <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/>
        <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
        <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" tempDir="/tmp/war-temp/"
                deployDir="/tmp/war-deploy/" watchDir="/tmp/war-listen/" watchEnabled="false"/>
        <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener" />
        <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener" />
        </Cluster>

以上内容很多,可以直接复制,不用做任何修改,两台主机都要配置

参考连接http://tomcat.apache.org/tomcat-7.0-doc/cluster-howto.html 

注意官网模板配置中有两处错误:

 <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener" />
 <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener" />
 #官网中此处末尾都没有加结束符 /

然后修改web.xml

cat web.cml
<distributable/> 
#此处指明tomcat的分布式集群

安装redis,并设置

yum -y install redis 
vim /etc/redis.conf
bind 0.0.0.0
#指定监听所有地址,默认监听端口是tcp6379

然后启动redis服务

接着配置tomcat主机,本处以其中一台为例,另一台也要按此方式配置

cat context.xml   #编辑如下内容
 <Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
 <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
      host="192.168.1.100"
      port="6379"
      database="0"
      maxInactiveInterval="60" />
#192.168.1.100是redis的地址

准备jar包,三个jar包,其下载地址如下

https://github.com/izerui/tomcat-redis-session-manager.git

然后将这三个jar包,放到tomcat的库目录中,即/usr/share/tomcat/lib/ 

重启tomcat服务

此时打开浏览器测试http://192.168.1.101/test/,会发现sessionID不变,但调度的后端主机改变了


总结:

redis只修改监听地址即可,其他不用修改任何配置;

httpd只是启动反代的作用,关键是配置对后端主机的调度;

tomcat集群需修改server.xml和web.xml文件,配合redis缓存还需配置context.xml和准备jar包


结束

以上是关于httpd反代 + tomcat cluster + redis会话保持的主要内容,如果未能解决你的问题,请参考以下文章

Nginx/Httpd反代tomcat配置

apache反代tomcat出现的问题

Tomcat集群session复制,httpd/nginx反代Tomcat集群

nginx反代httpd,实现三种tomcat代理模型至后端的tomcat服务器,会话绑定的三种方式

nginx + tomcat cluster

高性能Web服务之Httpd负载均衡Tomcat实现Session Sticky及Session Cluster