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 配置了 <distributable/> 元素
  • 确保 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;
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 集群配置

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

<!-- channelSendOptions=6 同步复制 -->
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="6">
<!-- 集群 Session 管理器 -->
<Manager className="org.apache.catalina.ha.session.BackupManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"
mapSendOptions="6"/>
<!--
<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="192.168.10.2"
port="5000"
selectorTimeout="100"
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"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/>
</Channel>
<!-- 此 vavle 拦截请求,并将 Session 信息发给内部节点 -->
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=".*\.gif|.*\.js|.*\.jpeg|.*\.jpg|.*\.png|.*\.htm|.*\.html|.*\.css|.*\.txt"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>

简单描述下工作原理:

  1. nginx 将请求转发给 Tomcat1,请求登录认证,创建会话,生成 Cookie,在响应返回之前,将 Session 信息复制到 Tomcat2
  2. 再次请求时,nginx 将带着会话 Cookie 的请求转发给了 Tomcat2,Tomcat2 发现内部 Session 池中有关联的已认证成功的 Session 对象,不再认证返回请求资源

4. 验证负载均衡和 Session 复制

4.1 测试环境

  1. 使用两台 PC 部署 Tomcat,对应关系是:172.31.1.41-Tomcat1,172.31.1.42-Tomcat2
  2. 部署基于使用 Tomcat 自带的 SessionExample 程序,编写了一个 tomcat-benchmark 的 web 应用
  3. 结合 Tomcat 自带的 Manager 应用,查看已部署应用内部 Session 池

4.2 负载均衡

修改 tomcat-benchmark 部署描述符文件中的 context-param 为 "I'm Tomcat 1/2" 用于区分两个 Tomcat,启动 Nginx 和 Tomcat,在浏览器访问 172.31.1.42:8080 可以看到请求在两个服务器间切换:

4.3 Session 复制

为了方便理解,这里先把 Nginx 的负载均衡策略设置成 ip_hash:

  1. 假设 Nginx 始终将请求定位到 Tomcat1 上,然后在 Tomcat1 上创建会话,往会话中添加一些属性
  2. 关闭 Tomcat1 模拟故障,此时 Nginx 会带着之前的会话 Cookie 将请求转发到 Tomcat2,上
  3. 查看 Tomcat2 上是否存在与 Cookie(JSESSIONID) 关联的 Session 信息,若有表示复制成功

整个过程如下:

动图正好与上述描述的相反,可以看到 Session 信息从 Tomcat2 复制到了 Tomcat1 中。

5. 小结

搜索微信号「顿悟源码」,回复「Tomcat」后,可获取本文测试使用的工程以及 Nginx 和 Tomcat 的配置文件。

注意这几点,轻轻松松配置 Nginx + Tomcat 的集群和负载均衡的更多相关文章

  1. 在Linux上使用Nginx为Solr集群做负载均衡

    在Linux上使用Nginx为Solr集群做负载均衡 在Linux上搭建solr集群时需要用到负载均衡,但测试环境下没有F5 Big-IP负载均衡交换机可以用,于是先后试了weblogic的proxy ...

  2. 结合Apache和Tomcat实现集群和负载均衡 JK 方式 2 (转)

    本文Apache+Tomcat集群配置       基于最新的Apache和Tomcat,具体是2011年4月20日最新的Tomcat和Apache集群和负载均衡配置. 准备环境 Apache Apa ...

  3. 结合Apache和Tomcat实现集群和负载均衡 JK 方式

    本文基本参考自 轻松实现Apache,Tomcat集群和负载均衡,经由实操经历记录而成,碰到些出入,以及个别地方依据个人的习惯,所以在一定程度上未能保持原文的完整性,还望原著者海涵. 因原文中有较多的 ...

  4. 结合Apache和Tomcat实现集群和负载均衡

    http://fableking.iteye.com/blog/360870 TomcatApacheJSP应用服务器Web  本文基本参考自 轻松实现Apache,Tomcat集群和负载均衡,经由实 ...

  5. 用apache和tomcat搭建集群,实现负载均衡

    型的企业应用每天都需要承受巨大的访问量,在着巨大访问量的背后有数台服务器支撑着,如果一台服务器崩溃了,那么其他服务器可以使企业应用继续运行,用户对服务器的运作是透明化的,如何实现这种透明化呢?由如下问 ...

  6. Tomcat服务器集群与负载均衡实现

    一.前言 在单一的服务器上执行WEB应用程序有一些重大的问题,当网站成功建成并开始接受大量请求时,单一服务器终究无法满足需要处理的负荷量,所以就有点显得有 点力不从心了.另外一个常见的问题是会产生单点 ...

  7. nginx与tomcat搭建集群,负载均衡

    --------------------------------------------------- 搭建环境(在桌面上即可完成测试) 先准备2个tomcat服务器 解压tomcat压缩包 得到 把 ...

  8. 用Nginx搭建IIS集群实现负载均衡

    长话短说,我们用Nginx来搭建一个简单的集群,实现Web应用的负载均衡,架构图如下: 两台Web服务器,一台静态资源服务器,因为是演示,我们以网站形式部署在本机IIS中 一台Nginx代理服务器,安 ...

  9. 实战Apache+Tomcat集群和负载均衡

    实战Apache+Tomcat集群和负载均衡 目录 1.    什么是J2EE集群... 3 1.1.     序言... 3 1.2.     基本术语... 3 伸缩性(Scalability): ...

随机推荐

  1. POJ 3370 Halloween treats(抽屉原理)

    Halloween treats Every year there is the same problem at Halloween: Each neighbour is only willing t ...

  2. datagrid的formatter

    1.formatter函数 formatter:function(value,rowData,rowIndex){ return 'xxx'; } 注意: (1)formatter一定要有返回,且返回 ...

  3. windows phone UI吐槽---跑偏了就再也跑不回来了

    首先wp的ui灵感来自瑞士的平面设计:      先上两张图,嗯,确实不错,简洁明了,强调的是信息本身,而不是冗余的界面元素,传达准确. 在现实生活中这种突出信息的设计语言也不时见到:    可以总结 ...

  4. IOS开发学习笔记030-xib实现淘宝界面

    使用xib文件实现界面,然后通过模型更新数据. 1.使得控制器继承自UITableViewController 2.创建xib文件,实现界面如下:一个UIImageView,两个lable 3.新建一 ...

  5. flask url_for()和redirect的区别

    一. 两者用来重定向的时候,被操作的对象不同. redirect直接是url,就是app.route的路径参数. url_for()是对函数进行操作. from flask import Flask, ...

  6. monolog使用

    安装composer curl -sS https://getcomposer.org/installer | phpmv composer.phar /usr/local/bin/composer ...

  7. REDIS基础笔记

    Redis基础笔记 资源链接 简介 简介 安装 五种数据类型及相应命令 1. 字符串类型 2. 散列类型 3. 列表类型 4. 集合类型 5. 有序集合 其他 事务 SORT 生存时间 任务队列 发布 ...

  8. JAVA 程序监控基础简述

    最近在项目中自感程序木有问题,也没有什么错误日志出来.但就是有人反映服务慢,有时连不上的情况.为了解决这么妖的问题只能去详细的看看运行中的程序到底出了什么情况,这时如果有个比较好的监控工具可以监控运行 ...

  9. linux下编译lua库

    编辑MakeFile INSTALL_TOP= /usr/local修改为目标install位置 执行 make linux make install 如果提示依赖libreadline  可以直接a ...

  10. 用canvas绘制android机器人

    直接上代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...