Tomcat

Tomcat


JVM的核心组成部分:

  • Class Loder
  • 执行引擎

Java编程语言特性:面向对象,多线程,结构化错误处理,垃圾收集,动态链接,动态扩展

堆:创建的对象都在堆内存中 GC:垃圾收集器,主要收集堆内存中的对象

JDK:java开发工具箱,提供了JAVA的类库,开发工具和api

JRE:java运行时环境(java runtime environment),运行java代码,不能开发java代码

JRE(java runtime environment):包含了JVM和其他一些简单功能的JAVA运行环境,适用于只运行java程序时。

JDK(java DevelopmentKit)比JRE包含了更多东西,除了能作为JAVA运行环境,还提供了很多用于开发的工具适用于开发程序时使用

JAVA SE是java开发标准版,里面有JDK,Java EE是企业版,本质上ee只是比se多提供了几个类库而已。

JVM运行时区域:运行为多个线程

  • 方法区:线程共享,用于存储被虚拟机加载的类信息、常量、静态变量等 持久代
  • 堆:jvm所管理的内存中最大的一部分,也是GC管理的主要区域,主流的算法都基于分代收集方式进行,新生代和老年代,贡献内存区;
  • Java栈:线程私有,存储线程自己的局部变量等信息
  • PC寄存器:(program count register),线程独占的内存空间
  • 本地方法栈:依赖于平台

Web Container:

  • 商业实现:
    1. WebSphere(IBM)
    2. WebLogic(Oracle)
    3. Oc4j
    4. Glassfish
    5. JBoss
  • 开源实现:
    1. Tomcat
    2. Jetty
    3. Resin

运行过程图解

  • jsp --> jasper--> servlet --> complie --> bytecodes --> jvm

Tomcat核心组件

catalina:servlet container

Coyote:http connection

Jasper: JSP Engine

Tomcat 开发语言: Java

Tomcat instance : 运行中的tomcat进程(java进程)

  • server:即一个tomcat实例
  • Engine:Tomcat的核心组件,用于运行jsp或servlet代码
  • Connector: 接收并解析用户请求,将请求映射为Engine中运行的代码,之后将运行结果构建成响应报文
  • service:用于把connector组件和engine组件关联起来,一个service只能包含一个engine组件和一个或多个connector
  • host:类似于httpd中的虚拟主机
  • Context:类似于httpd中的alias

注意:每个组件都由类来实现,有些组件的实现还不止一种

顶级类组件:server

服务类组件:service

容器类组件:engine,host,context

连接器组件:connector

被嵌套类组件:valve, logger,realm

Tomcat运行模式

  • standalone:通过内置的Web Server(http connector)来接收客户端的请求
  • proxy:由专门的web server服务客户端的http请求
    1. in-process : 部署于同一主机
    2. network: 部署于不同主机

安装Tomcat

官方站点

  • 安装JDK,配置环境变量

    [root@localhost ~]# cat /etc/profile.d/jdk.sh 
    export JAVA_HOME=/usr/java/latest
    export PATH=$JAVA_HOME/bin:$PATH
    
  • 安装Tomcat配置环境变量

    [root@localhost ~]# cat /etc/profile.d/tomcat.sh 
    export CATALINA_HOME=/usr/local/tomcat
    export PATH=$CATALINA_HOME/bin:$PATH
    

Tomcat目录结构:

  • bin:脚本及启动时用到的类
  • lib:类库
  • conf:配置文件
  • logs:日志文件
  • webapps:应用程序默认部署目录
  • work:工作目录
  • temp:临时文件目录

配置文件

  • server.xml:主配置文件
  • context.xml: 每个webapp都可以有专用的配置文件,这些配置文件通常位于webapp应用程序目录下的WEB-INF目录中,用于定义会话管理器、JDBC等,conf/context.xml是为各webapp提供默认配置的
  • web.xml:每个webapp部署之后才能被访问,此文件则用于为所有的webapp提供默认部署相关配置
  • tomcat-users.xml:用户认证的账号和密码配置文件
  • catalina.policy:当使用-security选项启动tomcat实例时会读取此配置文件来实现其安全运行策略
  • catalina.properties:Java属性的定义文件,用于设定类加载器路径等,一级一些JVM性能相关的调优参数
  • logging.properties:日志相关的配置信息

WEB-INF/:当前webapp的私有资源目录,通常存放当前webapp自用的web.xml

META-INF/:当前webapp的私有资源目录,通常存放当前webapp自用的context.xml

classes/:此webapp的私有类

lib/: 此webapp的私有类,被打包为jar格式类

index.jsp:webapp的主页

webapp归档格式:

  • .war:webapp
  • .jar:EJB的类
  • .rar:资源适配器
  • .ear:企业级应用程序

Tomcat配置文件结构

<server>
    <service>
        <connector port="8080"/>   #http协议默认端口
        <connector port="8009" protocol="AJP/1.3"/>   #ajp协议默认端口
        <engine>
            <Host>
            </Host>
                <Context />
        </engine>
    </service>
</server>

手动添加一个测试应用程序:

  • 创建特定目录结构

    mkdir -p myapp/{lib, classes. WEB-INF, MEAT-INF}
    
  • 测试文件

    [root@localhost myapp]# cat index.jsp 
    <%@ page language="java" %>
    <%@ page import="java.util.*" %>
    <html>
    <head>
    <title> JSP test page </title>
    </head>
    <body>
    <% out.println("hello world"); %>
    </body>
    </html>
    
    

示例配置文件

<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>
  <Service name="Catalina">
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" enableLookups="false" />
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
   <Engine name="Catalina" defaultHost="localhost">
     <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase" />
      </Realm>

<!--  从此处开始添加以下两个Host容器作为虚拟主机 -->
<!-- 定义一个在$CATALINA_HOME之外的虚拟主机 -->
      <Host name="www.longshuai.com"  appBase="/www/longshuai"
            unpackWARs="true" autoDeploy="true">
          <Context path="" docBase="/www/longshuai" reloadable="true" />
          <Context path="/xuexi" docBase="xuexi" reloadable="true" />
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="longshuai_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
<!-- 定义一个在$CATALINA_HOME/webapps下的虚拟主机 -->
      <Host name="www.xiaofang.com"  appBase="webapps/xiaofang"
            unpackWARs="true" autoDeploy="true">
          <Context path="" docBase="" reloadable="true" />
          <Context path="/xuexi" docBase="xuexi" reloadable="true" />
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="xiaofang_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
<!-- 默认虚拟主机localhost,可不修改 -->
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
        <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>
    </Engine>
  </Service>
</Server>

除了engine中定义的默认localhost虚拟主机,另外布置了两个虚拟主机www.longshuai.com和www.xiaofang.com,它们的程序目录分别为/www/longshuai和$CATALINA_HOME/webapps/xiaofang,所以需要提前建立好这两个目录。另外,在context中定义了docBase,对于uri路径/xuexi,它的文件系统路径分别为/www/longshuai/xuexi目录和$CATALINA_HOME/webapps/xiaofang/xuexi,所以也要在上面两个程序目录中定义好xuexi目录。除此之外,还分别为这3个虚拟主机定义了日志,它们的路径为相对路径logs,相对于$CATALINA_HOME。

再提供appBase目录和docBase目录。

mkdir -p /www/longshuai/xuexi
mkdir -p /usr/local/tomcat/webapps/xiaofang/xuexi

再提供测试用的index.jsp文件。内容大致如下,分别复制到以下四个目录中:
/www/longshuai/
/www/longshuai/xuexi/
/usr/local/tomcat/webapps/xiaofang/
/usr/local/tomcat/webapps/xiaofang/xuexi

并将out.println的输出内容分别稍作修改,使能够区分读取的是哪个index.jsp。

<%@ page language="java" %>
<%@ page import="java.util.*" %>
<html>
  <body>
    <% out.println("hello world from longshuai Root"); %>
  </body>
</html>

配置解析

定义连接器时可以配置的属性非常多,但通常定义HTTP连接器时必须定义的属性只有“port”,定义AJP连接器时必须定义的属性只有“protocol”,因为默认的协议为HTTP。以下为常用属性的说明:

  • address:指定连接器监听的地址,默认为 0.0.0.0
  • maxThreads:支持的最大并发连接数,默认为200
  • port:监听的端口,默认为0
  • protocol:连接器使用的协议,默认为HTTP/1.1,定义AJP协议时通常使用AJP/1.3
  • redirectPort:如果某连接器支持的协议是HTTP,当接收客户端发来的HTTPS请求时,则转发至此属性定义的端口
  • connectionTimeout:等待客户端发送请求的超时时间,单位为毫秒。默认为60000,即一分钟
  • enableLookups:是否通过request.getRemoteHost()进行DNS查询以获取客户端的主机名,默认为True
  • acceptCount:设置等待队列的最大长度,通常在tomcat所有处理线程均处于繁忙状态时,新发来的请求将放置在等待队列中

下面定义了一个多个属性的SSL连接器:

<Connector port="8443"
           maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
           enableLookups="false" acceptCount="100" debug="0" scheme="https" secure="true"
           clientAuth="false" sslProtocol="TLS" />

Host组件

位于Engine容器中用于接收请求并进行相应处理的主机或虚拟主机

<Host name="localhost" appBase="webapps"
      unpackWARs="true" autoDeploy="true"
      xmlValidation="false" xmlNamespaceAware="false">
</Host>

常用属性说明

  • appBase:此Host的webapps目录,即存放非归档的web应用程序目录或归档后的WAR文件的目录路径,可以使用基于$CATALINA_HOME的相对路径
  • autoDeploy:在Tomcat处于运行状态时放置于appBase目录中的应用程序文件是否自动进行deploy:默认为true
  • unpackWars:在启用此webapps时是否对WAR格式的归档文件先进行展开:默认为true

虚拟主机定义示例:

<Engine name="Catalina" defaultHost="localhost">
    <Host name="localhost" appBase="webapps">
        <context path="" docBase="ROOT"/>
        <context path="/bbs" docBase="/web/bbs"
                 reloadable="true" crossContext="true"/>
    </Host>
    <Host name="www.template.com" appBase="/web/tem">
        <context path="/" docBase="ROOT"/>
    </Host>
</Engine>

主机别名定义:

如果一个主机有两个或两个以上的主机名:额外的名称均可以以别名的形式进行定义,如下:

<Host name="www.template.com" appBase="webapps" unpackWARs="true">
    <alias>template.com</alias>  
</Host>

撇开tomcat作为servlet容器的行为。它和apache、nginx的功能大致都能对应上。例如以nginx为例,以下是nginx提供web服务时的配置结构:

server {
    listen PORT;
    server_name www.a.com;   # 对应于<host name=www.a.com>
    location / {             # 对应于context path=""
            root   html;     # 对应于docBase
        }
    location /xuexi {        # 对应于context path="/xuexi"
            root   html/xuexi;
        }
}

Tomcat中的appBase和docBase详细说明

这两货虽然意义很明确,但"潜规则"很严重。以下面的配置为例。

<host name=www.a.com appBase=/www/a >
    <context path="" docBase=/www/a />
    <context path="/xuexi" docBase=/www/a/xuexi />
</host>

appBase是虚拟主机存放webapp的目录,它可以是相对路径,也可以是绝对路径。如果是相对路径,则相对于$CATALINA_HOME,严格并准确地说是$CATALINA_BASE。

path是URI的匹配路径,相当于nginx的location后的路径。tomcat要求每个虚拟主机必须配置一个空字符串的path,该条context作为URI无法被明确匹配时的默认context,它相当于nginx中location / {}的作用。

docBase则是每个webapp的存放目录(或者是已归档的war文件),它可以是相对路径,也可以是绝对路径,提供相对路径时它相对于appBase。该目录一般在appBase的目录下,但并不规定一定要放在appBase下。对于web服务来说,它相当于nginx的root指令,但对于webapp来说,一个context就相当于一个webapp,而docBase正是webapp的路径。

"潜规则"在于默认的context如何提供。有以下几种情况:

  1. 明确定义了<context path="" docBase=webappPATH>,此时默认context的处理路径为webappPATH。
  2. 明确定义了<context path="">,但却没给定docBase属性,此时该默认context处理路径为appBase/ROOT目录,注意ROOT为大写。
  3. 完全没有定义path=""的context时,即host容器中没有明确的path="",此时将隐式定义一个默认context,处理路径为appBase/ROOT目录。
  4. 定义了path但没有定义docBase属性时,docBase将根据path推断出它的路径。推断的规则如下:(注:此时推断的不是默认context,而是对应context的docbase)
context path    context name    推断出的docBase路径
--------------------------------------------------
/foo            /foo            foo    
/foo/bar        /foo/bar        foo/bar
Empty String    Empty String    ROOT

显然,没有给定path=""或缺少docbase时,都以ROOT作为目录。以下是几个定义示例:

# 虚拟主机中没有定义任何context,将以appBase下的ROOT作为默认处理路径
<Host appBase="webapps">
</Host>

# 没有定义path=""的context,但定义了path非空的context,也将以ROOT作为默认处理路径
# 如果下面的Context容器中省略docBase属性,则推断出该context的docBase路径为appBase/xuexi
<Host appBase="webapps">
    <Context path="/xuexi" docBase="webappPATH" />
</Host>

# 某个context定义了path="",该context将作为默认context
# 但该默认context如果没有定义docBase,将推断出其docBase路径为appBase/ROOT
<Host appBase="webapps">
    <Context path="" docBase="webappPATH" />
</Host>

# 某个context定义了path="",该context将作为默认context
# 下面的默认context明确定义了docBase
<Host appBase="webapps">
    <Context path="" docBase="webappPATH" />
</Host>

举个直观的例子,如果某个Host配置如下。

<Host name="www.xiaofang.com" appBase="/www/xiaofang" unpackWARs="true" autoDeploy="true">
    <Context path="/xuexi" docBase="xuexi" reloadable="true" />
</Host>

那么浏览器访问http://www.xiaofang.com:8080/xuexi/将请求/www/xiaofang/xuexi/index.jsp

由于没有定义path=""的Context组件,因此浏览器访问http://www.xiaofang.com:8080将请求/www/xiaofang/ROOT/index.jsp。注意,是ROOT目录。

如果加上<Context path="" docBase="" reloadable="true" />,则访问http://www.xiaofang.com:8080将请求/www/xiaofang/index.jsp。注意,不是ROOT目录,而是相对于appBase的根目录,即/www/xiaofang。

尽管本文解释了一大堆关于appBase和docBase的设置,但一般都会采用大众所熟知的配置方式:appBase设置为"webapps",即$CATALINA_HOME/webapps,而docBase设置为webapps下的webapp应用名。这样配置不仅符合eclipse部署webapp时默认的部署目录结构(eclipse部署应用时,将WebContent下的内容复制到docBase下,将servlet java源代码编译后的class文件复制到WEB-INF/classes目录下),更利于维护webapp和相关配置。例如:

<Context docBase="MyWeb" path="/MyWeb" reloadable="true" />
<Context docBase="SecondWeb" path="/SecondWeb" reloadable="true" />
<Context docBase="WEB" path="/WEB" reloadable="true" />

但这样的配置有个缺点,因为项目名称一般都会带有大写字母,使得在浏览器访问时,也要带有大写字母。例如输入http://www.a.com/MyWeb/index.jsp。因此,可采用另一种配置方式:设置Host的appBase为webapps下的某个目录,然后在path上配置uri匹配路径。如下:

<Host name="www.xiaofang.com" appBase="webapps/MyWeb" unpackWARs="true" autoDeploy="true">
    <Context path="/xuexi" docBase="xuexi" reloadable="true" />
    <Context path="" docBase="" reloadable="true" />
</Host>

注意:path不能以“/”结尾

被嵌套的valve

Valve中文意思是阀门,类似于过滤器,它可以工作于Engine和Host/Context之间、Host和Context之间以及Context和Web应用程序的某资源之间。一个容器内可以建立多个Valve,而且Valve定义的次序也决定了它们生效的次序。

有多种不同的Valve:

  • AccessLogValve:访问日志Valve
  • ExtendedAccessValve:扩展功能的访问日志Valve;
  • JDBCAccessLogValve:通过JDBC将访问日志信息发送到数据库中;
  • RequestDumperValve:请求转储Valve;
  • RemoteAddrValve:基于远程地址的访问控制
  • RemoteHostValve:基于远程主机名称的访问控制
  • SemaphoreValve:用于控制Tomcat主机上任何容器上的并发访问数量;
  • JvmRouteBinderValve:在配置多个Tomcat为以Apache通过mod_proxy或mod_jk作为前端的集群架构中,当期望停止某节点时,可以通过此Valve将用记请求定向至备用节点;使用此Valve,必须使用JvmRouteSessionIDBinderListener;
  • ReplicationValve:专用于Tomcat集群架构中,可以在某个请求的session信息发生更改时触发session数据在各节点间进行复制;
  • SingleSignOn:将两个或多个需要对用户进行认证webapp在认证用户时连接在一起,即一次认证即可访问所有连接在一起的webapp;
  • ClusterSingleSingOn:对SingleSignOn的扩展,专用于Tomcat集群当中,需要结合ClusterSingleSignOnListener进行工作;

其中RemoteHostValve和RemoteAddrValve可以分别用来实现基于主机名称和基于IP地址的访问控制,控制本身可以通过allow或deny来进行定义,这有点类似于Apache的访问控制功能。如下面的Valve实现了仅允许本机访问/probe:

<Context privileged="true" path="/probe" docBase="probe">
  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
  allow="127.0.0.1"/>
</Context>

其中相关属性定义有:

  • className:在对应位置的后缀上加上".valves.RemoteHostValve"或".valves.RemoteAddrValve";
  • allow:以逗号分开的允许访问的IP地址列表,支持正则,点号“.”用于IP地址时需要转义;仅定义allow项时,非明确allow的地址均被deny;
  • deny: 以逗号分开的禁止访问的IP地址列表,支持正则;使用方式同allow;仅定义deny项时,非明确deny的地址均被allow;

另外一个常用的Valve为AccessLogValve,定义方式大致如下:

<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" />

其中prefix和suffix表示日志文件的前缀名称和后缀名称。pattern表示记录日志时的信息和格式。


LNMT

流程:

client --> nginx --> reverse_proxy --> http --> tomcat (http connector)

       location ~* .(jsp|do)$ {
        proxy_pass http://www.template.com:8080;
}

LAMT

client --> http --> httpd --> reverse_proxy --> (http|ajp) --> tomcat(http connector |ajp connector)

反代模块:

​ 主:proxy_module

​ 子:proxy_module_http, proxy_module_ajp

​ 第三方模块:jk

​ ajp协议

httpd要扩展模块需要借助apxs,它是httpd的开发包httpd-devel中工具,所以先要安装httpd-devel。如果是编译安装的httpd,则devel包已经装好,如果是yum安装,则需要额外安装httpd-devel包。

yum -y install httpd httpd-devel

httpd虚拟主机反向代理

基于proxy_module_http

<VirtualHost *:80>
  ServerName www.template.com
  ProxyVia On
  ProxyRequests Off
  ProxyPreserveHost On
  <Proxy *>
    Require all granted
  </Proxy>
    ProxyPass / http://192.168.175.3:8080/
    ProxyPassReverse / http://192.168.175.3:8080/
  <Location />
    Require all granted
  </Location>
</VirtualHost>

基于proxy_module_ajp

<VirtualHost *:80>
  ServerName www.template.com
  ProxyVia On
  ProxyRequests Off
  ProxyPreserveHost On
  <Proxy *>
    Require all granted
  </Proxy>
    ProxyPass / ajp://192.168.175.3:8009/
    ProxyPassReverse / ajp://192.168.175.3:8009/
  <Location />
    Require all granted
  </Location>
</VirtualHost>

如果不想把status页面反代至后端服务器可以加上 ProxyPass /status !

<VirtualHost *:80>
  ServerName www.template.com
  ProxyVia On
  ProxyRequests Off
  ProxyPreserveHost On
  <Proxy *>
    Require all granted
  </Proxy>
    ProxyPass /status !
    ProxyPass / ajp://192.168.175.3:8009/
    ProxyPassReverse / ajp://192.168.175.3:8009/
  <Location />
    Require all granted
  </Location>
</VirtualHost>

apache指令说明:

  • ProxyPreserveHost {on|off}:如果启用此功能,代理会将用户请求报文中的Host:行发送给后端的服务器,而不再使用ProxyPass指定的服务器地址。如果想在反向代理中支持虚拟主机,则需要开启此项,否则就无需打开此功能
  • ProxyVia {on|off|Full|Block}:用于控制在http首部是否使用Via,主要用于在多级代理中控制代理请求的流向。默认为off,即不启用此功能,on表示每个请求和响应报文均添加Via,Full表示每个Via行都会添加当前apache的版本号信息,Block表示每个代理请求报文中的Via都会被移除
  • ProxyRequest {on|off}:是否开启apache正向代理的功能,启用此项时为了代理http协议必须启用mod_proxy_http模块,同时,如果为apache设置了ProxyPass,则必须将ProxyRequests设置为off
  • ProxyPass [path] ! | url [key=value key=value….] : 将后端服务器某URL与当前服务器的某虚拟路径关联起来作为提供服务的路径,如果path以“/”结尾,则对应的url也必须以“/”结尾
    • min:连接池的最小容量
    • max:连接池的最大容量
    • loadfactor:用于负载均衡集群配置中,定义对应后端服务器的权重,取值范围为:1-100
    • retry:当apache将请求发送至后端服务器得到错误响应时等待多长时间以后再重试,单位是秒

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

  • lbmethod:apache实现负载均衡的调度算法,默认是byrequests,即基于权重将统计请求个数进行调度,bytraffic则执行基于权重的流量计数调度,bybusyness通过考量每个后端服务器的当前负载进行调度

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

  • nofailover:取值为on或off,设置为on时表示后端服务器故障时,用户的session将损坏,因此,在后端服务器不支持session复制时可将其设置为on

  • stickysession:调度器sticky session的名字,根据web程序语言的不同,其值为JSESSIONID或PHPSESSIONID

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

    <Proxy balancer://hotcluster>
        BalancerMember http://www1.template.com:8080 loadfactor=1
        BalancerMember http://www2.template.com:8080 loadfactor=2
        ProxySet lbmethod=bytraffic
    </Proxy>
    
  • ProxyPassReverse:用于让apache调整HTTP重定向响应报文中的Location、Content-Location及URI标签所对应的URL,在反向代理环境中必须使用此指令避免重定向绕过proxy服务器

基于mod_proxy实现负载均衡

在http.conf全局配置文件中配置如下内容:

ProxyRequests off
<Proxy balancer://lbcluster1>
    BalancerMember ajp://172.16.100.1:8009 loadfactor=10 route=TomcatA
    BalancerMember ajp://172.16.100.2:8009 loadfactor=10 route=TomcatB
</Proxy>

<VirtualHost *:80>
    ServerAdmin admin@163.com
    ServerName www.template.com
    ProxyPass / balancer://lbcluster1/
    ProxyPassReverse / balancer://lbcluster1/
</VirtualHost>

<Proxy balancer://hotcluster>
    BalancerMember http://www1.template.com:8080 loadfactor=1
    BalancerMember http://www2.template.com:8080 loadfactor=2 
    ProxySet lbmethod=bytraffic
</Proxy>
<Proxy balancer://lbcluster1>
   BalancerMember http://192.168.175.4:8080 loadfactor=10 route=TomcatA
   BalancerMember http://192.168.175.5:8080 loadfactor=10 route=TomcatB
</Proxy>

<VirtualHost *:80>
  ServerName www.template.com
  ProxyVia On
  ProxyRequests Off
  ProxyPreserveHost On
  <Proxy *>
    Require all granted
  </Proxy>
    ProxyPass / balancer://lbcluster1/
    ProxyPassReverse / balancer://lbcluster1/
  <Location />
    Require all granted
  </Location>
</VirtualHost>

如果需要会话绑定,可像如下配置:

Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
<Proxy balancer://lbcluster1>
   BalancerMember http://192.168.175.4:8080 loadfactor=10 route=TomcatA
   BalancerMember http://192.168.175.5:8080 loadfactor=10 route=TomcatB
   ProxySet stickysession=ROUTEID
</Proxy>

<VirtualHost *:80>
  ServerName www.template.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实现负载均衡:

#Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
<Proxy balancer://lbcluster1>
   BalancerMember ajp://192.168.175.4:8009 loadfactor=10 route=TomcatA
   BalancerMember ajp://192.168.175.5:8009 loadfactor=10 route=TomcatB
   ProxySet stickysession=ROUTEID
</Proxy>

<VirtualHost *:80>
  ServerName www.template.com
  ProxyVia On
  ProxyRequests Off
  ProxyPreserveHost On
  <Proxy *>
    Require all granted
  </Proxy>
    ProxyPass / balancer://lbcluster1/
    ProxyPassReverse / balancer://lbcluster1/
  <Location />
    Require all granted
  </Location>
</VirtualHost>

配置apache通过mod_jk模块与tomcat连接

mod_jk是ASF的一项目,是一工作于apache端基于AJP协议与tomcat通信的连接器,它是apache的一个模块,是AJP协议的客户端(服务端是Tomcat的AJP连接器)

apache要使用mod_jk连接器,需要在启动时加载此连接器的模块,为了便于管理mod_jk模块相关的配置,这里使用一个专门的配置文件/etc/httpd/extra/httpd-jk.conf来保存相关指令及其设置,其内容如下:

#Load the mod_jk
LoadModule jk_module modules/mod_jk.so
JkWorkersFile /etc/httpd/extra/worker.properties
JkLogFile logs/mod_jk.log
JkLogLevel debug
JkMount /* TomcatA
JkMount /status stat1

当前最新稳定版的mod_jk是1.2.42版本。

mod_jk下载地址:http://tomcat.apache.org/download-connectors.cgi
mod_jk官方手册:http://tomcat.apache.org/connectors-doc/

httpd要扩展模块需要借助apxs,它是httpd的开发包httpd-devel中工具,所以先要安装httpd-devel。如果是编译安装的httpd,则devel包已经装好,如果是yum安装,则需要额外安装httpd-devel包。

此处为了方便,httpd使用yum安装。所以编译mod_jk的方式如下:

yum -y install httpd httpd-devel
tar xf tomcat-connectors-1.2.42-src.tar.gz
cd tomcat-connectors-1.2.42-src/native/
./configure --with-apxs=/usr/bin/apxs --prefix=/usr/local/tomcat/mod_jk
make && make install

此处暂先配置httpd与其中一个tomcat(192.168.100.22)连接。后文在说明负载均衡时再引入另一个tomcat。

先提供一个额外的httpd配置文件。

[root@xuexi ~]# cat /etc/httpd/conf.d/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" will send all request to TomcatA   ########
JkMount   /*.jsp        TomcatA
JkMount   /status/*     statA
JkUnMount /images/*     TomcatA
JkUnMount /css/*.*      TomcatA
JkUnMount /css_js/*     TomcatA
JkUnMount /*.html       TomcatA
JkUnMount /*.js         TomcatA

mod_jk的配置文件官方手册:http://tomcat.apache.org/connectors-doc/reference/apache.html。以下是几个常用的指令说明

  • LoadModule指令用于装载mod_jk相关模块,除此之外还需要在httpd的配置文件中设置其它一些指令来配置其工作属性。如:
  • JkWorkersFile用于指定保存了worker相关工作属性定义(见下文)的配置文件。
  • JkLogFile用于指定mod_jk模块的日志文件。
  • JkLogLevel用于指定日志级别(info,error,debug),此外还可以使用JkRequestLogFormat自定义日志信息格式。
  • JkMount(格式:JkMount )则用于控制URL与Tomcat workers的对应关系。可以理解为转发请求的意思,例如"/status/*"表示url地址后加上/status/可转发至statA这个worker上。注意,JkMount匹配的URL是相对的。如果JkMount指令放在Location指令中,如<Location /app>,则JkMount将从/app的后面开始匹配。

JkMount和JkUnMount是很重要的指令,mod_jk性能之所以比mod_proxy好,就是因为通过这两个指令可以实现动静分离,使得只将动态请求转发给tomcat。其中JkMount指定要转发给tomcat处理的请求,JkUnMount指定明确不转发给tomcat而是在本地处理的请求。虽然不指定JkUnMount时,也表示不转发给tomcat,但如果有重叠时,则应该指定JkUnMount。例如下面的例子,除了/myapp/下的js文件,其他都转发给tomcat1处理。

JkMount /myapp/* tomcat1
JkUnMount /myapp/*.js tomcat1

对于apache来说,每一个后端Tomcat实例中的engine都可以视作一个worker,而每一个worker的地址、Connector的端口等信息都需要在apache端指定以便可以识别并使用这些worker。配置这些信息的文件通常为"workers.properties",其具体路径是使用前面介绍过的JkWorkersFile指定的。在apache启动时,mod_jk会扫描此文件获取每一个worker配置信息。如这里使用/etc/httpd/conf.d/workers.properties

workers.properties文件一般由两类指令组成:一是mod_jk可以连接的各worker名称列表,二是每一个worker的属性配置信息。详细的配置方法见官方手册:http://tomcat.apache.org/connectors-doc/reference/workers.html

以下是和上述/etc/httpd/conf.d/mod_jk.conf中配置相对应的/etc/httpd/conf.d/workers.properties。

[root@xuexi tomcat]# cat /etc/httpd/conf.d/workers.properties
worker.list=TomcatA,statA
worker.TomcatA.type=ajp13
worker.TomcatA.host=192.168.100.22
worker.TomcatA.port=8009
worker.TomcatA.lbfactor=1
worker.statA.type = status

关于worker的配置,它们分别遵循如下使用语法。

worker.list = <a comma separated list of worker_name>
worker.<worker_name>.<property>=<property value>

其中worker.list指令可以重复指定多次。worker_name是Tomcat中engine组件中jvmRoute属性的值(jvmRoute可以不指定,此时worker_name仅用于标识worker)。

根据工作机制的不同,worker有多种不同的类型,每个worker都需要指定其类型,即设定woker..type项。常见的类型如下:其中ajp13是默认值。

  • ajp13:此类型是web server和tomcat首选的类型。此外,还有ajp12和ajp14,但它们一个废弃一个处于测试阶段。
  • lb:lb用于负载均衡场景中的worker;此worker并不真正负责处理用户请求,而是将用户请求调度给其它类型为ajp13的worker。
  • status:用户显示负载均衡中各worker工作状态的特殊worker,它不处理任何请求,也不关联到任何实际工作的tomcat实例。

由于status是状态监控页面,所以应该保证其安全性,可以在httpd的配置文件中加入以下控制列表:

# 注意,必须加上尾随斜线,因为在mod_jk.conf中已经明确了"/status/*"
# For http 2.2
<Location /status/>
    Order deny,allow
    Deny from all
    Allow from 192.168.100.0/24
</Location>

# For http 2.4
<Location /status/>
    Requrie ip 192.168.100
</Location>

除了type属性外,worker其它常见的属性有:

除了type属性外,worker其它常见的属性有:

  • host:worker所在的主机,更具体的是tomcat上connector组件设置的ajp监听地址;
  • port:worker的AJP1.3连接器监听的端口;
  • connection_pool_minsize:最少要保存在连接池中的连接的个数;默认为pool_size/2;
  • connection_pool_timeout:连接池中连接的超时时长;
  • mount:由当前worker提供的context路径,如果有多个则使用空格格开;可考虑在httpd端使用JkMount替代。
  • retries:错误发生时的重试次数;
  • socket_timeout:mod_jk等待worker响应的时长,默认为0,即无限等待;
  • socket_keepalive:是否启用keep alive的功能,1表示启用,0表示禁用;
  • lbfactor:worker的权重,可以在负载均衡的应用场景中为worker定义此属性;

另外,在负载均衡模式中专用的属性还有:

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

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

通过mod_jk负载均衡tomcat

使用mod_jk实现tomcat的负载均衡有一个好处,tomcat上可以禁用http协议(将监听此协议的Connector配置删除即可),防止外界直接通过http请求tomcat。

配置apache,使其支持负载均衡,修改/etc/httpd/conf.d/mod_jk.conf为如下内容:

LoadModule      jk_module  modules/mod_jk.so
JkWorkersFile   /etc/httpd/conf.d/workers.properties
JkLogFile       logs/mod_jk.log
JkLogLevel      notice
JkMount         /*.jsp     TomcatLB
JkMount         /status/*  statA

编辑/etc/httpd/conf.d/workers.properties,修改为如下内容:为测试负载效果,不启用stick_session。

worker.list=TomcatLB,statA
worker.statA.type=status
worker.TomcatLB.type=lb
worker.TomcatLB.sticky_session=false
worker.TomcatLB.balance_workers=TomcatA,TomcatB
worker.TomcatA.type=ajp13
worker.TomcatA.host=192.168.175.4
worker.TomcatA.port=8009
worker.TomcatA.lbfactor=5
worker.TomcatB.type=ajp13
worker.TomcatB.host=192.168.175.5
worker.TomcatB.port=8009
worker.TomcatB.lbfactor=10

在mod_jk负载均衡中,后端tomcat的engine组件需要添加jvmRoute参数,该参数会为当前server实例设置全局惟一标识符,因此每一个实例的jvmRoute的值均不能相同,且jvmRoute的值必须等于balance_workers的成员值。对于上面的配置,Engine应该如下设置:此处还修改了name,但这不是要求要修改的。

<!--  在tomcatA上设置  -->
<Engine name="Standalone" defaultHost="localhost" jvmRoute="TomcatA">
<!--  在tomcatB上设置  -->
<Engine name="Standalone" defaultHost="localhost" jvmRoute="TomcatB">

添加index.jsp,内容如下:

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

会话管理器

  • 标准会话管理器(StandardManager)

​ 默认为StandardManager

  • 持久会话管理器(PersistentManager)

    FileStore:保存至文件中的示例

    <Manager className="org.apache.catalina.session.PersistentManager"
             saveOnRestart="true">
        <Store className="org.apache.catalina.session.FileStore"
               directory="/data/tomcat-sessions" />
    </Manager>
    

​ JDBC:保存至JDBCStore中的示例

<Manager className="org.apache.catalina.session.PersistenManager"
         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

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

    分别在server.xml 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="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.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>
    

    注意:为需要使用session cluster的webapps 开启 session distribution功能

    在WEB-INF/web.xml中添加 **<distributable /> **

    tomcat实现的session集群,与负载均衡器无关

  • BackupManager:两两做成一个集群

session集群示例配置文件:

  1. TomcatA
<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<!-- Note:  A "Server" is not itself a "Container", so you may not
     define subcomponents such as "Valves" at this level.
     Documentation at /docs/config/server.html
 -->
<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <!-- Security listener. Documentation at /docs/config/listeners.html
  <Listener className="org.apache.catalina.security.SecurityListener" />
  -->
  <!--APR library loader. Documentation at /docs/apr.html -->
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <!-- Global JNDI resources
       Documentation at /docs/jndi-resources-howto.html
  -->
  <GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>

  <!-- A "Service" is a collection of one or more "Connectors" that share
       a single "Container" Note:  A "Service" is not itself a "Container",
       so you may not define subcomponents such as "Valves" at this level.
       Documentation at /docs/config/service.html
   -->
  <Service name="Catalina">

    <!--The connectors can use a shared executor, you can define one or more named thread pools-->
    <!--
    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
        maxThreads="150" minSpareThreads="4"/>
    -->


    <!-- A "Connector" represents an endpoint by which requests are received
         and responses are returned. Documentation at :
         Java HTTP Connector: /docs/config/http.html
         Java AJP  Connector: /docs/config/ajp.html
         APR (HTTP/AJP) Connector: /docs/apr.html
         Define a non-SSL/TLS HTTP/1.1 Connector on port 8080
    -->
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <!-- A "Connector" using the shared thread pool-->
    <!--
    <Connector executor="tomcatThreadPool"
               port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    -->
    <!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443
         This connector uses the NIO implementation. The default
         SSLImplementation will depend on the presence of the APR/native
         library and the useOpenSSL attribute of the
         AprLifecycleListener.
         Either JSSE or OpenSSL style configuration may be used regardless of
         the SSLImplementation selected. JSSE style configuration is used below.
    -->
    <!--
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150" SSLEnabled="true">
        <SSLHostConfig>
            <Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
                         type="RSA" />
        </SSLHostConfig>
    </Connector>
    -->
    <!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2
         This connector uses the APR/native implementation which always uses
         OpenSSL for TLS.
         Either JSSE or OpenSSL style configuration may be used. OpenSSL style
         configuration is used below.
    -->
    <!--
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
               maxThreads="150" SSLEnabled="true" >
        <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
        <SSLHostConfig>
            <Certificate certificateKeyFile="conf/localhost-rsa-key.pem"
                         certificateFile="conf/localhost-rsa-cert.pem"
                         certificateChainFile="conf/localhost-rsa-chain.pem"
                         type="RSA" />
        </SSLHostConfig>
    </Connector>
    -->

    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />


    <!-- An Engine represents the entry point (within Catalina) that processes
         every request.  The Engine implementation for Tomcat stand alone
         analyzes the HTTP headers included with the request, and passes them
         on to the appropriate Host (virtual host).
         Documentation at /docs/config/engine.html -->

    <!-- You should set jvmRoute to support load-balancing via AJP ie :
    <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
    -->
    <Engine name="Catalina" defaultHost="node2.template.com" jvmRoute="TomcatA">

      <!--For clustering, please take a look at documentation at:
          /docs/cluster-howto.html  (simple how to)
          /docs/config/cluster.html (reference documentation) -->
      <!--
      <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
      -->

      <!-- Use the LockOutRealm to prevent attempts to guess user passwords
           via a brute-force attack -->
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- This Realm uses the UserDatabase configured in the global JNDI
             resources under the key "UserDatabase".  Any edits
             that are performed against this UserDatabase are immediately
             available for use by the Realm.  -->
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <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="node2.template.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="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.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>
	<Context path="" docBase="ROOT" />
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="/data/logs"
               prefix="node2_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>

    </Engine>
  </Service>
</Server>

  1. TomcatB

    <?xml version="1.0" encoding="UTF-8"?>
    <!--
      Licensed to the Apache Software Foundation (ASF) under one or more
      contributor license agreements.  See the NOTICE file distributed with
      this work for additional information regarding copyright ownership.
      The ASF licenses this file to You under the Apache License, Version 2.0
      (the "License"); you may not use this file except in compliance with
      the License.  You may obtain a copy of the License at
    
          http://www.apache.org/licenses/LICENSE-2.0
    
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      See the License for the specific language governing permissions and
      limitations under the License.
    -->
    <!-- Note:  A "Server" is not itself a "Container", so you may not
         define subcomponents such as "Valves" at this level.
         Documentation at /docs/config/server.html
     -->
    <Server port="8005" shutdown="SHUTDOWN">
      <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
      <!-- Security listener. Documentation at /docs/config/listeners.html
      <Listener className="org.apache.catalina.security.SecurityListener" />
      -->
      <!--APR library loader. Documentation at /docs/apr.html -->
      <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
      <!-- Prevent memory leaks due to use of particular java/javax APIs-->
      <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
      <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
      <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
    
      <!-- Global JNDI resources
           Documentation at /docs/jndi-resources-howto.html
      -->
      <GlobalNamingResources>
        <!-- Editable user database that can also be used by
             UserDatabaseRealm to authenticate users
        -->
        <Resource name="UserDatabase" auth="Container"
                  type="org.apache.catalina.UserDatabase"
                  description="User database that can be updated and saved"
                  factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
                  pathname="conf/tomcat-users.xml" />
      </GlobalNamingResources>
    
      <!-- A "Service" is a collection of one or more "Connectors" that share
           a single "Container" Note:  A "Service" is not itself a "Container",
           so you may not define subcomponents such as "Valves" at this level.
           Documentation at /docs/config/service.html
       -->
      <Service name="Catalina">
    
        <!--The connectors can use a shared executor, you can define one or more named thread pools-->
        <!--
        <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
            maxThreads="150" minSpareThreads="4"/>
        -->
    
    
        <!-- A "Connector" represents an endpoint by which requests are received
             and responses are returned. Documentation at :
             Java HTTP Connector: /docs/config/http.html
             Java AJP  Connector: /docs/config/ajp.html
             APR (HTTP/AJP) Connector: /docs/apr.html
             Define a non-SSL/TLS HTTP/1.1 Connector on port 8080
        -->
        <Connector port="8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   redirectPort="8443" />
        <!-- A "Connector" using the shared thread pool-->
        <!--
        <Connector executor="tomcatThreadPool"
                   port="8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   redirectPort="8443" />
        -->
        <!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443
             This connector uses the NIO implementation. The default
             SSLImplementation will depend on the presence of the APR/native
             library and the useOpenSSL attribute of the
             AprLifecycleListener.
             Either JSSE or OpenSSL style configuration may be used regardless of
             the SSLImplementation selected. JSSE style configuration is used below.
        -->
        <!--
        <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
                   maxThreads="150" SSLEnabled="true">
            <SSLHostConfig>
                <Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
                             type="RSA" />
            </SSLHostConfig>
        </Connector>
        -->
        <!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2
             This connector uses the APR/native implementation which always uses
             OpenSSL for TLS.
             Either JSSE or OpenSSL style configuration may be used. OpenSSL style
             configuration is used below.
        -->
        <!--
        <Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
                   maxThreads="150" SSLEnabled="true" >
            <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
            <SSLHostConfig>
                <Certificate certificateKeyFile="conf/localhost-rsa-key.pem"
                             certificateFile="conf/localhost-rsa-cert.pem"
                             certificateChainFile="conf/localhost-rsa-chain.pem"
                             type="RSA" />
            </SSLHostConfig>
        </Connector>
        -->
    
        <!-- Define an AJP 1.3 Connector on port 8009 -->
        <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
    
    
        <!-- An Engine represents the entry point (within Catalina) that processes
             every request.  The Engine implementation for Tomcat stand alone
             analyzes the HTTP headers included with the request, and passes them
             on to the appropriate Host (virtual host).
             Documentation at /docs/config/engine.html -->
    
        <!-- You should set jvmRoute to support load-balancing via AJP ie :
        <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
        -->
        <Engine name="Catalina" defaultHost="node1.template.com" jvmRoute="TomcatB">
    
          <!--For clustering, please take a look at documentation at:
              /docs/cluster-howto.html  (simple how to)
              /docs/config/cluster.html (reference documentation) -->
          <!--
          <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
          -->
    
          <!-- Use the LockOutRealm to prevent attempts to guess user passwords
               via a brute-force attack -->
          <Realm className="org.apache.catalina.realm.LockOutRealm">
            <!-- This Realm uses the UserDatabase configured in the global JNDI
                 resources under the key "UserDatabase".  Any edits
                 that are performed against this UserDatabase are immediately
                 available for use by the Realm.  -->
            <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
                   resourceName="UserDatabase"/>
          </Realm>
    
          <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="node1.template.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="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.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>
            <Context path="" docBase="ROOT" />
            <Valve className="org.apache.catalina.valves.AccessLogValve" directory="/data/logs"
                   prefix="node1_access_log" suffix=".txt"
                   pattern="%h %l %u %t &quot;%r&quot; %s %b" />
          </Host>
    
        </Engine>
      </Service>
    </Server>
    
    
原文地址:https://www.cnblogs.com/Template/p/9764039.html