游戏服务器开发经验(一)道具防刷
前言 在多年的游戏服务器开发工作中,在大多数时候,开发内容仅仅是将策划的需求“翻译”成服务器程序代码。但是这份工作需要的严谨程度非常高,远远不止将需求实现而已。 有一些内容是开发过程中就需要有意识去注意的。如:必须校验客户端传参;先扣除道具,再改状态,最后发奖励以保证防止玩家刷奖励等。做到这一步,基本上能保证客户端的行为能在服务器的控制以内。 但还有一些内容,是由于项目长期开发过程中,多个需求互相杂糅导致的问题。比如今天的功能可能和去年年初的功能耦合,但是触发条件比较苛刻,埋得比较深。这种问题一般不会是什么影响服务器启动的大问题,但是很有可能会造成业务逻辑的漏洞。面对这种问题,我们是比较难在开发中能提前预知,一般是靠人力测试或者接口压力测试的时候查看报错日志来发现。 还有一些是需求过于复杂,变动太大,程序跟不上策划思路。这种情况其实更考验沟通能力,准确来说,是发现策划“核心需求”的能力。策划想要的东西可能和他说的内容并不一致,他想要的需求也和他真正告诉你的不一致。所以这就要求我们的代码能够支持一定的灵活性,能够提前预判策划真正想要的目标效果。当然这也需要我们程序员多玩不同类型的游戏,从而尽可能让思路和策划在同一水平面上。 本系列是本人在多年游戏服务器开发过程中,积累了些许经验,闲暇时总结在此处。 道具防刷 网络游戏最担心的事情,除了服务器崩溃之外,就是道具被玩家无限重复获得,俗称“刷奖励”。在大多数情况下,发放道具都是非常基础的功能。一般发放道具这一步不会有什么太大问题,问题主要会出现在发放道具前的业务逻辑校验。 如果校验的条件覆盖面不足,当玩家没有付出足够代价的情况下,获得了道具,会大大影响服务器内的经济系统。好比有人发现能去商店“零元购”而不被制裁,那就没有人愿意劳动了。 防刷原则:校验条件 -> 扣消耗 -> 改状态 -> 发奖励 无论什么情况,都务必遵循此条件:校验条件 -> 扣消耗 -> 改状态 -> 发奖励。 一般来说,校验条件放最前面没有异议,但是扣消耗、改状态、发奖励却不一定大家都会认同。在有事务和锁的情况下,完全可以做到开启事务后,对核心对象上锁,校验好消耗和奖励,然后一并提交。但是对于游戏服务器来说,消耗和奖励是允许一定程度的误差的(因为可以后期补发、扣除等操作)并且服务器性能的优先级高于消耗和奖励的优先级。如果每次玩家去游戏商城进行道具购买,或者挑战关卡通关都要有事务和锁的开销,会大大影响效率。 因此在没有事务和锁的情况下,扣消耗、改状态、发奖励这三个步骤中,我们优先要让玩家吃亏,必须先扣除消耗。然后再修改状态,让下一次请求来临时校验新的条件。最后再发放奖励。 补救措施:完善的资源道具产销日志 玩家在游戏中的每一笔消耗和获得,都需要记录下来。除了玩家信息、道具信息、变更数量等一定要记录的内容之外,还至少包含以下内容:日志枚举(数字,用于数据库中创建索引),产销细节(提供一个字符串,记录本次产销相关的事件,关联的id,如通关的副本id、购买的商品id等)。如此一来,即使真的存在被刷道具的情况,也能快速定位到被刷的数量。 这个日志最好能不要删除。这里就可以考虑使用大数据相关的数据库来存储这种大量结构化数据了。 事前预防:最重要的是把状态改对 被刷道具的原因基本上都是状态没有正确更改。大部分情况下,用心的开发人员会记得修改状态。 但是还会有一种比较隐秘的Bug情况:修改的状态可能并不是这个业务需要的状态。这种情况最容易发生在复制其他功能的代码到自己的功能,然后删改细节的时候不小心遗漏。 事前预防:填写正确的产销日志信息 另外,道具产销的日志也一定要认真检查填写的日志信息。这一部分是非常容易忽略的。因为即使代码进行了自测,道具正常扣除与增加,也无法直观地看到日志里的内容。 事前预防:任何一行代码,有条件都要自测 没有人比你懂你的代码,哪怕是用心Review你代码的领导。所以千万不要有侥幸心理,有条件自测就多点一下,能断点走一遍看看就走一遍。这个过程并不会花费太多时间。但是却能很快让你看到代码中的缺漏。