`
cywhoyi
  • 浏览: 422032 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

JVM的集群下的共享

 
阅读更多
 Terrocotta - 基于JVM的Java应用集群解决方案
前言

越来越多的企业关键应用都必须采用集群技术,实现负载均衡(Load Balancing)、容错(Fault Tolerance)和灾难恢复(Failover)。以达到系统可用性(High Availability)和可伸缩性(Scalability)的要求。

关于J2EE集群技术的基本原理和常用实现方式,TheServerSide.com有一篇经典的文章:
http://www.theserverside.com/tt/articles/article.tss?l=J2EEClustering
CSDN上,陶建风先生在他的博客中也作了翻译:
http://blog.csdn.net/ESoftWind/archive/2006/10/19/1341089.aspx
这篇文章虽然发表于2005年,但它对集群技术的概念、原理和实现的基本描述至今依然适用。刚刚接触集群技术的朋友不妨阅读一下这篇文章,以便掌握集群技术的基本知识。

我写这篇文章是想介绍一个新的Java集群技术,Terracotta。它采用了与众不同的手段,解决了传统集群技术面临的一些关键问题。可以说为Java集群技术的实现吹来了一股新鲜的空气。

Terracotta(http://terracotta.org/)是一个开源的框架。他的创始人Ari Zilka原本是Walmat.com的首席架构师。他于2003年成立Terracotta公司,并且将产品开源。该产品在2006年左右趋于成熟,在很多财富500强企业获得成功应用。2009年Terracotta在该年度的JavaOne会议中获得Duke奖,并由Java创始人James Gosling先生亲自把该奖颁发给了Ari Zilka先生。

本文着重介绍Terracotta技术的基本原理,尤其是它与其它集群技术的根本区别之处。然后会用一个简单的例子说明Terracotta的基本使用方式。在以后的文章里,我会陆续详细介绍Terrocotta的不同应用场景和技巧。
基本原理
Terracotta最大的特点是它使用Java二进制代码增强的方式(binary code injection)截获集群节点对数据的修改和获取的请求,利用单独的Terracotta服务器调配数据的流向,以达到最高的网络效率。这两点可以说是与传统集群技术采用的序列化和网络广播机制在实现思路上的根本不同。另外从开发人员角度来说,Teraccotta隐藏在Java API之后,开发人员不需要学习新的API。只需要使用标准的JDK数据结构(java.util.*, java.concurent.*等)、内置Java协同、加锁机制(synchronized, object.wait, object.notify等)开发代码,在Terracotta平台之上就可以把单机基于POJO的应用扩展到多机集群上。因此开发人员的学习曲线很短。

Terracotta集群方案由两部分组成:Terracotta驱动器和Terracotta服务器:
  
graphic
其中驱动器部分(也称为Terracotta客户端)与应用程序执行在相同的JVM中。实际上应用程序是由Terracotta驱动器载入到内存中的。载入的同时,会对Java二进制代码进行增强。用户提供Terracotta配置文件指定本地程序中哪些数据需要在集群中共享。这样Terracotta就可以通过增强的代码截获对这些共享数据的读写请求,并且与Terracotta服务器协作,实现共享数据在集群中的一致性。对于Java代码中使用的“锁”也是利用相同的机制实现全局协同;
Terracotta服务器则首先记录所有节点对共享数据和锁的访问信息,为读取数据的节点提供最新数据,把修改的数据通知给正在使用中这些数据的节点等等。服务器除了协调节点间数据的获取和变化通知以外,还利用其本地内存和硬盘实现共享数据的缓存和持久化。

由于Terracotta驱动器和服务器都有缓存数据的能力,有时我们也称Terracotta驱动器为一级缓存L1,服务器为二级缓存L2。

Terracotta这一体系架构跟其它集群解决方案相比,有如下几点好处:
1、避免Java序列化,只把被修改的字段的数据传递给服务器和使用节点,大大减少CPU和内存消耗;
2、避免数据的广播,只把修改的数据通知给正在使用该数据的节点,大大降低了网络流量;
3、利用服务器实现网络扩展内存,使得有限内存的客户端节点可以访问远大于其内存容量的数据结构,而不必担心发生内存逸出的异常;
4、通过服务器实现共享数据持久化,通过服务器集群实现容错性等等
5、无须学习新的API,大大降低开发成本
企业版的Terracotta服务器还提供了数据分片(striping)的功能,使得集群吞吐量随着Terracotta服务器数量的增加达到线性增长。
Terracotta插件
在核心产品的基础上,Terracotta制定了通用扩展机制Terracotta Integration Module - TIM。Terracotta本身提供了大量的插件,应用于不同的集群应用场景,比如Tomcat session复制、Spring Security整合、与Hibernate的整合、异步数据库持久化等等。所有官方TIM可以在如下网站中找到:
http://forge.terracotta.org/releases/projects.html
用户也可以开发新的TIM,以适应自己的应用需求。

比如TIM-Session实现了Web应用服务器结点间session信息的共享。由于它利用了Terracotta集群间高效数据共享的机制实现session共享,整个集群的吞吐量可以随着服务器节点的增加而线性增长。与之相比,Tomcat自带的session集群实现,最多只能支持到4个节点左右。当节点数目进一步增加的时候,各节点的CPU使用率和网络负载会达到极限,反而降低整个集群的吞吐量。基于Terracotta的Tomcat集群可以达到几十个节点甚至更多。

我会在以后的文章中详细介绍重要的TIM插件和他们的应用场景。
基于Terracotta的Java集群
下面用一个简单的Java程序描述如何利用Teracotta事件Java集群。这个例子大概只比一般的Hello World稍微复杂一点。目的主要是介绍使用Terracotta的最简单流程。我会在以后的文章中详细介绍不同应用场景下Terracotta不用的使用方式和解决问题的方法。

首先看看Java代码。这是一个简单的多线程程序,启动后生成两个线程,给一个共享的计数器加一,然后打印出计数器的值:
1     package simpleparallel;
2     
3     public class Main implements Runnable{
4        
5         private Object lock = new Object();
6         private int count = 0;
7         private static Main inst = new Main();
8     
9         /**
10          * @param args
11          */
12         public static void main(String[] args) {
13             new Thread(inst).start();
14             new Thread(inst).start();
15         }
16     
17         public void run() {
18             //keep increasing count by one every few seconds
19     
20             while(true){
21                 synchronized(lock){
22                     count++;
23                     System.out.println(Thread.currentThread().getName() + " increased count to:"+count);
24                 }
25                 try{
26                     Thread.sleep((int)(5000*Math.random()));
27                 }
28                 catch(Exception e){
29                     e.printStackTrace();
30                 }
31             }
32            
33         }
34     
35     }

Details


注意代码中没有任何特殊的JDK以外的API。
单独执行这个程序,会看到如下现实的结果。

  graphic

现在我们要把这个代码放到集群上。目的是让多个JVM共同访问同一个计数器,并且能够互斥地对它进行累加,而在全集群范围内不会产生数据冲突。
具体的操作步骤如下:
1、下载并安装JDK 1.5或1.6,设置系统的JAVA_HOME环境变量
2、下载、安装Terracotta环境
     目前最新的Terracotta版本是3.0.1, 不过3.1马上就要发布了,所以我们使用3.1 stable1,可以从下列地址下载:
http://terracotta.org/web/display/orgsite/Download
或者直接从这个地址下载3.1 stable1 。
     用 java -jar terracotta-3.1.0-stable1-installer.jar 启动安装程序,把Terracotta安装到指定的目标目录。
假设安装目录是 $TC_HOME(Unix/Linux)或%TC_HOME%(Windows)
3、到刚才的Java代码的开发目录下,确认代码已经用javac编译好。假设编译目标文件在bin目录下。
4、创建一个文本文件tc-config.xml, 把下面的配置保存在该文件中:

36     <?xml version="1.0" encoding="UTF-8"?>
37     <con:tc-config xmlns:con="http://www.terracotta.org/config">
38       <servers>
39         <server host="%i" name="localhost">
40           <dso-port>9510</dso-port>
41           <jmx-port>9520</jmx-port>
42           <data>terracotta/server-data</data>
43           <logs>terracotta/server-logs</logs>
44           <statistics>terracotta/cluster-statistics</statistics>
45         </server>
46       </servers>
47       <clients>
48         <logs>terracotta/client-logs</logs>
49         <statistics>terracotta/client-statistics/%D</statistics>
50       </clients>
51       <application>
52         <dso>
53           <instrumented-classes>
54             <include>
55               <class-expression>simpleparallel.Main</class-expression>
56             </include>
57           </instrumented-classes>
58           <roots>
59             <root>
60               <field-name>simpleparallel.Main.inst</field-name>
61             </root>
62           </roots>
63           <locks>
64             <autolock>
65               <method-expression>void simpleparallel.Main.run()</method-expression>
66               <lock-level>write</lock-level>
67             </autolock>
68           </locks>
69         </dso>
70       </application>
71     </con:tc-config>

Details

5、启动Terracotta服务器:
$TC_HOME/bin/start-tc-server.sh 
or
%TC_HOME%\bin\start-tc-server.bat

6、打开两个或者更多的Terminal或DOS窗口,分别启动一个测试程序:
$TC_HOME/bin/dso-java.sh -cp . simpleparallel.Main
or
%TC_HOME%\bin\dso-java.bat -cp . simpleparallel.Main

下图是同时执行三个程序的屏幕截图:
graphic
  
可见计数器已经在集群中被3个Java程序实例所共享。每个程序有两个线程访问计数器。这样整个集群中实际上有6个线程在同时累加计数器。

从上面的启动顺序看,整个Java代码没有作任何改动。只是增加了一个tc-config.xml文件,并且用Terracotta的dso-java启动程序启动这个Java程序就可以了。
tc-config.xml文件是使用Terracotta时最重要的配置文件。

这里面最重要的几个配置为:
1、roots:用来制定集群中要共享的数据。
      <roots>
        <root>
          <field-name>simpleparallel.Main.inst</field-name>
        </root>
    </roots> 
我们的例子制定共享Main类的inst对象,它包含的count和lock对象也就随之被整个集群共享了。
2、locks:
用来制定对共享数据操作的时候采用的加锁机制。
    <locks>
        <autolock>
          <method-expression>void simpleparallel.Main.run()</method-expression>
          <lock-level>write</lock-level>
        </autolock>
  </locks>    
这个例子中给Main.run()方法定义了自动锁(autolock)。他告诉Teraccotta当这个方法对共享的数据加锁的时候(注意:Main.lock对象是共享的),使得这个锁在整个集群范围内生效。这样一来集群中任何一个线程锁住这个对象的时候,其它任何线程都要等这个锁解除后才能访问被保护的数据(Main.count)。这样计数器的访问也就在整个集群中得到了保护。
总结
Terracotta是唯一一个在JVM层实现Java集群的平台。开发团队可以在对已有的Java程序作最小修改的情况下,把系统移植到集群中。在开发新的Java代码时,也只需要按照正常的Java代码开发方式编写代码即可,无需学习任何新的API。
Terracotta通过配置文件指定集群中要共享的数据和对该数据进行访问的方法的加锁方式。这也保证了代码跟平台的松散耦合。

今天介绍的主要还是Terracotta的基本原理。实际开发的Java应用大部分都是基于Web的应用,并且有很多系统使用了Hibernate, Tomcat, Spring等工具和平台。在以后的文章中我会陆续介绍Terracotta是如何支持这些工具的。
分享到:
评论

相关推荐

    nginx-upstream-jvm-route nginx共享Session

    标题 "nginx-upstream-jvm-route nginx共享Session" 涉及到的是在使用Nginx作为反向代理服务器时,如何实现多个Java应用服务器(通常指的是JVM实例)之间的Session共享。这通常在构建高可用性和负载均衡的Web服务...

    Tomcat集群Session共享所有文件.zip

    为了解决这个问题,有多种策略可以实现Session的集群共享: 1. **粘性会话(Sticky Sessions)**:这是一种最简单的方法,通过负载均衡器将用户的请求始终定向到最初创建Session的服务器。这种方式虽然简单,但限制...

    tomcat7集群实现session共享

    当我们谈论“Tomcat7集群实现session共享”时,我们关注的是如何在多个Tomcat实例之间有效地同步用户会话信息,以便在集群环境中提供高可用性和负载均衡。 首先,理解session共享的重要性。在Web应用中,session是...

    spring4+redis3+nginx1实现tomcat集群session共享源码

    总结,本方案通过Spring Session结合Redis的持久化存储以及Nginx的负载均衡和粘滞会话策略,有效地解决了Tomcat集群环境下的Session共享问题,提高了应用的可用性和扩展性。对于需要处理高并发和大规模用户量的Web...

    2008Amazon四星半新书_The+Definitive+Guide+to+Terracotta_+Cluster+the+JVM+for+Spring,+Hibernate+and+P.rar

    这本书对于理解分布式系统、JVM集群以及企业级应用的可扩展性具有重要的指导价值。 Terracotta是一个开源的软件平台,它允许开发者将Java应用程序部署在分布式环境中,同时保持内存的一致性和状态同步。通过集群JVM...

    Weblogic12 集群配置手册

    2. 磁盘共享:确保集群中的服务器能够访问共享存储,以便在实例之间共享应用和数据。 3. 会话持久化:配置会话持久化策略,确保会话在服务器故障后能够恢复。 七、集群管理和维护 1. 健康检查:定期执行健康检查,...

    tomcat下验证集群是否成功app

    1. **配置服务器节点**:每台Tomcat服务器都需要配置为集群的一部分,这包括修改`server.xml`文件,添加`Cluster`、`Manager`和`Deployer`元素,以及设置共享的JVM间通信(JVMRoute,用于跟踪请求)。 2. **共享...

    windows jboss 集群2

    【标题】:Windows环境下JBoss集群配置详解 在IT行业中,服务器集群是一种常见的高可用性和负载均衡解决方案。本文将深入探讨如何在Windows操作系统上配置JBoss应用服务器的集群环境,帮助开发者和系统管理员更好地...

    windows下was8集群安装操作手册

    集群是指一组相互协作的服务器,它们可以共享工作负载并提供冗余,从而提高服务的可用性和性能。在WAS中,集群是一种管理单元,包含多个成员,每个成员都是一个独立的WAS实例。 3. **准备工作** 在开始安装前,...

    黑马程序员-tomcat集群部署文档资料

    在集群中,各个节点之间可以共享数据和服务,共同处理任务,提升整体性能。 【集群环境介绍】 集群环境通常由硬件、软件和服务三部分组成。硬件包括多台高性能服务器、高速网络设备以及存储设备。软件层面,集群...

    weblogic9.2集群部署方法

    1.1.2 集群概念:一个集群是由多个相互协作的服务器实例组成的,它们共享应用程序和资源,提供故障转移和负载均衡。 1.1.3 配置集群应用的必要条件:硬件资源充足,网络连接稳定,操作系统支持多实例运行,以及...

    nginx-upstream-jvm-route-0.1.tar.gz

    《Nginx、Upstream与JVM Route:构建高效集群Session复制方案》 在现代Web应用架构中,负载均衡和高可用性是不可或缺的组成部分。Nginx作为一款高性能的反向代理服务器,常被用于处理HTTP和HTTPS请求,通过Upstream...

    jboss集群技术介绍

    - **集群(Cluster)**:指一组协同工作的服务器,它们共享相同的负载并能够互相替代,以提高系统的可用性和性能。 - **节点(Node)**:集群中的单个服务器实例。 - **分区(Partition)**:集群中的逻辑分组,用于...

    tomcat集群部署.

    在Tomcat集群中,多台Tomcat服务器共享相同的Web应用,能够互相备份,实现负载均衡和故障转移。 2. **集群的优点**: - **负载均衡**:通过将请求分散到多个服务器上,防止单一服务器过载。 - **高可用性**:如果...

    weblogic集群配置方法-具体实施步骤

    - **集群的目的**:通过负载均衡、故障转移和资源共享来提高服务的稳定性和性能。 - **WebLogic Server实例**:每个运行WebLogic Server软件的独立进程称为一个实例,它们可以组成一个集群。 2. **集群配置前准备...

    一晚上搞定Tomcat集群

    2. **复制应用和共享session**:在集群环境中,所有Tomcat实例必须部署相同的应用程序,并且必须能够共享用户的session数据。这意味着你需要确保每个Tomcat实例的webapps目录下有相同的项目文件,特别是包含应用配置...

    The Definitive Guide to Terracotta 分布式JVM框架

    - **内存共享机制**:Terracotta的核心技术在于其独特的内存共享机制,能够在不同的JVM实例之间共享对象的状态,从而减少冗余数据的复制。 - **集群通信协议**:采用高效的通信协议来协调不同节点之间的数据交互,...

    Websphere6.1集群安装和配置最终.rar

    - **共享资源**:设置共享库、数据源、JMS队列和主题等,这些资源将在集群中的所有节点间共享。 - **负载均衡**:配置集群内的负载均衡策略,例如基于请求量、响应时间或服务器负载的分配方式。 - **故障转移**:...

    集群环境下log4j配置

    在集群环境中,管理和跟踪日志信息是一项挑战,特别是在多个服务器共享同一套程序的情况下。日志配置的正确设定对于确保每个服务器生成的日志独立且可区分至关重要。Log4j 是一个广泛使用的 Java 日志框架,它允许...

    weblogic8.1集群负载均衡

    2. **共享存储**:集群中的服务器实例需要访问共享存储,以便共享集群状态、JMS队列和文件系统资源。 3. **网络配置**:确保网络通信的稳定性和效率,可能需要配置多网络接口以支持内部和外部通信。 4. **健康检查...

Global site tag (gtag.js) - Google Analytics