• web服务之Tomcat反向代理,负载均衡,SessionID


    结合反向代理实现tomcat部署

    常见部署方式介绍

    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
    

    利用 nginx 反向代理实现全部转发置指定同一个虚拟主机

    配置说明

    利用nginx反向代理功能,实现上图的代理功能,将用户请求全部转发至指定的同一个tomcat主机
    利用nginx指令proxy_pass 可以向后端服务器转发请求报文,并且在转发时会保留客户端的请求报文中的host首部

    #从yum源安装nginx
    [root@tomcat ~]# yum install nginx -y
    [root@tomcat ~]# vim /etc/nginx/nginx.conf
    #全部反向代理测试
    location / {
    # proxy_pass http://127.0.0.1:8080; # 不管什么请求,都会访问后面的localhost虚拟主机
    proxy_pass http://node1.longxuan.vip:8080; # 此项将用户访问全部请求转发到node1的虚拟
    主机上
    #proxy_pass http://node2.longxuan.vip:8080; #此项将用户访问全部请求转发到node2的虚拟
    主机上
    #以上两项都需要修改nginx服务器的/etc/hosts,实现node1.magedu.com和node2.magedu.com
    到IP的解析
    }
    [root@tomcat ~]# nginx -t
    [root@tomcat ~]# systemctl restart nginx
    #说明: proxy_pass http://FQDN/ 中的FQDN 决定转发至后端哪个虚拟主机,而与用户请求的URL无关
    #如果转到后端的哪个服务器由用户请求决定,可以向后端服务转发请求的主机头实现,示例:
    proxy_set_header Host $http_host;
    

    案例

    一台主机,实现nginx和tomcat
    tomcat上有两个虚拟主机node1和node2
    
    #先按3.4.5.4介绍方式在同一下主机上建立两个tomcat虚拟主机,node1.longxuan.vip和node2.longxuan.vip
    
    #修改/etc/hosts文件,实现名称解析
    [root@centos8 ~]# vim /etc/hosts
    127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
    centos8.localdomain
    ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
    172.31.0.100 node1.longxuan.vip node2.longxuan.vip
    
    #安装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.longxuan.vip:8080;
    }
    ......
    
    [root@centos8 ~]# systemctl enable --now nginx
    #先别访问node1,node2和IP都可以看到一样的node1的虚拟主机页面
    [root@centos8 ~]# curl http://node1.longxuan.vip/
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>jsp例子</title>
    </head>
    <body>
    后面的内容是服务器端动态生成字符串,最后拼接在一起
    node1.longxuan.vip
    </body>
    </html>
    [root@centos8 ~]# curl http://node2.longxuan.vip/
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>jsp例子</title>
    </head>
    <body>
    后面的内容是服务器端动态生成字符串,最后拼接在一起
    node2.longxuan.vip
    </body>
    </html>
    [root@centos8 ~]# curl http://127.0.0.1/
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>jsp例子</title>
    </head>
    <body>
    后面的内容是服务器端动态生成字符串,最后拼接在一起
    node1.longxuan.vip
    </body>
    </html>
    [root@centos8 ~]# curl http://172.31.0.100/
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>jsp例子</title>
    </head>
    <body>
    后面的内容是服务器端动态生成字符串,最后拼接在一起
    node1.longxuan.vip
    </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.longxuan.vip:8080;
    }
    ......
    
    #先别访问node1,node2和IP都可以看到一样的node2的虚拟主机页面
    [root@centos8 ~]# curl http://node1.longxuan.vip/
    [root@centos8 ~]# curl http://node2.longxuan.vip/
    [root@centos8 ~]# curl http://127.0.0.1/
    [root@centos8 ~]# curl http://172.31.0.100/
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>jsp例子</title>
    </head>
    <body>
    后面的内容是服务器端动态生成字符串,最后拼接在一起
    node2.longxuan.vip
    </body>
    </html>
    

    利用nginx实现动静分离代理

    配置说明

    可以利用nginx实现动静分离

    [root@centos8 ~]# vim nginx.conf
    root /usr/share/nginx/html;
    #下面行可不加
    #location / {
    # root /data/webapps/ROOT;
    # index index.html;
    #}
    # ~* 不区分大小写
    location ~* .jsp$ {
        proxy_pass http://node1.longxuan.vip:8080; #注意: 8080后不要加/,需要在nginx服务器修改 /etc/hosts
    }
    

    以上设置,可以将jsp的请求反向代理到tomcat,而其它文件仍由nginx处理,从而实现所谓动静分离。
    但由于jsp文件中实际上是由静态资源和动态组成,所以无法彻底实现动静分离。实际上Tomcat不太适
    合做动静分离,用它来管理程序的图片不好做动静分离部署

    案例

    #准备三个不同的资源文件
    [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.longxuan.vip/test.html
    [root@centos8 ~]# curl http://node2.longxuan.vip/test.html
    [root@centos8 ~]# curl http://127.0.0.1/test.html
    [root@centos8 ~]# curl http://172.31.0.8/test.html
    /usr/share/nginx/html/test.html
    
    #访问test.jsp,观察结果都一样访问的是tomcat的默认主机资源
    [root@centos8 ~]# curl http://node1.longxuan.vip/test.jsp
    [root@centos8 ~]# curl http://node2.longxuan.vip/test.jsp
    [root@centos8 ~]# curl http://127.0.0.1/test.jsp
    [root@centos8 ~]# curl http://172.31.0.8/test.jsp
    /usr/local/tomcat/webapps/ROOT/test.jsp
    

    利用httpd实现基于http协议的反向代理至后端Tomcat服务器

    配置说明

    httpd也提供了反向代理功能,所以可以实现对tomcat的反向代理功能
    范例:查看代理相关模块

    [root@centos8 ~]# httpd -M|grep proxy
    AH00558: httpd: Could not reliably determine the server's fully qualified domain
    name, using centos8.localdomain. Set the 'ServerName' directive globally to
    suppress this message
    proxy_module (shared)
    proxy_ajp_module (shared) #ajp
    proxy_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) #http
    proxy_hcheck_module (shared)
    proxy_scgi_module (shared)
    proxy_uwsgi_module (shared)
    proxy_wstunnel_module (shared)
    proxy_http2_module (shared)
    

    proxy_http_module模块代理配置

    [root@centos8 ~]# vim /etc/httpd/conf.d/http-tomcat.conf
    <VirtualHost *:80>
    ServerName node1.longxuan.vip
    ProxyRequests Off
    ProxyPass / http://127.0.0.1:8080/
    ProxyPassReverse / http://127.0.0.1:8080/
    ProxyPreserveHost On
    ProxyVia On
    </VirtualHost>
    

    ProxyRequests:Off 关闭正向代理功能,即启动反向代理
    ProxyPass:反向代理指令,指向后端服务器
    ProxyPassReverse:当反向代理时,返回给客户端的报文需将之重写个别后端主机的response头,
    如:Location,Content-Location,URI
    ProxyPreserveHost:On时让反向代理保留原请求的Host首部转发给后端服务器,off 时则删除
    host首部后再转发至后面端服务器, 这将导致只能转发到后端的默认虚拟主机
    ProxyVia:On开启。反向代理的响应报文中提供一个response的via首部,默认值off

    说明: 关于ProxyPreserveHost

    #分别访问下面不同链接
    http://httpd服务IP/
    http://node1.longxuan.vip/
    http://node1.longxuan.vip/index.jsp
    #以上3个URL看到了不同的页面,说明ProxyPreserveHost On起了作用
    #设置ProxyPreserveHost Off再看效果,说明什么?
    

    利用 httpd 实现基于AJP协议的反向代理至后端Tomcat服务器

    AJP 协议说明

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

    启用和禁用 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 -ntl
    

    注意: secretRequired="" 必须加上,否则出现以下错误提示

    [root@centos8 tomcat]# cat logs/catalina.log
    Caused 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 -ntl
    
    #配置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 -ntl
    

    httpd 实现 AJP 反向代理

    配置说明

    相对来讲,AJP协议基于二进制比使用HTTP协议的连接器效率高些。
    proxy_ajp_module模块代理配置

    <VirtualHost *:80>
        ServerName node1.longxuan.vip
        ProxyRequests Off
        ProxyVia On
        ProxyPreserveHost On
        ProxyPass / 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.llongxuan.vip
    ProxyRequests Off
    ProxyVia On #此项对AJP无效
    ProxyPreserveHost On #此项对AJP无效
    ProxyPass / ajp://127.0.0.1:8009/
    </VirtualHost>
    
    [root@centos8 ~]# systemctl restart httpd
    #再次用用下面不同URL访问,可以看以下结果
    [root@centos8 ~]# curl http://node1.longxuan.vip/test.html
    /data/node1/ROOT/test.html
    
    [root@centos8 ~]# curl http://node2.longxuan.vip/test.html
    /data/node2/ROOT/test.html
    
    [root@centos8 ~]# curl http://172.31.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.longxuan.vip/test.html
    /data/node1/ROOT/test.html
    
    [root@centos8 ~]# curl http://node2.longxuan.vip/test.html
    /data/node2/ROOT/test.html
    
    [root@centos8 ~]# curl http://172.31.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.longxuan.vip/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 your
    request due to maintenance downtime or capacity
    problems. Please try again later.</p>
    </body></html>
    

    实现 tomcat 负载均衡

    动态服务器的问题,往往就是并发能力太弱,往往需要多台动态服务器一起提供服务。如何把并发的压
    力分摊,这就需要调度,采用一定的调度策略,将请求分发给不同的服务器,这就是Load Balance负载
    均衡。
    当单机Tomcat,演化出多机多级部署的时候,一个问题便凸显出来,这就是Session。而这个问题的由
    来,都是由于HTTP协议在设计之初没有想到未来的发展。

    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的连接创建销毁成本高,对服务器有很大的影响。所以,自Http1.1开始,支持keep-alive,默认也开启,一个连接打开后,会保持一段时间(可设置),浏览器再访问该服务器就使用这个Tcp连接,减轻了服务器压力,提高了效率。
    
    服务器端如果故障,即使Session被持久化了,但是服务没有恢复前都不能使用这些SessionID。
    
    如果使用HAProxy或者Nginx等做负载均衡器,调度到了不同的Tomcat上,那么也会出现找不到
    SessionID的情况。
    

    会话保持方式

    session sticky会话黏性

    Session绑定
        nginx:source ip, cookie
        HAProxy:source ip, cookie
    优点:简单易配置
    缺点:如果目标服务器故障后,如果没有做sessoin持久化,就会丢失session,此方式生产很少使用
    

    Session 复制集群

    Tomcat自己的提供的多播集群,通过多播将任何一台的session同步到其它节点。
    
    缺点
    Tomcat的同步节点不宜过多,互相即时通信同步session需要太多带宽
    每一台都拥有全部session,内存损耗太多
    

    Session Server

    session 共享服务器,使用memcached、redis做共享的Session服务器,此为推荐方式
    

    范例:

    #只需在172.31.0.100的nginx主机上实现域名解析
    [root@centos8 ~]# vim /etc/hosts
    #添加以下三行
    172.31.0.100 proxy.longxuan.vip proxy
    172.31.0.101 t1.longxua.vip t1
    172.31.0.102 t2.longxuan.vip t2
    

    负载均衡tomcat主机准备

    修改tomcat的虚拟机主机为自定义的主机名,并设为默认的虚拟主机
    t1虚拟主机配置conf/server.xml

    <Engine name="Catalina" defaultHost="t1.longxuan.vip">
        <Host name="t1.longxuan.vip" appBase="/data/webapps" autoDeploy="true" >
        </Host>
    </Engine>
    

    t2虚拟主机配置conf/server.xml

    <Engine name="Catalina" defaultHost="t2.longxuan.vip">
        <Host name="t2.longxuan.vip" appBase="/data/webapps" autoDeploy="true" >
        </Host>
    </Engine>
    

    准备负载均衡规划测试用的jsp文件

    在t1和 t2节点创建相同的文件/data/webapps/ROOT/index.jsp

    #项目路径配置
    [root@centos8 ~]# 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>
    
    #设置权限
    [root@centos8 ~]# chown -R tomcat.tomcat /data/webapps/
    

    Nginx 实现后端 tomcat 的负载均衡调度

    Nginx 实现后端 tomcat 的负载均衡

    nginx 配置如下

    [root@centos8 ~]# vim /etc/nginx/nginx.conf
    #在http块中加以下内容
    #注意名称不要用下划线
    upstream tomcat-server {
        #ip_hash; # 先禁用看看轮询,之后开启开黏性
        #hash $cookie_JSESSIONID; # 先禁用看看轮询,之后开启开黏性
        server t1.longxuan.vip:8080;
        server t2.longxuan.vip:8080;
    }
    server {
        location ~* .(jsp|do)$ {
            proxy_pass http://tomcat-server;
        }
    }
    

    测试 http://proxy.longxuan.vip/index.jsp,可以看到轮询调度效果,每次刷新后端主机和SessionID都会变化

    [root@proxy ~]# curl http://proxy.longxuan.vip/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>172.31.0.101:8080</div>
    <div>SessionID = <span
    style="color:blue">2E4BFA5135497EA3628F1EBDA56493E</span></div>
    Thu Jul 09 17:58:06 CST 2021
    </body>
    </html>
    [root@proxy ~]#curl http://proxy.longxuan.vip/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>172.31.0.102:8080</div>
    <div>SessionID = <span
    style="color:blue">C5CC437BC05EE5A8620822C4578E71B7C</span></div>
    Thu Jul 09 17:58:07 CST 2021
    </body>
    </html>
    

    实现 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的hash
        server t1.longxuan.vip:8080;
        server t2.longxuan.vip:8080;
    }
    

    配置完reload nginx服务。curl 测试一下看看效果。

    #用curl访问每次都调度到172.31.0.102主机上,但因为curl每次请求不会自动携带之前获取的cookie,所有SessionID每次都在变化
    [root@proxy ~]# curl http://proxy.longxuan.vip/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>172.31.0.102:8080</div>
    <div>SessionID = <span
    style="color:blue">C471641C26865B08B2FDA970BE7C71A6</span></div>
    Thu Jul 09 18:02:48 CST 2021
    </body>
    </html>
    [root@proxy ~]#curl http://proxy.longxuan.vip/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>172.31.0.102:8080</div>
    <div>SessionID = <span
    style="color:blue">3F61232DFD791A94D60D0D2E9561309A</span></div>
    Thu Jul 09 18:02:52 CST 2021
    </body>
    </html>
    

    通过图形浏览器看到主机不变,sessionID不变

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

    [root@t2 ~]# systemctl restart tomcat
    

    通过浏览器看到主机不变,但sessionID和上一次变化,但后续刷新不再变化

    Httpd 实现后端tomcat的负载均衡调度

    和nginx一样, httpd 也支持负载均衡调度功能

    httpd 的负载均衡配置说明

    使用httpd -M 可以看到proxy_balancer_module,用它来实现负载均衡。

    官方帮助: http://httpd.apache.org/docs/2.4/mod/mod_proxy_balancer.html
    
    方式 依赖模块
    http负载均衡 mod_proxy,mod_proxy_http,mod_proxy_balancer
    ajp负载均衡 ,mod_proxy,mod_proxy_ajp,mod_proxy_balancer

    负载均衡配置说明

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

    ProxyPass 和 BalancerMember 指令参数

    参数 缺省值 说明
    min 0 连接池最小容量
    max 1 - n 连接池最大容量
    retry 60 apache请求发送到后端服务器错误后等待的时间秒数。0表示立即重试

    Balancer 参数

    参数 缺省值 说明
    loadfactor 定义负载均衡后端服务器权重,取值范围: 1 - 100
    lbmethod byrequests 负载均衡调度方法。byrequests 基于权重的统计请求个数进行调度bytrafficz 执行基于权重的流量计数调度bybusyness 通过考量每个后端服务器当前负载进行调度
    maxattempts 1 放弃接受请求前,实现故障转移的次数,默认为1,其最大值不应该大于总的节点数
    nofailover Off On 表示不允许故障转移, 如果后端服务器没有Session副本可以设置为On,Off表示故障可以转移
    stickysession 调度器的sticky session名字,根据web后台编程语言不同,可以设置为JSESSIONID或PHPSESSIONID

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

    启用 httpd 的负载均衡

    在 tomcat 的配置中Engine使用jvmRoute属性,通过此项可得知SessionID是在哪个tomcat生成

    #t1的conf/server.xml配置如下:
    <Engine name="Catalina" defaultHost="t1.longxuan.vip" jvmRoute="Tomcat1">
    <Host name="t1.longxuan.vip" appBase="/data/webapps" autoDeploy="true">
    </Host>
    #t2的conf/server.xml配置如下:
    <Engine name="Catalina" defaultHost="t2.longxuan.vip" jvmRoute="Tomcat2">
    <Host name="t2.longxuan.vip" appBase="/data/webapps" autoDeploy="true">
    </Host>
    

    这样设置后 SessionID 就变成了以下形式:

    SessionID = 9C949FA4AFCBE9337F5F0669548B36DF.Tomcat1
    

    httpd配置如下

    [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.longxuan.vip:8080 loadfactor=1
        BalancerMember http://t2.longxuan.vip:8080 loadfactor=2
    </Proxy>
    <VirtualHost *:80>
        ServerName proxy.longxuan.vip
        ProxyRequests Off
        ProxyVia On
        ProxyPreserveHost On #off时不向后端转发原请求host首部,而转发采用BalancerMember指
    向名称为首部
        ProxyPass / balancer://tomcat-server/
        ProxyPassReverse / balancer://tomcat-server/
    </VirtualHost>
    #开启httpd负载均衡的状态页
    <Location /balancer-manager>
        SetHandler balancer-manager
        ProxyPass !
        Require all granted
    </Location>
    

    loadfactor设置为1:2,便于观察。观察调度的结果是轮询的。

    实现 session 黏性

    官方文档:http://httpd.apache.org/docs/2.4/mod/mod_proxy_balancer.html
    
    %{BALANCER_WORKER_ROUTE}e The route of the worker chosen.
    

    范例:

    [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.longxuan.vip:8080 loadfactor=1 route=T1 #修改行,指定后端
    服务器对应的ROUTEID
        BalancerMember http://t2.longxuan.vip:8080 loadfactor=1 route=T2 #修改行
        ProxySet stickysession=ROUTEID #添加此行,指定用cookie中的ROUTEID值做为调度条件
    </Proxy>
    <VirtualHost *:80>
        ServerName proxy.longxuan.vip
        ProxyRequests Off
        ProxyVia On
        ProxyPreserveHost On
        ProxyPass / balancer://tomcat-server/
        ProxyPassReverse / balancer://tomcat-server/
    </VirtualHost>
    #开启httpd负载均衡的状态页
    <Location /balancer-manager>
        SetHandler balancer-manager
        ProxyPass !
        Require all granted
    </Location>
    

    用浏览器访问发现Session不变了,一直找的同一个Tomcat服务器

    #观察结果
    [root@proxy ~]# curl http://proxy.longxuan.vip/index.jsp #轮询
    [root@proxy ~]# curl -b "ROUTEID=.T1" http://proxy.longxuan.vip/index.jsp #固定调度到
    t1
    [root@proxy ~]# curl -b "ROUTEID=.T2" http://proxy.longxuan.vip/index.jsp
    [root@centos7 ~]# curl http://proxy.longxuan.vip/index.jsp -I
    HTTP/1.1 200
    Date: Wed, 15 Jul 2021 00:55:05 GMT
    Server: Apache/2.4.37 (centos)
    Content-Type: text/html;charset=ISO-8859-1
    Transfer-Encoding: chunked
    Set-Cookie: JSESSIONID=214D58236E1BD3095814B86A65C46C8A.Tomcat1; Path=/;
    HttpOnly
    Via: 1.1 proxy.longxuan.vip
    Set-Cookie: ROUTEID=.T1; path=/
    [root@centos7 ~]# curl -b "JSESSIONID=214D58236E1BD3095814B86A65C46C8A.Tomcat1;
    ROUTEID=.T1" http://proxy.longxuan.vip/index.jsp
    

    重新启动 tomcat2 的tomcat服务,再查看保持不变

    [root@t2 ~]# systemctl start tomcat
    

    实现 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.longxuan.vip:8009 loadfactor=1 route=T1 #修改此行
        BalancerMember ajp://t2.longxuan.vip:8009 loadfactor=1 route=T2 #修改此行
    #ProxySet stickysession=ROUTEID #先注释此行
    </Proxy>
    <VirtualHost *:80>
        ServerName proxy.longxuan.vip
        ProxyRequests Off
        ProxyVia On
        ProxyPreserveHost On
        ProxyPass / balancer://tomcat-server/
        ProxyPassReverse / balancer://tomcat-server/
    </VirtualHost>
    <Location /balancer-manager>
        SetHandler balancer-manager
        ProxyPass !
        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.longxuan.vip:8009 loadfactor=1 route=T1
        BalancerMember ajp://t2.longxuan.vip:8009 loadfactor=2 route=T2
        ProxySet 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的高可用性来解决上述问题。

    Tomcat 官方实现了 Session 的复制集群,将每个Tomcat的Session进行相互的复制同步,从而保证所有Tomcat都有相同的Session信息.

    配置说明

    官方文档:

    https://tomcat.apache.org/tomcat-9.0-doc/cluster-howto.html
    https://tomcat.apache.org/tomcat-8.5-doc/cluster-howto.html
    

    说明

    <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" #45564/UDP
            frequency="500" #间隔500ms发送
            dropTime="3000"/> #故障阈值3s
        <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
            address="auto" #监听地址,此项建议修改为当前主机的IP
            port="4000" #监听端口
            autoBind="100" #如果端口冲突,自动绑定其它端口,范围是4000-4100
            selectorTimeout="5000" #自动绑定超时时长5s
            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.MessageDispatchIntercep
    tor"/>
    </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.ClusterSessionListener"/>
    </Cluster>
    #注意:tomcat7的官方文档此处有错误
    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">
      </Cluster>
    

    配置说明

    Cluster 集群配置
    Manager 会话管理器配置
    Channel 信道配置
    
        Membership 成员判定。使用什么多播地址、端口多少、间隔时长ms、超时时长ms。同一
    个多播地址和端口认为同属一个组。使用时修改这个多播地址,以防冲突
        Receiver 接收器,多线程接收多个其他节点的心跳、会话信息。默认会从4000到4100依次尝
    试可用端口
            address="auto",auto可能绑定到127.0.0.1上,所以一定要改为当前主机可用的IP
        Sender 多线程发送器,内部使用了tcp连接池。
        Interceptor 拦截器
        
    Valve
        ReplicationValve 检测哪些请求需要检测Session,Session数据是否有了变化,需要启动复制过程
    
    ClusterListener
        ClusterSessionListener 集群session侦听器
        
    使用<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
    添加到<Engine> 所有虚拟主机都可以启用Session复制
    添加到<Host> ,该虚拟主机可以启用Session复制
    最后,在应用程序内部启用了才可以使用
    

    案例: 实现 Tomcat Session 集群

    环境准备:

    IP 主机名 服务 软件
    172.31.0.100 proxy.longxuan.vip 调度器 Nginx、HTTPD
    172.31.0.101 t1.longxuan.vip tomcat1 JDK8、Tomcat8
    172.31.0.102 t2.longxuan.vip tomcat2 JDK8、Tomcat8

    时间同步,确保NTP或Chrony服务正常运行
    防火墙规则

    在 proxy 主机设置 httpd (或nginx)实现后端tomcat主机轮询
    [root@proxy ~]# cat /etc/httpd/conf.d/tomcat.conf
    <Proxy balancer://tomcat-server>
    BalancerMember http://t1.longxuan.vip:8080 loadfactor=1
    BalancerMember http://t2.longxuan.vip:8080 loadfactor=1
    </Proxy>
    <VirtualHost *:80>
        ServerName proxy.longxuan.vip
        ProxyRequests Off
        ProxyVia On
        ProxyPreserveHost On
        ProxyPass / balancer://tomcat-server/
        ProxyPassReverse / balancer://tomcat-server/
    </VirtualHost>
    
    [root@proxy ~]# systemctl restart httpd
    

    在所有后端tomcat主机上修改conf/server.xml

    本次把多播复制的配置放到t1.longxuan.vip和t2.longxuan.vip虚拟主机里面, 即Host块中。
    特别注意修改Receiver的address属性为一个本机可对外的IP地址。

    修改 t1 主机的 conf/server.xml

    #将5.1 内容复制到conf/server.xml的Host块内或Engine块(针对所有主机)
    [root@t1 ~]# vim /usr/local/tomcat/conf/server.xml
    [root@t1 ~]# cat /usr/local/tomcat/conf/server.xml
    .....以上省略.....
    <Host name="t1.longxuan.vip" appBase="/data/webapps" unpackWARs="true"
    autoDeploy="true">
    ###################在<Host> </host>块中间加下面一段内容##############################
    <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="230.100.100.100" #指定不冲突的多播地址
    port="45564"
    frequency="500"
    dropTime="3000"/>
    <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
    address="172.31.0.101" #指定网卡的IP
    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.MessageDispatchIntercep
    tor"/>
    </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.ClusterSessionListener"/>
    </Cluster>
    #######################################以上内容是新加的#################################
    </Host>
    </Engine>
    </Service>
    </Server>
    
    [root@t1 ~]# systemctl restart tomcat
    [root@t1 ~]# ss -ntl
    

    简化说明

    t1的conf/server.xml中,如下

    <Host name="t1.longxuan.vip" appBase="/data/webapps" autoDeploy="true" >
    #其他略去
        <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
            address="172.31.0.101" #只改此行
            port="4000"
            autoBind="100"
            selectorTimeout="5000"
            maxThreads="6"/>
    

    修改 t2 主机的 conf/server.xml

    [root@t2 ~]# vim /usr/local/tomcat/conf/server.xml
    [root@t2 ~]# cat /usr/local/tomcat/conf/server.xml
    .....以上省略.....
    <Host name="localhost" appBase="webapps"
    unpackWARs="true" autoDeploy="true">
    <!-- SingleSignOn valve, share authentication between web applications
    Documentation at: /docs/config/valve.html -->
    <!--
    <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
    -->
    <!-- Access log processes all example.
    Documentation at: /docs/config/valve.html
    Note: The pattern used is equivalent to using pattern="common" -->
    <Valve className="org.apache.catalina.valves.AccessLogValve"
    directory="logs"
    prefix="localhost_access_log" suffix=".txt"
    pattern="%h %l %u %t &quot;%r&quot; %s %b" />
    </Host>
    <Host name="t2.longxuan.vip" appBase="/data/webapps" autoDeploy="true" >
    ###################在<Host> </host>块中间加下面一段内容##############################
    <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="230.100.100.100"
    port="45564"
    frequency="500"
    Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
    address="172.31.0.102" #此行指定当前主机的IP,其它和T1节点配置相
    同
    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.MessageDispatchIntercep
    tor"/>
    </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.ClusterSessionListener"/>
    </Cluster>
    #######################################以上内容是新加的#################################
    </Host>
    </Engine>
    </Service>
    </Server>
    
    [root@t2 ~]# systemctl restart tomcat
    [root@t2 ~]# ss -ntl
    

    简化说明

    t2主机的server.xml中,如下

    <Host name="t2.longxuan.vip" appBase="/data/webapps" autoDeploy="true" >
    其他略去
        <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
            address="172.31.0.102" #只改此行
            port="4000"
            autoBind="100"
            selectorTimeout="5000"
            maxThreads="6"/>
    

    尝试使用刚才配置过得负载均衡(移除Session黏性),测试发现Session还是变来变去。

    修改应用的web.xml文件开启该应用程序的分布式

    参考官方说明: https://tomcat.apache.org/tomcat-8.5-doc/cluster-howto.html
    
    Make sure your web.xml has the <distributable/> element
    

    为所有tomcat主机应用web.xml的 标签增加子标签 来开启该应用程序的分布式。

    修改t1主机的应用的web.xml文件
    [root@t1 ~]# ll /usr/local/tomcat/webapps/ROOT/WEB-INF/
    total 4
    -rw-r----- 1 tomcat tomcat 1227 Jul 1 05:53 web.xml
    [root@t1 ~]# cp -a /usr/local/tomcat/webapps/ROOT/WEB-INF/ /data/webapps/ROOT/
    [root@t1 ~]# tree /data/webapps/ROOT/
    /data/webapps/ROOT/
    ├── index.jsp
    └── WEB-INF
        └── web.xml
    1 directory, 2 files
    
    #在倒数第二行加一行
    [root@t1 ~]# vim /data/webapps/ROOT/WEB-INF/web.xml
    [root@t1 ~]# tail -n3 /data/webapps/ROOT/WEB-INF/web.xml
    </description>
    <distributable/> #添加此行
    </web-app>
    
    #注意权限
    [root@t1 ~]# ll /data/webapps/ROOT/WEB-INF/
    total 4
    -rw-r----- 1 tomcat tomcat 1243 Jan 17 09:37 web.xml
    [root@t1 ~]# systemctl restart tomcat
    
    #同时观察日志
    [root@t1 ~]# tail -f /usr/local/tomcat/logs/catalina.out
    15-Jul-2021 11:29:10.998 INFO [Membership-MemberAdded.]
    org.apache.catalina.ha.tcp.SimpleTcpCluster.memberAdded Replication member added:
    [org.apache.catalina.tribes.membership.MemberImpl[tcp://{172, 31, 0, 102}:4000,
    {172, 31, 0, 102},4000, alive=1022, securePort=-1, UDP Port=-1, id={89 -26 -30 -99
    16 80 65 95 -65 14 -33 124 -55 -123 -30 82 }, payload={}, command={}, domain=
    {}]]
    

    修改t2主机的应用的web.xml文件

    #与5.2.3.1上的t1相同的操作
    [root@t2 ~]# cp -a /usr/local/tomcat/webapps/ROOT/WEB-INF/ /data/webapps/ROOT/
    [root@t2 ~]# vim /data/webapps/ROOT/WEB-INF/web.xml
    [root@t2 ~]# tail -n3 /data/webapps/ROOT/WEB-INF/web.xml
    </description>
    <distributable/> #添加此行
    </web-app>
    
    #注意权限
    [root@t2 ~]# ll /data/webapps/ROOT/WEB-INF/
    total 4
    -rw-r----- 1 tomcat tomcat 1243 Jan 17 09:38 web.xml
    [root@t2 ~]# systemctl restart tomcat
    #同时观察日志
    [root@t2 ~]# tail -f /usr/local/tomcat/logs/catalina.out
    15-Jul-2021 11:29:12.088 INFO [t2.longxuan.vip-startStop-1]
    org.apache.catalina.ha.session.DeltaManager.getAllClusterSessions Manager [],
    requesting session state from
    [org.apache.catalina.tribes.membership.MemberImpl[tcp://{172, 31, 0, 101}:4000,
    {172, 31, 0, 101},4000, alive=208408, securePort=-1, UDP Port=-1, id={118 -108
    -116 119 58 22 73 113 -123 -96 -94 111 -65 -90 -87 -107 }, payload={}, command=
    {}, domain={}]]. This operation will timeout if no session state has been
    received within [60] seconds.
    

    测试访问

    重启全部Tomcat,通过负载均衡调度到不同节点,返回的SessionID不变了。

    用浏览器访问,并刷新多次,发现SessionID 不变,但后端主机在轮询
    但此方式当后端tomcat主机较多时,会重复占用大量的内存,并不适合后端服务器众多的场景

    #修改t1和t2的配置项,删除jvmRoute配置项
    [root@t1 tomcat]# vim conf/server.xml
    <Engine name="Catalina" defaultHost="t1.longxuan.vip" >
    
    [root@t1 tomcat]# systemctl restart tomcat
    #多次执行下面操作,可以看到SessionID不变
    [root@centos7 ~]# curl -b 'JSESSIONID=1A3E7EED14F3E44FAF7469F8693E1CB6'
    proxy.longxuan.vip/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>172.31.0.102:8080</div>
    <div>SessionID = <span
    style="color:blue">1A3E7EED14F3E44FAF7469F8693E1CB6</span></div>
    Wed Jul 15 11:33:09 CST 2021
    </body>
    </html>
    [root@centos7 ~]# curl -b 'JSESSIONID=1A3E7EED14F3E44FAF7469F8693E1CB6'
    proxy.longxuan.vip/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>172.31.0.101:8080</div>
    <div>SessionID = <span
    style="color:blue">1A3E7EED14F3E44FAF7469F8693E1CB6</span></div>
    Wed Jul 15 11:33:10 CST 2021
    </body>
    </html>
    [root@centos7 ~]#
    

    故障模拟

    #模拟t2节点故障
    [root@t2 ~]# systemctl stop tomcat
    #多次访问SessionID不变
    [root@centos7 ~]# curl -b 'JSESSIONID=1A3E7EED14F3E44FAF7469F8693E1CB6'
    proxy.longxuan.vip/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>172.31.0.101:8080</div>
    <div>SessionID = <span
    style="color:blue">1A3E7EED14F3E44FAF7469F8693E1CB6</span></div>
    Wed Jul 15 12:01:16 CST 2021
    </body>
    </html>
    

    恢复实验环境

    本小节结束,为学习后面的内容,删除此节相关配置,为后续内容准备

    #恢复t1环境
    [root@t1 ~]# vim /usr/local/tomcat/conf/server.xml
    [root@t1 ~]# tail /usr/local/tomcat/conf/server.xml
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
            prefix="localhost_access_log" suffix=".txt"
            pattern="%h %l %u %t &quot;%r&quot; %s %b" />
          </Host>
          <Host name="t1.longxuan.vip" appBase="/data/webapps" unpackWARs="true" autoDeploy="true">
          </Host>
        </Engine>
      </Service>
    </Server>
    
    [root@t1 ~]# rm -f /data/webapps/ROOT/WEB-INF/web.xml
    [root@t1 ~]# systemctl restart tomcat
    
    #恢复t2环境
    [root@t2 ~]# vim /usr/local/tomcat/conf/server.xml
    [root@t2 ~]# tail /usr/local/tomcat/conf/server.xml
            prefix="localhost_access_log" suffix=".txt"
            pattern="%h %l %u %t &quot;%r&quot; %s %b" />
        </Host>
            <Host name="t2.longxuan.vip" appBase="/data/webapps" autoDeploy="true" >
            </Host>
       </Engine>
     </Service>
    </Server>
    
    [root@t2 ~]# rm -f /data/webapps/ROOT/WEB-INF/web.xml
    [root@t2 ~]# systemctl restart tomcat
    
  • 相关阅读:
    Java的动态项目的目录结构
    Tomcat配置—部署项目的方式
    Dependence Inject依赖注入
    Spring的基本入门
    对象的内存图解
    docker 搭建 mysql 基础测试环境
    程序员的人前显圣词库
    记录一次springboot security + oauth2.0 整合。第一篇,怎么找教程
    通过公网服务器一步到位访问内网服务器
    Spring 概述
  • 原文地址:https://www.cnblogs.com/xuanlv-0413/p/15168162.html
Copyright © 2020-2023  润新知