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的效果。
成功!!!