跨服务通信标准的两种方案:框架和服务网格
在微服务应用中,关键路径的可恢复性和可用性只会和其中最薄弱的环节一致。每个服务都对应用整体的可用性有影响,当服务的依赖链中引入的新服务或者改动时,必须避免发生突发事件,显著地降低应用的可用性。同样,都不希望在故障发生时才发现关键功能不具备对这种故障的容错能力。
当应用采用了多种不同的技术或者由不同的团队负责底层的服务时,为了保证交互的可靠性,维护一套统一的方案就会变得异常困难。不同团队面临着不同的交付压力,不同的服务也有着不同的需求,最糟糕的情况是,开发者会忘记遵循可恢复性的实践。
服务拓扑结构的任何修改都会产生负面影响。为market-data服务添加一个新的下游协作服务(增强其依赖性)会降低market-data服务的可用性,而添加一个消费者又会降低market-data服务整体的容量,降低已有消费服务的可用性。
依赖链中新增服务的可用性影响框架(framework)和代理(proxy)是在两种采用跨服务通信标准的不同技术方案,它们通过默认确保服务通信的可恢复性和安全性来简化工程师们正确工作的难度。
将通信过程标准化是开发微服务基座(chassis)的重要组成部分。
框架
一种常见的确保服务间正确通信的方式是强制使用特定的类库:一套实现了断路器、重试和后备方案等常见的交互模式的类库。使用类库将所有服务之间的交互标准化有如下优点。
(1)避免使用自有方案实现服务调用,这可以提高整个应用的可靠性。
(2)简化对任意数量的服务之间的通信方案改进或优化的过程。
(3)能够从代码上清晰、一致地将网络调用和本地调用区分开。
(4)可以扩展提供支撑功能,比如收集服务调用的数据指标。
当公司内使用同一种语言(或者少数几种语言)写代码时,这种方法往往会更有效。Hystrix是Netflix公司打算为公司里的所有Java服务提供一套控制分布式服务的交互的标准方案。
服务网格
还有一种办法,可以引入Linkerd或者Envoy这样的服务网格(service mesh)系统来管理服务之间的重试、后备方案以及断路器,而不再需要每个服务自己去完成这样的功能。服务网格扮演的是代理的角色。下图阐述了服务网格处理服务间通信的过程。
服务之间通过服务网格进行通信不同于服务之间直接通信,在服务网格中,服务是通过一个服务网格应用来相互通信的,这个应用通常是作为一个单独的进程,它是和服务本身部署在同一台主机上的。开发者可以配置一个代理来管理相应的流量——对请求进行重试、管理超时或者在不同服务间进行负载均衡。从调用方的角度,这个网格并不存在——它和往常一样向另一个服务发送HTTP或者RPC调用。
虽然这种方式会导致负责服务的工程师不能确切地了解服务之间的交互处理方式,但是对于那些用多种不同技术开发的应用而言,这能够减少服务之间的通信防御性工作,提高通信安全性。否则,想要在不同的语言上都实现一致的通信方式会需要大量的投入,因为不同的生态圈或者类库在可恢复性的功能上各有不同,支持力度上也会有所差异。
摘取自 摩根·布鲁斯和保罗·A.佩雷拉的《微服务实战》