《企业级容器云架构开发指南》—2.3.2 微服务的进程间通信
2.3.2 微服务的进程间通信
在单体式应用中,各个模块之间的调用是通过编程语言级别的方法或者函数来实现的。但是一个基于微服务的分布式应用是运行在多台机器上的。一般来说,每个服务实例都是一个进程。因此服务之间的交互必须通过进程间通信(IPC)来实现。
1. IPC通信类型
当为某一个服务选择IPC时,首先需要考虑服务之间如何交互。客户端和服务器端之间有很多的交互模式,我们可以从两个维度进行归类。
第一个维度是这些交互是一对一还是一对多:
一对一:每个客户端请求有一个服务实例来响应。
一对多:每个客户端请求有多个服务实例来响应。
第二个维度是这些交互是同步还是异步:
同步模式:客户端请求需要服务器端即时响应,甚至可能由于等待而阻塞。
异步模式:客户端请求不会阻塞进程,服务器端的响应可以是非即时的。
表2-2显示了不同交互模式。
表2-2 不同的交互模式
一对一的交互模式有以下几种方式。
请求/响应:一个客户端向服务器端发起请求,等待响应。客户端期望此响应即时到达。在一个基于线程的应用中,等待过程可能造成线程阻塞。
通知(也就是常说的单向请求):一个客户端请求发送到服务器端,但是并不期望服务器端响应。
请求/异步响应:客户端发送请求到服务器端,服务器端异步响应请求。客户端不会阻塞,而且被设计成默认响应,不会立刻到达。
一对多的交互模式有以下几种方式。
发布/ 订阅:客户端发布通知消息,被零个或者多个感兴趣的服务消费。
发布/异步响应:客户端发布请求消息,然后等待从感兴趣服务发回的响应。
每个服务都是以上这些模式的组合,对某些服务,一个IPC机制就足够了;而对另外一些服务则需要多种IPC机制组合。
了解了交互模式,接下来看看如何定义API。API是服务器端和客户端之间的契约,不管选择了什么样的IPC机制,重要的是使用某种交互式定义语言(IDL)来精确定义一个服务的API。在开发之前,需要先定义服务的接口,并与客户端开发者详细讨论并确认。这样的讨论和设计会大幅度提高API的可用度以及满意度。API定义实质上依赖于选择哪种IPC。如果使用消息机制,API则由消息频道(channel)和消息类型构成;如果使用HTTP机制,API则由URL和请求、响应格式构成。
2. IPC技术
目前有很多不同的IPC技术,服务之间的通信可以使用同步的请求/响应模式,如基于HTTP的REST或者Thrift。另外,也可以选择异步的、基于消息的通信模式,如AMQP或者STOMP。
对于同步方式而言,我们可以用请求/响应来概括整个过程,发起方发起一个远程调用后,发起方会阻塞自己并等待整个操作的完成,同步对于响应的低延迟有高要求,因而在目前这也是不太实际的。
异步的通信模型有两种。一种是基于消息的请求/响应方式,这与同步的不同,当使用基于异步交换消息的进程通信方式时,一个客户端通过向服务器端发送消息提交请求。如果服务器端需要回复,则会发送另外一个独立的消息给客户端。因为通信是异步的,客户端不会因为等待而阻塞,相反客户端理所当然地认为响应不会立刻接收到。
另外一种是基于事件的方式,服务提供方不发起请求,而是发布一个事件,然后期待调用方接收消息,并知道该怎么做,服务提供方不需要知道什么会对此做出响应,这也意味着可以在不影响服务提供方的情况下对该事件添加新的订阅。
使用消息机制有很多优点:
解耦客户端和服务器端:客户端只需要将消息发送到正确的channel。客户端完全不需要了解具体的服务实例,更不需要一个发现机制来确定服务实例的位置。
Message Buffering:在一个同步请求/响应协议中,如HTTP,所有的客户端和服务器端必须在交互期间保持可用。而在消息模式中,消息broker(代理)将所有写入channel的消息按照队列方式管理,直到被消费者处理。也就是说,在线商店可以接受客户订单,即使下单系统很慢或者不可用,只要保持下单消息进入队列就好了。
弹性客户端–服务器端交互:消息机制支持以上说的所有交互模式。
直接进程间通信:基于RPC机制,试图唤醒远程服务看起来跟唤醒本地服务一样。
然而,消息机制也有自己的缺点:
额外的操作复杂性:消息系统需要单独安装、配置和部署。消息broker必须高可用,否则系统的可靠性将会受到影响。
实现基于请求/响应交互模式的复杂性:请求/响应交互模式需要完成额外的工作。每个请求消息必须包含一个回复渠道ID和相关ID。服务器端发送一个包含相关ID的响应消息到channel中,使用相关ID来将响应对应到发出请求的客户端。这个时候使用一个直接支持请求/响应的IPC机制会更容易些。
- 点赞
- 收藏
- 关注作者
评论(0)