集群式游戏服务器架构方案设计开发

时间:2009-11-20   来源:   网友评论:0   人气: 1307 作者: 胡章优 吉林大学机械学院

自从2003年开发VOIP Radius Server以及修改Gnugk以来,从事服务器开发已经近五年了,对服务器开发也有一些自己独到的看法以及见解。当摆脱了技术本身的束缚之后,才理解重要的并不是某种技术的运用,而是整体设计的考虑,也慢慢明白了设计是开发的灵魂的道理。

从技术层面来看,各个平台都有一些自己特有的东西,比如Windows 平台下面的IOCP技术,可以说为了支持大的并发,IOCP是一个Windows平台的必选方案。而在Linux下面Epoll又是所有开发人员需要掌握的技术。当然还有FreeBSD下面Kqueue的应用了。一些其他平台也有自己独有的AIO库。

随着网络开发的进一步理念加深,跨平台库也吸引了越来越多的使用者的眼光。比如行业里面最出名的莫过于ACE、ASIO(Boost公司)两大支持库。新的版本中都对IOCP支持,使用的是Proactor设计模式实现的。

当我们拥有了以上的知识背景后,我们就可以开始着手设计了。而这仅仅是一个必要条件,而不是重复条件。为什么呢?
我们先来提一下集群式服务器开发的常用几个技术知识。
1:线程
2:线程池
3:内存池
4:数据库连接池
5:为了达到1:10000的连接,可以采用Server-Client的连接方式,而为了达到1:10000*100的连接,我们怎么办呢?一般会采用Client-> ConnServer -> LogicServer。这是技术背景。ConnServer在接受完Client 的连接后,将Logic Server 暴露给Client,并立刻断开连接。以后的数据交互就和Conn Server没有关系了,这种架构有很多的优势。

[图一:标准集群GameServer架构方案]

首先要说的是线程,在服务器开发中,线程是一个非常重要的概念,尤其是现在多核服务器的发展。当然,提到了线程自然应该说到线程之间的互斥。这也是服务器开发者们在开发最初最容易出现的问题。体现在一个资源或者多个资源在多个线程中共享使用如何避免出现脏数据的问题。
  线程池,池,顾名思义,是一个存储容器,一个浅显的比方,我们把水事先存放在水池里面,当我们需要的时候,就去里面取,用完了就还给池(其实这里并不是非常合适的例子,毕竟我们用完了水是丢掉)。这是一个由多个线程组成的一个队列,当有事情发生时候,我们把当前的空闲的线程丢给他,为他服务。当下一个事件发生的时候,我们又从池里面取一个空闲的线程丢给他,为他服务。当服务完毕,把线程丢回池中。起到反复利用的目的。
  内存池,同样也是一个池。这个概念的产生是为了避免服务器频繁的分配内存,而采取预先分配一定数目的对象,并将对象们放到队列中,当需要的时候,从该队列中取出,当用完,就返回池中。比如我们的Server可能会存在10000个连接,我们预先开辟10000个Client对象,存储在list pFreeClientsList中,当需要的时候,从队列中pop一个出来,当使用完毕就丢回pFreeClientsList。这种机制很好的起到了避免频繁开辟内存对象的目的,可以很好的提高系统的性能。
  数据库连接池,同上面一致的道理,在服务器中,数据库访问也是一个很大的瓶颈,所以同样采取上面的道理,使用连接池的概念。当然在数据库连接方面也有一个特殊的问题存在。就是数据库的连接不宜过多,所以传统的来一个处理,就开一个连接是不合理的,必须采用控制适当的连接次数。
  当然另外一些需要提到的是内存数据库。硬盘的访问速度和内存的访问速度不是一个数量级的,而且随着内存的硬件价格越来越低,内存数据库的可行性也越来越高,尤其是实时性要求高的系统,完全可以采用内存数据库和物理数据库想结合的方法来处理。
  当系统的连接数量从万上百万级别的时候,服务器程序就超越了服务器本身,我们需要考虑的问题将从一下几个方面开展:
  1:如何划分系统中功能?
  2:如何保证整个系统的性能可控,直观的说就是系统每一步时候瓶颈在哪里?


 

文章评论