详解微服务技术中进程间通信

在单体应用中,一个组件调用其它组组件时,是通过语言级的方法或者函数调用,而一个基于微服务的应用是运行于多个服务器上的分布式系统,每个服务实例是一个典型的进程 。所以,如下图显示的,服务必须通过内部进程交互机制(IPC)进行交互 。

详解微服务技术中进程间通信

文章插图
 
 
交互风格 
在为一个服务选择IPC的时候,首先考虑一下这些服务是如何交互的是很有用处的 。有多种client/server的交互风格,它们可以通过两个维度分类,第一种维度是交互是一对一,还是一对多的:
 
  • 一对一:每个客户端的请求只被一个服务实例处理
  • 一对多:每个客户端请求被多个服务实例处理
  • 第二种维度是交互是同步的还是异步的:
  • 同步:客户端期望从服务得到及时的返回,并且甚至可以因此阻塞片刻
  • 异步:客户端不会在等待返回结果的时候阻塞,返回结果也没必要立刻被发送出来
 
下表显示出各种交互风格:
详解微服务技术中进程间通信

文章插图
 
有如下几种一对一的交互形式:
 
请求/响应:客户端发送一个请求给一个服务,并且等待响应结果,客户端期望结果能快速的返回,在一个基于线程的应用中,发送请求的线程甚至可能在等待的时候被阻塞 。
  • 通知(一种单向请求):客户端发送一个请求到服务,但不期望有响应发送回来 。
  • 请求/异步响应:客户端往服务发送请求,响应结果异步的返回 。客户端不会在等待的时候阻塞,而且客户端是基于响应在一段时间之后才返回的假设来设计的 。
有如下几种一对多的交互形式:
  • 发布/订阅:客户端发布消息,消息被零或者多个感兴趣的服务消费
  • 发布/异步响应:客户端发布一个请求消息,等待固定的一段时间,以获得从感兴趣的服务返回的响应结果
 
每个服务一般都使用这几种交互风格的组合风格 。对于一些服务来说,单一的IPC机制就足够了,而其它的服务可能需要组合使用若干种IPC机制 。下面的图给出当客户请求行程时,在一个打车应用可能出现的一些交互 。
详解微服务技术中进程间通信

文章插图
 
 
这些服务使用了通知,请求/响应,发布/订阅的交互方式 。比如说,一个乘客的智能手机向行程管理服务发送了一个上车请求,行程管理服务通过请求/响应方式向乘客服务确认乘客的账户是否是活跃账户,行程管理服务于是创建一个行程订单,并且用发布/订阅方式通知其它的服务,包括一个分发服务,用以定位空闲的司机 。
 
定义API 
服务的API是服务与它所有的客户端之间的一种契约,不管选用何种IPC机制,使用一些接口定义语言(IDL),对于精确定义服务API是很重要的,甚至已经有一些关于使用API-first Approach来定义服务的好的讨论 。
 
开发一个微服务从书写接口定义以及与客户端开发人员一起review这些接口定义开始,在不断的对这些API定义进行迭代,最终才算是实现了一个微服务 。这种基于前端的设计方式,增加了构建出符合客户端需求的机会 。
 
在文章的后面你会看到,API定义的特性依赖与你使用的IPC机制,如果你使用消息机制,API就会涉及到消息通道和消息类型;如果你选用HTTP方式,那么API就会包含一些URL和请求/响应的格式,之后我们会详细的介绍IDL 。
 
API的演进 
一个服务的API会随着时间而经常变化 。在单体应用中,通常是很直接的修改API,再更新所有的调用之处,但在基于微服务的应用中,情况要困难得多,甚至你API的所有消费者是同一个应用中的其它服务 。你通常不能强迫所有的客户端步调一致的升级它们的服务 。而且你可能会大量的开发服务的新版本,于是新旧版本的服务会同时运行,制定一个处理这种问题的战略原则显得很重要 。
 
如何处理一个API的变化,取决于这种变化的多少 。有的变化很少,可以向后兼容之前的版本,比如,你可能只是在请求或者响应格式中增加一些属性 。设计出具有鲁棒原则的客户端和服务是有意义的,那些使用更旧的API的客户端应该能够继续和新版本的服务工作得很好,服务会给请求中没有的属性提供默认值,客户端会忽略那些响应中额外的属性 。使用IPC机制和消息格式是重要的,让你能轻易的演进API 。


推荐阅读