再谈分布式服务架构

在两年前,我曾经设计过一版,高可伸缩服务器架构, 但只进行了理论推演,并没有使用具体业务逻辑验证过。以这两年的经验来看,这个架构不具备可实施性。 在之前的架构中,我只考虑了Gate和其服务之间的交互。没有考虑其他服务之间也会有基于"玩家"的交互,还可能有基于"联盟"等其他对象的交互。 按这套模型继续演化下去,为了解决"任意两服务"之间的交互问题,势必需要所有服务都有一份相同的Agent对象。这样一来,整个架构的复杂性就大大提升了。 ……

游戏上线一个月后的反思

大约在1个月前,游戏终于上线了,在这一个月以来,服务器竟然crash了5+次,还有几次严重Bug. 除了觉得测试力度不够之外,我也在想到底有那些环节是我能做而没做好的。 仔细思考下来,出Bug的原因大概有两种典型情况。 写代码时,逻辑思维不严谨,并且函数之间耦合性过强,导致随便一个很平常的改动,都会产生新的Bug, 甚至是crash. 比如我经常写出类似下面这种函数之间耦合性过强代码。 struct foo { bool isfinish; time_t rsttime; //... }; static viod try_reset(s……

谈谈随机数的使用

在日常开发中,伪随机函数几乎是必不可少的一个函数。 大部分我们在使用这个函数时,就自然而然拿来用了,很少去思考用的对不对,反正他是随机的,并且也很难去验证(需要各种大量数据统计)。 所以即使概率看起来不太对,也可以安慰自己说,其实是统计的数据量不够。但有时候真的是因为我们误用了随机函数。 在《计算机程序设计艺术》卷2中,详细介绍了线性同余序列的生成算法。 下面就以线性同余算法为例,来分析一下,为什么随机函数还有可能被误用,他原本不就是随机的么? 在游……

Lua中的函数式编程

最近在用Lua实现Websocket协议时,碰到了一个直击我的思维惯性的弱点的Bug。代码大约如下(实际实现较为复杂,比如还支持wss协议,因此定位到问题也着实花费了一些功夫,毕竟GC的执行是异步的.): [lua] –websocket.lua local M = {} local mt = { __index = M, __gc = function(sock) close_via_c_layer(sock[1]) end} function M:connect(url) local ip,port = parse from url local fd = connect_via_c_layer(ip,port); local sock = setmetatable({fd}, mt) return so……

重构登录逻辑

终于又甩掉了一个包袱, 这是我重构完第一句想说的话。 从我入职开始, 就因为这套登录逻辑的复杂性而略为不满, 其间还坑过我一次,但是因为一直勉强能用,所以也没有理由对它动手。 这一次终于因为不能够满足新需求,而让我有理由可以重构这段代码了。 旧的登录流程大致如下: $UST=(uid,session,token) Client-------------AuthServer---------------------GameServer-----------DBProxy *--"账号密码认证" ---> * 检查账号密码, ……

Unity资源管理(续)

上次增加资源半自动释放机制之后,根据log显示已经有30%~40%的资源被释放掉了(大部分为UI资源)。然而内存问题,并没有明显改善。 我们的资源管理是通过一个叫做ABM的模块进行管理的,ABM采用标准的引用计数方案来管理资源和AssetBundle的生命周期。 当使用ABM.load_asset时会首先检查这个资源的引用计数是否为0,如果为0则会触发加载相应AssetBundle操作。 加载AssetBundle时会首先检查AssetBundle的引用计数是否为0,如果不为0则直接将引用计数加1.并将结果返回即可。 如果AssetBu……

DC3算法

最近做了一个差量更新工具, 实质就是一个Diff工具。这个Diff工具在本地生成一个patch文件。客户端通过网络下载到本地后,根据本地文件和patch文件来生成最新版本文件。 与传统patch不同的是,为了尽可能的减少网络传输,patch文件需要尽可能的小,并且不需要逆向patch(从版a到版本b生成的patch, 版本b使用这个patch可以还原到版本a). 基于以上考虑,我重新设计了一个二进制patch格式,整个patch文件中有两种Action(分别是COPY, INSERT),大致数据结构如下: [c] struct COPY { ……

开卷有益(UNIX编程艺术篇)

最近《计算机程序设计艺术》看多了,每次写完代码之后,总会习惯估算一下指令级的开销。导致每次写代码都是性能导向,违反了很多设计准则。因此打算重新看一下《UNIX编程艺术》,来拉一下已经严重倾斜的天平。 刚看了二页,又想起一个困扰我多年的问题,而没想到的是这次我似乎想到了解决办法。 在写服务器程序时,将数据持久化到数据库,是一个必不可少的操作。它需要将一个结构体进行打包,然后通过网络发给数据库,数据库再进行,并将操作结果通过网网络返回给应用程序。虽然可以……

谈谈我对数据同步的理解

We性质b和网游最大的不同也许就在于数据同步。 Web的工作流程(这里不包括页游)虽然也有很多变化,但是一般都大致分为三步。 1. 在浏览器输入网址, 浏览器通过HTTP协议请求服务器加载数据,服务器在收到HTTP请求之后,从数据库加载相应的数据(有可能是HTML,JS等一些用于浏览器渲染的数据)并返回给客户端。这一步我称之为查询。 2. 浏览器收到服务器返回的数据之后,将数据渲染并呈现给用户。这一步我称之为渲染。 3. 用户在看到浏览器呈现的内容之后,根据需要去执行不同的操作……

又一个lua调试器

最初,我并没有打算为Silly提供一个lua调试器,因为我本人不是一个重度调试器使用者。在开发期间出bug,看一下代码,打几条log可能比使用调试器会更快的找到问题,尤其是服务端程序,在很多时候其实只有log这一原始工具可以使用。但就我周围的人来推断,应该还是有很多重度调试器使用者。 因此,最终还是计划为Silly增加一个lua调试器作为基本组件存在。但是这个调试器到底以哪种方式提供调试功能,我一直在纠结中。 就我个人而言,我用过至少两种完全不同的调试器,gdb和dtrace(严……