Tomcat 集群是当单台服务器达到性能瓶颈, 通过横向扩展的方式提高整体系统性能的有效手段. Nginx 是一个高性能的 HTTP 和反向代理 web 服务器, 可以通过简单的配置实现 Tomcat 集群的负载均衡.
本文使用的 Tomcat 是 8.5.35 版本, Nginx 是 1.14.2 版本. 接下来看下配置的过程以及可能会遇到的问题, 首发于微信公众号「顿悟源码」.
1. 概述
对于 Web 应用来说, 集群最大的问题就是 Session 信息的共享, 一般有以下解决方法:
使用粘性会话, 比如, 使用 IP Hash 的负载均衡策略, 将当前用户的请求都集中到一台服务器上; 缺点是单点故障, 会话丢失
使用 Session 复制, 使用 Tomcat 自带的 Session 复制策略, 将会话信息同步到集群的各个节点; 缺点是消耗更多内存和带宽, 适用于小型集群
使用第三方缓存中间件缓存整个集群会话信息, 比如 Redis 缓存, 可由应用程序控制与 Session 的关联, 也可以适配 Tomcat
当然了, 也可以把会话信息存到共享文件系统或者数据库
在配置 Nginx 的过程中, 可能会遇到以下问题:
配置 upstream 名称时不能使用下划线, 比如 tomcat_ha, 否则 Tomcat 会抛出 The character [_] is never valid in a domain name 的异常
在 Windows 上杀掉所有的 nginx.exe 进程, taskkill /fi "imagename eq nginx.exe" /f
在 Windows 上有个 pid 为 4 的系统进程会占用 80 端口, 所以这里将 nginx 改为了 8000
在配置 Tomcat 集群的过程中, 需要注意的问题:
确保 Web.xml 配置了 元素
确保 Context 的 Manager 别被替换成了标准会话管理器
Receiver.address 不要配置成 auto, 因为默认可能会绑定 127.0.0.1;Receiver.port 可改也可不改, Tomcat 会自行检测 4000-4100 范围内的可用端口, 自动处理冲突
如果在不同服务器上, 需要关闭防火墙或开端口, 还有时间同步
2. Nginx 核心配置
Nginx 使用的是默认配置, 添加和修改的核心配置如下:
- http {
- ...
- #gzip on;
- #设置负载均衡的服务器列表和权重
- upstream tomcat-ha {
- #ip_hash;
- server 172.31.1.41:8080 weight=1;
- server 172.31.1.42:8080 weight=1;
- }
- server {
- listen 8000;
- server_name localhost;
- #charset koi8-r;
- #access_log logs/host.access.log main;
- location / {
- root html;
- index index.HTML index.htm;
- #转发请求
- proxy_pass http://tomcat-ha$request_uri;
- proxy_set_header Host $http_host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
- }
- ...
- }
- }
3. Tomcat 集群配置
启用集群配置, 在 元素中添加以下配置:
- expireSessionsOnShutdown="false"
- notifyListenersOnReplication="true"
- mapSendOptions="6"/>
- expireSessionsOnShutdown="false"
- notifyListenersOnReplication="true"/>
- -->
- address="228.0.0.4"
- port="45564"
- frequency="500"
- dropTime="3000"/>
- address="192.168.10.2"
- port="5000"
- selectorTimeout="100"
- maxThreads="6"/>
- filter=".*\.gif|.*\.js|.*\.jpeg|.*\.jpg|.*\.png|.*\.htm|.*\.html|.*\.CSS|.*\.txt"/>
简单描述下工作原理:
nginx 将请求转发给 Tomcat1, 请求登录认证, 创建会话, 生成 Cookie, 在响应返回之前, 将 Session 信息复制到 Tomcat2
再次请求时, nginx 将带着会话 Cookie 的请求转发给了 Tomcat2,Tomcat2 发现内部 Session 池中有关联的已认证成功的 Session 对象, 不再认证返回请求资源
4. 验证负载均衡和 Session 复制
4.1 测试环境
使用两台 PC 部署 Tomcat, 对应关系是: 172.31.1.41-Tomcat1,172.31.1.42-Tomcat2
部署基于使用 Tomcat 自带的 SessionExample 程序, 编写了一个 tomcat-benchmark 的 Web 应用
结合 Tomcat 自带的 Manager 应用, 查看已部署应用内部 Session 池
4.2 负载均衡
修改 tomcat-benchmark 部署描述符文件中的 context-param 为 "I'm Tomcat 1/2" 用于区分两个 Tomcat, 启动 Nginx 和 Tomcat, 在浏览器访问 172.31.1.42:8000 可以看到请求在两个服务器间切换:
4.3 Session 复制
为了方便理解, 这里先把 Nginx 的负载均衡策略设置成 ip_hash:
假设 Nginx 始终将请求定位到 Tomcat1 上, 然后在 Tomcat1 上创建会话, 往会话中添加一些属性
关闭 Tomcat1 模拟故障, 此时 Nginx 会带着之前的会话 Cookie 将请求转发到 Tomcat2, 上
查看 Tomcat2 上是否存在与 Cookie(JSESSIONID) 关联的 Session 信息, 若有表示复制成功
整个过程如下:
正好与上述描述的相反, 可以看到 Session 信息从 Tomcat2 复制到了 Tomcat1 中.
来源: http://server.51cto.com/sOS-597102.htm