优化网络数据包

这段时间一直在跟踪腾讯测试那边反馈的bug单,把相关问题分发到相关负责同事,并实时跟踪,能修的会修一下并回归测试,没问题再提交让腾讯测试那边再回归一次。

增加了几个小需求,优化了几处代码。比较重要的是帮派拍卖功能。因为架构的原因,一个事务需要拆分为好几步。比如我竞价一个物品,需要A)先检查能不能竞价,把请求转发到其他服务那边,检查完后再根据结果是否进行下一步。之后B)才开始走网络扣钱然后等待结果,此时协程切换出去,等扣钱的请求响应回来后,再去C)修改拍卖品的数据。这里分成三步后,第二步会让出CPU,这里回来后会有些问题,下面拆分下几个具体情况以及怎么处理。

不考虑并发的情况,在理想情况下,A检查顺利通过,执行B的扣钱逻辑,响应回来后,修改物品的竞价数据。如果B回来时,玩家已经离开,那么根据lua的闭包,获取到的玩家已经无效的,再更改他的数据其实没什么用。如果B扣钱失败,逻辑没什么问题,如果扣钱成功但是玩家下线或者修改竞价物品时失败、那么走后面的对账补偿。

如果考虑两个人的并发请求同时到来,会发生什么情况呢?原始设计没有考虑到这种情况,只写了顺利情况,后来出现了P1和Q1同时竞价,导致某个人以更低的价格竞价,即少扣钱,那这个很严重的。把两个人的三个步骤分别为P1P2P3,Q1Q2Q3,如果P1检查通过,需要花2个铜钱,执行P2时挂起切换到Q1Q2顺利执行,Q1也是以2个铜钱竞价并扣钱,那么最后总有一个被覆盖,最终竞价变成2而不是正确的4。这里其实很好解决,但是有些细节需要注意和处理好,比如支付过程中超时失败,需要恢复一些状态保护,这样可以让其他人竞价,类似超时和锁的字段信息。竞价时检查通过并设置超时时间比如15秒,定时走一秒就减1,当为0时解锁。并发请求到来时,在某些操作上串行化,使得先来的人上锁,完成整个事务或者回滚状态,其他人竞价时可以暂时提示被其他人竞价等。这里一些失败的情况需要解锁拍卖品,至于设置超时时间多久还是看业务需求,一般完成一个事务应该很快,不排除网络问题。

这里主要考虑修改竞价数据时,竞价时,检查时,需要保证不同的操作看到的状态是不一样的,可能这句话我说的不是很清楚。

打个比方,我带着一百元去超市买方便面,此时钱肯定够,那么我是不是该拿着方便面去结账?而不是先结账再去拿方便面?当然方便面上又没有暂时被锁定的状态,这样其他人去购买时会提示暂时不可用,稍后再来。结账时,可能出现机器坏了,或者人不在,在或者我的钱掉了什么的,那方便面还是要放回去或者解锁状态。整个情况大概如此。

这里一个事务涉及到三个服务,一个是全局拍卖物品服务,一个是网络,一个是本场景。任何一步都可能失败,第一步失败没问题,数据状态没有改变,第二步失败,需要回滚数据状态,成功保持,第三步是建立在第二步基础上的。这里不像那种数据库中的事务提交,这里只涉及一处资源的修改,如果涉及多处,可能需要再考虑些。

一个系统功能涉及到非常多的知识点,关于他的设计方案和思路可以参考之前的,这里讨论跟具体业务没多大关系,更像是咱们平时购物时的情况。有些优化的地方,需要结合业务需求,选择处更合适的方案。

下面讨论下网络包的优化。一个场景是同屏战斗,比如一个世界BOSS,一百来个人来抢,都开了PK模式,打人也打怪,那么就需要同步很多数据,带来集中的流量下发。

比如,一般广播一个血量变化的消息,可能需要包括哪个对象,变化后的血量变化基本信息,然后上层业务不会粘包,底层网络框架设置nodelay,一个tcp包发送出去,一般会六七十个字节的小包。由于业务不同,可能立即发送,这样把一个人的hp变化广播给其他一百来个人,一秒钟一个人受击两次的话,那么一秒钟就会总共发2*100*100个这样的数据包,很吓人的。

另外不是那种接入层和业务层的分离情况,这里框架目前的实现是一个数据包发送给一百个人,需要拷贝同一条消息到这一百个消息队列中,然后走各自的发送(目前skynet新增的一个模块支持只拷贝一次,即要把广播的消息拷贝一次到一个服务中,由这个服务来广播给这一百来个人,具体实现没看过)。这里可以有优化的地方,这种信息需要做到基本实时的,不能定时发送有延迟,如果有变化实时发送那么就会有性能问题,做到适中实时。

这里每个消息包的字段不能再少了,只能粗粒度化广播消息。这里该广播的还是要广播,只是需要把频率下降,延迟短一点,均匀些,具体情况就不说了,每个人的思考不一样,多想想。

这半个月还是很累的,事情多,晚上后半夜基本写代码写不动,只能看看资料和文档。有时间就看看leveldb代码实现,今年差不多计划完成,在忙碌中度过,希望明年继续努力些,更主动承担些。

你可能感兴趣的:(优化网络数据包)