« C 语言中统一的函数指针 | 返回首页 | 换了个新手机 »

游戏多服务器架构的一点想法

把网络游戏服务器分拆成多个进程,分开部署。这种设计的好处是模块自然分离,可以单独设计。分担负荷,可以提高整个系统的承载能力。

缺点在于,网络环境并不那么可靠。跨进程通讯有一定的不可预知性。服务器间通讯往往难以架设调试环境,并很容易把事情搅成一团糨糊。而且正确高效的管理多连接,对程序员来说也是一项挑战。

前些年,我也曾写过好几篇与之相关的设计。这几天在思考一个问题:如果我们要做一个底层通用模块,让后续开发更为方便。到底要解决怎样的需求。这个需求应该是单一且基础的,每个应用都需要的。

正如 TCP 协议解决了互联网上稳定可靠的点对点数据流通讯一样。游戏世界实际需要的是一个稳定可靠的在游戏系统内的点对点通讯需要。

我们可以在一条 TCP 连接之上做到这一点。一旦实现,可以给游戏服务的开发带来极大的方便。

可以把游戏系统内的各项服务,包括并不限于登陆,拍卖,战斗场景,数据服务,等等独立服务看成网络上的若干终端。每个玩家也可以是一个独立终端。它们一起构成一个网络。在这个网络之上,终端之间可以进行可靠的连接和通讯。

实现可以是这样的:每个虚拟终端都在游戏虚拟网络(Game Network)上有一个唯一地址 (Game Network Address , GNA) 。这个地址可以预先设定,也可以动态分配。每个终端都可以通过游戏网络的若干接入点 ( GNAP ) 通过唯一一条 TCP 连接接入网络。接入过程需要通过鉴权。

鉴权过程依赖内部的安全机制,可以包括密码证书,或是特别的接入点区分。(例如,玩家接入网络就需要特定的接入点,这个接入点接入的终端都一定是玩家)

鉴权通过后,网络为终端分配一个固定的游戏域名。例如,玩家进入会分配到 player.12345 这样的域名,数据库接入可能分配到 database 。

游戏网络默认提供一个域名查询服务(这个服务可以通过鉴权的过程注册到网络中),让每个终端都能通过域名查询到对应的地址。

然后,游戏网络里所有合法接入的终端都可以通过其地址相互发起连接并通讯了。整个协议建立在 TCP 协议之上,工作于唯一的这个 TCP 连接上。和直接使用 TCP 连接不同。游戏网络中每个终端之间相互发起连接都是可靠的。不仅玩家可以向某个服务发起连接,反过来也是可以的。玩家之间的直接连接也是可行的(是否允许这样,取决于具体设计)。

由于每个虚拟连接都是建立在单一的 TCP 连接之上。所以减少了互连网上发起 TCP 连接的各种不可靠性。鉴权过程也是一次性唯一的。并且我们提供域名反查服务,我们的游戏服务可以清楚且安全的知道连接过来的是谁。

系统可以设计为,游戏网络上每个终端离网,域名服务将广播这条消息,通知所有人。这种广播服务在互联网上难以做到,但无论是广播还是组播,在这个虚拟游戏网络中都是可行的。

在这种设计上。在逻辑层面,我们可以让玩家直接把聊天信息从玩家客互端发送到聊天服务器,而不需要建立多余的 TCP 连接,也不需要对转发处理聊天消息做多余的处理。聊天服务器可以独立的存在于游戏网络。也可以让广播服务主动向玩家推送消息,由服务器向玩家发起连接,而不是所有连接请求都是由玩家客互端发起。

虚拟游戏网络的构成是一个独立的层次,完全可以撇开具体游戏逻辑来实现,并能够单独去按承载量考虑具体设计方案。非常利于剥离出具体游戏项目来开发并优化。

最终,我们或许需要的一套 C 库,用于游戏网络内的通讯。api 可以和 socket api 类似。额外多两条接入与离开游戏网络即可。

Comments

大叔们,我是什么时候能懂啊

這個提議是可行的~ 形成一個虛擬網路
1. 多個用戶端 <--> (多個 TCP)portal server&#8231;
2. portal server<--> (單一 TCP) lobby server.
3. portal server<--> (單一 TCP) chat server.
4. portal server<--> (單一 TCP) auth server.
5. lobby server<--> (單一 TCP) game server1.
6. lobby server<--> (單一 TCP) game server2.

portal server 負責將用戶端轉換成一個虛擬 socket 後再連接到 game server.

轉換後很多指令的處理反而變的乾淨直覺, 比如用戶的帳密認証, 由 portal server 收到後透過虛擬 socket 後轉送到到 auth server 後不需等待, 當 auth server 回覆後再透過虛擬 socket 回覆給用戶, 這個過程中 portal server 不用被阻塞.

後端 game serverX 可以直接透過虛擬 socket 發送訊息給用戶端.

這個系統是已實作的了~ 效果不錯, 只是前期 bug 不好處理, 只是沒想到也有人已經有相同的觀念.

目前比較不好處理的是虛擬伺服器之前的斷線跟斷線重連及用戶端的即時斷線重連反而不好處理, 雖然已處理也測試過, 但不知是否有未知的盲點.

這是一個不錯的方式.

多服构架优点巨大,但是开发维护成本也会提高,只是利大于弊

进程间用TCP通信,网络连接的不安全性几乎可以忽略,因为服务器组都是在一个机房的,如果网络出问题势必大部分服务器都出问题

每个进程中都有用户代理, 只保存和处理该进程关心的用户动作和数据

所有服务进程都用一套网络层这个是必须的

进程间通信会网状进行,功能进程分割越多 进程间通信量越大,这个要权衡好.

我一直认为多进程少线程的服务器的表现肯定优于多线程少进程的服务器

sipX不就是楼上机器人所说的C<->A<->S的架构吗

我也认为这是yy, 只是看起来挺美

这就是YY

这个方法是可行的。
MS和APPLE都有自己的一套解决方案。
我用的方法和你的方法类似。
C<->A<->S
A是一个AGENT,也是一个名字解释器。
S注册到AGENT,C连接AGENT,通过名字在AGENT中建立一条和S的虚拟链路,并且在链路建立时,就进行身份验证。
这样,只要一个连接,就可以和所有的服务器进行交互。

不过你说的,维护多个连接状态,是个很繁琐的事情。

所以我在设计时,只允许一次建立一个虚拟链路。

但是,通过DISPATCHER节点,可以将关键信息,转发到相应的处理节点,而处理节点到AGENT又是一个回路。就是单路进,多路出。并且有了AGENT,广播就是一件非常惬意的事情了。

Tibco Rendezvous

bigworld?服务是entity,玩家也是entity。
entity之间通讯。

我比太懂啦,但是窝窝好像就是这样,副本和游戏世界单独存在于特别的服务器上,副本服务器挂了,游戏世界还是可以正常继续

ryzom已经把很多模块分开,并且它的服务器数量达到10多个了。。。

你的文章真的很不错啊 收藏咯

很好的想法,我们已经用了比较简单的一种:聊天和相关数据由单独的一个server,有时就挂了,但游戏照样玩,只是看不到聊天内容了

很好的想法

貌似跟Structured Stream类似,参见某篇Sigcomm论文,有兴趣可以自己google出来。

这个可以考虑用rabbitMQ实现非同期话的部分,性能很不错

多服务器架构是会有很多好处,但是虚拟连接的方案似乎不能解决网络连接不可靠的问题,单一的tcp连接本身也会出现通讯故障甚至断线,那么基于这个tcp连接的虚拟连接不都失效了吗?另外,对客户端开放服务端的模块结构这点也值得商榷,因为这样就失去了不改变客户端的情况下优化服务端模块结构的机会。

很像Erlang或者OpenMPI

原理有点像是个微内核实现。

嗯,比如聊天信息,就放到单独的 web 服务器就够了。
问题就成了:
当 web 服务器当机的时候, 聊天没法聊了,游戏还能玩

用一个TCP连接能够处理一个终端到多个点的通信?
一个A/B机器之间的TCP能够和C机器通信么?

VFS,Network,云风现在这么热衷基础模块的构架,看来是想打造一个不依赖于平台的framework,可以在PC,嵌入式产品快速移植。

游戏开发中有一原则,永远不要相信客户端数据。基于这个原则下,这个将玩家机器作为网络终端在安全性上必然要下很大的功夫

足够高效的中间件 ?

可以把网络从功能进程里完全剥离出去:与网络通信直接相关的东西放进一个独立的进程,然后它与功能进程使用管道进行通信。对于功能进程来说,它只是读写标准输入输出,至于消息从哪来、到哪去,它不需要在物理层面关系,也就是说它会在消息里指定某个消息要发给哪些对象,或者在收到的消息里会有个属性描述这个消息从哪来,但在物理上都只是来自于stdin、发往stdout。这样功能进程不需要包含任何额外的头文件、库就可以接入到服务器组网络内。

很好的想法,
相当于分布式环境中,提供提供了名字作为消息发动目标的服务。
实际应用过程中可能需要1)多播处理。
2)同一个对象或数据在多个进程之中都存在的情况,如何设定处理规则

云服务器,嘿嘿。

这不就是erlang的"!"吗

创建一个内部的网络服务器,变成真正意义上的“网络游戏”。把作为Object的玩家抽象改为终端抽象,感觉很不错,不过对于多个终端的集中的状态管理会不会比较复杂?

Post a comment

非这个主题相关的留言请到:留言本