微服务架构指的是将大型复杂系统按功能或者业务需求垂直切分成更小的子系统,这些子系统以独立部署的子进程存在,它们之间通过轻量级的、跨语言的同步(比如REST,gRPC)或者异步(消息)网络调用进行通信。
微服务架构的重要特征:
- 整个应用程序被拆分成相互独立但包含多个内部模块的子进程。
- 与模块化的单体应用(Modular Monoliths)或 SOA 相反,微服务应用程序根据业务范围或领域垂直拆分。
- 微服务边界是外部的,微服务之间通过网络调用(RPC 或消息)相互通信。
- 微服务是独立的进程,它们可以独立部署。
- 它们以轻量级的方式进行通信,不需要任何智能通信通道。
微服务最佳实践
- 单一责任原则
就像代码中的类一样,它仅仅在单个原因情况下改变,微服务也是采用类似的方式建模。构建可能会改变一个以上的业务这种臃肿的服务是一个坏的实践。
- 独立的数据存储
如果你的所有微服务都共享一个数据库,这就违背了使用微服务的目的。对这个数据库的任何的改变或者故障都会影响使用该数据库的所有微服务。根据微服务的需要选择正确的数据库,定制化基础设施以及对应数据的存储,并且让你的服务独占它。理想情况下,任何需要访问该数据的其他微服务只能通过拥有写权限的微服务提供的API来访问。
- 使用异步通信实现松散耦合
为了避免构建出一个紧密耦合的组件网格(Mesh),可以考虑在微服务之间使用异步通信。
- 使用熔断器快速实现故障容错
如果你的微服务依赖于另一个系统来提供响应,并且该系统需要很长时间才会响应,那么你的总体响应SLA将会受到影响。为了避免这种场景并且快速做出响应,你需要遵循的一个简单的微服务最佳实践是使用熔断器来使外部的调用超时,然后返回一个默认响应或者错误。熔断器模式可以参考最下面的引用。这种方式可以隔离故障服务,而不会导致级联故障,可以让你的服务保持在健康的状态。
- 通过API网关代理微服务请求
相比于系统中的每个微服务都单独提供API授权,请求/相应日志以及限流功能,使用一个单独API网关做这些事情会更有价值。调用你微服务的客户端可以连接到API网关而不是直接调用微服务接口。这种方式可以让你的微服务避免做那些额外的调用,并且微服务内部URL可以被隐藏,这可以让你更灵活的从API网关重定向流量到一个微服务的更新版本。当允许第三方访问你的微服务时,那么更有必要使用这种方式,因为你可以在请求到达微服务之前对传入流量进行限流以及拒绝来自API网关的未授权请求。你也可以选择一个单独的外部网关,让它可以接收外部网络的流量。
- 确保API变更向后兼容
你可以安全的对API进行变更并且快速的发布它们,只要这些改变不影响已有的调用者。一种可能的选项是通知你的调用者,让他们通过集成测试来对做出的变更进行验证。但是,这种代价会比较高,因为所有依赖项都需要在一个环境中排队,这会使你的协调工作变慢。一个更好的选项是对你的API使用合约测试。你的API消费者对API提供预期响应结果的合约。
- 版本化微服务重大变更
不可能让变更总是保持向后兼容。当你做了一个重大的变更的时候,同时需要继续支持老的接口,这时候可以暴露一个新版本的接口。消费者可以在方便的时候选择新的版本。但是有太多版本的API对于维护相应的代码人来说会是一场噩梦。因此,有一种规范的方法是通过和客户端一起协作或在内部将流量重新路由到较新的版本,从而弃用较旧的版本。
- 使用专用基础设施托管微服务
你已经开发出了满足所有检查的最好的微服务,但是使用了一个很差的托管平台,那么最终的效果依然会表现的很差。将你的微服务基础设施与其他组件隔离可以实现故障隔离和最佳性能。隔离微服务依赖的组件基础设施也同样重要。
- 创建独立的发布通道
你的微服务需要有一个单独的发布通道,这个通道不和你所在组织中的其他组件关联。这样的话你就不会和别人有冲突以及浪费和多个团队协调的时间。
- 建立组织效率
尽管微服务给你提供了独立开发和发布的自由,但是对于跨领域关注(cross cutting concerns)来说,某些标准还是需要遵循的,这样才不会让每个团队都花费时间为这些问题创建独特的解决方案。这在诸如微服务分布式架构中是非常重要的,在这种架构中,你需要能够连接难题(puzzle)中的所有部分才能看清全局。因此,对于API安全,日志聚合,监控,API文档,秘钥管理,配置管理,分布式追踪等,企业级解决方案是必须要有的。