通讯机制
前言
在微服务架构中,为了彻底隔绝不同服务,采用了最坚决的方案:强制要求不同服务之间通过远程访问方式进行通讯。
在这点上,微服务和以OSGi为代表的Java模块化方案形成鲜明对比。
访问方式
在微服务间做远程访问,目前主要的方式是有以下三种类型:
- REST
- RPC
- 定制
后面我们详细介绍前两种方式的做法和可选的常见实现方案。
第三中定制方式,简单说就是自己按照需要选择不同的类库:
- 网络通讯,可以选择 netty/mina等
- 协议可以选择 HTTP/HTTP2/TCP/UDP 等
- 编解码方案 可以选择 Rest/protocol buffer/thrift 等
然后以上三种情况可以有多种排列组合,最后的结果可以是五花八门,就不一一列举了。
网络通讯类库
在涉及网络通讯时,必然会有选择网络通讯类库的问题,目前主要是各种 NIO 类库。
在介绍具体的访问方式之前,先过一下 NIO 类库,后面的各种访问方式都有可能使用到这些 NIO 类库。
交互方式
进程间通讯的交互方式,可以分为两个维度:
第一个维度是交互对象的数量
- 一对一: 每个客户端请求确切地被一个服务实例处理
- 一对多: 每个客户端请求被多个服务实例处理
第二个维度是交互时应答的返回方式
- 同步: 客户端期待服务在一定时间内应答,当等待时客户端甚至会阻塞
- 异步: 客户端在等待应答时不阻塞,而应答不需要立即发送
两个维度组合之后得到多种可能的方式:
One-to-One | One-to-Many | |
---|---|---|
Synchronous | Request/response | |
Asynchronous | Notification | Publish/subscribe |
Asynchronous | Request/async response | Publish/async responses |
一对一的交互方式:
- Request/response: 标准的请求/应答方式。客户端发送请求到服务并等待应答。客户端期待应答在适当的时间内到达。在基于线程的程序中,发起请求的线程在等待时可能阻塞。
- Notification(或者单路请求): 客户端发送请求到服务但是不期待有答复。
- Request/async response: 客户端发送请求到服务,服务器端异步给回复。客户端在等待时不阻塞,而在设计上通常是假定可能不会很快就有应答。
一对多的交互方式:
- Publish/subscribe: 客户端发布通知消息,然后被0个或者多个关注的服务消费
- Publish/async responses: 客户端发布请求消息,然后等待一定数量的从关注的服务返回的应答