Terracotta和SmartFoxServer 2X集群的配置(详细)

转自:http://www.ijavaboy.com

一、集群介绍 
在本文中,我们会深入研究如何构建高可用性、无单点故障(no single point of failure)、高横向扩展性和快速故障恢复的SmartFoxServer集群。 
1、什么是集群 
概括的讲,服务器集群是为了提高一个或多个服务的可用性和性能,而协同工作的一个计算机组(a group of computers)。集群中的每个计算机称为一个“节点”(node),根据集群的架构不同,每个节点在集群中可以有不同的角色,起不同的作用。比如可以有通用服务器节点、网关节点、缓存节点、备份节点等。 
从客户端的角度看,集群常常被视为一个单独的计算机/实体(computer / entity)。 
2、研究目标 
为了构建基于SmartFoxServer的在线多用户游戏服务的一个原型,使其随着应用的流量和知名度的提升仍能提供高可用性、快速故障恢复和高横向扩展性。 
在下面的几章,我们将检验这个服务的架构,使用的技术并分析在本研究中服务器端使用的代码。

二、Terracotta配置

1、Terracotta服务器组的配置 
Terracotta服务器组,主要是为了协调每一个Terracotta客户端(这里指SFS2X)之间的数据通信和同步。为了避免Terracotta服务器成为整个集群中的脆弱和单点故障的点。我们使用Terracotta服务器组的形势。就是使用两台Terracotta服务器,运行在主从模式下。这样当主Terracotta服务器出现故障的时候,从Terracotta服务器可以接着主Terracotta服务器而运行。

整个配置如下tc-config.xml:

<?xml version="1.0" encoding="UTF-8"?>

<!--

All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved.

-->

<tc:tc-config xmlns:tc="http://www.terracotta.org/config"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.terracotta.org/schema/terracotta-6.xsd">

  <!-- Tell DSO where the Terracotta server can be found;
       See
       - Terracotta Configuration Guide and Reference
       - About Terracotta Configuration Files
       for additional information. -->

  <tc-properties>
  <property name="12.l1reconnect.enabled" value="true" />
  <property name="12.l1reconnect.timeout.millis" value="5000" />
  </tc-properties>
  <servers>
    <server host="192.168.168.88" name="server1">
      <dso-port>9510</dso-port>
      <jmx-port>9520</jmx-port>
      <data>%(user.home)/terracotta/server1/server-data</data>
      <logs>%(user.home)/terracotta/server1/server-logs</logs>
      <statistics>%(user.home)/terracotta/server1/server-statistics</statistics>
    </server>

    <server host="192.168.168.88" name="server2">
      <dso-port>9511</dso-port>
      <jmx-port>9522</jmx-port>
      <data>%(user.home)/terracotta/server2/server-data</data>
      <logs>%(user.home)/terracotta/server2/server-logs</logs>
      <statistics>%(user.home)/terracotta/server2/server-statistics</statistics>
    </server>
  </servers>

  <clients>
  <logs>%(user.home)/terracotta/client-logs</logs>
  </clients>

</tc:tc-config>

将该配置文件放在启动start-tc-server.bat或者start-tc-server.sh的目录下,由于使用了多台Server,启动的时候,需要加上Server的名称

上例中启动server1的时候,使用: 
cmd> C:\Program Files\Terracotta\terracotta-ee-3.6.1\bin>start-tc-server.bat -n serve 
r1

启动server2的时候,将server1改成server2即可

2、Terracotta客户端的配置—即Terracotta和SmartForServer 2X的整合

为了让Terracotta可以识别SmartFoxServer 2X,或者说,让SFS2X加入到Terracotta集群中去,我们需要修改SFS2X的启动脚本。

SFS2X原来的启动脚本如下:

@java -cp “./;lib/*;lib/Jetty/*;extensions/__lib__/*” -Dfile.encoding=UTF-8 com.smartfoxserver.v2.Main $1 $2 $3

修改后的启动脚本如下:

@java -Xbootclasspath/p:”D:/Terracotta/terracotta-ee-3.6.1/lib/dso-boot/dso-boot-hotspot_win32_160_22.jar” -Dtc.install-root=D:/Terracotta/terracotta-ee-3.6.1 -Dtc.config=tc-cluster.xml -cp “./;lib/*;lib/Jetty/*;extensions/__lib__/*” -Dfile.encoding=GBK com.smartfoxserver.v2.Main 1% %2 %3

加入了红色的部分让Terracotta识别SFS2X实例以及修改了-Dfile.encoding参数,这样控制台可以显示中文。

注意:上面使用了tc-cluster.xml作为Terracotta客户端的配置文件。 
3、Terracotta客户端的配置文件tc-cluster.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--

  All content copyright (c) 2003-2007 Terracotta, Inc.,
  except as may otherwise be noted in a separate copyright notice.
  All rights reserved.

-->
<tc:tc-config xmlns:tc="http://www.terracotta.org/config"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.terracotta.org/schema/terracotta-6.xsd">

  <!-- Tell DSO where the Terracotta server can be found;
       See
       - Terracotta Configuration Guide and Reference
       - About Terracotta Configuration Files
       for additional information. -->

  <tc-properties>
  <property name="12.l1reconnect.enabled" value="true" />
  <property name="12.l1reconnect.timeout.millis" value="5000" />
  </tc-properties>
  <servers>
    <server host="192.168.168.88" name="server1">
      <dso-port>9510</dso-port>
      <jmx-port>9520</jmx-port>
      <data>%(user.home)/terracotta/server1/server-data</data>
      <logs>%(user.home)/terracotta/server1/server-logs</logs>
      <statistics>%(user.home)/terracotta/server1/server-statistics</statistics>
    </server>

    <server host="192.168.168.88" name="server2">
      <dso-port>9511</dso-port>
      <jmx-port>9522</jmx-port>
      <data>%(user.home)/terracotta/server2/server-data</data>
      <logs>%(user.home)/terracotta/server2/server-logs</logs>
      <statistics>%(user.home)/terracotta/server2/server-statistics</statistics>
    </server>
  </servers>

  <clients>
  <logs>%(user.home)/terracotta/client-logs</logs>
  </clients>

  <application>
    <dso>
      <!-- Our app requires these custom objects/classes to be shared - the following declarations
           tells DSO which ones they are. When the app runs under DSO, instances of these classes
           will broadcast changes in their state.

           A good idiom when writing an app that you intend to cluster via TC DSO, is to group the
           classes you wish to share under a single package (although if you follow the MVC pattern
           this tends to happen naturally) - this way the list of classes you wish to instrument
           can be concise -->
      <instrumented-classes>
        <include>
          <class-expression>demo.cluster.data.*</class-expression>
        </include>

      </instrumented-classes>

      <!-- These methods (originating from local objects) operates on objects declared as shared. This
           section tells DSO to assume a lock on those objects for the duration of the call; essentially this
           section declares that all methods found for all classes found for all packages should assume the
           behavior described -->
      <locks>
        <autolock>
          <method-expression>* *..*.*(..)</method-expression>
        </autolock>
      </locks>

      <!-- We declare the following fields a root, making it
           available for all instances of our app that runs via DSO -->
      <roots>
        <root>
          <field-name>demo.cluster.data.DataStore.usersInCluster</field-name>
    </root>
    <root>
          <field-name>demo.cluster.data.DataStore.postOffice</field-name>
    </root>
      </roots>

    </dso>
  </application>

</tc:tc-config>

application标签上面的部分一定要和Terracotta服务器组的tc-cluster.xml配置一致。

application标签内配置需要共享的数据以及使用的锁机制等信息,具体的可以参考Terracotta官方文档。

注意:扩展中需要共享的数据就是在这里配置。 
4、修改SFS2X的启动代码。

上面的配置虽然可以将SFS2X成功加入Terracotta集群。但是,由于Terracotta要求所有加载共享数据的ClassLoader,必须命名。

而SFS2X加载每一个扩展之前都会创建一个URLClassLoader实例。使用该实例来加载扩展。这样的目的是为了使得SFS2X支持热部署。

如果不重新定义一个命名的ClassLoader,当在扩展中需要操作共享数据的时候,你会得到一个ClassLoader没有命名的异常。为了解决这个问题,我们需要重新实现SFS2X的加载扩展的机制。

我们使用一个自定义的类ClusterClassLoader来加载我们需要集群的扩展。

public class ClusterClassLoader extends URLClassLoader implements NamedClassLoader{

  private static final String NAME = "ClusterClassLoader";

  private String loaderName;

  public ClusterClassLoader(URL[] classpath, ClassLoader parent) {
    super(classpath, parent);

    try {
      ClassLoader parentLoader = ClusterClassLoader.class.getClassLoader();
                        Class<?> namedClassLoader = parentLoader.loadClass("com.tc.object.loaders.NamedClassLoader");

                        Class<?> helper = parentLoader.loadClass("com.tc.object.bytecode.hook.impl.ClassProcessorHelper");
                        Method m = helper.getMethod("registerGlobalLoader", new Class[] { namedClassLoader }); 

                        m.invoke(null, new Object[] { this });

    } catch (Exception e) {
      e.printStackTrace();
    }

    System.out.println("实例化了一个ClusterClassLoader");
  }

  public String __tc_getClassLoaderName() {

    return NAME;
  }

  @Override
  public void __tc_setClassLoaderName(String arg0) {

    this.loaderName = arg0;
  }

}

注意,这个类实现了NamedClassLoader接口,这个接口是Terracotta提供的。然后我们在实例化ClusterClassLoader的时候,使用ClassProcessorHelper的静态方法registerGlobalLoader来注册。也许这里,应该放在一个静态的区域来完成,否则每次实例化的时候,都调用了一次registerGlobalLoader.而这里需要的名称是ClusterClassLoader这个类的名称,而不是每个实例的名称。开始的时候,将所有扩展都使用这个类,结果找不到共享数据引用到的数据。然后,限制只有名称为cluster的扩展才使用这个类来加载。这样变相地只注册了一次该命名的ClassLoader类。后面还待测试。

具体的细节可以参看修改后的启动源码。

完成修改后,将SFS2X\lib目录下的boot.jar替换为我们修改后的boot.jar,同时不要忘记将tim-api-1.3.0.jar也一并放入lib文件夹下。

注记:上一篇: 利用Terracotta实现SmartFoxServer2X集群 ,好像不少网友都对细节感兴趣,这里特此补发一篇,详解细节部分。

为了回馈广大网友,我实现了一个集群实例服务器端和客户端源码,以及修改后的boot.jar源码。全部放在了GitHub上。地址: 
点击访问(在SFS2X-Cluster目录下) 
欢迎下载,仅供学习参考使用。里面说明详细,相信大家应该可以彻底了解SFS2X和Terracotta集群配置的要点。至此,SFS2X和Terracotta集群的问题,相信可以告一段落了。前不久,GitHub被墙了,如果你还是无法访问,请留下QQ或者邮箱,但是不保证及时就能发给你,毕竟工作很忙。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值