二十一、服务化最佳实践

选取最合适的服务组合


1 性能和时延问题

由本地 API 调用变为远程网络通信,增加了额外的性能损耗。

1.1 RPC 框架高性能设计

  1. I/O 调度模型
  2. 序列化框架
  3. 线程调度模型:并行/无锁化算法

1.1.1 I/O 调度模型

使用 Netty,它在各种 NIO 框架中性能排名第一:

  1. 零拷贝:使用堆外内存。
  2. 内存池:使用堆外内存池。
  3. 无锁化的串行设计:尽量局部无锁化的串行线程。
  4. 高效并发编程:Volatile、CAS。

1.1.2 序列化框架

二进制序列化框架

1.1.3 高性能的 Reactor 线程模型

  1. 专门的 NIO 线程:Acceptor 线程用于监听服务端,接受客户端的 TCP 连接请求。
  2. 网络 I/O 操作:读、写等由一个 NIO 线程池负责。
  3. 1 个 NIO 线程可以同时处理 N 条链路(epoll)。

1.2 业务最佳实践

  1. 能异步的尽可能使用异步或并行服务调用。
  2. 线程池的参数配置必须合理(上下文切换损耗)。
  3. 尽量减少要传输的码流大小。
  4. 超时时间合理设置。
  5. 核心服务独立线程池。
  6. 利用 Docker 做物理资源层隔离。

2 事务一致性问题

2.1 分布式事务设计方案

使用两阶段提交(具体参考 Paxos协议)。

阶段一:全局事务管理器向所有事务参与者发送准备请求:事务参与者向全局事务管理器恢复自己是否准备就绪。
阶段二:全局事务管理器接收到所有事务参与者的回复之后做判断,如果所有事务参与者都可以提交,则向所有事务提交者发送提交申请,否则进行回滚。事务参与者根据全局事务管理器的指令进行提交或者回滚操作。

2.2 分布式事务优化

在大多数的业务场景中,我们可以使用最终一致性替代传统的强一致性,尽量避免使用分布式事务。
在实践中常用的最终一致性方案就是使用带有事务功能的 MQ 做中间人角色,它的工作原理如下:在做本地事务之前,先向 MQ 发送一个 prepare 消息,然后执行本地事务,本地事务提交成功的话,向 MQ 发送一个 commit 消息,否则发送一个 rollback 消息,取消之前的消息。MQ 只会收到 commit 确认才会将消息投递出去,所以这样的形式可以保证在一切正常的情况下,本地事务和 MQ 可以达到一致性。但是分布式调用存在很多异常场景,例如网络超时、VM宕机等,假如系统执行了 local_tx() 成功之后,还没来及将 commit 消息发送给 MQ ,或者说发送出去由于网络超时等原因, MQ 没有收到 commit ,发生了 commit 消息丢失,那么 MQ 就不会把 prepare 消息投递出去。 MQ 会根据策略去尝试询问(回调)发消息的系统(checkCommit)进行检查该消息是否应该投递出去或者丢弃,得到系统的确认之后, MQ 会做投递还是丢弃,这样就完全保证了 MQ 和发消息的系统的一致性,从而保证了接收消息系统的一致性。

3 研发团队协作问题

3.1 共用服务注册中心

为了方便开发测试,经常会在线下共用一个所有服务贡献过得服务注册中心,这时,一个正在开发中的服务发布到服务注册中心,可能会导致一些消费者不可用。
解决方案:可以让服务提供者开发方,只订阅服务(开发的服务可能依赖其它服务),而不注册正在开发的服务,通过直连测试正在开发的服务。工作原理图如下:

3.2 直连提供者

如果服务提供者多实例部署,但是服务提供者存在 BUG,就需要做远程端点调试,这会带来两个问题:

  1. 调试过程中可能被其它消费者消费。
  2. 服务提供者多实例部署,远程调试地址无法确定,调试效率低。

解决策略:直连指定服务提供者。

3.3 多团队进度协同

假如前端 Web 门户依赖后台 A/B/C/D 4 个服务,分别由 4 个不同的研发团队负责,门户要求新特性 2 周内上线。 A/B 可以按期,但是 C/D 由于有其它更高优先级的任务,只能延期。导致依赖的服务越多,交付效率越低。
解决策略:调用链将应用、服务、中间件之间的依赖关系串接并展示出来,基于调用链首入口的交付时间做输入,利用依赖管理工具,自动计算出调用链上各个服务的最迟交付时间点,避免人为需求排序失误导致的需求延期。

3.4 服务降级和 Mock 测试

3.5 协同调试问题

当依赖的服务尚未开发完成,将路由切换到模拟测试模式,自动调用 Mock 桩。上线时自动切换到真实的服务提供者。

3.6 接口前后兼容性

  1. 严格遵守兼容性代码规范,文档实时同步更新通知。

4 个人总结

事务一致性问题、测试效率问题、依赖开发等,这只列举了部分问题,还有更多的问题需要在实践中探索,找出适合自己产品的服务化最佳实践。