项目现有架构缺陷与解决方案

代码框架部分

Cache(缓存)

项目现状

  • 线上部署的是 redis cluster.
  • 线下(开发环境) 部署的也是 redis cluster.
  • 代码里面支持 memcached, redis, redis cluster. 扩展了三套实现.
  • redis 驱动采用的 go-redis package.

问题描述

  • 开发环境不必要使用redis cluster. 可能是想跟线上保持一致,所以线下跟线上是一样的部署方案. 直接使用单节点redis即可.在配置方面也可以支持兼容线上的集群. 开发环境搭建更容易,效率更高.

  • 代码里面不必要支持 memcached. memcached 作为早期的缓存模块, 最近些年已经逐步被redis替代. 目前只有个别特性适合使用memcached. 对于大部分项目而言, 能把redis用好就可以了.

  • go-redis 包虽然很受欢迎, 但是官方更推荐redigo包作为golang的redis驱动. go-redis包把常用命令已封装,不利于开发人员扩展,不够灵活. 可以考虑换掉.

  • 代码的书写规范不良. 开发人员经验不足的情况下, 容易写出 性能低, 不安全, 维护性低 的代码.

解决方案

  • 线上 redis cluster 规格保持不变, 调整要兼容线上实例.
  • 线下环境 采用单节点部署. 这样简单方便.
  • 代码里面 memcached 模块删除掉.
  • 驱动 把 go-redis 更换为 redigo 包, 且我们自己封装相关API, 模块的扩展性和灵活性以及维护性都更高.
  • 提供各个场景下的代码书写规范. 让其他同事在写新代码时做参考.

方案评估

  • 优先度:
    重要&紧急
  • 人天數:
    1人, 6-8day
  • 預期效果:
    • 提高开发效率和可维护性,减少或避免数据覆盖问题导致的数据不一致性,减少此类bug
    • 正确使用可使服务器性能大幅提升,负载能力提升,用户体验更流畅.

通信协议

此问题主要是指项目由之前通信协议强转弱,代码调整了一半的问题分析.

问题描述

  • Gin框架是一个小巧强大的http框架. 其最重要的两个特性是中间件参数自动解析. 这两个特性在我们项目中并没有得到应有的发挥.
  • HTTP协议,body里面存放的是PB格式的二进制数据. 从业内经验上来看, 很少有这么设计的.
  • 当前很多函数的代码过于冗余,重复代码过多.

解决方案

  • 优化Gin框架模块.

  • 支持更多的中间件,把业务代码里面的各种检测工作以及日志相关代码工作都提取到中间件环节. 提升商业代码编写效率.

  • 新的接口都采用 Http的普通传参+参数自动解析的方式进行.

  • 封装公共response结构以及API.

  • 所有接口必须编写接口文档. 方便 client/server 开发同学查阅, 贡献资料库, 对新人也有帮助.

方案评估

  • 优先度:
    重要&不紧急
  • 人天數:
    2人(前后端各1), 40-60day (此项任务可以分阶段完成)
  • 預期效果(阶段1 20day):
    • 符合业内规范
    • 定制相关规范完成
    • 1/3的接口那可纳入中间件管理.商业逻辑代码得到精简.并发能力提升.
  • 預期效果(阶段2 20day):
    • 2/3的接口调整完毕.
  • 預期效果(阶段3 20day):
    • 接口调整全部完成
    • 为后面的架构优化提供基础.

PlayerMgr_handle_Command

问题描述
项目中的Gateway服务在处理User Request时,使用了异步处理的方式,所有请求都封装到了特定的Channel中.由一个Goroutine(用户态线程)统一处理. 个人猜测这么写的原因可能是由于之前在使用强连接时的处理机制.现在改为弱连接后继续沿用了. 这种处理方式带来的问题:

  • 多线程转单线程处理,丢弃了golang的天然并发优势.
  • 线性处理请求.一旦有请求阻塞或耗时,后面的请求都要排队等待.在用户量大的时候非常容易导致阻塞等待甚至timeout等情况.
  • 服务的运行性能更加低效.

解决方案
这块代码不敢贸然更改, 不太清楚业务是否真的需要单线程来处理(预防多线程安全问题)

  • 如果没有多线程安全问题 或者 安全问题可以预防的话, 这个处理机制是要改成并发的方式更优.

方案评估

  • 优先度:
    重要&紧急
  • 人天數:
    1人, 8day
  • 預期效果:
    • 压榨服务器性能,提升负载能力以及服务响应及时性.
    • 减少由于请求量过大带来的通讯阻塞甚至loadding和timeout问题.

ORM(对象关系映射)

ORM框架技术大约流行与五六年前. 主要用在DB模型到程序代码结构的自动转换 以及 帮助开发者自动生成SQL语句. 可以在开发过程中提高开发效率和安全性

问题描述

  • 我们的项目中使用的是标准库自带的sql基本驱动. 跟 java 里面jdbc驱动类似.
  • 由于没有使用orm框架技术.可能会带来开发效率的降低 和 维护性降低.
  • 项目中的大部分sql业务都是使用的SP.这种写法大约是好多年前流行的.早些年软件的服务器为了避免因为sql语句的更改而重新启动服务器,多采用SP的sql写法.当然也有一些其他原因(sql语句需要跨库调用,提升部分性能等). 我们这个项目不晓得什么原因没有使用orm技术.

解决方案

  • 可以考虑引入 xorm 或者 grom 包.
  • 符合业内主流开发技术栈.

方案评估

  • 优先度:
    不重要&不紧急
  • 人天數:
    多人, N day (此项调整改动量较大)
  • 預期效果:
    • 符合业内规范
    • 提升开发效率.

配置文件管理

问题描述

  • 配置与程序相分离, 微服务的概念里面有要尽量使程序保持独立和轻量.所以配置文件通常都是需要隔离出去管理的.我们的项目现在还在使用本地配置文件以及大量的控制台启动参数.

  • 配置内容热更新, 我们项目的配置热更新是依赖定时器实现的.不能够及时的察觉配置变化.

解决方案

  • 采用 etcd 组件管理项目中用到的所有配置文件内容.
  • 调整项目代码调整以支持动态热更新.

方案评估

  • 优先度:
    不重要&不紧急
  • 人天數:
    1人, 8day
  • 預期效果:
    • 符合业内规范
    • 提升开发效率.

其他问题

由于时间有限对项目代码了解的深度不足, 对业务或者其他模块的代码问题暂作保留, 多是一些封装和优化问题.

服务架构部分

日志服务器

现有架构

  • 日志记录分散
  • 影响服务器性能
  • ELK集成了存储与查阅分析功能
  • 缺失告警系统

调整架构

  • 日志统一归类,云存储
  • 对系统性能影响小
  • 需要调研合适的对接云端存储的查阅分析工具

方案评估

  • 优先度:
    重要&不紧急
  • 人天數:
    2 人, 20 day
  • 預期效果:
    • 所有日志可以统一流入log_server统一管理.
    • 告警系统可以第一时间让相关人员感知错误的发生,迅速响应处理问题.

API网关服务

为什么需要有API网关(盗用别人的一张图)

当前我们的项目可以说没有API网关(gateway其本质是大厅服务器).

解决方案

  • 后期要增加适合我们的API网关.

方案评估

  • 优先度:
    重要&不紧急
  • 人天數:
    N 人, N day (需要前面几项任务作为前提条件)
  • 預期效果:
    • 客户端与后端的耦合度降低,支持 安全、流控、过滤、缓存、监控等 API 管理功能,好处太多.
    • 强大的服务器必然有一个强大的API网关.

消息队列服务

问题描述
当前我们客户端要展示的公告类消息都是通过客户端的定时器不停的到服务端去拉取的.这无疑会对服务器造成大量的无用请求.浪费服务端资源. 如果把拉取频率降低,则用户不能及时得到最新消息.有损用户体验. 如果同一时间数据量过大,也存在爆数据的问题.

解决方案

  • HTTP + Websocket 并走. 编写一个推送服务.当有消息需要发送给用户时,第一时间推送给用户. 此链路,客户端只做保活和接收消息,不做其他消息发送.
  • Http -> 所有的请求/应答.
  • Wsocket -> 只接收服务端的推送,断线自动重连上即可.

架构图

方案评估

  • 优先度:
    重要&不紧急
  • 人天數:
    2 人, 30 day
  • 預期效果:
    • 所有需要让客户端知道的讯息内容,可以第一时间推送给用户.
    • 服务内部可以通过MQ做高效数据中转,降低服务雪崩风险.
    • 可以检测用户的网络环境,真实的登陆和登出时间等其他数据.

服务架构

综上所述,服务架构未来可调整的方向:

现有架构

调整架构

  • API Gate: 客户端的唯一入口.流量 协议 安全 日志 统计 过滤 等一系列问题 都可以这个服务负责. 后方的内部服务专心做商业逻辑即可.
  • Push : 专门负责用户的消息及时消息推送. 搭配Gate的高并发,提升用户体验.
  • 协议: Client与Gamte以及Push只需要简单的http(json)协议即可. 服务内部可选[http|grpc].
  • 绿色节点的服务是服务用户的, 蓝色节点的是服务内部的系统服务.
  • 补一套MQ(消息队列系统)组成数据管理集群, 可以支持 日志 用户推送消息 异步调用 等功能模块.
  • 日志服务器 与 定时任务 服务器 作为区分集群的平台级服务 在大后方提供服务.
  • 缺少一个 etcd 配置管理器节点…

方案评估

  • 优先度:
    重要&不紧急
  • 人天數:
    N 人, N day (需要前面几项任务作为前提条件)
  • 預期效果:
    • 我的目标是10W DAU,不知道大家希望是…
    • 专业强大的服务架构是我们走向巨人的基石.