|
|
51CTO旗下网站
|
|
移动端

注意这几点,轻轻松松配置 Nginx + Tomcat 的集群和负载均衡

Tomcat 集群是当单台服务器达到性能瓶颈,通过横向扩展的方式提高整体系统性能的有效手段。Nginx 是一个高性能的 HTTP 和反向代理 web 服务器,可以通过简单的配置实现 Tomcat 集群的负载均衡。

作者:wskwbog来源:顿悟源码|2019-05-28 15:05

【大咖·来了 第7期】10月24日晚8点观看《智能导购对话机器人实践》

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 使用的是默认配置,添加和修改的核心配置如下:

  1. http { 
  2.   ... 
  3.   #gzip  on
  4.    
  5.   #设置负载均衡的服务器列表和权重 
  6.   upstream tomcat-ha { 
  7.       #ip_hash;  
  8.       server 172.31.1.41:8080 weight=1; 
  9.       server 172.31.1.42:8080 weight=1; 
  10.   } 
  11.    
  12.   server { 
  13.       listen       8000; 
  14.       server_name  localhost; 
  15.  
  16.       #charset koi8-r; 
  17.       #access_log  logs/host.access.log  main; 
  18.  
  19.       location / { 
  20.           root   html; 
  21.           index  index.html index.htm; 
  22.           #转发请求 
  23.           proxy_pass http://tomcat-ha$request_uri; 
  24.           proxy_set_header Host $http_host; 
  25.           proxy_set_header X-Real-IP $remote_addr; 
  26.           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
  27.           proxy_set_header X-Forwarded-Proto $scheme; 
  28.       } 
  29.       ... 
  30.   } 

3. Tomcat 集群配置

启用集群配置,在 元素中添加以下配置:

  1. <!-- channelSendOptions=6 同步复制 --> 
  2. <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="6"
  3.   <!-- 集群 Session 管理器 --> 
  4.   <Manager className="org.apache.catalina.ha.session.BackupManager" 
  5.              expireSessionsOnShutdown="false" 
  6.              notifyListenersOnReplication="true" 
  7.              mapSendOptions="6"/> 
  8.   <!-- 
  9.   <Manager className="org.apache.catalina.ha.session.DeltaManager" 
  10.            expireSessionsOnShutdown="false" 
  11.            notifyListenersOnReplication="true"/> 
  12.   --> 
  13.   <!-- 集群内部通信配置 --> 
  14.   <Channel className="org.apache.catalina.tribes.group.GroupChannel"
  15.     <Membership className="org.apache.catalina.tribes.membership.McastService" 
  16.                 address="228.0.0.4" 
  17.                 port="45564" 
  18.                 frequency="500" 
  19.                 dropTime="3000"/> 
  20.     <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" 
  21.               address="192.168.10.2" 
  22.               port="5000" 
  23.               selectorTimeout="100" 
  24.               maxThreads="6"/> 
  25.     <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"
  26.       <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/> 
  27.     </Sender> 
  28.     <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/> 
  29.     <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/> 
  30.     <Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/> 
  31.   </Channel> 
  32.   <!-- 此 vavle 拦截请求,并将 Session 信息发给内部节点 --> 
  33.   <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" 
  34.          filter=".*\.gif|.*\.js|.*\.jpeg|.*\.jpg|.*\.png|.*\.htm|.*\.html|.*\.css|.*\.txt"/> 
  35.   <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/> 
  36. </Cluster> 

简单描述下工作原理:

  • 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 中。

【编辑推荐】

  1. Tomcat 中的 Session 和 Cookie的爱恨情仇
  2. Tomcat 容器的安全认证和鉴权
  3. 超实用的Tomcat启动脚本实现
  4. 使用SSL配置Nginx反向代理的简单指南
  5. 深入Tomcat 架构及启动过程「含部署」
【责任编辑:武晓燕 TEL:(010)68476606】


点赞 0
分享:
大家都在看
猜你喜欢

订阅专栏+更多

16招轻松掌握PPT技巧

16招轻松掌握PPT技巧

GET职场加薪技能
共16章 | 晒书包

289人订阅学习

20个局域网建设改造案例

20个局域网建设改造案例

网络搭建技巧
共20章 | 捷哥CCIE

645人订阅学习

WOT2019全球人工智能技术峰会

WOT2019全球人工智能技术峰会

通用技术、应用领域、企业赋能三大章节,13大技术专场,60+国内外一线人工智能精英大咖站台,分享人工智能的平台工具、算法模型、语音视觉等技术主题,助力人工智能落地。
共50章 | WOT峰会

0人订阅学习

读 书 +更多

3D游戏开发大全(高级篇)

在我的第一本书——《3D游戏开发大全》中,我们曾经对3D游戏开发完成了一次犹如探索原始丛林般的旅程:首先,我们对3D游戏产业进行了初步了...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊

51CTO服务号

51CTO播客