Nginx+Apache+Tomcats负载均衡集群及session cluster实现
一、拓扑
二、部署Tomcat服务器
以其中的tomcat服务器A做配置讲解,B服务器同理
1、准备:JDK 、Tomcat
JDK:使用centos7自带的openjdk 1.8.0_131
[root@node1 ~]# java -version openjdk version "1.8.0_131" OpenJDK Runtime Environment (build 1.8.0_131-b12) OpenJDK 64-Bit Server VM (build 25.131-b12, mixed mode)
Tomcat: 使用base源中提供的tomcat 7.0.76
[root@node1 ~]# yum info tomcat 已加载插件:fastestmirror, langpacks Loading mirror speeds from cached hostfile * base: mirrors.aliyun.com * extras: mirrors.aliyun.com * updates: mirrors.aliyun.com 已安装的软件包 名称 :tomcat 架构 :noarch 版本 :7.0.76 发布 :6.el7 大小 :303 k 源 :installed 来自源:base/
2、部署tomcat
在/data/webapp 目录下部署测试使用的webapp,目录结构如下:
[root@node1 ~]# cd /data/webapp/ROOT/ [root@node1 ROOT]# ll 总用量 4 drwxr-xr-x 2 root root 6 6月 11 19:36 classes -rw-r--r-- 1 root root 183 6月 11 19:38 index.jsp drwxr-xr-x 2 root root 6 6月 11 19:36 lib drwxr-xr-x 2 root root 6 6月 11 19:36 META-INF drwxr-xr-x 2 root root 6 6月 11 19:36 WEB-INF
编辑测试页面:
[root@node1 ROOT]# vim index.jsp <%@ page language = "java" %> <%@ page import = "java.util.*" %> <html> <head> <title> Jsp Test Page </title> </head> <body> <% out.println("Hello Node1 Your SessionID :"); String id = session.getId(); %> <%=id%> </body> </html>
编辑tomcat配置文件/etc/tomcat/server.conf,创建一个HOST虚拟机来提供我们的测试webapp,并将其设置为默认虚拟机,能够通过主机名直接访问,其配置如下:
<Host name="www.yaya.com" appBase="/data/webapp" #定义测试webapp的访问根路径 unpackWARs="true" autoDeploy="true"> <Context path="" dacBase="ROOT" reloadable="true"> </Context> </Host>
开启服务并测试:
LISTEN 0 100 :::8080 :::* users:(("java",pid=2372,fd=49))
确保8080端口依然被tomcat监听后,使用客户端访问
同理配置Tomcat服务器B
三、前端Apache配置
让apache(这里使用httpd2.4)监听在80端口,工作为反向代理模式,将Nginx主机调度来的请求反代至tomcat服务器,tomcat服务器提供http connector接收请求。
httpd用到的模块:主模块:proxy_module 次模块:proxy_module_http
查看httpd的模块是否已经装载:
[root@node1 ~]# vim /etc/httpd/conf.modules.d/00-proxy.conf # This file configures all the proxy modules: LoadModule proxy_module modules/mod_proxy.so LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so LoadModule proxy_ajp_module modules/mod_proxy_ajp.so LoadModule proxy_balancer_module modules/mod_proxy_balancer.so LoadModule proxy_connect_module modules/mod_proxy_connect.so LoadModule proxy_express_module modules/mod_proxy_express.so LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so LoadModule proxy_ftp_module modules/mod_proxy_ftp.so LoadModule proxy_http_module modules/mod_proxy_http.so #我们所需要的模块已经加载 LoadModule proxy_scgi_module modules/mod_proxy_scgi.so LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
添加一个httpd虚拟机来实现反向代理的功能,在/etc/httpd/conf.d/下创建virtualhost.conf,其配置如下:
[root@node1 conf.d]# vim /etc/httpd/conf.d/virtualhost.conf <VirtualHost *:80> ServerName node1.yaya.com ProxyVia on #在http首部中添加经由谁转发 ProxyRequests off #关闭httpd的正向代理功能 ProxyPreserveHost on #保留请求首部中的HOST发往后端,因为后端tomcat是虚拟机是做了基于主机名访问 <Proxy *> Require all granted #所有合法用户都能使用代理功能 </Proxy> ProxyPass / http://192.168.50.138:8080/ #反向代理到本机的8080端口 ProxyPassReverse / http://192.168.50.138:8080/ <location /> Require all granted #url访问控制,允许所有合法用户访问 </location> </VirtualHost>
在windows主机中添加主机名解析:
修改windows主机中的host文件,在C:\Windows\System32\drivers\etc 中,找到hosts文件,用记事本打开:
开启httpd服务并测试
我们可以直接通过80端口访问到后端的tomcat容器,因此,说明httpd已经将请求成功反向代理至tomcat容器,同理配置tomcat服务器B
四、配置Nginx负载均衡主机
编辑nginx配置文件:
首先定义后端的upserver:
upstream dynamicjsp { server 192.168.50.138 ; server 192.168.50.139 ; }
定义反向代理策略,让Nginx主机负责处理静态请求,动态请求将发往后端的tomcat服务器
location ~* \.(html|htm|jpg)$ { } location / { proxy_pass http://dynamicjsp ; }
开启nginx服务并测试:
可以看出,动态资源由后台的tomcat服务器响应
静态资源请求:
而静态资源由Nginx主机执行响应
五、session cluster实现
我们实现了基于主机名访问,负载均衡,动静分离,但是session绑定的问题依然没有解决,每一次被调度,都被认为是一个新的请求,sessionID在不断改变,我们理想的应该是,不管被调度到哪一台后端主机,客户的session信息应该是不变的,因此,我们还要实现session cluster,其基本原理是:后端应用服务器通过多播方式共享本地的session记录信息,最终每个后端服务器的保存了所以用户的session信息。
这里我们以tomcat内置的session manager--DeltaManager来演示
构建session cluster步骤:
1、后端各节点配置使用DeltaManager
2、为需要使用session cluster的webapps开启session distribution功能
tomcat官网中给出了session cluster的实现配置:
https://tomcat.apache.org/tomcat-7.0-doc/cluster-howto.html
这里我们在HOST组件中添加配置信息(tomcatA和tomcatB都需要配置):
<Host name="www.yaya.com" appBase="/data/webapp" unpackWARs="true" autoDeploy="true"> #我们自己定义的虚拟机 <Context path="" dacBase="ROOT" reloadable="true"> </Context> <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8"> <Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true"/> #实现DeltaManager的类 <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" #发送心跳信息的频率,单位ms 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> </Host>
再次请求测试:
可以看到在实现负载均衡的同时也实现了session cluster的效果。
成功!!!