背景介绍
公司是一家小的游戏公司,日活百万左右,同时最高在线人数30w左右。公司的核心服务使用C++开发,生产环境是windows.
游戏基础服务主要职责就是承载公司游戏的登陆、业务逻辑、通知、游戏数据结算、玩家信息统计等功能,而具体的游戏逻辑在各个游戏团队的游戏服务中负责。
游戏基础服务一旦出现问题,玩家就无法游戏,因为无法登陆、无法结算…. 所以是需要高可靠的服务。
我的主要职责就是维护基础服务的稳定运行。
以上是职责介绍,下面是刚入职时基础服务的架构。
早期的架构
架构基本是按照业务单元进行分服务开发,但也不像微服务那么细微。
大致讲解:
整个架构是比较清晰的,而且按照功能进行划分,所有服务都支持横向扩展,db使用分库分表设计。所以在性能上、横向扩展都没有太大问题。
但实际在维护的过程中,还是会发现很多不合理的地方。
- 升级一个简单的功能,需要重启很多重要的服务。每次升级都很纠结
- 版本发布、代码编写很不方便
- 出现问题定位很费时间
- 问题随机、随时出现,没任何预兆
…………
大量的非工作时间被白白浪费!!!!!!!!
不合理的地方
1 | 自己的备忘录里面记录了服务大致需要整改的点有100多处 |
生产工具落后
使用的还是VC6 编译器。
无法使用c++1x的语法、写代码不方便、开源库不好支持等等
没有持续集成环境
版本发布依赖领导的时间。(生产环境的版本必须由领导的机器编译),有次出现问题,问题定位5分钟,版本发布却花了3个小时。
服务无法灰度升级
服务升级都要在凌晨6点升级,而且升级过程中整体服务无法使用
单个服务异常影响整体
整个架构里面服务相互链接构成网状,当某个服务异常时,常常会关联其他服务出现异常
整体服务容错性不足
单台block、check异常,就会导致这个节点上的所有玩家和游戏出现异常
没有健康监控功能
出现问题都是玩家反馈,研发自己都不知道服务是否出现异常;
没有预警机制
当性能、内存、io等不足时没有提早告知进行准备
定位方法落后
采用原始的vistual stdio 调试,没有分析dump的能力
msmq 功能扩展、维护、定位麻烦
服务的管理、配置落后
整体架构缺陷
这个涉及点比较多,后续慢慢展开。
整改原因
就是想做!!
优化点
升级开发工具到vs2013
服务性能监控
服务消息堆积数量、进程cpu、磁盘容量、提交内存大小 数据到大数据平台。
出现问题时,基本都是第一时间就能够在钉钉收到预警通知。
使用jenkins进行持续集成
windbg分析的持续培训
C++的优化
原来都采用的MFC的CMap、CString、线程、锁等都需要替换为stl、boost类型
调整架构,支持灰度发布
1 | 目前还在持续优化中 |
设计的方法:
模块设计“幂等性”
服务尽量无状态
这样游戏、玩家可以随机指定链接,然后引入负载均衡+域名管理,就可以方便地地给服务器导流,支持灰度升级重试次数控制 + 熔断
redis缓存、MQ 异步
隔离设计
将影响玩家的业务和统计业务,中间搭建 actik中转服务隔离开来
所有下游统计业务都需要经过actik服务进行清洗,然后才能到具体的业务服务中去玩家隔离
比如将pc、移动、微信玩家连接的服务进行隔离,减少影响面。使用rabbitmq替换msmq
rabbitmq支持AMQP协议,扩展、管理、维护都非常方便数据库的优化
分库、分表;购买新硬件、数据备份、导入导出
使用mqsql 替换sql server
总结
无意间看到一篇服务弹力设计的文章,总结的比我好,自己就是朝这个方向在调整!
后续计划
引入稳定的gate服务
统一配置中心
linux化
服务go语言化
效果
- 基础服务稳定性提高非常明显,两年就没出现过重大事故。
- 升级也方便了很多,大部分都可以灰度升级。
- 线上出现问题也能快速定位,出现问题心不慌。