Tomcat Cluster

时间:2021-02-23 14:36:20   收藏:0   阅读:0

下面我们来介绍一下tomcat几种实际应用:

(1) LB tomcat
    nginx tomcats
    apache tomcats
(2) LB tomcat cluster
(3) LB tomcat
    session server
        memcached

前面我们还了解了会话保持有三种方式:

session sticky
session cluster
session server

下面我们来分别实现这些应用:

首先,我们准备环境:

192.168.2.50, node4.ckh.com
192.168.2.30, node5.ckh.com
192.168.2.70, node6.ckh.com

一、nginx + tomcat

node5配置

1、准备环境

1.1 都安装jdk和tomcat并配置环境变量

1.2 tomcat配置

(1)开启日志

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

(2)添加host虚拟主机

<Host name="node5.ckh.com" appBase="/data/webapps" autoDeploy="true">
  <Context path="" docBase="ROOT" reloadable="true" />
    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="/data/logs"
      prefix="web1_access_log" suffix=".txt"
      pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>

1.3 创建所需目录

# mkdir -pv /data/webapps/ROOT/{lib,classes,META-INF,WEB-INF}
# mkdir /data/logs

1.4 编写测试页面

# vim /data/webapps/ROOT/index.jsp
<%@ page language="java" %>
<%@ page import="java.util.*" %>
<html>
<head>
<title> JSP Test Page On node5 </title>
</head>
<body>
<% out.println("hello, node5"); %>
</body>
</html>

node4配置

node4上配置只要将node5改成node4,其他配置都不变。

node6配置

1.3 nginx配置

http上下文中定义backend server:

upstream tcsrvs {
server node4.ckh.com:8080;
server node5.ckh.com:8080;
}

server上下文中定义将动态资源反向代理至后端server:

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

1.4 测试

浏览器访问: http://192.168.2.70/index.jsp, 
默认访问的localhost虚拟主机,所以node4和node5上还需要在server.xml中将默认虚拟主机改为我们定义的虚拟主机名。
再次访问,成功负载均衡。

如果我们期望用户的请求直接到后端某一特定主机,而不要让它负载均衡,用来实现做session sticky的功能。
我们只需要在upstream中添加ip_hash就可以:

upstream tcsrvs {
    ip_hash;
    server node4.ckh.com:8080;
    server node5.ckh.com:8080;
}

二、apache + tomcat

apache结合tomcat来实现反向代理、负载均衡这些功能时有三种实现方式:

(1) http协议实现
  apache:     mod_proxy     mod_proxy_http     mod_proxy_balancer   tomcat     http connector (2) ajp协议实现
  apache:     mod_proxy     mod_proxy_ajp     mod_proxy_balancer   tomcat     ajp connector (3) jk模块实现
  apache:     mod_jk   tomcat:     ajp connector

第一种方法的实现:

1. node6上httpd配置
1.1 取消中心主机的配置

# vim /etc/httpd/conf/httpd.conf
  注释掉DocumentRoot

1.2 定义虚拟主机:

# vim /etc/httpd/conf.d/vhosts.conf
<Proxy balancer://lbcluster1>
BalancerMember http://192.168.2.50:8080 loadfactor=10 route=TomcatB
BalancerMember http://192.168.2.30:8080 loadfactor=10 route=TomcatA
</Proxy>
<VirtualHost *:80>
ServerName web1.ckh.com
ProxyVia On
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / balancer://lbcluster1/
ProxyPassReverse / balancer://lbcluster1/
<Location />
Require all granted
</Location>
</VirtualHost>

node4 AND node5配置

# vim server.xml
<Engine name="Catalina" defaultHost="node4.ckh.com" jvmRoute="TomcatB">
<Engine name="Catalina" defaultHost="node5.ckh.com" jvmRoute="TomcatA">

编辑tomcat中index.jsp

node4

<%@ page language="java" %>
<html>
<head>
<title>TomcatB</title>
</head>
<body>
<h1><font color="blue">TomcatB.ckh.com</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("ckh.com", "ckh.com"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>

node5

<%@ page language="java" %>
<html>
<head>
<title>TomcatA</title>
</head>
<body>
<h1><font color="red">TomcatA.ckh.com</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("ckh.com", "ckh.com"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>

如果要实现会话绑定session sticky:

node6:

# vim /etc/httpd/conf.d/vhosts.conf
添加如下两处内容即可实现会话保持功能
  Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED  //1
    <Proxy balancer://lbcluster1>
    BalancerMember http://192.168.2.50:8080 loadfactor=10 route=TomcatB
    BalancerMember http://192.168.2.30:8080 loadfactor=10 route=TomcatA
    ProxySet stickysession=ROUTEID  //2
    </Proxy>
    <VirtualHost *:80> 
    ServerName web1.ckh.com 
    ProxyVia On
    ProxyRequests Off 
    ProxyPreserveHost On 
    <Proxy *> 
    Require all granted
    </Proxy>
    ProxyPass / balancer://lbcluster1/ 
    ProxyPassReverse / balancer://lbcluster1/ 
    <Location /> 
    Require all granted
    </Location>
    </VirtualHost>

第二种方法的实现:ajp协议的示例

node6:

# vim /etc/httpd/conf.d/vhosts.conf
要想实现会话绑定,只要将1处内容注释去掉即可
  <Proxy balancer://lbcluster1>
    BalancerMember http://192.168.2.50:8080 loadfactor=10 route=TomcatB
    BalancerMember http://192.168.2.30:8080 loadfactor=10 route=TomcatA
    #ProxySet stickysession=ROUTEID  //1
    </Proxy>
    <VirtualHost *:80> 
    ServerName web1.ckh.com 
    ProxyVia On
    ProxyRequests Off 
    ProxyPreserveHost On 
    <Proxy *> 
    Require all granted
    </Proxy>
    ProxyPass / balancer://lbcluster1/ 
    ProxyPassReverse / balancer://lbcluster1/ 
    <Location /> 
    Require all granted
    </Location>
    </VirtualHost>

node4 AND node5

# vim /usr/local/tomcat/conf/server.xml
ajp connector注释要打开,可能1和2这两处内容要修改
<Connector protocol="AJP/1.3"
               port="8009"
               address="::"   //1
               redirectPort="8443" 
               secretRequired="" />   //2

测试反向代理和负载均衡
浏览器访问:http://192.168.2.70/index.jsp

补充:mod_proxy_balancer模块内置的manager:

node6中虚拟主机中定义:

<Location /balancer-manager>
SetHandler balancer-manager
Proxypass !
Order Deny,Allow
Allow from all
</Location>

有些httpd版本可能支持下面写法:

<Location /balancer-manager>
SetHandler balancer-manager
Proxypass !
Require all granted
</Location>

第三种方法的实现

下载tomcat-connectors: 

http://archive.apache.org/dist/tomcat/tomcat-connectors/jk/tomcat-connectors-1.2.46-src.tar.gz

安装tomcat-connectors

# tar xf tomcat-connectors-1.2.46-src.tar.gz
# cd tomcat-connectors-1.2.46-src
# cd native
# ./configure --help    
编译安装tomcat-connectors,所以我们需要安装开发坏境
# yum install httpd-devel gcc glibc-devel -y
# yum groupinstall "Development Tools" --setopt=group_package_types=mandatory,default,optional -y
# ./configure --with-apxs=/usr/bin/apxs
# make && make install

反代示例:

# cd /etc/httpd/conf.d
# vim mod_jk.conf
LoadModule jk_module modules/mod_jk.so
JKWorkersFile /etc/httpd/conf.d/workers.properties
JKLogFile logs/mod_jk.log
JKLogLevel debug
JKMount /* TomcatA
JKMount /status/ stat1
# vim /etc/httpd/conf.d/workers.properties
worker.list=TomcatA,stat1
worker.TomcatA.port=8009
worker.TomcatA.host=192.168.2.30
worker.TomcatA.type=ajp13
worker.TomcatA.lbfactor=1
worker.stat1.type = status

注意:status的访问要做访问控制

负载均衡示例:

# cd /etc/httpd/conf.d
# vim mod_jk.conf
LoadModule jk_module modules/mod_jk.so
JKWorkersFile /etc/httpd/conf.d/workers.properties
JKLogFile logs/mod_jk.log
JKLogLevel debug
JKMount /* lbcluster1
JKMount /status/ stat1
# vim /etc/httpd/conf.d/workers.properties
worker.list = lbcluster1,stat1
worker.TomcatA.type = ajp13
worker.TomcatA.host = 192.168.2.30
worker.TomcatA.port = 8009
worker.TomcatA.lbfactor = 1
worker.TomcatB.type = ajp13
worker.TomcatB.host = 192.168.2.50
worker.TomcatB.port = 8009
worker.TomcatB.lbfactor = 1
worker.lbcluster1.type = lb
worker.lbcluster1.sticky_session = 0
worker.lbcluster1.balance_workers = TomcatA, TomcatB
worker.stat1.type = status

要想实现会话绑定,只需要修改worker.properties中这一行:

worker.lbcluster1.sticky_session = 1

mod_jk模块详情可参考下面的文档:

配置apache通过mod_jk模块与Tomcat连接
    mod_jk是ASF的一个项目,是一个工作于apache端基于AJP协议与Tomcat通信的连接器,它是apache的一个模块,是AJP协议的客户端(服务端是Tomcat的AJP连接器)。
    # tar xf tomcat-connectors-1.2.46-src.tar.gz
    # cd tomcat-connectors-1.2.37-src/native/
    # ./configure --with-apxs=/usr/local/apache/bin/apxs
    # make && make install

    apache要使用mod_jk连接器,需要在启动时加载此连接器模块。为了便于管理与mod_jk模块相关的配置,这里使用一个专门的配置文件
    /etc/httpd/extra/httpd-jk.conf来保存相关指令及其设置。其内容如下:
    LoadModule jk_module modules/mod_jk.so
    JKWorkersFile /etc/httpd/extra/workers.properties
    JKLogFile logs/mod_jk.log
    JKLogLevel debug
    JKMount /* TomcatA 
    JKMount /status/ stat1

    除了需要使用LoadModule指令在apache中装载模块外,mod_jk还需要在apache的主配置文件中设置其他一些指令来配置其工作属性。如JKWorkersFile则用于指定保存了worker相关工作属性定义的配置文件,JKLogFile则用于指定mod_jk模块的日志文件,JKLogLevel则可用于指定日志的级别(info,error,debug),此外还可以使用JKRequestLogFormat自定义日志信息格式。而JKMount(格式:JKMount <URL to match> <Tomcat worker name>)指定则用于控制URL与Tomcat workers的对应关系。
    为了让apache能使用/etc/httpd/extra/httpd-jk.conf配置文件中的配置信息,需要编辑/etc/httpd/httpd.conf,添加如下一行:Include /etc/httpd/extra/httpd-jk.conf
    对于apache代理来说,每一个后端的Tomcat实例中的engine都可以视作一个worker,而每一个worker的地址、连接器的端口等信息都需要在apache端指定以便apache可以识别并使用这些worker。约定俗成,配置这些信息的文件通常为workers.properties,其具体路径则是使用前面介绍过的JKWorkersFile指定的,在apache启动时,mod_jk会扫描此文件获取每一个worker的配置信息。比如,我们这里使用/etc/httpd/extra/workers.properties。
    workers.properties文件一般由两类指令组成:一是mod_jk可以连接的各worker名称列表,二是每一个worker的属性配置信息。它们分别遵循如下使用语法。
    worker.list = < a comma separated list of worker names >
    worker. <worker name> .<property> = <property value>

    其中worker.list指令可以重复指定多次。而worker name则是Tomcat中engine组件jvmRoute参数的值。如:
    worker.TomcatA.host=192.168.2.30
    根据其工作机制的不同,worker有多种不同的类型,这是需要为每个worker定义的一项属性worker.<worker name>.type。常见的类型如下:
    1.ajp13:此类型表示当前worker为一个运行着的Tomcat实例
    2.lb: lb即load balancing,专用于负载均衡场景中的worker;此worker并不真正负责处理用户请求,而是将用户请求调度给其他类型为ajp13的worker。
    3.status: 用于显示分布式环境中各实际worker工作状态的特殊worker,它不处理任何请求,也不关联到任何实际工作的worker实例。具体示例请参见后文中的配置。
    worker其他常见的属性说明:
    1.host: Tomcat 7的worker实例所在的主机;
    2.port: Tomcat 7实例上AJP1.3连接器的端口;
    3.connection_pool_minsize:最少要保存在连接池中的连接的个数;默认为pool_size/2;
    4.connection_pool_timeout:连接池中连接的超时时长;
    5.mount:由当前worker提供的context路径,如果有多个则使用空格隔;此属性可以由JKMount指令代替;
    6.retries:错误发生时的重试次数;
    7.socket_timeout:mod_jk等待worker响应的时长,默认为0,即无限等耐;
    8.socket_keepalive:是否启用keep alive的功能,1表示启用,0表示禁用;
    9.lbfactor:worker的权重,可以在负载均衡的应用场景中为worker定义此属性;

    另外,在负载均衡模式中,专用的属性还有:
    1.balance_workers:用于负载均衡模式中的各worker的名称列表,需要注意的是,出现在此处的worker名称一定不能再任何worker.list属性列表中定义过,并且worker.list属性中定义的worker名字必须包含负载均衡worker。具体示例请参见后文中的定义。
    2.method:可以设定为R、T或B;默认为R,即根据请求的个数进行调度;T表示根据已经发送给worker的实际流量大小进行调度;B表示根据实际负载情况进行调度。
    3.sticky_session:在将某请求调度至某worker后,源于此址的所有后续请求都将直接调度至此worker,实现将用户session与某worker绑定。默认值为1,即启用此功能。如果后端的各worker之间支持session复制,则可以将此属性值设为0.

    根据前文中的指定,这里使用/etc/httpd/extra/workers。
    properties来定义一个名为TomcatA的worker,并为其指定几个属性。文件内容如下:
    worker.list=TomcatA,stat1
    worker.TomcatA.port=8009
    worker.TomcatA.host=192.168.2.30
    worker.TomcatA.type=ajp13
    worker.TomcatA.lbfactor=1
    worker.stat1.type = status    

至此,一个基于mod_jk模块与后端名为TomcatA的worker通信的配置已经完成,重启httpd服务即可生效。

配置基于mod_jk的负载均衡
1、为了避免用户直接访问后端Tomcat实例,影响负载均衡的效果,建议在Tomcat 7的各实例上禁用HTTP/1.1连机器。
2、为每一个Tomcat 7实例的引擎添加jvmRoute参数,并通过其为当前引擎设置全局唯一标识符。如下所示,需要注意的是,每一个实例的jvmRoute的值均不能相同。
<Engine name="Standalone" defaultHost="localhost" jvmRoute="TomcatA">    

而后去配置apache,修改/etc/httpd/extra/httpd-jk.conf为如下内容:
LoadModule jk_module modules/mod_jk.so
JKWorkersFile /etc/httpd/extra/workers.properties
JKLogFile logs/mod_jk.log
JKLogLevel debug
JKMount /* lbcluster1
JKMount /jkstatus/ stat1

编辑/etc/httpd/etra/workers.properties,添加如下内容:
worker.list = lbcluster1,stat1
worker.TomcatA.type = ajp13
worker.TomcatA.host = 192.168.2.30
worker.TomcatA.port = 8009
worker.TomcatA.lbfactor = 1
worker.TomcatB.type = ajp13
worker.TomcatB.host = 192.168.2.50
worker.TomcatB.port = 8009
worker.TomcatB.lbfactor = 1
worker.lbcluster1.type = lb
worker.lbcluster1.sticky_session = 0
worker.lbcluster1.balance_workers = TomcatA, TomcatB
worker.stat1.type = status

session cluster实现

通过内置组件session manager来实现

会话管理器(session manager)有:
  StandardManager
  PersistentManager
    FileStore
    JDBC
  DeltaManager
  BackupManager

构建session cluster示例:

(1)各节点配置使用deltamanager

# cd /usr/local/tomcat/conf
# vim server.xml
在我们定义的虚拟主机内添加:
<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.1.7" //修改组播地址
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="auto" //修改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>

(2)为需要使用session cluster的webapps开启session distribution的功能

# cp web.xml /data/webapps/ROOT/WEB-INF/
# vim /data/webapps/ROOT/WEB-INF/web.xml
在web-app中添加如下一行:
<distributable/>
另一个tomcat节点一样的配置

前端不需要其他修改即可正常工作,可以是http协议或是ajp协议,或是使用jk模块的形式。

会话管理器参考内容:

标准会话管理器和持久会话管理器

标准会话管理器(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参数定义,默认为60s)检查一次超时会话。
保存至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>

 

 

 



 

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!