利用Terracotta实现SmartFoxServer2X集群
博客搬家啦——为了更好地经营博客,本人已经将博客迁移至www.ijavaboy.com。这里已经不再更新,给您带来的不便,深感抱歉!这篇文章的新地址:点击我 两个多月没有更新博客了,那是因为刚进入一个新的领域,疯狂地学习并工作。这两个月,对于我来说,是一次新的
博客搬家啦——为了更好地经营博客,本人已经将博客迁移至www.ijavaboy.com。这里已经不再更新,给您带来的不便,深感抱歉!这篇文章的新地址:点击我
两个多月没有更新博客了,那是因为刚进入一个新的领域,疯狂地学习并工作。这两个月,对于我来说,是一次新的旅程。从之前的Android开发,一不小心溜入游戏服务器端的开发。现在,终于有了一点闲暇,记录一下这两个月中学到的和领悟到的知识。
两个月前,进入一家做互联网3D产品的创业公司,而我负责的,正是服务器端的开发。和传统的3D游戏不同,这里没有复杂的游戏逻辑,只专注于产品需要的功能,客户端中不外乎用户的登陆和聊天等功能。而服务器端主要的任务就是处理用户的登陆登出和各种信息的同步。之前的一个月,学习了SmartFoxServer引擎,同时一并学习了下Unity3D引擎(因为客户端使用的是这个,学这个主要是为了可以很好地和客户端配合)。
一直到几个星期前,当老大说要支持高达200000个用户同时在线的时候,才知道SFS2X试用版最多只可以支持100个用户,几经周折破解了SFS2X,消除了这个限制。但是,就算消除了限制,让一台机子同时处理200K个用户同时在线并操作,最后的结果只有一个——它将活活累死!于是,到SFS官方论坛和网站上寻求答案,虽然英文马马虎虎,但还可以表情达意,最终得知Terracotta是个好东东。而且官方有一个SmartFoxServer1.6和Terracotta集成的文档。
正当我兴致突起,准备大干一场的时候,无意中被当头一棒——SmartFoxServer2X明确表态,从2X起,SmartFoxServer不再支持Terracotta集群。花了好几个昼昼夜夜,在其官方论坛上用那生硬的English发帖询问,结果终于得到证实,2X开始真的不支持或者不再提倡使用Terracotta来集群。再次看到1.6的那份官方集群文档的最后一句:
Finally the future releases of SmartFoxServer will move towards a tighter integration with Terracotta,
to provide even more distributed services out of the box, and further simplify the development
我不禁哑然!
后来,翻阅了大量了官方论坛上的帖子,却又找到官方人员的相关言论说,可以按照1.6思想的来使用Terracotta完成SFS的集群。于是,我决定尝试一把...
写好了集群扩展的代码,当想要测试一把的时候,才发现,怎样让Terracotta识别SFS2X呢?也就是怎样将SFS2X作为Terracotta集群的客户端来启动呢?
下载了1.6的集群的Demo,看到了它是使用了一个新的bat文件来启动的。看了下这个文件,其中含有Terracotta的启动包,终于明白了,原来如此。于是将其拷贝到
SFS2X的启动bat文件中,成功实现将SFS2X加入到Terracotta集群中。通过Terracotta Developer Console也可以看到连接上的客户端。
兴奋之余,将写好的SFS2X集群扩展Demo打了个jar包放到了SFS2X中,又写了个测试的Client,结果一运行,报了一个大大的异常,从异常信息看出,这个和ClassLoader有关。
之前学习SFS2X的时候,看到过官方介绍过2X中使用了新的ClassLoader机制。核心SFS2X使用SystemClassLoader加载,每一个扩展使用一个新的ClassLoader进行加载,这样是为了方便应用扩展的热部署。但是,这个热部署我倒不太愿意用,现在又因为这个鸟东东和Terracotta集群有了冲突。
从Terracotta的官方论坛中又再次得知,加载Terracotta*享数据的ClassLoader必须命名,Terracotta就是根据ClassLoader的名称来完成不同JVM之间相同数据的同步。
这下彻底死了个翘翘,难道注定了无法实现SFS2X和Terracotta的集成吗?心有不甘。。。
这时,一个强烈的念头涌上心头,SmartFoxServer2X不是用java写的嘛,反编译你的源码,殊死一搏吧。
这个时候,发现其代码并没有进行加密,心中大喜。反编译后的代码清楚无比,看到了在加载每个扩展的时候,其都定义了一个URLClassLoader来完成扩展的加载。那么我现在就需要替换掉这个URLClassLoader,而使用自己的定义的ClassLoader。
于是引入Terracotta和SmartFoxServer相关的jar包,重新实现了个命了名的ClassLoader,让这个ClassLoader完成扩展的加载。
打成jar包,替换掉原来的jar包,运行起来,OK!测试通过,集群终于实现。
实现集群的目的,主要是为了分担负载和容错。那么现在如何实现负载均衡成为一个关键,看了很多关于负载均衡的资料,基本是基于Http请求的负载均衡。但是,对于像SmartFoxServer一样的游戏服务器端引擎来说,其使用的往往是Tcp或者Udp协议。而我们知道,Http协议是无状态的,用户的每一次请求都可以做到负载均衡。而Tcp或者Udp使用的是长连接的形式,用户一旦和某个物理机器连接了,那么直到他主动退出或者这个物理机器上的SmartFoxServer出现故障,否则其在登陆中所发出的每一次请求都是在同一个TCP或者UDP连接中完成的。那么如何实现SFS2X的负载均衡呢?
有两个思路:
1、客户端维护一个服务器端可用的SFS2X节点的列表,然后每次请求的时候随即获取一个进行连接,如果请求超时或者失败,则再重新选择一个尝试连接。但是这个方案不能根据负载状况进行请求。
2、就是外加一个负载均衡服务器,这个服务器作为一个普通的Web Server。可以使用Tomcat或者Apache等。他主要的功能就是负责维护每个SFS2X节点的负载情况(每个节点上登陆的用户数)和可用的SFS2X节点信息。当一个客户端请求登陆SFS2X服务器的时候,其首先发送Http请求到这个WebServer,这个WebServer会查询并返回当前所有可用的节点和每个节点对应的负载信息。然后,客户端根据返回的数据,选择一个负载最小的节点进行连接。但是这个方案,这个单点的WebServer容易成为整个系统的瓶颈,同时可能成为单点故障。但是这个可以使用传统的负载均衡技术来避免这些问题。
第一个基本排除,采用第二个。但是第二个又引发一个问题。就是负载均衡服务器和SFS2X集群如何完成数据的同步。是每个SFS2X节点每隔一定的时间将连接到本机的用户数等信息发送到一个存储媒介,这样,负载均衡服务器每次只需要查询这个存储媒介就可以了。但是,这个会成为瓶颈吗?
I DON'T KNOW,JUST TEST IT!
上一篇: Data Guard–物理主备库切换
下一篇: php终究能干什么