使用 Docker 构建微服务架构,服务与服务之间的通信有什么最佳实践?

关注者
210
被浏览
22,167

17 个回答

之前各位的回复已经比较完善,这里补充最新才出现的一个概念 - SERVICE MESH(服务网格) ,对于 Kubernetes 和 Cloud Native 的拥趸而言,它值得关注。

这个概念是开发 Linkerd 的 Buoyant 公司率先使用,其定义是提供安全的、快速的、可靠地服务间通讯,对应用透明。潜台词就是所有应用流量的控制都可以在 Service Mesh 中实现。

A service mesh is a dedicated infrastructure layer for handling service-to-service communication. It’s responsible for the reliable delivery of requests through the complex topology of services that comprise a modern, cloud native application. In practice, the service mesh is typically implemented as an array of lightweight network proxies that are deployed alongside application code, without the application needing to be aware.
————What's a service mesh? And why do I need one?

Service Mesh 简单架构如下:

大量服务相互调用时,Service Mesh 架构如下:

目前比较火的 Service Mesh 开源项目是 Istio,由 Google、IBM、Lyft 共同开发,它提供了一个完整的解决方案,通过为整个服务网格提供行为洞察和操作控制来满足微服务应用程序的多样化需求。

Istio官方文档中文版介绍,Istio 逻辑上分为数据面板和控制面板。

  • 数据面板由一组智能代理(Envoy)组成,代理部署为边车,调解和控制微服务之间所有的网络通信。
  • 控制面板负责管理和配置代理来路由流量,以及在运行时执行策略。

Istio 目前仅支持在 Kubernetes 上的服务部署,但未来版本中将支持其他环境。

Service Mesh 的更详细解读,可以参考以下文章:

微服务架构越来越复杂的情况下,Service Mesh 能够让很多工作变得更简单。Kubernetes 被 Google 硬生生推进了 AWS 和 Azure,Azure Container Service(ACS)都变成以 Kubernetes 为主的 AKS 了。Istio 的前途,还是很值得期待的。

当然,英国互联网金融初创公司 Monzo 因为特定版本 Kubernetes 和 Linkerd 的不兼容引发的血案再次告诉我们,新技术应用到生产环境之前要经过缜密的论证,然而技术人员对新技术的发展,始终要保持开放的心态去了解的。


网易云为您提供容器服务,欢迎点击免费试用

参考这篇文章:

「Chris Richardson 微服务系列」微服务架构中的进程间通信

具体阅读笔记如下:

基于微服务的分布式应用是运行在多台机器上的;一般来说,每个服务实例都是一个进程。因此,如下图所示,服务之间的交互必须通过进程间通信(IPC)来实现。

对于微服务架构的交互模式,文章从两个维度进行了描述,即

一对一:每个客户端请求有一个服务实例来响应。

一对多:每个客户端请求有多个服务实例来响应。

同步模式:客户端请求需要服务端即时响应,甚至可能由于等待而阻塞。

异步模式:客户端请求不会阻塞进程,服务端的响应可以是非即时的。

对于分为这两个维度进行描述意义不太大,对于同步模式往往只能是1对1,而且还需要同步等待容易引起阻塞,而对于异步模块往往采用消息机制来实现,同时配合消息中间件可以进一步实现消息的发布订阅。而对于EDA事件驱动架构要看到其本质也是伊布消息中间件和消息的发布订阅。

异步消息机制可以做到最大化的解耦,对于数据CUD的场景可以看到是比较容易通过异步消息机制实现的,但是会进一步引入事务一致性问题,即在采用异步消息 机制后往往通过BASE事务最终一致性来解决事务层面的问题。而对于查询功能可以看到是比较难通过异步消息API实现的,在引入这个之前可以看到需要考虑 两方面的问题并解决。

其一是服务网关需要有数据缓存能力,以解决无法从源端获取数据的场景。其二是前端开发框架本身需要支持异步调用和数据装载模式,特别是对于数据查询功能对于用户来讲,在前端的感受仍然需要时同步的。即通过异步方式返回了查询数据后可以动态刷新前端展示界面。

服务版本的问题:这是不可避免要遇到的问题,特别是对于RestAPI调用,由于Json格式本身无Schema返回更加容易忽视了对服务 版本的管理和控制。要知道对于Json数据格式变化仍然会导致RestAPI调用后处理失败。因此服务版本仍然采用大小版本管理机制比较好,对于小版本变 更则直接对原有服务进行覆盖同时对所有受影响的服务消费端进行升级;而对于大版本升级则本质是新增加了一个新服务,而对于旧版本服务逐步迁移和替代。

处理局部失败:文中提到了Netfilix的服务解决方案,对于失败问题的解决要注意常用的仍然是服务超时设置,断路器机制,流量控制,缓存数据或默认值返回等。不论采用哪种失败处理策略,都需要考虑应该尽量减少服务调用失败或超时对最终用户造成的影响。

基于请求/响应的同步 IPC

使用同步的、基于请求/响应的 IPC 机制的时候,客户端向服务端发送请求,服务端处理请求并返回响应。一些客户端会由于等待服务端响应而被阻塞,而另外一些客户端可能使用异步的、基于事件驱动的客户端代码,这些代码可能通过 Future 或者 Rx Observable 封装。然而,与使用消息机制不同,客户端需要响应及时返回。这个模式中有很多可选的协议,但最常见的两个协议是 REST 和 Thrift。

Thrift 也能够让你选择传输协议,包括原始 TCP 和 HTTP。原始 TCP 比 HTTP 更高效,然而 HTTP 对于防火墙、浏览器和使用者来说更友好。文中对于两种实现方式已经描述的相当详细,可以看到当前互联网OpenAPI平台和微服务架构实现中仍然是大量以采用Rest API接口为主。

而对于消息格式的选择,可以看到在使用RestAPI接口的时候,更多的是采用了Json消息格式而非XML,对于SOAP WebService则更多采用了XML消息格式。如果采用Thrift则还可以采用二进制消息格式以提升性能。