网游服务器系列之二:常用的网游服务器集群设计

两面人原创,CSDN 首发

网游服务器集群设计至少需要达到以下目标:

  • 高负载能力

既定的硬件配置下能够尽可能支持更多的用户

  • 高响应能力

用户的响应延迟尽量要小,一般而言,对于RPG类游戏非战斗情况下延迟应低于500ms,PVE战斗情况下要低于300毫秒,PVP战斗下应低于200毫秒。对于格斗类游戏,延迟要求应该更小。

  • 可伸缩性

很少的硬件下也能部署出完整的系统,负载要求提高时可以通过新增硬件来提高负载能力。但硬件投入的增加和负载能力的增长应该是线性关系。

另外由于现在的服务器多核CPU,四核已近非常普及,很快八核乃至更多核心的CPU也会普及,所以服务器集群设计时也要考虑充分利用多核CPU的处理能力。

目前大多数网络游戏都会采用类似图1的集群设计方案。服务器分为前端连接服务组和后端功能服务器组。

图1常用的网游服务器集群设计

前端的连接服务器都是双网卡,一面直接面向公共网络的,另一面和后端的所有功能服务器在同一个千兆局域网内。功能服务器不会直接面向公共网络,外部只能通过连接服务器将报文转发给功能服务器,功能服务器之间根据需要建立通讯连接。游戏客户端通过TCP与某一个连接建立连接,连接服务器收到上传的数据报文后分析报文头,然后将报文转发给相应的功能服务器。每个连接服务器在公网这一端会接受来自不同用户的大量并发连接,而而对后端的功能服务器只有有限的几个连接。从外网收到的数据会通过这几个内网连接分发给后端功能服务器处理。

这样设计有几点好处。

首先是客户端和服务器集群之间只需要维护一个连接。网游服务器和Web应用的服务器是有很大差别的,用户使用Web服务的过程是由一次次的http请求完成的,这些请求都是采用的tcp短连接。而且这些请求都只需指向一台Web服务器,即使服务器使用多台Web服务器分担负载,同一个用户在一次会话中的所有请求也必须被负载均衡器指派到同一台Web服务器。而网络游戏(WebGame除外)一般采用C/S结构,客户端和服务器之间是长连接。游戏过程中玩家会从一个地图走到另一个地图,会进入副本战斗,结没有束后回到主城,这些行为都可能导致用户会使用不同的功能服务器的服务。如果没有连接服务器,客户端就有可能会和很多的功能服务器连接,甚至是同时和多个功能服务器连接。这样客户端就要实现连接管理,多个连接也使客户端处理网络错误(比如判断是否掉线)带来麻烦。对服务器而言,

第二个好处就是在服务器端可以把大量并发连接的数据收发操作和游戏逻辑的处理分开。在网络编程中,大量并发连接的处理一直以来都是难点中的难点。很多设计模式专门来解决这个问题。各个操作系统也持续的在内核中针对性的提高并发连接处理的能力,并提供相应的API。基本上各个操作系统都都提供了异步I/O的编程接口。Windows下的IOCP,Linux的epoll,FreeBSD 的kqueue。即使采用异步I/O机制,大量并发连接的处理对CPU资源的消耗也是比较大的。连接服务器专注于处理并发连接,可以让功能服务器专注于逻辑处理。每个功能服务器的本职工作应该是高效的的处理游戏逻辑,如果所有的功能服务器都要处理大量的并发连接对服务器的处理效率会有较大影响,同时所有功能服务器都暴露在公共网络也是不小的安全隐患。

那么一台连接服务器应该能支持多少并发连接呢?我们知道连接服务器的功能仅仅只是数据转发,它做的工作比绝大多数http server 做的都简单。那么如果设计得好,它的并发能力不应该低于主流的http server。常用的Apache Server 一般支持5000个并发连接没有问题,优化一下配置,最好再调整一下Linux内核参数,可以支持到一万以上。更轻量级的Nginx 号称可以支持到5万以上。而实际上大多数网游的连接服务器能支持的数量却少的可怜,一般1000是及格,2000是优秀,3000以上就很难得了。

为什么这么低呢?主要原因有两点。

第一个原因是由网络游戏(尤其是MMORPG)的数据通信特点导致的。前一篇文章中我已经提到了网游有非常大量的下行广播数据。任何一个玩家做出一个动作(走跑跳、攻击等等),都需要服务器广播给周围的所有玩家,同时这个动作所造成的场景中的其他变化也需要立即广播出去。玩家聚集得越集中,广播量就越大,而且这个增长之间是指数关系。假如功能服务器需要把一个数据广播给周围30个人,为了减少功能服务器的数据发送量,它发到连接服务器的是这30个人的列表和实际的数据内容。连接服务器就要负责分别发送给30个人。所以广播压力主要是集中在连接服务器。而且从游戏设计和运营的角度上讲,现在的网游越来越倾向于把玩家通过工会战、战场等活动聚集起来,人多才好玩嘛。这是与一般Web 应用相比的一个很大差别。因此连接服务器支持的并发连接数远远不能和主流的http server相比。

另一个原因是TCP的传输机制。绝大部分游戏客户端和服务器都是采用TCP连接,好处是数据传输可靠,编程也方便。但是对于大量的广播报文而言,TCP的可靠性却导致的发送效率低下。实际上广播报文中的70%都是玩家(以及NPC)位置的同步数据,这些数据其实不需要很高的可靠性,即使丢了一个数据包,过一会就会收到下一个新位置的信息,客户端只需要平滑处理一下就可以掩饰得很好。

广播效率上不去对游戏服务器的负载能力的影响非常大。广播不出去的数据就会累积在连接服务器上,导致连接服务器的内存无限增长,同时客户端的响应延迟也增加,玩家就会感觉很卡。解决的办法要么降低每组服务器的人数,要么多加连接服务器。实际上多数网游就是这么做的。这样连接服务器的主要作用到不是分担并发连接,而是分担广播压力,似乎改个名字叫广播服务器更合适一些。

 

下一篇文章是针对本文的问题,提出一个采用QoS机制,通过定制Linux中的IPVS模块设计的高效网游数据广播方案,敬请关注。

你可能感兴趣的:(游戏开发)