微服务架构设计原则

目录

单一责任原则

相似于编写函数代码,每一个函数只提供一个具体的功能。web

例如:你正在构建用于订购披萨的微服务。你能够基于单一责任原则构建下述组件来提供完整的服务,诸如:数据库

  • InventoryService
  • OrderService
  • PaymentService
  • UserProfileService
  • DeliveryNotificationService

InventoryService 仅仅有获取或更新披萨种类或配料库存相关的API,一样的,其余也只会提供对应功能的 API。安全

独立数据存储原则

若是你的全部微服务都共享一个数据库,这就违背了使用微服务的目的。由于对这个统一数据库的任何的改变或者故障都会影响到使用该数据库的全部微服务。架构

根据微服务的须要选择正确的数据库,定制化基础设施以及对应数据的存储,而且让微服务独占它。理想状况下,任何须要访问该数据的其余微服务只能经过拥有写权限的微服务提供的 API 来访问。框架

使用异步通讯实现松散耦合

在这里插入图片描述

同步调用仍是异步调用?异步

  • 同步调用:简单,一致性强,可是容易出调用问题,性能体验上也会差些,特别是调用层次多的时候。
  • 异步调用:既能减低调用服务之间的耦合,又能成为调用之间的缓冲,确保消息积压不会冲垮被调用方,同时能保证调用方的服务体验,继续干本身该干的活,不至于被后台性能拖慢。不过须要付出的代价是一致性的减弱,须要接受数据最终一致性。还有就是后台服务通常要 实现幂等性,由于消息发送出于性能的考虑通常会有重复(保证消息的被收到且仅收到一次对性能是很大的考验)。最后就是必须引入一个独立的 Broker(e.g. MQ),若是公司内部没有技术积累,对 Broker 分布式管理也是一个很大的挑战。

为了不构建出一个紧密耦合的组件网格(Mesh),能够考虑在微服务之间使用异步通讯。例如:服务 A 依赖服务 B。当服务 B 返回响应消息,服务 A 再返回成功给调用服务 A 的调用者。若是调用者对服务 B 的内容不关心,那么服务 A 能够异步调用服务 B,而且这个时候能够当即返回成功给调用者。分布式

一个更好的选择是在微服务通讯之间使用事件机制。你的微服务能够发布一个事件消息到消息总线上,能够用来通知一个状态的改变或者一个失败事件,而且任何对该事件感兴趣的微服务均可以得到该消息而后作出相应的处理。例如:上面提到的披萨订单系统中,当客户的订单被接收到或者订单已经完成以及运输的状态消息均可以使用异步通讯给客户发送通知消息。通知服务能够监听订单提交的消息事件而后将相应的通知推送给客户。svg

REST 仍是 RPC?函数

  • REST:基于 HTTP 协议,更容易实现,服务端技术选型也更灵活些,各个语言都能支持,同时能跨客户端,对客户端没有特殊的要求,只要封装了 HTTP SDK 就能调用,因此相对使用的广一些。
  • RPC:传输协议更高效,安全更可控,特别在一个公司内部,若是有统一个的开发规范和统一的服务框架时,他的开发效率优点更明显些。

经过 APIGW 代理微服务请求

相比于系统中的每一个微服务都单独提供 API 受权,使用一个单独 APIGW 作这些事情会更有价值。调用微服务的客户端能够链接到 APIGW 而不是直接调用微服务的接口。这种方式可让微服务避免作那些额外的调用,而且微服务内部 URL 也能够被隐藏,这能够更灵活的从 APIWG 重定向流量到一个微服务的更新版本。微服务

当容许第三方访问微服务时,那么更有必要使用这种方式,由于能够在请求到达微服务以前对传入流量进行限流以及拒绝来自 APIGW 的未受权请求。

确保 API 变动向后兼容

你能够安全的对 API 进行变动而且快速的发布它们,只要这些改变不影响已有的调用者。一种可能的选项是通知你的调用者,让他们经过集成测试来对作出的变动进行验证。可是,这种代价会比较高,由于全部依赖项都须要在一个环境中排队,这会使你的协调工做变慢。

一个更好的选项是对你的 API 使用合约测试。你的 API 消费者对 API 提供预期响应结果的合约。做为 API 提供者的你能够集成这些合约测试做为你构建的一部分而且这些能够安全的保证重大的 API 变动。消费者能够测试你发布的存根(stubs)做为他们构建的一部分。这种方式可让你经过独立测试合约变动来更快速的发布产品。

版本化微服务的重大变动

不可能让变动老是保持向后兼容。当你作了一个重大的变动的时候,同时须要继续支持老的接口,这时候能够暴露一个新版本的接口。消费者能够在方便的时候选择新的版本。

可是有太多版本的 API 对于维护相应的代码人来讲会是一场噩梦。所以,有一种规范的方法是经过和客户端一块儿协做或在内部将流量从新路由到较新的版本,从而弃用较旧的版本。

使用熔断器快速实现故障容错

若是微服务依赖于另外一个系统来提供响应,而且该系统须要很长时间才会响应,那么微服务的整体响应 SLA 将会受到影响。为了不这种场景而且快速作出响应,你须要遵循的一个简单的微服务最佳实践就是使用熔断器来使外部的调用超时,而后返回一个默认响应或者错误。

熔断模式能够隔离故障服务,而不会致使级联故障,可让整个服务系统保持在健康的状态。咱们能够选择使用 Netflix 开发的 Hystrix,这要比使用 HTTP 的 CONNECT_TIMEOUT 和 READ_TIMEOUT 更好,由于它不会启动超出配置范围的其余线程。

使用专用基础设施托管微服务

将微服务基础设施与其余组件隔离能够实现故障隔离和最佳性能,隔离微服务依赖的组件基础设施也一样重要。

例如:上面披萨订单的案例中,库存微服务使用库存数据库。使用专用的托管机器不只对于库存微服务很重要,并且对于库存数据库一样也很重要。

建立独立的发布流水线

微服务须要有一个单独的 CI/CD 流水线,这个独立的流水线不和你所在组织中的其余组件关联。这样的话你就不会和别人有冲突以及浪费和多个团队协调的时间。

创建组织效率

尽管微服务提供了独立开发和发布的自由,可是对于跨领域关注(Cross Cutting Concerns)来讲,某些标准仍是须要遵循的,这样才不会让每一个团队都花费时间为这些问题建立独特的解决方案。这在诸如微服务分布式架构中是很是重要的,在这种架构中,你须要可以链接难题(Puzzle)中的全部部分才能看清全局。所以,对于 API 安全,日志聚合,监控,API 文档,秘钥管理,配置管理,分布式追踪等,在一个企业级微服务解决方案中都是必须的。