热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Apache+Tomcat集群+负载均衡

PartI:取经处: http:www.ramkitech.com201210tomcat-clustering

Part I:

取经处: http://www.ramkitech.com/2012/10/tomcat-clustering-series-simple-load.html

     http://blog.csdn.net/bluishglc/article/details/6867358

这部分先弄个简单的Load Balance的例子。

对Apache Server和Tomcat二者之间的关系有一定了解后,应该可以理解下面盗取的结构图:

Apache + Tomcat集群 + 负载均衡

在实际生产环境中,不会采取单个Tomcat实例的架构,因为没有任何灾备机制。一旦发生自热灾害,硬件损坏或者内存泄漏等严重错误,都会导致所谓的服务器宕机。

为了避免这种情况的发生,必定采用灾备机制。典型的做法就是在多台server上部署同一个Application,然后各个server之间相互为backup。

但这样,随之而来的问题就是如何分布用户请求。不可能告诉用户所有的Tomcat server IP,然后一会访问这个,过一会又访问另外一个,太不人性化了!

  这就引出了负载均衡(Load Balance)这个概念。所有用户请求都由Apache Server接收,之后根据内部逻辑分发请求给各个Tomcat。

简单的Load Balance:

环境:CentOS7,Tomcat8.5.4,Apache httpd-2.4.23,tomcat-connectors-1.2.41

1. 安装Apache Server(略过)

2. 钱不够,只有一台笔记本,遂安装Tomcat并配置多个实例来模拟多个tomcat server(可以参照之前的blog进行配置)

  假设3个tomcat实例命名为tomcat1,tomcat2,tomcat3

3. 安装并编译mod_jk.so(略过),用于之后Apache Server同Tomcat通信。

4. 以上准备工作完成后,下面就是Load Balance的配置喽。

  1. 通过mod_jk moudle建立Apache Server同Tomcat的通信

    1. 在${ApacheServerPath}/conf下创建workers.properties,内容如下:

worker.list=loadbalancer,stat
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=tomcat1,tomcat2,tomcat3
worker.tomcat1.type=ajp13
worker.tomcat1.port=8009
worker.tomcat1.host=localhost
worker.tomcat2.type=ajp13
worker.tomcat2.port=8019
worker.tomcat2.host=localhost
worker.tomcat3.type=ajp13
worker.tomcat3.port=8029
worker.tomcat3.host=localhost
worker.stat.type=status

    2. 在${ApacheServerPath}/conf/httpd.conf中添加如下内容:

LoadModule jk_module modules/mod_jk.so
JkWorkersFile conf/workers.properties
JkLogFile logs/mod_jk.log
JkLogLevel emerg
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
JkRequestLogFormat "%w %V %T"
JkMount /status stat
JkMount /* loadbalancer

5. 启动Apache Server,各个tomcat实例进行负载均衡测试。

  测试之前先在各个ROOT下创建index.html文件,用来区分哪个tomcat server被调用。

  1. 请求localhost,看整个服务是否可用;

  2. 请求localhost/status,看Load Balance情况。

 

Part II:

看到一篇稍好的blog,算是补充吧。http://freeloda.blog.51cto.com/2033581/1301888/

接Part I,虽然实现了简单的负载均衡,但是很明显存在问题。很多blog都拿购物车举例,也很通俗易懂:Part I实现的负载均衡基本会将每次的请求均匀转发到tomcat server上。当我们在购物车中添加了一项,之后再刷新页面发送新的请求,这时的Apache Server将会分发该请求到新的tomcat server,再一次创建新的session,导致购物车之前的添加项全部丢失,严重影响用户体验。

为解决这个问题,可以通过Sticky Session(粘性会话),实际上就是让Apache Server能够识别正确的Tomcat Server。

从Session的简单原理入手,当用户第一次请求时,Apache Server转发到Tomcat Server,相应创建session(位于tomcat server的内存中)。一个Session可以想象成类似Map的容器,可以CRUD各种属性。对应这个session,有一个Session ID(在Tomcat中,又称为jsessionid)。该Session ID将附到HTTP Response中返回客户端,存储于浏览器中。当用户再次发送类似的请求时,会将Session ID封装到HTTP Request中,经Apache Server转发到Tomcat Server。

所以,对Session ID改进,达到Sticky Session的目的。

由于Session ID是Tomcat Server生成的,所以理所应当修改各个Tomcat的配置文件。

1. 修改每个tomcat实例的server.xml – 在Engine标签中添加jvmRoute属性(和workers.properties中的balance_workers各项相对应)

Apache + Tomcat集群 + 负载均衡

OK!

2. 测试,启动Apache Server和Tomcat。

在浏览器发出的HTTP Request中,会发现

COOKIE:JSESSIOnID=40025608F7B50E42DFA2785329079227.tomcat1

实现Sticky Session。

 

Part III:

实现Sticky Session还不足以解决某个Tomcat宕掉的影响。假设某个Tomcat宕掉,那相应的Session全部失效,严重影响用户体验!

这就又引出Session Replication(复制会话)的概念。也就是相同的Session在其他Server中也存在,当Server宕掉,另一台可以立即被使用。

实现会话复制的方案有不少:

1. 建立Session服务器,所有Session全部存储于该服务器之上。当某个Tomcat Server宕掉后,其他server可以从该Session服务器中复制一份过来。缺点是一旦Session服务器宕掉,所有Session均失效,代价更大。

2. Tomcat集群方案

  1. 采用多播的方式在Tomcat Server之间通信来复制Session,一个server的session在其他所有server均存在。缺点是如果参与集群的server数量过多,必然会导致单个server的负载过重。所以不适合大集群环境。

  2. 采用Backup机制,比如两台Tomcat之间通信以保证各自Session在对方有备份。

 

先来尝试多播方式的Tomcat集群:)

一共3个步骤:

  1. enable多播路由;2. 添加Cluster标签到conf/server.xml中;3. 给app添加

这里面的多播是网络通信里的概念,正在不断了解过程中。。。区别于单播与广播,和字面意思相一致。对于Tomcat集群来说,各个之间必然进行通信,成为一组,多播是首选吧。

既然是会话复制,就应该涉及到session的管理问题。在Tomcat集群中,SessionManager负责session的管理,分以下4种:


  • Standard Manager

  • Persistent Manager

  • Delta Manager

  • Backup Manager

  Standard Manager

  这个是tomcat默认使用的session管理。但针对stand-alone(单机)tomcat,不能用于tomcat集群环境。

  Persistent Manager

  会将session信息定期存储于文件/数据库中,可以配置以何种方式存储。但由于定期存储和更新,可能导致session更新不够及时。

  Delta Manager

  Tomcat集群默认使用的session管理。每当session发生变化,比如setAttribute(), removeAttribute(),都会及时在其他集群节点上更新。这也就很容易造成集群中的tomcat负载过重,所以不适合大规模的集群环境。

  Backup Manager

  这个可以看作是Persistent Manager和Delta Manager的折中。两套Tomcat server互为Backup。

 

————–NND,先吐槽下,多播方式的Tomcat集群愣是前前后后耗费了2天的时间才搞定!咱国人的博客水准真是亟待提高,还是参考了老外的博客最终搞定。。。

环境:根据Part II已经实现Sticky Session,但要说明下我的CentOS7是Win7上的虚拟机。

下面记录我在build多播方式的Tomcat集群过程中的每步以及遇到的问题:

1. 按照官方文档以及该blog,copy其中Cluster标签的默认配置到各个tomcat实例中的server.xml文件中(位于Enginee标签下),并为各个tomcat实例设置不同的Receiver端口。

  这里需要注意,tomcat-8.5.4关于Cluster的默认配置里已经没有,而且MessageDispatch15Interceptor“/>已经变成MessageDispatchInterceptor“/>

2. route add -net 224.0.0.0 netmask 240.0.0.0 dev your_ethernet接口,添加your_ethernet接口到路由表中。

3. 在各个tomcat实例的app中的web.xml中添加标签

OK,启动httpd和3个tomcat实例(都在CentOS虚拟机上)。

按照该blog的测试方法,查看每个tomcat实例的manager界面,看是否session之间共享。结果不是。。。

在仔细检查各个配置文件并确定没问题后,开始天马行空的想,漫无目的的搜索,但大部分的信息都是讲怎么一步步配置还有零散的一些问题解决方案。尝试了几个后(比如给Membership标签添加bind属性,绑定本地IP;修改Receiver的address属性值为本地IP)都没解决,心想解决问题真心不能靠运气啊!

但是从哪下手呢?  –  日志

相比较于Windows,在Linux下启tomcat不会有滚动日志显示,不能实时知道tomcat的状态。

总结一下我所遇到的问题:

  1. java.io.IOException: Network is unreachable

    Unable to join multicast group, make sure your system has multicasting enabled

  很明显,提示多播功能可能没有enable。但是我的确做了这步的,而且通过route -etcpdump -ni your_ethernet接口 host 228.0.0.4也证实了(好blog)。最后有点儿醍醐灌顶的认为应该是防火墙的问题,就把CentOS自带的firewall.service给remove掉了,也防止对Receiver的端口的影响。

  2. SimpleTcpCluster.startInternal Unable to start cluster

    ChannelException: java.net.SocketException: No such device; No faulty members identified.

  这个提示让人无从下手,但根据这篇blog所说,应该是虚拟机的网络设置不当造成的。我最后选择了桥接模式,记得重启后才生效。

  3. skipping state transfer. No members active in cluster group

  这个是耗费我时间最多的一项。仅仅提示你No members active而没有说明可能的原因!我是各种搜索各种尝试,整的自己晕晕乎乎的,各种郁闷(根上还是网络通信/编程这块不懂造成的)。

  在解决这个问题之前,我用公司laptop的Win7环境搭了差不多相同的tomcat集群+httpd。之后顺利实现loadbalance+tomcat集群。在查看log的过程中,发现第一个启来的tomcat会有skipping state transfer. No members active in cluster group的日志,当时窃喜!说不定我CentOS上的那套集群实际上已经成功了呢?!可惜仅限于美好的想法。不过Win7下的log倒是让我知道了什么样的情况表示tomcat集群成功built起来了:”Replication member added:org.apache.catalina.tribes.membership.MemberImpl[tcp:”。

  误打误撞搜到这么一篇***,大概意思是multicast已经enable,但是tomcat就是无法集群。里面提到了IPv4和IPv6,一脸萌比。。。不过下面的回答倒是让我有了些希望。Tomcat8.5.4默认绑定IPv6,当发现server不工作时,应改绑定IPv4。

  在httpd和3个tomcat实例都启来后,我尝试请求localhost,得到503页面,之后查看mod_jk.log,发现loadbalance没有问题。再尝试http直接访问tomcat,没有问题。所以断定tomcat接收分发的请求出现问题。由于接收请求是通过ajp13协议进行,很可能IPv4和IPv6捣鬼了。

  参考blog,将tomcat运行环境与IPv4绑定。

到此,多播方式的Tomcat集群 + 负载均衡 终于搞定!

PS: 能花半天时间做记录,我也是醉醉的了,估计仅此一次吧:)

 


推荐阅读
  • Skywalking系列博客1安装单机版 Skywalking的快速安装方法
    本文介绍了如何快速安装单机版的Skywalking,包括下载、环境需求和端口检查等步骤。同时提供了百度盘下载地址和查询端口是否被占用的命令。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • 本文介绍了在Linux下安装和配置Kafka的方法,包括安装JDK、下载和解压Kafka、配置Kafka的参数,以及配置Kafka的日志目录、服务器IP和日志存放路径等。同时还提供了单机配置部署的方法和zookeeper地址和端口的配置。通过实操成功的案例,帮助读者快速完成Kafka的安装和配置。 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
  • 本文介绍了Java后台Jsonp处理方法及其应用场景。首先解释了Jsonp是一个非官方的协议,它允许在服务器端通过Script tags返回至客户端,并通过javascript callback的形式实现跨域访问。然后介绍了JSON系统开发方法,它是一种面向数据结构的分析和设计方法,以活动为中心,将一连串的活动顺序组合成一个完整的工作进程。接着给出了一个客户端示例代码,使用了jQuery的ajax方法请求一个Jsonp数据。 ... [详细]
  • 目录浏览漏洞与目录遍历漏洞的危害及修复方法
    本文讨论了目录浏览漏洞与目录遍历漏洞的危害,包括网站结构暴露、隐秘文件访问等。同时介绍了检测方法,如使用漏洞扫描器和搜索关键词。最后提供了针对常见中间件的修复方式,包括关闭目录浏览功能。对于保护网站安全具有一定的参考价值。 ... [详细]
  • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 延迟注入工具(python)的SQL脚本
    本文介绍了一个延迟注入工具(python)的SQL脚本,包括使用urllib2、time、socket、threading、requests等模块实现延迟注入的方法。该工具可以通过构造特定的URL来进行注入测试,并通过延迟时间来判断注入是否成功。 ... [详细]
author-avatar
mylvfamily
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有