企业级web应用服务器--Tomcat(四)

企业级web应用服务器--Tomcat(四)
一、结合反向代理实现tomcat部署1、常见部署方式介绍

standalone模式,Tomcat单独运行,直接接受用户的请求,不推荐反向代理,单机运行,提供了一个Nginx作为反向代理,可以做到静态由nginx提供响应,动态jsp代理给Tomcat LNMT:Linux + Nginx + MySQL + Tomcat LAMT:Linux + Apache(Httpd)+ MySQL + Tomcat前置一台Nginx,给多台Tomcat实例做反向代理和负载均衡调度,Tomcat上部署的纯动态页面更适合 LNMT:Linux + Nginx + MySQL + Tomcat多级代理 LNNMT:Linux + Nginx + Nginx + MySQL + Tomcat 2、利用 nginx 反向代理实现全部转发置指定同一个虚拟主机

1)利用nginx指令proxy_pass 可以向后端服务器转发请求报文,并且在转发时会保留客户端的请求报文中的host首部

#从yum源安装nginx#yum install nginx -y#vim /etc/nginx/nginx.conf#全部反向代理测试location / {# proxy_pass http://127.0.0.1:8080; # 不管什么请求,都会访问后面的localhost虚拟主机proxy_pass http://node1.magedu.com:8080; # 此项将用户访问全部请求转发到node1的虚拟主机上#proxy_pass http://node2.magedu.com:8080; #此项将用户访问全部请求转发到node2的虚拟主机上#以上两项都需要修改nginx服务器的/etc/hosts,实现node1.magedu.com和node2.magedu.com到IP的解析}#nginx -t#systemctl restart nginx#说明: proxy_pass http://FQDN/ 中的FQDN 决定转发至后端哪个虚拟主机,而与用户请求的URL无关#如果转到后端的哪个服务器由用户请求决定,可以向后端服务转发请求的主机头实现,示例:proxy_set_header Host $http_host; 2)案例环境说明:一台主机,实现nginx和tomcattomcat上有两个虚拟主机node1和node2 #在同一下主机上建立两个tomcat虚拟主机,node1.syk.top和node2.syk.top#修改/etc/hosts文件,实现名称解析[root@centos8 ~]#vim /etc/hosts127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4centos8.localdomain::1 localhost localhost.localdomain localhost6 localhost6.localdomain610.0.0.100 node1.syk.top node2.syk.top#安装nginx[root@centos8 ~]#yum -y install nginx#修改nginx.conf配置文件[root@centos8 ~]#vim /etc/nginx/nginx.conf......#修改location / 此行,添加以下内容location / {#proxy_pass http://127.0.0.1:8080;proxy_pass http://node1.syk.top:8080;}......[root@centos8 ~]#systemctl enable --now nginx#先别访问node1,node2和IP都可以看到一样的node1的虚拟主机页面[root@centos8 ~]#curl http://node1.syk.top/<!DOCTYPE html><html><head><meta charset="utf-8"><title>jsp例子</title></head><body>后面的内容是服务器端动态生成字符串,最后拼接在一起node1.syk.top</body></html>[root@centos8 ~]#curl http://node2.syk.top/<!DOCTYPE html><html><head><meta charset="utf-8"><title>jsp例子</title></head><body>后面的内容是服务器端动态生成字符串,最后拼接在一起node2.syk.top</body></html>[root@centos8 ~]#curl http://127.0.0.1/<!DOCTYPE html><html><head><meta charset="utf-8"><title>jsp例子</title></head><body>后面的内容是服务器端动态生成字符串,最后拼接在一起node1.syk.top</body></html>[root@centos8 ~]#curl http://10.0.0.100/<!DOCTYPE html><html><head><meta charset="utf-8"><title>jsp例子</title></head><body>后面的内容是服务器端动态生成字符串,最后拼接在一起node1.syk.top</body></html>[root@centos8 ~]#systemctl restart nginx#再次修改nginx.conf配置文件[root@centos8 ~]#vim /etc/nginx/nginx.conf......#修改location / 行,添加以下内容location / {#proxy_pass http://127.0.0.1:8080;proxy_pass http://node2.syk.top:8080;}......#先别访问node1,node2和IP都可以看到一样的node2的虚拟主机页面[root@centos8 ~]#curl http://node1.syk.top/[root@centos8 ~]#curl http://node2.syk.top/[root@centos8 ~]#curl http://127.0.0.1/[root@centos8 ~]#curl http://10.0.0.100/<!DOCTYPE html><html><head><meta charset="utf-8"><title>jsp例子</title></head><body>后面的内容是服务器端动态生成字符串,最后拼接在一起node2.syk.top</body></html> 3、利用nginx实现动静分离代理1)配置说明可以利用nginx实现动静分离代理vim nginx.confroot /usr/share/nginx/html;#下面行可不加#location / {# root /data/webapps/ROOT;# index index.html;#}# ~* 不区分大小写location ~* \.jsp$ {proxy_pass http://node1.magedu.com:8080; #注意: 8080后不要加/,需要nginx修改/etc/hosts}以上设置,可以将jsp的请求反向代理到tomcat,而其它文件仍由nginx处理,从而实现所谓动静分离。但由于jsp文件中实际上是由静态资源和动态组成,所以无法彻底实现动静分离。实际上Tomcat不太适合做动静分离,用它来管理程序图片不好做动静分离部署 2)案例#准备三个不同的资源文件[root@centos8 ~]#echo /usr/local/tomcat/webapps/ROOT/test.html >/usr/local/tomcat/webapps/ROOT/test.html[root@centos8 ~]#echo /usr/local/tomcat/webapps/ROOT/test.jsp >/usr/local/tomcat/webapps/ROOT/test.jsp[root@centos8 ~]#echo /usr/share/nginx/html/test.html >/usr/share/nginx/html/test.html[root@centos8 ~]#vim /etc/nginx/nginx.conf......root /usr/share/nginx/html;#location / {##}location ~* \.jsp$ {proxy_pass http://127.0.0.1:8080;}......[root@centos8 ~]#systemctl restart nginx#访问test.html,观察结果都一样访问的是nginx自身的资源[root@centos8 ~]#curl http://node1.syk.top/test.html[root@centos8 ~]#curl http://node2.syk.top/test.html[root@centos8 ~]#curl http://127.0.0.1/test.html[root@centos8 ~]#curl http://10.0.0.8/test.html/usr/share/nginx/html/test.html#访问test.jsp,观察结果都一样访问的是tomcat的默认主机资源[root@centos8 ~]#curl http://node1.syk.top/test.jsp[root@centos8 ~]#curl http://node2.syk.top/test.jsp[root@centos8 ~]#curl http://127.0.0.1/test.jsp[root@centos8 ~]#curl http://10.0.0.8/test.jsp/usr/local/tomcat/webapps/ROOT/test.jsp 4、利用httpd实现基于http协议的反向代理至后端Tomcat服务器1)配置说明httpd也提供了反向代理功能,所以可以实现对tomcat的反向代理功能功能模块:查看代理相关模块 [root@centos8 ~]#httpd -M|grep proxyAH00558: httpd: Could not reliably determine the server's fully qualified domainname, using centos8.localdomain. Set the 'ServerName' directive globally tosuppress this messageproxy_module (shared)proxy_ajp_module (shared) #ajpproxy_balancer_module (shared)proxy_connect_module (shared)proxy_express_module (shared)proxy_fcgi_module (shared)proxy_fdpass_module (shared)proxy_ftp_module (shared)proxy_http_module (shared) #httpproxy_hcheck_module (shared)proxy_scgi_module (shared)proxy_uwsgi_module (shared)proxy_wstunnel_module (shared)proxy_http2_module (shared) proxy_http_module模块代理配置 vim /etc/httpd/conf.d/http-tomcat.conf<VirtualHost *:80>ServerName node1.syk.topProxyRequests OffProxyPass / http://127.0.0.1:8080/ProxyPassReverse / http://127.0.0.1:8080/ProxyPreserveHost OnProxyVia On</VirtualHost> ProxyRequests:Off 关闭正向代理功能,即启动反向代理ProxyPass:反向代理指令,指向后端服务器ProxyPassReverse:当反向代理时,返回给客户端的报文需将之重写个别后端主机的response头,如:Location,Content-Location,URIProxyPreserveHost:On时让反向代理保留原请求的Host首部转发给后端服务器,off 时则删除host首部后再转发至后面端服务器, 这将导致只能转发到后端的默认虚拟主机ProxyVia:On开启。反向代理的响应报文中提供一个response的via首部,默认值off 2)案例#基于httpd实现反向代理后端的tomcat #对不同的虚拟主机生成页面文件[root@centos8 ~]#echo /usr/local/tomcat/webapps/ROOT/test.html >/usr/local/tomcat/webapps/ROOT/test.html[root@centos8 ~]#echo /data/node1/ROOT/test.html > /data/node1/ROOT/test.html[root@centos8 ~]#echo /data/node2/ROOT/test.html > /data/node2/ROOT/test.html#提前准备好tomcat的两个虚拟主机的配置[root@centos8 ~]#tail /usr/local/tomcat/conf/server.xml</Host><Host name="node1.syk.top" appBase="/data/node1/" unpackWARs="true"autoDeploy="true"></Host><Host name="node2.syk.top" appBase="/data/node2/" unpackWARs="true"autoDeploy="true"></Host></Engine></Service></Server>#修改httpd配置[root@centos8 ~]#yum -y install httpd[root@centos8 ~]#vim /etc/httpd/conf.d/tomcat.conf[root@centos8 ~]#cat /etc/httpd/conf.d/tomcat.conf<VirtualHost *:80>ServerName node1.syk.topProxyRequests OffProxyVia OnProxyPreserveHost OnProxyPass / http://127.0.0.1:8080/ProxyPassReverse / http://127.0.0.1:8080/</VirtualHost>[root@centos8 ~]#systemctl restart httpd#用下面不同URL访问,可以看不同结果[root@centos8 ~]#curl http://node1.syk.top/test.html/data/node1/ROOT/test.html[root@centos8 ~]#curl http://node2.syk.top/test.html/data/node2/ROOT/test.html[root@centos8 ~]#curl http://127.0.0.1/test.html/usr/local/tomcat/webapps/ROOT/test.html[root@centos8 ~]#curl http://10.0.0.8/test.html/usr/local/tomcat/webapps/ROOT/test.html#修改配置[root@centos8 ~]#vim /etc/httpd/conf.d/tomcat.conf#只修改下面一行ProxyPreserveHost Off[root@centos8 ~]#systemctl restart httpd#再次用用下面不同URL访问,可以看相同结果[root@centos8 ~]#curl http://node1.syk.top/test.html/usr/local/tomcat/webapps/ROOT/test.html[root@centos8 ~]#curl http://node2.syk.top/test.html/usr/local/tomcat/webapps/ROOT/test.html[root@centos8 ~]#curl http://10.0.0.8/test.html/usr/local/tomcat/webapps/ROOT/test.html[root@centos8 ~]#curl http://127.0.0.1/test.html/usr/local/tomcat/webapps/ROOT/test.html 5、利用 httpd 实现基于AJP协议的反向代理至后端Tomcat服务器

AJP(Apache JServ Protocol)是定向包协议,是一个二进制的TCP传输协议,相比HTTP这种纯文本的协议来说,效率和性能更高,也做了很多优化。但是浏览器并不能直接支持AJP13协议,只支持HTTP协议。所以实际情况是,通过Apache的proxy_ajp模块进行反向代理,暴露成http协议给客户端访问。

1)启用和禁用 AJP

注意: Tomcat/8.5.51之后版本基于安全需求默认禁用AJP协议案例: Tomcat/8.5.51之后版启用支持AJP协议[root@centos8 tomcat]#vim conf/server.xml#取消前面的注释,并修改下面行,修改address和secretRequired<Connector protocol="AJP/1.3" address="0.0.0.0" port="8009"redirectPort="8443" secretRequired="" />[root@centos8 tomcat]#systemctl restart tomcat[root@centos8 tomcat]#ss -ntlState Recv-Q Send-Q Local Address:Port Peer Address:PortLISTEN 0 128 0.0.0.0:22 0.0.0.0:*LISTEN 0 100 127.0.0.1:25 0.0.0.0:*LISTEN 0 128 [::]:22 [::]:*LISTEN 0 100 [::1]:25 [::]:*LISTEN 0 1 [::ffff:127.0.0.1]:8005 *:*LISTEN 0 100 [::ffff:127.0.0.1]:8009 *:*LISTEN 0 100 *:8080 *:*LISTEN 0 128 *:80 *:*注意: secretRequired="" 必须加上,否则出现以下错误提示[root@centos8 tomcat]#cat logs/catalina.logCaused by: java.lang.IllegalArgumentException: The AJP Connector is configured with secretRequired="true" but the secret attribute is either null or "". This combination is not valid.除httpd外,其它支持AJP代理的服务器非常少,比如Nginx就不支持AJP,所以目前一般都禁用AJP协议端口案例:禁用AJP协议#Tomcat/8.5.50版本之前默认支持AJP协议[root@centos8 ~]#ss -ntlState Recv-Q Send-Q Local Address:Port Peer Address:PortLISTEN 0 128 0.0.0.0:22 0.0.0.0:*LISTEN 0 100 *:8080 *:*LISTEN 0 128 *:80 *:*LISTEN 0 128 [::]:22 [::]:*LISTEN 0 1 [::ffff:127.0.0.1]:8005 *:*LISTEN 0 100 *:8009 *:*#配置tomcat配置文件,删除下面一行[root@centos8 ~]#vim /usr/local/tomcat/conf/server.xml<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />[root@centos8 ~]#systemctl restart tomcat[root@centos8 ~]#ss -ntlState Recv-Q Send-Q Local Address:Port Peer Address:PortLISTEN 0 128 0.0.0.0:22 0.0.0.0:*LISTEN 0 100 *:8080 *:*LISTEN 0 128 *:80 *:*LISTEN 0 128 [::]:22 [::]:*LISTEN 0 1 [::ffff:127.0.0.1]:8005 *:*2)httpd 实现 AJP 反向代理相对来讲,AJP协议基于二进制比使用HTTP协议的连接器效率高些。 proxy_ajp_module模块代理配置<VirtualHost *:80>ServerName node1.syk.topProxyRequests OffProxyVia OnProxyPreserveHost OnProxyPass / ajp://127.0.0.1:8009/</VirtualHost>查看Server Status可以看到确实使用的是ajp连接了。

案例 :启用httpd的AJP反向代理功能

[root@centos8 ~]#vim /etc/httpd/conf.d/tomcat.conf[root@centos8 ~]#cat /etc/httpd/conf.d/tomcat.conf<VirtualHost *:80>ServerName node1.syk.topProxyRequests OffProxyVia On #此项对AJP无效ProxyPreserveHost On #此项对AJP无效ProxyPass / ajp://127.0.0.1:8009/</VirtualHost>[root@centos8 ~]#systemctl restart httpd#再次用用下面不同URL访问,可以看以下结果[root@centos8 ~]#curl http://node1.syk.top/test.html/data/node1/ROOT/test.html[root@centos8 ~]#curl http://node2.syk.top/test.html/data/node2/ROOT/test.html[root@centos8 ~]#curl http://10.0.0.8/test.html/usr/local/tomcat/webapps/ROOT/test.html[root@centos8 ~]#curl http://127.0.0.1/test.html/usr/local/tomcat/webapps/ROOT/test.html[root@centos8 ~]#vim /etc/httpd/conf.d/tomcat.conf#只修改下面一行,关闭向后端转发请求的host首部ProxyPreserveHost Off#再次用用下面不同URL访问,可以看到和上面一样的结果,说明AJP协议和Http不同,自动转发所有首部信[root@centos8 ~]#curl http://node1.syk.top/test.html/data/node1/ROOT/test.html[root@centos8 ~]#curl http://node2.syk.top/test.html/data/node2/ROOT/test.html[root@centos8 ~]#curl http://10.0.0.8/test.html/usr/local/tomcat/webapps/ROOT/test.html[root@centos8 ~]#curl http://127.0.0.1/test.html/usr/local/tomcat/webapps/ROOT/test.html

#可以通过status页面看到下面AJP的信息

#用iptables禁用AJP的访问[root@centos8 ~]#iptables -A INPUT -p tcp --dport 8009 -j REJECT[root@centos8 ~]#curl http://node1.syk.top/test.html<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><html><head><title>503 Service Unavailable</title></head><body><h1>Service Unavailable</h1><p>The server is temporarily unable to service yourrequest due to maintenance downtime or capacityproblems. Please try again later.</p></body></html> 6、实现 tomcat 负载均衡动态服务器的问题,往往就是并发能力太弱,往往需要多台动态服务器一起提供服务。如何把并发的压力分摊,这就需要调度,采用一定的调度策略,将请求分发给不同的服务器,这就是Load Balance负载均衡。当单机Tomcat,演化出多机多级部署的时候,一个问题便凸显出来,这就是Session。而这个问题的由来,都是由于HTTP协议在设计之初没有想到未来的发展。1)HTTP的无状态,有连接和短连接无状态:指的是服务器端无法知道2次请求之间的联系,即使是前后2次请求来自同一个浏览器,也没有任何数据能够判断出是同一个浏览器的请求。后来可以通过cookie、session机制来判断。 浏览器端第一次HTTP请求服务器端时,在服务器端使用session这种技术,就可以在服务器端产生一个随机值即SessionID发给浏览器端,浏览器端收到后会保持这个SessionID在Cookie当中,这个Cookie值一般不能持久存储,浏览器关闭就消失。浏览器在每一次提交HTTP请求的时候会把这个SessionID传给服务器端,服务器端就可以通过比对知道是谁了;Session通常会保存在服务器端内存中,如果没有持久化,则易丢失;Session会定时过期。过期后浏览器如果再访问,服务端发现没有此ID,将给浏览器端重新发新的SessionID;更换浏览器也将重新获得新的SessionID有连接:是因为它基于TCP协议,是面向连接的,需要3次握手、4次断开。短连接:Http 1.1之前,都是一个请求一个连接,而Tcp的连接创建销毁成本高,对服务器有很大的影响。所以,自Http 1.1开始,支持keep-alive,默认也开启,一个连接打开后,会保持一段时间(可设置),浏览器再访问该服务器就使用这个Tcp连接,减轻了服务器压力,提高了效率。 服务器端如果故障,即使Session被持久化了,但是服务没有恢复前都不能使用这些SessionID。如果使用HAProxy或者Nginx等做负载均衡器,调度到了不同的Tomcat上,那么也会出现找不到SessionID的情况。2)会话保持方式(1)session sticky会话黏性 Session绑定: nginx:source ip, cookie HAProxy:source ip, cookie优点:简单易配置缺点:如果目标服务器故障后,如果没有做sessoin持久化,就会丢失session,此方式生产很少使用(2)Session 复制集群Tomcat自己的提供的多播集群,通过多播将任何一台的session同步到其它节点。缺点:Tomcat的同步节点不宜过多,互相即时通信同步session需要太多带宽;每一台都拥有全部session,内存损耗太多。(3)Session Serversession 共享服务器,使用memcached、redis做共享的Session服务器,此为推荐方式。3)负载均衡规划和准备

#只需在10.0.0.100的nginx主机上实现域名解析vim /etc/hosts#添加以下三行10.0.0.100 proxy.syk.top proxy10.0.0.101 t1.syk.top t110.0.0.102 t2.syk.top t2(1)负载均衡tomcat主机准备修改tomcat的虚拟机主机为自定义的主机名,并设为默认的虚拟主机t1虚拟主机配置conf/server.xml <Engine name="Catalina" defaultHost="t1.syk.top"><Host name="t1.syk.top" appBase="/data/webapps" autoDeploy="true" ></Host></Engine> t2虚拟主机配置conf/server.xm<Engine name="Catalina" defaultHost="t2.syk.top"><Host name="t2.syk.top" appBase="/data/webapps" autoDeploy="true" ></Host></Engine> (2)准备负载均衡规划测试用的jsp文件 #在t1和 t2节点创建相同的文件/data/webapps/ROOT/index.jsp#项目路径配置mkdir -pv /data/webapps/ROOT#编写测试jsp文件,内容在下面vim /data/webapps/ROOT/index.jsp<%@ page import="java.util.*" %><!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>tomcat test</title></head><body><div>On <%=request.getServerName() %></div><div><%=request.getLocalAddr() + ":" + request.getLocalPort() %></div><div>SessionID = <span style="color:blue"><%=session.getId() %></span></div><%=new Date()%></body></html>#设置权限chown -R tomcat.tomcat /data/webapps/ 4)Nginx 实现后端 tomcat 的负载均衡调度 (1)Nginx 实现后端 tomcat 的负载均衡 nginx 配置如下 :vim /etc/nginx/nginx.conf#在http块中加以下内容#注意名称不要用下划线upstream tomcat-server {#ip_hash; # 先禁用看看轮询,之后开启开黏性#hash $cookie_JSESSIONID; # 先禁用看看轮询,之后开启开黏性server t1.syk.top:8080;server t2.syk.top:8080;}server {location ~* \.(jsp|do)$ {proxy_pass http://tomcat-server;}}测试 http://proxy.magedu.com/index.jsp,可以看到轮询调度效果,每次刷新后端主机和SessionID都会变化

[root@proxy ~]#curl http://proxy.syk.top/index.jsp<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>tomcat test</title></head><body><h1> tomcat website </h1><div>On tomcat-server</div><div>10.0.0.101:8080</div><div>SessionID = <spanstyle="color:blue">2E4BFA5135497EA3628F1EBDAE62493E</span></div>Thu Jul 09 17:58:06 CST 2020</body></html>[root@proxy ~]#curl http://proxy.syk.top/index.jsp<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>tomcat test</title></head><body><h1> tomcat website </h1><div>On tomcat-server</div><div>10.0.0.102:8080</div><div>SessionID = <spanstyle="color:blue">C5CC437BC05EE5A8620822CB07E71B7C</span></div>Thu Jul 09 17:58:07 CST 2020</body></html>(2)实现 session 黏性 在upstream中使用ip_hash指令,使用客户端IP地址Hash。 [root@proxy ~]#vim /etc/nginx/nginx.conf#只添加ip_hash;这一行upstream tomcat-server {ip_hash; #启动源地址hash#hash $cookie_JSESSIONID #启动基于cookie的hashserver t1.syk.top:8080;server t2.syk.top:8080;}配置完reload nginx服务。curl 测试一下看看效果。#用curl访问每次都调度到10.0.0.102主机上,但因为curl每次请求不会自动携带之前获取的cookie,所有SessionID每次都在变化[root@proxy ~]#curl http://proxy.syk.top/index.jsp<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>tomcat test</title></head><body><h1> tomcat website </h1><div>On tomcat-server</div><div>10.0.0.102:8080</div><div>SessionID = <spanstyle="color:blue">C471641C26865B08B2FDA970BE7C71A6</span></div>Thu Jul 09 18:02:48 CST 2020</body></html>[root@proxy ~]#curl http://proxy.syk.top/index.jsp<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>tomcat test</title></head><body><h1> tomcat website </h1><div>On tomcat-server</div><div>10.0.0.102:8080</div><div>SessionID = <spanstyle="color:blue">3F61232DFD791A94D60D0D2E9561309A</span></div>Thu Jul 09 18:02:52 CST 2020</body></html> #通过图形浏览器看到主机不变,sessionID不变

关闭Session对应的Tomcat服务,再重启启动它,看看Session的变化。

[root@t2 ~]#systemctl restart tomcat

通过浏览器看到主机不变,但sessionID和上一次变化,但后续刷新不再变化 5)Httpd 实现后端tomcat的负载均衡调度 (1)和nginx一样, httpd 也支持负载均衡调度功能 httpd 的负载均衡配置说明 :使用 httpd -M 可以看到 proxy_balancer_module,用它来实现负载均衡。

负载均衡配置说明

#配置代理到balancerProxyPass [path] !|url [key=value [key=value ...]]#Balancer成员BalancerMember [balancerurl] url [key=value [key=value ...]]#设置Balancer或参数ProxySet url key=value [key=value ...] ProxyPass 和 BalancerMember 指令参数

Balancer 参数

ProxySet指令也可以使用上面的参数。

(2)启用 httpd 的负载均衡

在 tomcat 的配置中Engine使用jvmRoute属性,通过此项可得知SessionID是在哪个tomcat生成 #t1的conf/server.xml配置如下:<Engine name="Catalina" defaultHost="t1.syk.top" jvmRoute="Tomcat1"><Host name="t1.syk.top" appBase="/data/webapps" autoDeploy="true"></Host>#t2的conf/server.xml配置如下:<Engine name="Catalina" defaultHost="t2.syk.top" jvmRoute="Tomcat2"><Host name="t2.syk.top" appBase="/data/webapps" autoDeploy="true"></Host> 这样设置后 SessionID 就变成了以下形式:SessionID = 9C949FA4AFCBE9337F5F0669548BD4DF.Tomcat1httpd配置如下 :[root@proxy ~]#vim /etc/httpd/conf.d/tomcat.conf[root@proxy ~]#cat /etc/httpd/conf.d/tomcat.conf<Proxy balancer://tomcat-server>BalancerMember http://t1.syk.top:8080 loadfactor=1BalancerMember http://t2.syk.top:8080 loadfactor=2</Proxy><VirtualHost *:80>ServerName proxy.syk.topProxyRequests OffProxyVia OnProxyPreserveHost On #off时不向后端转发原请求host首部,而转发采用BalancerMember指向名称为首部ProxyPass / balancer://tomcat-server/ProxyPassReverse / balancer://tomcat-server/</VirtualHost>#开启httpd负载均衡的状态页<Location /balancer-manager>SetHandler balancer-managerProxyPass !Require all granted</Location>#loadfactor设置为1:2,便于观察。观察调度的结果是轮询的。
#查看状态页

(3)实现 session 黏性

官方文档:http://httpd.apache.org/docs/2.4/mod/mod_proxy_balancer.html 案例:[root@proxy ~]#vim /etc/httpd/conf.d/tomcat.conf#添加此行,在cookie 添加 ROUTEID的定义Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/"env=BALANCER_ROUTE_CHANGED<Proxy balancer://tomcat-server>BalancerMember http://t1.syk.top:8080 loadfactor=1 route=T1 #修改行,指定后端服务器对应的ROUTEIDBalancerMember http://t2.syk.top:8080 loadfactor=1 route=T2 #修改行ProxySet stickysession=ROUTEID #添加此行,指定用cookie中的ROUTEID值做为调度条件</Proxy><VirtualHost *:80>ServerName proxy.syk.topProxyRequests OffProxyVia OnProxyPreserveHost OnProxyPass / balancer://tomcat-server/ProxyPassReverse / balancer://tomcat-server/</VirtualHost>#开启httpd负载均衡的状态页<Location /balancer-manager>SetHandler balancer-managerProxyPass !Require all granted</Location>用浏览器访问发现Session不变了,一直找的同一个Tomcat服务器#观察结果[root@proxy ~]#curl http://proxy.syk.top/index.jsp #轮询[root@proxy ~]#curl -b "ROUTEID=.T1" http://proxy.syk.top/index.jsp #固定调度到t1[root@proxy ~]#curl -b "ROUTEID=.T2" http://proxy.syk.top/index.jsp[root@centos7 ~]#curl http://proxy.syk.top/index.jsp -I HTTP/1.1 200Date: Wed, 15 Jul 2020 00:55:05 GMTServer: Apache/2.4.37 (centos)Content-Type: text/html;charset=ISO-8859-1Transfer-Encoding: chunkedSet-Cookie: JSESSIONID=214D58236E1BD3095814B86A65C46C8A.Tomcat1; Path=/;HttpOnlyVia: 1.1 proxy.syk.topSet-Cookie: ROUTEID=.T1; path=/[root@centos7 ~]#curl -b "JSESSIONID=214D58236E1BD3095814B86A65C46C8A.Tomcat1;ROUTEID=.T1" http://proxy.syk.top/index.jsp

关闭tomcat2的tomcat服务,再查看,转向另一台tomcat服务器

[root@t2 ~]#systemctl stop tomcat重新启动 tomcat2 的tomcat服务,再查看保持不变[root@t2 ~]#systemctl start tomcat查看状态页

案例:

[root@client ~]#curl -I www.magedu.orgHTTP/1.1 200Date: Sun, 10 Jan 2021 09:58:49 GMTServer: Apache/2.4.37 (centos)Content-Type: text/html;charset=ISO-8859-1Transfer-Encoding: chunkedSet-Cookie: JSESSIONID=9E1A624ABD2A0ABBD256EFB14B12D555.Tomcat2; Path=/;HttpOnlyVia: 1.1 proxy.magedu.orgSet-Cookie: ROUTEID=.T2; path=/[root@client ~]#curl -b "ROUTEID=.T1" www.magedu.org<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>tomcat test</title></head><body><h1>t1.magedu.org</h1><div>On www.magedu.org</div><div>10.0.0.101:8080</div><div>SessionID = <spanstyle="color:blue">A13BFA537739734CFDC12D59EA56710A.Tomcat1</span></div>Sun Jan 10 18:01:33 CST 2021</body></html> (4)实现 AJP 协议的负载均衡在上面基础上修改httpd的配置文件#在t1和t2的tomcat-8.5.51以上版本的需启用AJP[root@centos8 tomcat]#vim conf/server.xml#取消前面的注释,并修改下面行<Connector protocol="AJP/1.3" address="0.0.0.0" port="8009"redirectPort="8443" secretRequired="" />[root@proxy ~]#cat /etc/httpd/conf.d/tomcat.conf#Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/"env=BALANCER_ROUTE_CHANGED #注释此行<Proxy balancer://tomcat-server>BalancerMember ajp://t1.magedu.org:8009 loadfactor=1 route=T1 #修改此行BalancerMember ajp://t2.magedu.org:8009 loadfactor=1 route=T2 #修改此行#ProxySet stickysession=ROUTEID #先注释此行</Proxy><VirtualHost *:80>ServerName proxy.magedu.orgProxyRequests OffProxyVia OnProxyPreserveHost OnProxyPass / balancer://tomcat-server/ProxyPassReverse / balancer://tomcat-server/</VirtualHost><Location /balancer-manager>SetHandler balancer-managerProxyPass !Require all granted</Location>#ProxySet stickysession=ROUTEID先禁用,可以看到不断轮询的切换效果

#开启ProxySet后,发现Session不变了,一直找的同一个Tomcat服务器。

[root@proxy ~]#vim /etc/httpd/conf.d/tomcat.conf

<Proxy balancer://tomcat-server>BalancerMember ajp://t1.magedu.org:8009 loadfactor=1 route=T1BalancerMember ajp://t2.magedu.org:8009 loadfactor=2 route=T2ProxySet stickysession=ROUTEID #取消此行注释,只修改此行</Proxy>[root@proxy ~]#systemctl restart httpd #多次刷新页面,不再变化

虽然,上面的做法实现客户端在一段时间内找同一台Tomcat,从而避免切换后导致的Session丢失。但是如果Tomcat节点挂掉,那么Session依旧丢失。

[root@t1 ~]#systemctl stop tomcat 再恢复t1,观察到仍不会变化 [root@t1 ~]#systemctl start tomcat结论:假设有A、B两个节点,都将Session持久化。如果Tomcat A节点下线期间用户切换到了Tomcat B上,就获得了Tomcat B的Session,原有Sesssion将丢失,就算将持久化Session的Tomcat A节点再次上线了,也没用了。因此需要实现Session的高可用性来解决上述问题。

免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。
相关文章
返回顶部