阅读分享:游戏服务器的设计与面向日志的工作流

7月的工作平淡无奇,除了X系统由借鉴A游戏改成借鉴B游戏,就没什么了,还是谈点别的吧。

最近看了《游戏服务器端究竟解决了什么问题》,推荐给大家。作者关于烂框架的分析很有趣,框架定义角色时,不恰当的角色划分,会引起额外的复杂度,作者文章中后部分有分析。

作者对服务器消息流通的分析,相当见功力。游戏的服务器端,可以抽象的看成消息的生产者和消费者的集合。每一个生产者/消费者,就是一个服务。skynet的优势,在于提供了“服务”这个封装,一组功能相对独立的逻辑,可以组合在一个服务内,通过skynet转发通信,为其他服务提供相应功能。常见的消息生产者,包括和客户端通信、解包的gate模块,skynet提供的timer定时驱动。服务就是对这些消息进行响应,并通过和其他服务的互动,完成自己的功能。

在这个基础上,作者抽取出了消息pattern这个概念。常见的模式有C->Gate->S, S->Gate->C, S->Gate->C*。相对的,因为服务的存在,作者还引入了额外的MQ,来处理服务间的通讯问题。同理,有Service->MQ->Service, Service->MQ->Service*。

对于玩家存档的问题,作者抽象了一个数据服务来做这个事情。对应于烂框架的DB代理进程,只能用跟项目高度相关的API进行数据读取,数据服务提供了更高层的功能:剥离游戏服务状态。剥离状态后,从skynet的角度看,所有agent、service,都是做一些简单的计算、比较、排序,最后数据都会存到数据服务上。这样的好处是,剥离了状态的skynet,随便挂,不会丢数据,对用户透明。这个思路非常棒,但是进程间通讯的代价比skynet内服务间通讯要大,怎么避免服务间通讯引起频繁的数据服务通讯,是一个值得思考的问题。

作者对我启发最大的地方,是文末推荐的那篇《The Log》,作者是LinkedIn团队的开发成员。写Log是一件非常简单和入门的事,看完the log,却发现一直忽视了对log这种数据流的视角。文章字里行间,还透着点日志式数据库的意味。这篇文章比较长,核心思路是Table和Change Log是可以相互转化的,一个Table反映了当前的状态,而Log则记录了Table一路以来的状态转换。那么,只要有Log,其实Table不再重要,因为只要我回放Log,最终就可以得到Table。**这是一个有状态到无状态的转化**!然后Log这一块可以交给成熟的中间件处理,LinkdedIn是透过卡夫卡(Kafka)来完成的。消费者的消费速度慢?不要紧,无状态服务可以无限水平扩展。消息产生了消息链?没关系,丢回到Log中,下个周期再处理,完美!

顺便推荐一篇对The Log的引用文章,来自于Yelp团队:《billions of messages a day》, 里面对利用Log进行解耦作了更深入的剖析,对兼容Log格式变更也有自己的解决办法,有空可以看看

原文地址:https://www.cnblogs.com/Lifehacker/p/game-server-pattern-analysis-and-review-of-the-log.html