Linux入门攻坚——61、tomcat负载均衡集群-LB Cluster

当后端的tomcat服务器不足以应付请求,压力过大时,考虑做负载均衡集群,此时就需要考虑会话保持的问题,确保同一客户端请求能够被定向到同一台主机,保持会话的连续性。

会话保持,实现与客户端的绑定,确保用户会话的连续性,其实现主要有:

session sticky :会话粘性,通过一定的方式将一个客户的请求始终定向到确定的主机,两种

source ip:基于源IP进行绑定

cookie:基于cookie进行绑定

session cluster :会话集群,将多台主机做成集群,集群中的主机通过多播方式,将本机的session传递给集群中其他主机,这样,客户端在任意一台主机上都可以保证会话的连续性。

session server :使用会话服务器,集中保存会话信息,一般是高速缓存服务器,如

kv(key-value存储形式):memcached,redis

还有一种 url:基于url进行绑定,对于不同的客户端,会给出一个不同的url,一般是在url后增加区别的参数,后台主机基于url进行绑定,在客户端不支持cookie时,经常使用的方法。

(1)LB tomcat

nginx+tomcat,nginx做前端,将请求负载均衡至后端多个 tomcat节点,不是集群,仅是负载均衡。也可以是Apache+tomcat,apache的httpd做前端,实现负载均衡。基于session sticky做会话保持。

(2)LB tomcat cluster

后端tomcat做成集群,前端只负责负载均衡,不需要考虑会话保持问题,因为后端每个tomcat节点都保持有全部session。

(3)LB tomcat

session server方式实现会话保持,即所有会话信息保存在一台高性能缓存服务器中。这里将学习使用memcached保存会话。

实践:(1)LB Tomcat
Nginx做反代 ,环境:

两台tomca主机:192.168.61.128、192.168.61.129

一台nginx主机:192.168.61.130

128上部署一个Host为web2的主机,129上部署一个Host为web1的主机

将Engine的默认主机改为上面定义的主机:

130上部署Nginx,配置反向代理:

在http段中配置upstream和server:

对于以jsp或do结尾的文件,反向代理至tomcat,并且实现负载均衡

访问192.168.61.130:

访问192.168.61.130/index.jsp时,会出现负载均衡的现象,不停刷新页面,交替的在两个tomcat服务器切换。

做会话绑定,只需要将upstream中增加ip_hash:

此时,访问再刷新时,就会固定到同一个tomcat服务器。

Apache httpd做反代同时实现负载均衡 :有三种方案

1)apache:mod_proxy + mod_proxy_http + mod_proxy_balancer (httpd需加载的模块)

tomcat:http connector

2)apache:mod_proxy + mod_proxy_ajp + mod_proxy_balancer(httpd需加载的模块)

tomcat:ajp connector

3)apache:mod_jk (这个模块需要自己下载源代码编译)

tomcat:ajp connector

实践 1)方案

配置httpd,添加负载集群,增加一个虚拟主机:

route指的是后端tomcat服务器自己的jvm虚拟机的特有标识,在Engine标签中由jvmRoute定义。

修改inidex.jsp:

javascript 复制代码
<%@ page language="java" %>
<%@ page import="java.util.*" %>
<html>
    <head>
        <title>Web1</title>
    </head>
    <body>
	<h1><font color="red">Web1.test.com</font></h1>
	<table align="centre" border="1">
	    <tr>
		<td>Session ID</td>
	<% session.setAttribute("ZZZ.test","zzz.test"); %>
		<td><%= session.getId() %></td>
	    </tr>
	    <tr>
		<td>Create on</td>
		<td><%= session.getCreationTime() %></td>
	    </tr>
	</table>
    </body>
</html>

显示session ID及其创建时间。

测试访问:

不停地刷新,页面在web1和web2之间切换,session ID每次都变化。

apache httpd上的指令说明
ProxyPreserveHost {On|Off}:On启用此功能,代理会将用户请求报文中的Host:行发送给后端的服务器,而不再使用ProxyPass指定的服务器地址。如果想在反向代理中支持虚拟主机,则需要开启此项,否则就无需打开此功能。
ProxyVia {On|Off|Full|Block}:用于控制在http首部是否使用Via:,主要用于在多级代理中控制代理请求的流向。默认为Off,不启用此功能;On表示每个请求和响应报文均添加Via:;Full表示每个Via:行都会添加当前apache服务器的版本号信息;Block表示每个代理请求报文中的Via:都会被移除,包括原生请求报文中的Via。
ProxyRequests {On|Off}:是否开启apache正向代理的功能,httpd具有正向和反向代理功能,但不能同时实现;启用此项时为了代理http协议必须启用mod_proxy_http模块。同时,如果为apache设置了ProxyPass,则必须将ProxyRequests设置为Off,即启用反向代理功能。
ProxyPass [path] !|url [key=value key=value ...]]:将后端服务器某URL与当前服务器的某虚拟路径关联起来作为提供服务的路径,path为当前服务器上的某虚拟路径,url为后端服务器上某URL路径。使用此指令时必须将ProxyRequests的值设置为Off。需要注意的是,如果path以"/"结尾,则对应的url也必须以"/"结尾,反之亦然。也就是反向代理的设置,path是客户端请求的路径,url是反向代理服务器向后端服务器发送请求的路径。

另外,mod_proxy模块在httpd 2.1的版本之后支持与后端服务器的连接池功能,连接按需创建,可以保存至连接池中以备进一步使用。连接池大小或其它设定可以通过在ProxyPass中使用key=value的方式定义。常用的key如下:

  • min:连接池的最小容量,此值与实际连接个数无关,仅表示连接池最小要初始化的空间大小。
  • max:连接池的最大容量,每个MPM都有自己独立的容量;其值与MPM本身有关,如Prefork的总是为1,而其它的则取决于ThreadsPerChild指令的值。
  • loadfactor:用于负载均衡集群配置中,定义对应后端服务器的权重,取值范围为1-100。
  • retry:当apache将请求发送至后端服务器得到错误响应时等待多长时间以后再重试。单位是秒钟。

MPM:多路处理模块,负责绑定本机网络端口、接受请求,并调度子进程来处理请求的处理模块。
多路处理模块(Multi-Processing Modules,MPM)是Apache HTTP服务器2.0版本引入的核心功能组件,负责绑定网络端口、接收请求并通过调度子进程或线程处理请求。

如果Proxy指定是以balancer://开头,即用于负载均衡集群时,其还可以接受一些特殊的参数,如下所示:

  • lbmethod:apache实现负载均衡的调度方法,默认是byrequests,也就是轮询,即基于权重将统计请求个数进行调度,bytraffic则执行基于权重的流量计数调度,bybusyness通过考量每个后端服务器的当前负载进行调度。
  • maxattempts:放弃请求之前实现故障转移的次数,默认为1,其最大值不应该大于总的节点数。
  • nofailover:取值为On或Off,设置为On时表示后端服务器故障时,用户的session将损坏;因此,在后端服务器不支持session复制时可将其设置为On。
  • stickysession:调度器的sticky session的名字,根据web程序语言的不同,其值为JSESSIONID或PHPSESSIONID。

上述指令除了能在banlancer://或ProxyPass中设定之外,也可使用ProxySet指令直接进行设置,如:

<Proxy balancer://hotcluster>

BalancerMember http://web1.test.com:8080 loadfactor=1

BalancerMember http://web2.test.com:8080 loadfactor=2

ProxySet lbmethod=bytraffic

</Proxy>
ProxyPassReverse:用于让apache调整HTTP重定向响应报文中的Location、Content-Location及URI标签所对应的URL,在反向代理环境中必须使用此指令避免重定向报文绕过proxy服务器。

设置绑定会话:

增加两行,然后再次测试访问,这时,页面停留在一个服务器上,并且sessionID不会变化。如此就实现了session sticky,会话粘性。

mod_proxy状态信息的输出:mod_proxy模块有一个内置的管理页面,配置如下

<Location /balancer-manager>

SetHandler balancer-manager

Proxypass !

Order Deny,Allow

Allow from all

</Location>

实际配置中允许所有人访问,所以配置成Require all granted

访问测试:

实践 2)方案

只需将配置文件中BalancerMember后的http改为ajp,同时后面的端口由8080改为8009即可。

实践 3)方案:使用mod_jk模块,略。

Session Cluster

session manager:会话管理器,tomcat具有多种会话管理器

标准会话管理器 (StandardManager):

<Manager className="org.apache.catalina.session.StandardManager"

maxInactiveInterval="7200"/>

默认保存于$CATALINA_HOME/work/Catalina/<hostname>/<webapp-name>/下的SESSIONS.ser文件中。

maxActiveSessions:最多允许的活动会话数量,默认为-1,表示不限制;

maxInactiveInterval:非活动的会话超时时长,默认为60s;

pathname:会话文件的保存目录;

持久会话管理器 (PersistentManager):

将会话数据保存至持久存储中,并且能在服务器意外中止后重新启动时重新加载这些会话信息。持久会话管理器支持将会话保存至文件存储(FileStore)或JDBC存储(JDBCStore)中。

保存至文件中的示例:

<Manager className="org.apache.catalina.session.PersistentManager"

saveOnRestart="true">

<Store className="org.apache.catalina.session.FileStore"

directory="/data/tomcat-sessions"/>

</Manager>

每个用户的会话会被保存至directory指定的目录中的文件中,文件名为<session id>.session,并通过后台线程每隔一段时间(checkInterval参数定义,默认为60秒)检查一次超时会话。

保存至JDBCStore中的示例:

<Manager className="org.apache.catalina.session.PersistentManager"

saveOnRestart="true">

<Store className="org.apache.catalina.session.JDBCStore"

driverName="com.mysql.jdbc.Driver"

connectionURL="jdbc:mysql://localhost:3306/mydb?user=jb;password=pw"/>

</Manager>

DeltaManager会话管理器:通过多播,将本机的session多播给其他主机,即每台主机都拥有全部的session会话。适用规模较小的场景。

BackupManager会话管理器:分组做集群。

实践:使用tomcat cluster实现session共享

查阅Tomcat文档,最简单的用法是在Engine或Host中添加

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>

一般需要具体配置,如下:

javascript 复制代码
 <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"
                        frequency="500"
                        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.ClusterSessionListener"/>
        </Cluster>

Manager指定使用哪种会话管理器,这里是Deltamanager;

Channel定义多播通道,其中的Membership指定集群的组播地址、端口等信息,同时也就指定了组播成员;Receiver指定成员如何接收其他节点传递过来的session信息;Sender则指出自己如何把自己的session信息传播出去;

Interceptor,拦截器,用于异常的处理;

1)各节点配置使用DeltaManager;

2)为需要使用session cluster的webapps开启session Distribution的功能:

方法是在WEB-INF/web.xml中增加<distributable/>

针对自己的实际环境进行配置,即修改tomcat配置文件:修改/usr/local/tomcat/conf/server.xml

在具体的webapp中的WEB-INF目录下,修改web.xml,增加<distributable/>

/var/webapps/ROOT/WEB-INF/web.xml:

同样配置128节点主机配置。

启动两台主机,查看日志中的catalina.out:两个成员加入

配置httpd,将会话粘性配置去掉:

此时,httpd负载均衡是轮询,测试访问:

可以看到,session集群实现了。

修改httpd的配置文件,将http协议改为ajp协议,端口改为8009,能够实现同样的效果。

测试Nginx,将nginx的配置中ip hash去掉,即去掉session sticky

同样实现上面的效果。

相关推荐
洋葱 ☠1 小时前
极简部署linux免费ssl证书Let‘s Encrypt,自动续签,nginx/apache都可以,域名指向服务器即可,无需项目
linux·nginx·ssl
西门吹牛1 小时前
openwrt学习笔记
linux·笔记·学习
Mike_6662 小时前
Linux (Ubuntu) Jetson AArch64 架构 JetPack6.2 CUDA+CUDNN+PyTorch 安装踩坑经历
linux·pytorch·ubuntu
tianyuanwo2 小时前
Bash与Sh的诞生背景、底层原理及Linux多Shell解释器兼容性解析
linux·开发语言·bash
skywalk81632 小时前
Ubuntu宽屏显示器只有4:3分辨率问题的解决:用cvt和xrandr命令查看并配置显卡分辨率到1440x900
linux·运维·ubuntu·显示
都小事儿2 小时前
U-boot:自搬移
linux·spring boot
IT 乔峰2 小时前
基于 LVS-DR + Keepalived 的双机热备高可用负载均衡部署
负载均衡·lvs
JiMoKuangXiangQu2 小时前
Linux 内存 domain 管理
linux·内存管理·domain
warton882 小时前
ubuntu24下操作配置mysql8相关目录到指定地址
linux·运维·mysql