本文目录:
1. Tomcat 连接器协议类型
2. Tomcat 与 httpd/nginx 结合的方式
- Tomcat + nginx
- Tomcat + httpd(mod_jk)
4.1 编译 mod_jk 模块
4.2 配置 httpd 与 tomcat 的 ajp 连接
4.3 通过 mod_jk 负载均衡 tomcat
5. Tomcat+httpd(mod_proxy)
5.1 配置 httpd 代理到 tomcat
5.2 通过 mod_proxy 负载均衡 tomcat
tomcat 一般只提供动态资源处理功能, 而静态资源的请求则交给独立的 apache/httpd 或 nginx 来处理但 tomcat 与外界通信的唯一组件是连接器 Connector, 因此动态请求要转发给 tomcat 时, 需要和 Connector 通信 Connector 与外界通信的协议有两种: http/ajp
1. Tomcat 连接器协议类型
tomcat 的 Connector 组件支持两种协议类型的连接: httpajp
其中 http 又分为 http/1.1 和 http/2, 但因为 Servlet 的阻塞特性, 使得每个 http/2 的请求都需要单独的容器线程负责处理, 因此目前使用 http/2 的性能还很差而 AJP 又有 ajp12ajp13 和 ajp14, 其中 ajp12 的功能太简陋, ajp14 又处于试验期, 因此目前都适用 ajp13, 或者称为 ajp 1.3
基于 IO 模型, Connector 又分为 NIO/NIO2/APR 三种类型
设置连接器协议的方式如下:
- <!-- 定义使用 Http 协议的连接器, 其中 "HTTP/1.1" 表示自动选择 NIO/NIO2/APR -->
- <connector port="8080" protocol="HTTP/1.1">
- <connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol">
- <connector port="8080" protocol="org.apache.coyote.http11.Http11Nio2Protocol">
- <connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol">
- <!-- 定义使用 AJP 协议的连接器, 其中 "AJP/1.3" 表示自动选择 NIO/NIO2/APR -->
- <Connector port="8009" protocol="AJP/1.3"/>
- <Connector port="8009" protocol="org.apache.coyote.ajp.AjpNioProtocol"/>
- <Connector port="8009" protocol="org.apache.coyote.ajp.AjpNio2Protocol"/>
- <Connector port="8009" protocol="org.apache.coyote.ajp.AjpAprProtocol"/>
2. Tomcat 与 httpd/nginx 结合的方式
Tomcat 连接器与外界通信的两种协议中, ajp 只能和 apache 基金会开发的部分项目通信, 例如 httpd 要与非 apache 基金会开发的程序通信, 必须使用 http 协议因此, tomcat+nginx 时, tomcat 连接器的协议类型只能是 http
对于 tomcat+httpd,tomcat 端的连接器既可以使用 http, 也可以使用 ajp 协议但在 httpd 端, 也支持多种通信模块, 最常用的是 mod_proxy 和 mod_jk
tomcat+httpd 时, 几个需要注意的点:
(1).mod_jk 一般只和 tomcat 的 ajp 协议配合来通信而 mod_proxy 则不要求 tomcat 端的协议类型是 http 还是 ajp
(2). 配置时, 使用 mod_jk 比使用 mod_proxy 要复杂的多
(3). 使用 mod_jk 可以配置成只处理动态请求, 而不处理静态请求但 mod_proxy 则只能将所有请求都转发给 tomcat 因此, 在性能上 mod_jk 比 mod_proxy 不过由于前端可以使用反向代理工具, 因此这种情况下的 mod_jk 和 mod_proxy, 性能无差别
因此, 如果满足业务需求, 建议使用 mod_proxy, 它配置起来比 mod_jk 要简便的多, 且可定制的功能更多
稍作总结, apache 和 tomcat 通信的实现方式有 3 种:
apache:mod_jk<--> tomcat:ajp(虽然可以和 http 配合, 但不建议)
apache:mod_proxy <--> tomcat:ajp 或 http
下图是 httpd/nginx+tomcat 在动静分离时通常使用的架构模型
左边的模型中, nginx/httpd 需要处理静态请求, 并将动态请求转发给 tomcat, 同时实现负载均衡右边的模型中, 添加一层反向代理层, 无论是静态请求还是动态请求都负载到各自的服务器组后文的实验都采用左边的架构模型来完成
3. Tomcat + nginx
测试环境如下:
- [root@xuexi ~]# echo "[nginx]
- name=nginx
- baseurl=http://nginx.org/packages/centos/6/x86_64/
- enable=1
- gpgcheck=0" >/etc/yum.repos.d/nginx.repo
- [root@xuexi ~]# yum install -y nginx
- [root@xuexi ~]# vim /etc/nginx/conf.d/tomcat.conf
- upstream tomcat_servers {
- server 192.168.100.22:8080 weight=1 max_fails=2 fail_timeout=2;
- server 192.168.100.23:8080 weight=2 max_fails=2 fail_timeout=2;
- }
- server {
- listen 80;
- server_name 192.168.100.17;
- location / {
- root /usr/share/nginx/html;
- index index.html index.htm;
- }
- location ~* \.(jsp|jspx|do) {
- proxy_pass http://tomcat_servers;
- }
- }
启动 nginx 和 tomcatAtomcatB 然后在浏览器中分别访问静态资源和动态资源
- http://192.168.100.17
- http://192.168.100.17/index.jsp
其中第二个访问的是动态资源, 页面结果如下:
发现这个欢迎页面缺失了很多内容其实这些缺失的内容都是定义在 index.jsp 中的静态资源, 例如某些图片之所以会缺失, 是因为客户端发送请求给 nginx 后, nginx 将请求转发给 tomcat,tomcat 翻译 index.jsp 为 java 源文件, 然后执行该 servlet 执行 servlet 时, 将所需响应数据都回应给 nginx, 包括 index.jsp 中定义的图片链接标签当客户端收到这一次的响应数据后, 还会继续去请求图片, 但是这是静态请求, nginx 会自己处理而不会转发给 tomcat, 但 nginx 本身不知道图片在何处 (tomcat 才知道) 因此对于图片部分, nginx 将返回 404 错误, 使得客户端显示的页面缺失了一部分
在生产环境下, 不需要担心这样的二次静态请求缺失问题, 因为会将图片等静态数据存放在某个位置, 并配置好 nginx 如何找到这些静态数据
4. Tomcat + httpd(mod_jk)
测试环境如下:
使用 mod_jk 模块和 tomcat 连接时, tomcat 的连接器一般都使用 ajp 协议类型
mod_jk 不是 apache httpd 的原生模块, 而是类似于第三方模块, 因此需要额外编译 mod_jk 模块到 httpd 中, 就像将 php 模块添加到 httpd 中一样
4.1 编译 mod_jk 模块
当前最新稳定版的 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
4.2 配置 httpd 与 tomcat 的 ajp 连接
此处暂先配置 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: 可以设定为 RT 或 B; 默认为 R, 即根据请求的个数进行调度(wrr);T 表示根据已经发送给 worker 的实际流量大小进行调度; B 表示根据实际负载情况进行调度(leastconn)
sticky_session: 将某请求调度至某 worker 后, 此地址后续所有请求都将直接调度至此 worker, 实现将用户 session 与某 worker 绑定默认为值为 true, 即启用此功能如果后端的各 worker 之间支持 session 复制, 则可设为 false
至此, 一个基于 mod_jk 模块与后端名为 TomcatA 的 worker 通信的配置已经完成, 重启 httpd 服务即可生效
测试: 在浏览器中输入
- http://192.168.100.17/
- http://192.168.100.17/index.jsp
- http://192.168.100.17/status/
如果都能获取页面, 则表示 apache 通过 mod_jk 和 tomcat 基于 ajp 协议类型的连接已经成功
4.3 通过 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.100.22
- worker.TomcatA.port=8009
- worker.TomcatA.lbfactor=5
- worker.TomcatB.type=ajp13
- worker.TomcatB.host=192.168.100.23
- 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">
为了演示效果, 在 TomcatA 部署一个应用程序 test
[root@xuexi tomcat]# mkdir -p /usr/local/tomcat/webapps/test/WEB-INF/{classes,lib}
添加 index.jsp, 内容如下:
- [root@xuexi tomcat]# cat /usr/local/tomcat/webapps/test/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>
在 TomcatB 同样也部署一个应用程序 test 如下:
- [root@xuexi tomcat]# mkdir -p /usr/local/tomcat/webapps/test/WEB-INF/{classes,lib}
- [root@xuexi tomcat]# cat /usr/local/tomcat/webapps/test/index.jsp
- <%@ page language="java" %>
- <html>
- <head><title>TomcatB</title></head>
- <body>
- <h1><font color="blue">TomcatB </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>
重启 httpdtomcatAtomcatB 对应的服务程序在浏览器中输入 192.168.100.17/test/index.jsp 测试负载均衡是否生效
测试时, 轮调两次 tomcatB 后轮调一次 tomcatA 而且可以发现每次轮询时 Session ID 每次都是变化的, 因为没有开启 sticky_session, 所以 session 没有进行绑定
要绑定会话, 将 worker.properties 中的 sticky_session 设置为 true 即可
5. Tomcat+httpd(mod_proxy)
测试环境如下:
当 httpd 端采用 mod_proxy 和 tomcat 连接时, 可以采用 ajp 或 http 协议进行连接
要使用 mod_proxy 与 Tomcat 连接, 需要 apache 已经装载 mod_proxymod_proxy_httpmod_proxy_ajp 和 proxy_balancer_module(实现 Tomcat 负载均衡时用到)等模块使用 rpm 包安装的 httpd 一般默认已经启用它们, 如果是编译 httpd, 则在编译选项中加上以下对应几项:
--enable - proxy--enable - proxy - http--enable - proxy - ajp--enable - proxy - balancer
如果是已经编译好的 Httpd, 则可以使用 apxs 工具, 向 httpd 中添加这几个新模块添加方法见: httpd 添加新模块
确保 proxy 相关的模块已经加载了
- [root@xuexi ~]# httpd -M | grep proxy
- Syntax OK
- proxy_module (shared)
- proxy_balancer_module (shared)
- proxy_ftp_module (shared)
- proxy_http_module (shared)
- proxy_ajp_module (shared)
- proxy_connect_module (shared)
5.1 配置 httpd 代理到 tomcat
基于 ajp 连接协议和 tomcat 连接时, 向 httpd 添加以下配置文件如果要基于 http 协议连接 tomcat, 将上面配置文件的 ajp 协议改为 http 协议, 并修改端口即可
- [root@xuexi ~]# cat /etc/httpd/conf.d/ajp.conf
- <Location /status>
- SetHandler balancer-manager
- Proxypass ! # 表示此 Location 的 URL 不进行反向代理
- Require ip 192.168.100
- </Location>
- ProxyVia Off
- ProxyRequests Off
- ProxyPreserveHost Off
- ProxyPassMatch "^/(.*\.jsp)$" ajp://192.168.100.22:8009/$1
- ProxyPassReverse "^/(.*\.jsp)$" ajp://192.168.100.22:8009/$1
- <Proxy *>
- Require all granted
- </Proxy>
重启 httpd 注意, 重启前将前面 mod_jk 实验的配置文件删除掉
关于如上 apache 配置的几个指令, 解释如下 httpd 反向代理的详细内容, 可参见: 详细分析 apache httpd 反向代理的用法
ProxyVia {On|Off|Full|Block}
: 用于控制在 http 首部是否使用 "Via:", 主要用于在多级代理中控制代理请求的流向默认为 Off, 即不启用此功能; On 表示每个请求和响应报文均添加 "Via:";Full 表示每个 "Via:" 行都会添加当前 apache 服务器的版本号信息; Block 表示每个代理请求报文中的 "Via:" 都会被移除
ProxyRequests {On|Off}
: 是否开启 apache 正向代理的功能; 如果为 apache 设置了 ProxyPass 即反向代理, 则必须将 ProxyRequests 设置为 Off
ProxyPreserveHost {On|Off}
: 如果启用此功能, 代理会将用户请求报文中的 "Host:" 行发送给后端的服务器, 而不再使用 ProxyPass 指定的服务器 IP 地址如果后端一个 IP 上可能会有多个虚拟主机, 则需要开启此项明确转发给哪台虚拟主机, 否则就无需打开此功能
ProxyPassReverse: 在反向代理环境中必须使用此指令避免重定向报文绕过 proxy 服务器, 属性设置为 ProxyPass 一样基本上就可以
ProxyPass[path] ! |[url[key = value key = value...]]
: 将后端服务器某 URL 与当前服务器的某虚拟路径关联起来作为提供服务的路径, path 为当前服务器上的某虚拟路径, url 为后端服务器上某 URL 路径使用此指令时必须将 ProxyRequests 的值设置为 Off 需要注意的是, 如果 path 以 "/" 结尾, 则对应的 url 也必须以 "/" 结尾, 反之亦然
ProxyPassMatch[regex] ! |url[key = value[key = value...]]
: 正则格式的 ProxyPass
5.2 通过 mod_proxy 负载均衡 tomcat
关于 httpd 反向代理的负载均衡配置方式, 参见详细分析 apache httpd 反向代理的用法
在 httpd.conf 中配置如下内容:
- <proxy balancer://TomcatLB>
- BalancerMember ajp://192.168.100.38:8009 loadfactor=5
- BalancerMember ajp://192.168.100.36:8009 loadfactor=10
- </proxy>
- ProxyVia Off
- ProxyRequests Off
- ProxyPreserveHost Off
- ProxyPassMatch "^/(.*\.jsp)$" balancer://TomcatLB/$1
- ProxyPassReverse "^/(.*\.jsp)$" balancer://TomcatLB/$1
- <Proxy *>
- Require all granted
- </Proxy>
- <Location /status>
- SetHandler balancer-manager
- Proxypass !
- Require ip 192.168.100
- </Location>
重启 httpd 并在浏览器中输入
192.168.100.17 / test / index.jsp
测试, 测试时会轮调两次 tomcatB 再轮调一次 tomcatA
如果要实现 session 粘滞(绑定), 则修改 httpd 配置文件如下:
- <proxy balancer://TomcatLB>
- BalancerMember ajp://192.168.100.22:8009 loadfactor=5 route=TomcatA
- BalancerMember ajp://192.168.100.23:8009 loadfactor=10 route=TomcatB
- ProxySet lbmethod=byrequets
- </proxy>
- ProxyVia Off
- ProxyRequests Off
- ProxyPreserveHost Off
- ProxyPassMatch "^/(.*\.jsp)$" balancer://TomcatLB/$1 stickysession=JSESSIONID
- ProxyPassReverse "^/(.*\.jsp)$" balancer://TomcatLB/$1 stickysession=JSESSIONID
- <Proxy *>
- Require all granted
- </Proxy>
- <Location /status>
- SetHandler balancer-manager
- Proxypass !
- Require ip 192.168.100
- </Location>
然后分别配置 tomcatA 和 tomcatB 的 engine 组件, 分别加上 jvmRoute="TomcatA" 和 jvmRoute="TomcatB" 属性
- <Engine name="Catalina" defaultHost="localhost" jvmRoute="TomcatA">
- <Engine name="Catalina" defaultHost="localhost" jvmRoute="TomcatB">
重启 httpd 和 tomcatAtomcatB, 然后测试结果, 再测试时同一客户端将总是得到同一个结果, 不会出现负载均衡
回到 Linux 系列文章大纲: http://www.cnblogs.com/f-ck-need-u/p/7048359.html
回到网站架构系列文章大纲: http://www.cnblogs.com/f-ck-need-u/p/7576137.html
回到数据库系列文章大纲: http://www.cnblogs.com/f-ck-need-u/p/7586194.html
来源: https://www.cnblogs.com/f-ck-need-u/p/8414043.html