面向Web服务的游戏设计3:服务设计概述
在Web环境(HTTP协议)下,服务器端的服务是被动方式的,无法通过定时器来主动处理游戏控制和逻辑。同时每次服务的时间不可以太长,否则将导致服务超时,产生不可预料的后果。Web环境的特殊性决定了其游戏设计与常规客/服环境下的设计完全不同。应该指出,Web环境并不是设计和发布MMORPG游戏的理想选择,独立主机可以提供更好的性能和更简单的逻辑。但是租用Web共享空间的价格远低于独立主机,可以大大降低发布游戏的代价,让更多的业余游戏开发者可以承受,并参与到全民Web游戏制作的行列中来。
在传输层,笔者选择了WCF BINARY ENCODING作为服务器和客户端的通信方式。在上面的服务层,笔者从功能上把服务分为几类:一次性服务,非频繁周期服务,频繁周期服务,KEEP ALIVE服务,和任务分派服务等。
1 一次性服务
顾名思义,一次性服务就是在用户需要的时候才调用的服务,例如用户注册,登录,创建游戏人物等。该类服务的特点是:
- 功能上差异很大,共同点较少。如登录和创建游戏人物几乎没有任何共同之处。
- 每个服务参数的数量和类型相对比较固定。例如登录服务,只需要用户名和密码。
- 服务数量不是很多。目前可以想到的此类服务还不到10个。
该类服务的处理最简单,不需要什么技巧,针对每个特定的服务提供一个服务方法就好了。
2 非频繁周期服务
周期服务就是客户端按一定时间间隔轮询服务器服务。之所以再细分为频繁和非频繁,是因为不同的情况的需要。具体来说,非频繁周期服务的时间间隔为10秒或更长,例如聊天服务。鉴于用户的键盘输入速度以及聊天的更新对实时性的要求不是很高,10秒的轮询间隔一般就够用了。尤其对业余级的发布环境,太短的轮询间隔会加大服务器的负担。好比穷家过日子,有钱用在刀刃上,不重要的地方能省就省一点吧。
3 频繁周期服务
频繁周期服务的时间间隔为1秒,主要应用于对实时性要求比较高的场合,例如sprite的状态信息交换。尽管1秒的轮询间隔在表现效果上还不是很尽人意,但是我们需要平衡资源的消耗和表现效果。只要效果能够被大多数玩家接受的就可以了。单个连接消耗的资源越少,在总资源一定的条件下,表明可以容纳的连接数越多。这对于多人在线游戏是至关重要的。
sprite的状态信息交换需要传递大量数据,然而这些数据并非格式化的,而且变化组合几乎是无限的,我们不可能根据每种参数组合定义一个服务方法。另外,如何实现只传递更新了的数据,减小数据传输量,也值得考虑。笔者会在后续文章里专门讨论这个问题。
4 KEEP ALIVE服务
Keep alive报文大家也许不陌生,一般用来进行链路协议协商和保持链路连接状态。这里笔者是借用这个名称,来描述该类服务。大家知道Web服务器是被动方式的,如果需要处理任务,必须由客户端来触发服务才可以。KEEP ALIVE服务的实质就是由客户端触发Web服务器,来模拟Web服务器端的定时控制。
原理很简单,但是实现时需要考虑一些问题。多长的轮询时间间隔比较合适?每次服务处理多少任务比较合适?如果有大量的客户连接,如何控制KEEP ALIVE服务不会过于频繁?相信问题远不止于此,留待后面专门来讨论。
5 任务分派服务
上一篇介绍了如何把服务器端的繁重任务分派到客户端来处理,并把处理结果更新回服务器。原理和简单例子已经讨论过了,这里不再赘述。不少朋友对这个方案的可行性报怀疑态度,笔者不敢说它一定可行,这需要实践来检验。希望在后面游戏开发过程中有机会来证明。
上面只列举了几种主要的服务类型,具体实现中可能还需要其他类型来辅助。把服务分类的目的是分离不同的游戏逻辑,使游戏结构清晰,便于分别设计,实现和测试。一锅粥似的东西相信是每个程序员的梦魇。
细心的朋友可能看出,从项目开发的角度看,前面的文章主要属于预研阶段,研究开发游戏过程中可能遇到的问题及解决办法。本文则有点概要设计的意思了。园子里有位朋友曾提出未写游戏(代码),先写设计。笔者十分赞成这个观点,一个好的设计可以让后面的工作行如流水,事半功倍,反之则困难重重。在后面的文章里,笔者将详述上面几种服务的设计。
做过项目的朋友知道,概要设计在软件开发过程中占有极重要的地位,相当于一座大厦的设计蓝图,往往需要本项目甚至其他项目中的几个高级程序员反复讨论和修改才能定型。笔者一个人闭门造车,疏漏肯定是难免的,不足的地方大家多担待,多提宝贵意见。没有代码,罗罗嗦嗦一堆叙述,读起来可能比较乏味,谢谢耐心看到这里。