现在假设有如下构建的游戏服务器,游戏服务器有一组gate服务器,用来验证客户端,并且通过gate服务器来与一组主服务器,然后主服务器与关系服务器进行通信。
其中relation服务器用来处理各种关系,例如好友关系,师徒关系等。现在有一个玩家A添加玩家B为好友,那么客户端发送给服务端的消息流程如上所示。首先gate收到客户端消息,进行验证等,然后转发给Main1服务器, 这里假设玩家A的信息存储在Main1服务器上,然后Main1服务器检测玩家A的各种要求,如果满足要求,则将消息转发给Main2服务器,这里假设玩家B在Main2服务器,然后Main2服务器进行各种检测,如果满足条件,则将消息转发给Relation服务器,Relation服务器再进行各种检测,然后回复消息给客户端。假设Main1的服务器检测和Main2的服务器检测都可以独立完成,那么消息逻辑可以改为:
上面的设计方案,假设玩家A和玩家B都在Gate1上。我们查看上面的两幅图,可以看出后面这幅图比第一幅图多出了一条消息,但是,响应客户端的消息,下面这幅图平均来说却只需要经过三条网络通信,上面的那种需要4条网络消息。也就是说,正常情况下,下面的方案响应客户端的速度更快。对客户端来说,这无疑是一个好的消息。
那么我们先考虑一下,采用下面这种方式需要解决的问题,首先Relation服务器需要同时等待Main1和Main2的消息,然后才可以处理,这个需要添加一定的缓存,还需要一定的区分同一条消息的机制,这个在有些情况下,可以通过协议ID来区分,另外,也可以通过一个例如64位ID来区分,如果Relation服务器对接收到的超过20s甚至更长时间的消息都不再处理,那么64位ID可以保证在这段时间内不会重复。这种机制不需要重复,只需要在relation服务器中接收到消息时,设置当前时间,然后每隔一段时间,例如1s中清理一下就可以了。这种问题的处理,也可以参考hadoop的reduce函数的处理,当然可以参考的资料很多。然后,这种方案需要玩家在同一个Gate上,对于很多游戏来说,一组服务器,一个Gate足以,那么这个问题,自然不用处理。对于有多个Gate的情况,也可以如果在同一个Gate上,就采用上述做法,如果不在同一个Gate上,就采用原来的做法,只需要在协议中进行区分就可以了。至于为此添加的协议中的额外字段,不会很长,对网络的增加的压力应该不大。从上来看,这种方式是一种可行的方案。
我们考虑一下这种方案存在的不利之处。首先网路中增加了一条协议,增加了一条Gate到Main的消息,增加了一条Main到Relation的消息,减少了一条Main到Main的消息。这个建议测试一下,查看一下这种通信协议的增加,会不会成为游戏服务器的瓶颈。如果Main服务器之间的通信原本比较多的话,那么这种改变,可以减少Main之间的通信量。然后,增加了设计的复杂度,尤其是Relation的复杂度,同时增加了Relation的内存占用。对于很多游戏来说,Main服务器的处理逻辑是瓶颈,这种设计方式,可以将部分需要Main服务器处理的逻辑,转交给Relation服务器进行处理。如果存在很多别的服务器,使用类似的处理的话,可能会减少Main服务器的压力,从而增加一组服务器的承载能力。所以说这种设计方式,在有些情况下,不仅可以增加服务端对客户端的响应速度,而且可以增加一组服务器的承载量。
上面只是提供了一种简单的设想,可以供设计游戏服务器的程序员予以参考,如果有什么好的建议或者意见,也欢迎反馈。