本文共 5019 字,大约阅读时间需要 16 分钟。
Tomcat 集群与负载均衡 ( 专门术语简介 )
在单一的服务器上执行 WEB 应用程序有一些重大的问题,当网站成功建成并开始接受大量请求时,单一服务器终究无法满足需要处理的负荷量,所以就有点显得有点力不从心了。另外一个常见的问题是会产生单点故障,如果该服务器坏掉,那么网站就立刻无法运作了。不论是因为要有较佳的扩充性还是容错能力,我们都会想在一台以上的服务器计算机上执行 WEB 应用程序。所以,这时候我们就需要用到集群这一门技术了。
在进入集群系统架构探讨之前,先定义一些专门术语:
1. 集群 (Cluster) :是一组独立的计算机系统构成一个松耦合的多处理器系统,它们之间通过网络实现进程间的通信。应用程序可以通过网络共享内存进行消息传送,实现分布式计算机。
2. 负载均衡 (Load Balance) :先得从集群讲起,集群就是一组连在一起的计算机,从外部看它是一个系统,各节点可以是不同的操作系统或不同硬件构成的计算机。如一个提供 Web 服务的集群,对外界来看是一个大 Web 服务器。不过集群的节点也可以单独提供服务。
3. 特点:在现有网络结构之上,负载均衡提供了一种廉价有效的方法扩展服务器带宽和增加吞吐量,加强网络数据处理能力,提高网络的灵活性和可用性。集群系统 (Cluster) 主要解决下面几个问题:
高可靠性( HA ):利用集群管理软件,当主服务器故障时,备份服务器能够自动接管主服务器的工作,并及时切换过去,以实现对用户的不间断服务。
高性能计算( HP ):即充分利用集群中的每一台计算机的资源,实现复杂运算的并行处理,通常用于科学计算领域,比如基因分析,化学分析等。
负载平衡:即把负载压力根据某种算法合理分配到集群中的每一台计算机上,以减轻主服务器的压力,降低对主服务器的硬件和软件要求。
目前比较常用的负载均衡技术主要有:
1. 基于 DNS 的负载均衡
通过 DNS 服务中的随机名字解析来实现负载均衡,在 DNS 服务器中,可以为多个不同的地址配置同一个名字,而最终查询这个名字的客户机将在解析这个名字时得到其中一个地址。因此,对于同一个名字,不同的客户机会得到不同的地址,他们也就访问不同地址上的 Web 服务器,从而达到负载均衡的目的。
2. 反向代理负载均衡 (如 Apache+JK2+Tomcat 这种组合)
使用代理服务器可以将请求转发给内部的 Web 服务器,让代理服务器将请求均匀地转发给多台内部 Web 服务器之一上,从而达到负载均衡的目的。这种代理方式与普通的代理方式有所不同,标准代理方式是客户使用代理访问多个外部 Web 服务器,而这种代理方式是多个客户使用它访问内部 Web 服务器,因此也被称为反向代理模式。
3. 基于 NAT ( Network Address Translation )的负载均衡技术 (如 Linux Virtual Server ,简称 LVS )
网络地址转换为在内部地址和外部地址之间进行转换,以便具备内部地址的计算机能访问外部网络,而当外部网络中的计算机访问地址转换网关拥有的某一外部地址时,地址转换网关能将其转发到一个映射的内部地址上。因此如果地址转换网关能将每个连接均匀转换为不同的内部服务器地址,此后外部网络中的计算机就各自与自己转换得到的地址上服务器进行通信,从而达到负载分担的目的。
介绍完上面的集群技术之后,下面就基于 Tomcat 的集群架构方案进行说明:
上面是采用了 Apache httpd 作为 web 服务器的,即作为 Tomcat 的前端处理器,根据具体情况而定,有些情况下是不需要 Apache httpd 作为 web 服务器的,如系统展现没有静态页面那就不需要 Apache httpd ,那时可以直接使用 Tomcat 作为 web 服务器来使用。使用 Apache httpd 主要是它在处理静态页面方面的能力比 Tomcat 强多了。
1 、 用户的网页浏览器做完本地 DNS 和企业授权的 DNS 之的请求 / 响应后,这时候企业授权的 DNS (即 21cn BOSS DNS )会给用户本地的 DNS 服务器提供一个 NAT 请求分配器(即网关) IP 。
2 、 NAT 分配器,它会根据特定的分配算法,来决定要将连接交给哪一台内部 Apache httpd 来处理请求。大多数的 NAT 请求分配器提供了容错能力:根据侦测各种 WEB 服务器的失效状况,停止将请求分配给已经宕掉的服务器。并且有些分配器还可以监测到 WEB 服务器机器的负载情况,并将请求分配给负载最轻的服务器等等。 Linux Virtual Server 是一个基于 Linux 操作系统上执行的 VS-NAT 开源软件套件,而且它有丰富的功能和良好的说明文件。商业硬件解决方案 Foundry Networks 的 ServerIron 是目前业界公认最佳的请求分配器之一。
3 、 Apache httpd + Mod_JK2 在这里是作为负载均衡器,那为什么要做集群呢?如果集群系统要具备容错能力,以便在任何单一的硬件或软件组件失效时还能 100% 可用,那么集群系统必须没有单点故障之忧。所以,不能只架设一台有 mod_jk2 的 Apache httpd ,因为如果 httpd 或 mod_jk2 失效了,将不会再有请求被会送交到任何一个 Tomcat 实例。这种情况下, Apache httpd 就是瓶劲,特别在访问量大的网站。
4 、 Mod_JK2 负载均衡与故障复原,决定把 Apache httpd 当成 web 服务器,而且使用 mod_jk2 将请求传送给 Tomcat ,则可以使用 mod_jk2 的负载均衡与容错功能。在集群系统中,带有 mod_jk2 的 Apache httpd 可以做的事情包括:
A 、 将请求分配至一或多个 Tomcat 实例上
你可以在 mod_jk2 的 workers.properties 文件中,设定许多 Tomcat 实例,并赋于每个实例一个 lb_factor 值,以作为请求分配的加权因子。
B 、 侦测 Tomcat 实例是否失败
当 Tomcat 实例的连接器服务不再响应时, mod_jk2 会及时侦测到,并停止将请求送给它。其他的 Tomcat 实例则会接受失效实例的负载。
C 、 侦测 Tomcat 实例在失效后的何时恢复
因连接器服务失效,而停止将请求分配给 Tomcat 实例之后, mod_jk2 会周期性地检查是否已恢复使用性,并自动将其加入现行的 Tomcat 实例池中。
5 、 Tomcat 中的集群原理是通过组播的方式进行节点的查找并使用 TCP 连接进行会话的复制。这里提示一下就是,对每个请求的处理, Tomcat 都会进行会话复制,复制后的会话将会慢慢变得庞大。
6 、 Mod_jk2 同时支持会话亲和和会话复制。在 tomcat 5 中如何实现会话亲和和会话复制?把 server.xml 中的 <cluster/> 标签去掉就实现会话亲和,把 <cluster/> 标签加上就实现会话复制。
7 、 会话亲和:就是表示来自同会话的所有请求都由相同的 Tomcat 实例来处理,这种情况下,如果 Tomcat 实例或所执行的服务器机器失效,也会丧失 Servlet 的会话数据。即使在集群系统中执行更多的 Tomcat 实例,也永远不会复制会话数据。这样是提高集群性能的一种方案,但不具备有容错能力了。
8 、 使用会话复制,则当一个 Tomcat 实例宕掉时,由于至少还有另一个 Tomcat 实例保有一份会话状态数据,因而数据不会丧失。但性能会有所降低。 集群
传统独立服务器(非集群的)不提供任何失效无缝转移以及负载平衡能力。当服务器失败的时候,就无法获取整个网站的内容,除非服务器被重新唤起 ( 启动 ) 。由于服务器失效,任何存储在服务器内存中的 SESSION 都会丢失,用户必须重新登陆并且输入所有由于服务器失效丢失的数据。
不同的是,作为集群一部分的服务器则提供了可测性以及失效无缝转移能力。一个集群就是一组同步运行并且协同工作,能提供高可靠性,高稳定性以及高可测性的多服务器例程。服务端集群对客户端表现出来似乎就是一个单独的服务器例程。从客户端的视角来看,集群的客户端和单独的服务器没多大不同,但是他们通过提供实效无缝转移和 SESSION 复制做到了不间断服务以及 SESSION 数据持久性。 SESSION 复制
服务器集群通常操纵两种 SESSION : sticky sessions 和 replicated sessions 。 sticky sessions 就是存在 单机服务器 中的接受网络请求的 SESSION ,其他集群成员对该服务器的 SESSION 状态完全不清楚,如果存有 SESSION 的服务器失败的话,用户必须再次登陆网站,重新输入所有存储在 SESSION 中的数据。
另一种 SESSION 类型是,在一台服务器中 SESSION 状态被复制到集群中的其他 所有服务器 上 ,无论何时,只要 SESSION 被改变, SESSION 数据都要重新被复制。这就是 replicated session 。 sticky 和 replicated sessions 都有他们的优缺点, Sticky sessions 简单而又容易操作,因为我们不必复制任何 SESSION 数据到其他服务器上。这样就会减少系统消耗,提高性能。但是如果服务器失败,所有存储在该服务器内存中的 SESSION 数据也同样会消失。如果 SESSION 数据没有被复制到其他服务器,这些 SESSION 就完全丢失了。当我们在进行一个查询事务当中的时候,丢失所有已经输入的数据,就会导致很多问题。
为了支持 JSP HTTP session 状态的自动失效无缝转移, TOMCAT 服务器复制了在内存中的 SESSION 状态。这是通过复制存储在一台服务器上的 SESSION 数据到集群中其他成员上防止数据丢失以及允许失效无缝转移。 对象的状态管理
通过在服务器上的保存状态可以区分出 4 种对象:
● 无状态 :一个无状态对象在调用的时候不会在内存中保存任何状态,因为客户端和服务器端没必要保存任何有关对方的信息。在这种情况下,客户端会在每次请求服务器时都会发送数据给服务器。 SESSION 状态被在客户端和服务器端来回发送。这种方法不总是可行和理想的,特别是当传输的数据比较大或者一些安全信息我们不想保存在客户端的时候; ● 会话 :一个会话对象在一个 SESSION 中只被用于特定的某个客户端。在 SESSION 中,他可以为所有来自该客户端的请求服务,并且仅仅是这个客户端的请求。贯穿一个 SESSION ,两个请求间的状态信息必须保存。会话服务通常在内存中保存短暂的状态,当在服务器失败的时候可能会丢失。 SESSION 状态通常被保存在请求间的服务器的内存中。为了清空内存, SESSION 状态也可以被从内存中释放(就像在一个对象 CACHE )。在该对象中,性能和可量测性都有待提高,因为更新并不是被单独的写到磁盘上,并且服务器失败的时候数据也没办法抢救。
● 缓存 :缓存对象在内存中保存状态,并且使用这个去处理从多客户端来的请求。缓存服务的实现可以扩展到他们把缓存的是数据备份保存在后端存储器中(通常是一个关系数据库)。
● 独立的 :一个独立的对象在一个时间内只活跃在集群中的一台服务器上,处理来自多客户端的请求。他通常由那些私有的,持久的,在内存中缓寸的数据支持。他同样也在内存中保持短暂状态,在服务器失败的时候要重建或者丢失。当失败的时候,独立对象必须在同一个服务器上重起或者移植到另一台服务器上。 本文转自 weijie@java 51CTO博客,原文链接:http://blog.51cto.com/weijie/74936,如需转载请自行联系原作者