微服务架构( 二 )

有哪些挑战微服务的架构优势是有代价的,在采用微服务架构之前,我们要认识到未来可能面临的挑战:

  • 架构复杂度高 。相对于单体应用,微服务应用有很多可变的组件 。每个服务都更简单了,但整个系统变得更复杂了 。
  • 开发和测试麻烦,尤其是集成测试 。在实现一个微服务时,如果它依赖了其他服务,编写和测试过程都会比单体应用更复杂 。现存的工具在设计时可能并未考虑到服务依赖 。如果我们要对相互依赖的多个服务进行重构,难度也会比重构单体应用高 。在测试时,涉及到服务依赖,需要单独维护多套与线上相似的测试环境 。考虑到每个服务都有多个测试版本,迭代比较快时,很容易出问题 。
  • 互相独立的服务,很难做治理 。由于微服务以区中心化的方式去构建各个服务,在服务治理上增加了额外的难度 。最终整个应用中可能包含多个编程语言,使用了多种框架,开发人员可以更自由地选择小众的技术,导致后期维护成本反而更高 。
  • 容易产生网络拥塞和延迟 。很多小且功能独立的服务需要通过API或消息队列继续频繁的通信 。由于底层走网卡进行通信,对比单体架构的代码库依赖,网络通信的代价可能很高 。当服务的依赖链很长时,比如 A调用B,B调用C,C调用...,额外的网络延迟会高到无法接受 。所以在设计服务时,需要慎重考虑API的设计,应避免过度繁琐的API,考虑到编码格式(二进制协议优于文本协议),优先使用异步通信模式或消息队列模式;
  • 跨服务的数据一致性问题 。每个微服务负责自身的数据持久化,导致多个服务的数据可能存在不一致 。通常我们使用最终一致性原则解决这些问题;
  • 服务管理难度高 。微服务架构的成功采用离不开成熟的DevOps文化 。处理跨服务的日志追踪,尤其是一个用户操作触发整个链路的微服务调用,日志都要记录下来,并且在发生错误时,能够把整个调用链的日志拉取出来;
  • 服务的发布版本管理 。在更新服务时,不能对API做破坏性的更新,否则依赖它的服务可能会挂掉 。由于多个开发团队在同一时间段可能都要对服务做更新,所以接口设计必须保持向前或向后兼容 。一个典型的低级错误是:删除了API定义的某些字段,或修改了某些字段的业务含义;
  • 要求研发团队懂分布式系统 。微服务通常是分布式的,需要认真评估团队是否具备对应的能力和经验;
最佳实践
  • 基于业务场景对服务进行建模;
  • 尽量去中心化 。每个团队都要负责设计和构建服务,避免分享代码或底层数据结构 。
  • 数据存储只允许单个服务访问,每个服务根据自己的业务需求设计选择存储方案和数据格式 。
  • 服务间通过设计良好的API进行通信,应尽量避免透露实现细节 。API的定义应当基于业务场景进行设计,而不是根据内部的技术实现进行设计 。
  • 避免服务间的耦合 。服务间耦合的原因通常是把数据库schema透传给外部,或通信协议弹性比较差 。
  • 将跨业务域的需求交给API Gateway来处理,比如身份认证、SSL验证 。
  • 保持API Gateway的纯粹性,不掺入业务逻辑 。API Gateway只处理和转发client侧的请求,不感知任何业务逻辑 。否则API Gateway将成为一个依赖,导致服务间的耦合 。
  • 服务间应该高内聚、低耦合 。应该一起变化的逻辑应该被打包到一个服务里,统一部署 。如果他们分散在不同的服务里,这些服务将高度耦合在一起,一个服务的更新也将连锁导致另一个服务的更新 。两个服务间繁琐的通信是“高耦合低内聚”的体现 。
  • 故障隔离 。应当采取一定的恢复策略,以避免一个服务的故障引发连锁反应 。




推荐阅读