• tomcat企业级Web应用服务器配置与会话保持


    负载均衡

    1、动态服务器的问题,往往就是并发能力太弱,往往需要多台动态服务器一起提供服务。如何把并发的压力分摊,就
    需要调度,采用一定的调度策略,将请求分发给不同的服务器,这就是Load Balance负载均衡。

    2、当单机的Tomcat,演化出多机多级部署的时候,一个问题便凸显出来,这就是Session。而这个问题的由来,都是
    由于HTTP协议的设计之初没有想到未来的发展。

    HTTP的无状态,有连接和短连接

    1、无状态:指的是服务器端无法知道2次请求之间的联系,即使是前后2次请求来自同一个浏览器,也没有任何
    数据能够判断出是同一个浏览器的请求。后来可以通过cookie、session机制来判断。

    (1)浏览器端第一次HTTP请求服务器端时,在服务器端使用session这种技术,就可以在服务器端产生一个随机值即SessionID发给浏览器端,浏览器端收到后会保持这个SessionID在Cookie当中,

    这个Cookie值不能持久存储,浏览器关闭就消失。浏览器在每一次提交HTTP请求的时候会把这个SessionID传给服务器端,服务器端就可以通过比对知道是谁了

    (2)Session通常会保存在服务器端内存中,如果没有持久化,则易丢失

    (3)Session会定时过期。过期后浏览器如果再访问,服务端发现没有此ID,将重新获得新的SessionID

    (4)更换浏览器也将重新获得新的SessionID

    2、有连接:是因为它基于TCP协议,是面向连接的,需要3次握手、4次断开。

    3、短连接:Http 1.1之前,都是一个请求一个连接,而Tcp的连接创建销毁成本高,对服务器有很大的影响。所以,自Http 1.1开始,支持keep-alive,默认也开启,一个连接打开后,会保持一段时间(可设置),浏览器
    再访问该服务器就使用这个Tcp连接,减轻了服务器压力,提高了效率。

     服务器端如果故障,即使Session被持久化了,但是服务没有恢复前都不能使用这些SessionID。

    如果使用HAProxy或者Nginx等做负载均衡器,调度到了不同的Tomcat上,那么也会出现找不到SessionID的情况。

    会话保持方式

    1、session sticky会话黏性

    Session绑定

    nginx:source ip
    HAProxy:cookie
    

    优点:简单易配置

    缺点:如果目标服务器故障后,如果没有做sessoin持久化,就会丢失session

    幂等性:在同一次程序运行当中,对同一个值进行求hash,每次的hash值都一致。

    2、session复制集群

    Tomcat自己的提供的多播集群,通过多播将任何一台的session同步到其它节点。

    缺点

       1、Tomcat的同步节点不宜过多,互相及时通信同步session需要太多带宽

       2、每一台都拥有全部session,内存损耗太多

    3、session server

    session 共享服务器,使用memcached、redis做共享的Session服务器。

    实战一:实现Nginx反向代理到tomcat服务器

    1、环境准备:

    IP 主机名 服务  
    192.168.7.100 t0 调度器 Nginx 、HTTPD
    192.168.7.101 t1 tomcat1 JDK8、Tomcat1
    192.168.7.102 t2 tomcat2 JDK8、tomcat2

    2、修改三台主机的hosts配置文件

    修改hosts文件,做域名解析,也要在本地电脑的etc/hosts文件中做域名解析

    # vim  /etc/hosts
    192.168.7.100 t0.baidu.com t0
    192.168.7.101 t1.baidu.com t1
    192.168.7.102 t2.baidu.com t2

    3、在tomcat(0和1)定义环境变量配置,并创建项目路径

    # vim /etc/profile.d/tomcat.sh
    export CATALINA_HOME=/usr/local/tomcat
    export PATH=$CATALINA_HOME/bin:$PATH
    
    # .  /etc/profile.d/tomcat.sh
    

     新建项目目录

    [root@computer-2 ~]# mkdir -pv /data/webapps/ROOT
    

    在tomcat(0和1)服务器的/data/webapps/ROOT/目录下创建一个index.jsp文件,用来测试

    # vim  /data/webapps/ROOT/index.jsp
    <%@ page import="java.util.*" %>
    <!DOCTYPE html>
    <html lang="en">
    <head>
            <meta charset="UTF-8">
            <title>lbjsptest</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>
    

    4、配置tomcat(t0和t1)的配置文件

    1、修改t0主机的tomcat配置文件

    vim  /usr/local/tomcat/conf/server.xnl

    <Engine name="Catalina" defaultHost="t0.baidu.com"> #主要添加此行,将本地的localhost改为域名
    </Host>
            <Host name="t0.baidu.com" appBase="/data/webapps" autoDeploy="true" > #修改此行,此时不封口,就在下一行加上</Host>
       </Host>
        </Engine>  

    2、修改t1主机的tomcat配置文件

    vim /usr/local/tomcat/conf/server.xml  

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

     3、启动tomcat服务 

    # startup.sh
    

    5、配置nginx反向代理服务器

    # vim /etc/nginx/nginx.conf
    
    upstream tomcats {
    #ip_hash; # 先禁用看看轮询,之后开启开黏性
    server t1.baidu.com:8080;
    server t2.baidu.com:8080;
    }
    server {
    location ~* .(jsp|do)$ {
    proxy_pass http://tomcats;
      }
    }

    测试效果:

    t0主机已经可以通过域名进行访问

     t1主机也可以通过域名进行访问

    实战二:LNMT的会话保持原理及基于ip_hash实现

    (1) session sticky(贴) 基于hash 和cookie 来实现会话保持,简单的负载均衡算法

    ① 基于source_ip(源地址hash)

      nginx: ip_hash 、 haproxy: source 、 lvs: sh

    ② 基于cookie nginx基于cookie实现,需加载cookie模块,cookie 力度更新

      nginx:sticky 、haproxy: cookie

    (2) session cluster:delta session manager 基于tomcat集群会话保持

    分析:tomcat自身带的机制 session cluster,基于组播的方式,一个tomcat 被用户登录访问,记录session通过组播给集群中的其他机器复制一份;那么当用户再次访问时,每个机器都有session 会话记录;从而实现了会话保持

    (3) session server:redis(store), memcached(cache) 共享存储

    分析:新建立一个存放各个tomcat session记录的server,每台tomcat服务器都将自己的session记录在这个服务器中,用户再次访问,每台tomcat 都从这个server中获取;实现会话保持

    1、在t2主机安装nginx服务

    # yum install nginx  -y
    

    2、修改t2主机的nginx配置文件,做反向代理到后端tomcat服务器上

    vim  /etc/nginx/nginx.conf

    在http段定义

    upstream tomcats {
       #ip_hash;
       server t0.baidu.com:8080;
       server t1.baidu.com:8080;
    }
    

    在server段定义

    location ~* .(jsp|do)$ {
       proxy_pass  http://tomcats;
    }
    

    3、起动nginx服务

    # nginx
    

    测试效果:

    此时是默认的轮询调度算法:会访问的是192.168.7.100的地址

    再刷新一次就会变到192.168.7.101地址上,导致session ID变化,不能实现持久连接:

    简单实现基于ip hash 实现会话保持

    为了解决此session ID变化的问题,只需要在http段的upstream下面添加一列ip_hash即可,就会保持会话

    在upstream中使用ip_hash指令,使用客户端IP地址Hash。这个hash值使用IPv4地址的前24位或全部的IPv6地址。

    在http段定义

    upstream tomcats {
       ip_hash;
       server t0.baidu.com:8080;
       server t1.baidu.com:8080;
    }

     重启nginx: nginx -s reload

    再次测试效果:

    此时的session ID就会保持一致,会话保持,实现幂等性的性质。

     实战三:实现LAMP的httpd调度会话保持

    1、实现httpd的粘性调度

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

    负载均衡配置说明

    配置代理到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指令参数

     Balancer参数

    参数 缺省值 说明
    loadfactor   定义负载均衡后端服务器权重,取值范围1 - 100
    lbmethod byrequests

    负载均衡调度方法。
    byrequests 基于权重的统计请求个数进行调度;
    bytrafficz 执行基于权重的流量计数调度;
    bybusyness 通过考量每个后端服务器当前负载进行调度

    maxattempts 1

    放弃请求前实现故障转移的次数,默认为1,其最大值不应该大于总的节点数

    nofailover Off

    如果后端服务器没有Session副本,可以设置为On不允许故障转移。Off故障可以转移

    stickysession  

    调度器的sticky session名字,根据web后台编程语言不通,可以设置为
    JSESSIONID或PHPSESSIONID

    1、安装httpd服务

    #  yum install httpd - y
    

    2、配置httpd服务,实现session粘性,保持会话持久

    # vim  /etc/httpd/conf.d/vhosts.conf  #创建一个新的vhosts.conf配置文件
    <VirtualHost *:80>
            ServerName node1.baidu.com  #本机的hosts域名解析
            ProxyRequests Off
            ProxyVia On
            ProxyPreserveHost On
            ProxyPass / balancer://lbtomcats/
            ProxyPassReverse / balancer://lbtomcats/
    </VirtualHost>
    <Proxy balancer://lbtomcats>
            BalancerMember http://t0.baidu.com:8080 loadfactor=1
            BalancerMember http://t1.baidu.com:8080 loadfactor=2
    </Proxy>
    

    将httpd的主配置文件进行修改

    # vim  /etc/httpd/conf/httpd.conf
    注释 #DocumentRoot "/var/www/html"
    

    3、修改tomcat(0和1)的主配置文件

    #vim  /usr/local/tomcat/conf/server.xml
     <Engine name="Catalina" defaultHost="t0.baidu.com" jvmRoute="Tomcat1">  #加上后面的名称,方便辨认是哪个主机
    <Engine name="Catalina" defaultHost="t1.baidu.com" jvmRoute="Tomcat2">
    

    4、重启httpd和tomcat服务

    # systemctl  start  httpd
    # shutdown.sh
    # startup.sh

    查看网页效果

    此时查看网页效果,就一直保持在一个主机上的会话,session ID也不会再变化

     2、实现httpd服务的ajp调度

    1、修改httpd主配置文件

    # vim /etc/httpd/conf.d/vhosts.conf
    <VirtualHost *:80>
    <VirtualHost *:80>
            ServerName node1.baidu.com
            ProxyRequests Off
            ProxyVia On
            ProxyPreserveHost On
            ProxyPass / balancer://lbtomcats/
            ProxyPassReverse / balancer://lbtomcats/
    </VirtualHost>
    <Proxy balancer://lbtomcats>
    BalancerMember ajp://t0.baidu.com:8009 loadfactor=1 route=Tomcat1
    BalancerMember ajp://t1.baidu.com:8009 loadfactor=2 route=Tomcat2
    ProxySet stickysession=ROUTEID 
    </Proxy>

     

     2、重启服务

    # systemctl reload httpd 

    测试网页,查看此时也是具有粘性,保留session ID的会话保持

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

    假设有A、B两个节点,都将Session持久化。如果Tomcat A服务下线期间用户切换到了Tomcat B上,就获得了
    Tomcat B的Session,就算持久化Session的Tomcat A上线了,也没用了。

    实战四:实现LAMP及Tomcat Session集群(生产中用集群方式部署)

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

    配置说明

    1、Cluster 集群配置

    2、Manager 会话管理器配置

    3、Channel 信道配置

       (1) Membership 成员判定。使用什么多播地址、端口多少、间隔时长ms、超时时长ms。同一个多播地址和端口认为同属一个组。使用时修改这个多播地址,以防冲突

        (2)Receiver 接收器,多线程接收多个其他节点的心跳、会话信息。默认会从4000到4100依次尝试可用端口。

        (3)address="auto",auto可能绑定到127.0.0.1上,所以一定要改为可以用的IP上去Sender 多线程发送器,内部使用了tcp连接池。

    4、Interceptor 拦截器

    Valve

      ReplicationValve 检测哪些请求需要检测Session,Session数据是否有了变化,需要启动复制过程

    ClusterListener

    ClusterSessionListener 集群session侦听器

    前提:

    时间同步,确保NTP或Chrony服务正常运行。# systemctl status chronyd

    防火墙规则。# systemctl stop firewalld

    1、配置后端服务器t0的tomcat配置文件

    vim  /usr/local/tomcat/conf/server.xml

     </Host> #此Host和最后一行对应
            <Host name="t0.baidu.com" appBase="/data/webapps" autoDeploy="true" >  #此项已经存在
    
    
         <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.8"  #主要修改多播地址,多播地址范围:224-239之间
                            port="45564"
                            frequency="500"
                            dropTime="3000"/>
                <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                          address="192.168.7.100"  #修改为本机的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.MessageDispatchInterceptor"/>
              </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> #此host跟第一行对应
    

    2、修改后端服务器t1主机的tomcat配置文件

          </Host>
            <Host name="t1.baidu.com" appBase="/data/webapps" autoDeploy="true" >
    
              <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.8" #多播地址需要修改
                            port="45564"
                            frequency="500"
                            dropTime="3000"/>
                <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                          address="192.168.7.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.MessageDispatchInterceptor"/>
              </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>
    

    在t1可以查看tomcat日志,可以看到t0的IP地址,两者之间添加为集群关系:

     

    3、将httpd服务作为反向代理,修改httpd服务的配置文件,取消jdk配置文件的粘性。

    #vim  /etc/httpd/conf.d/vhosts.conf
    
    
    <VirtualHost *:80>
            ServerName node1.baidu.com
            ProxyRequests Off
            ProxyVia On
            ProxyPreserveHost On
            ProxyPass / balancer://lbtomcats/
            ProxyPassReverse / balancer://lbtomcats/
    </VirtualHost>
    <Proxy balancer://lbtomcats>
    BalancerMember ajp://t0.baidu.com:8009 loadfactor=1 route=Tomcat1
    BalancerMember ajp://t1.baidu.com:8009 loadfactor=2 route=Tomcat2
    #ProxySet stickysession=ROUTEID  #取消此行即可
    </Proxy>
    

    4、在tomcat(0和1)上复制web.xml主配置文件

    [root@mysql1 conf]# cp /usr/local/tomcat/conf/web.xml /data/webapps/ROOT/WEB-INF/

    5、修改复制过来的配置文件,为web.xml的<web-app> 标签增加子标签:vim  /data/webapps/ROOT/WEB-INF/web.xml

        <welcome-file-list>
            <welcome-file>index.html</welcome-file>
            <welcome-file>index.htm</welcome-file>
            <welcome-file>index.jsp</welcome-file>
        </welcome-file-list>
    
    <distributable/>  #只需要添加此行即可
    </web-app>

      

     6、重启httpd和tomcat服务

    # systemctl restart httpd
    # shutdown.sh
    # startup.sh
    

    测试网页效果:

    此时可以看待tomcat1和tomcat2的session ID保持一致,实验完成

     

     

    如果想实现LNMP集群会话保持,只需要将httpd的配置改为nginx配置,将nginx作为反向代理,upstream转发到后端服务器,其他的tomcat集群配置不变。

    vim /etc/nginx/nginx.conf

    upstream tomcat_srv {    #在http 段配置
    server 192.168.7.100:8080 weight=1;
    server 192.168.7.101:8080 weight=2;
    }
    
    location / {    #在server 段配置
            proxy_pass http://tomcat_srv;
    }
    location ~* .(jsp|do)$ {
            proxy_pass http://tomcat_srv;
    }
    

      

      

      

      

     

      

      

      

     

      

      

      

      

      

  • 相关阅读:
    Python基础知识(八)—字典
    Python基础知识(七)—元组
    Python基础知识(六)—关于列表深拷贝和浅拷贝及内存图
    Python基础知识(六)—列表
    Python基础知识(五)—字符串
    4、FTP、SSH协议简单介绍
    3、apt-get install xxx时,报错信信息: Could not get lock /var/lib/dpkg/lock-frontend
    2、NFS挂载根文件系统失败:Root-NFS: Unable to get mountd port number from server, using default
    EXPORT_SYMBOL是什么?
    用maven建立一个工程2
  • 原文地址:https://www.cnblogs.com/struggle-1216/p/12183175.html
Copyright © 2020-2023  润新知