Skip to content

微服务中的进程间通信

微服务与单体应用是不同的,不同的微服务很可能是部署在不同的服务器上,这也就使得不同服务之间的通信不能像单体应用一样可使用语言内部函数直接调用

进程间通信(Inter-Process Communication, IPC)主要是为了满足跨服务器的调用,在这种情况下最容易想到的实现方案是 REST 和消息传递

微服务中的进程间通信概述

对于进程间通信的技术,开发者有多种选择。可以选择给予同步通信的通信机制,比如 HTTP REST;也可以选择给予异步通信的方式,Go 语言提供了标准的 net/rpc 包以支持异步。
此外,在数据的交互上,可以使用基于文本的 JSON 或 XML,也可以选择基于而进行的 gRPC,gRPC 是 Go 语言进程间通信的重要工具

交互模式

对于交互方式,可以从两个维度来进行分析,第一个维度是从客户端与服务端的交互方式来划分,这其中又包括以下几种形式

  • 一对一: 客户端的一个请求对应服务端的一个请求
  • 一对多: 客户端的一个请求,需要服务端的多个请求

第二个维度是从同步/异步模式的角度来划分

  • 同步模式: 发起请求后等待被请求服务的处理结果,直到获取结果后再进行下一步
  • 异步模式: 发起请求后不会等待处理结果再进行其他操作,而是直接进行其他操作
  • 并行模式: 多数情况下服务都是串行调用的,比如 A 调用服务 1,服务 1 又调用服务 2,形成了 A->1->2 的形式,但有些时候 A 需要同时调用 1 和 2 得到一个返回,这就是并行。并行可以提高效率

通信和服务之间的关系如图 13-1 所示

图13_1通信和服务 图 13-1 通信和服务

服务端在收到请求后,经过业务处理、消息编码等操作,最终序列化后的结果一般都放在中间消息队列中。可以看到,消息队列以外的部分对于服务端是不可见的。
不管客户端采用何种方式(同步或异步),只要服务端是处理完消息没有等待就放入消息队列的,就认为服务端是同步模式

因为这里是在介绍进程间的交互模式,不是整个框架的交互模式,所以不要把框架提供的异步认为是服务的异步。
所以,可以认为服务是天生同步的,不过在调用方式上又可以将其分为以下几种形式

  • 单向通知: 请求方向服务方发送请求到服务端,但是并不关心返回
  • 请求-响应: 请求方向服务方发起请求,然后请求方的该线程一直等待服务方的返回,这种方式在 Go 语言中比较常见,因为 Go 语言擅长处理多线程
  • 请求-响应-异步通知: 请求发起后,服务端立即开始响应,不过结果是通过异步通知的方式告知请求方的。比如缴费充值接口

服务的调用也可以认为是天生同步的。
如果是一对多的调用方式,还可以梳理出发布/订阅等方式,不过在理解了服务的天然同步性以后,这些都没有那么重要了

使用 Go 语言进行微服务开发时,进行进程间通信要比其他语言更为容易。Go 语言天生的并行性让开发人员在服务端可以更容易地进行并行模式的设计。
当然在 I/O 上还是会有瓶颈。当有高并发同时出现的时候,I/O 资源总是最珍贵的,不过 Go 语言的并行性和线程池以及消息队列的模式同样可以很好地解决这些问题。
在使用 Go 语言进行微服务开发时,可以选择 Go 语言开发的 NSQ 或 NATS 等消息框架

API 定义

当探讨 IPC 通信时,如果使用的是 HTTP1.X 协议,那么性能就非常容易成为问题。
由于 HTTP1.X 使用的是同步阻塞方式,也就是说,一个访问一个线程,因此如果内部进程间的通信非常频繁,那么很显然,使用这种方式在性能上不够优秀

如果一定要使用 Restful API 作为 IPC 选择,也应该使用 HTTP2.0,其优点如下:

  • 支持双向流
  • 可实现消息头压缩
  • 单 TCP 的多路复用
  • 服务端的推送

最推荐的是 Google 公司开源的 gRPC

protobuf 格式

进程间通信可以使用基于文本的 JSON 或者 XML 等来实现,不过在 Go 语言的微服务世界中,protobuf 使用得更为广泛

protobuf 简介

protobuf(Google Protocol Buffer)是 Google 旗下的一种平台无关、语言无关、可扩展的序列化结构数据格式,很适合作为数据存储和不同语言之间相互通信的数据交换格式。
在项目中,工程师只要编写一个协议格式(同一 proto 文件)即可,该 proto 文件将被编译成不同的语言版本加入到各自的工程中去。
这样,不同的语言就可以解析其他语言通过 protobuf 序列化的数据了。
目前官网针对 C++、Python、Java、Go 等语言提供了支持。Google 在 2008 年 7 月 7 号将其作为开源项目对外公布

相比于其他数据交互格式,protobuf 有如下优点:

  • 序列化以后体积比 JSON 和 XML 格式小,便于网络传输
  • 支持跨平台、跨语言
  • 有很好的 "向后" 兼容性
  • 序列化和反序列化速度快,高于 JSON 的处理速度

gRPC 包

gRPC 是基于 HTTP2.0 设计的,所以就有诸如双向流、流量控制、头部压缩、单 TCP 连接上的多复用请求等特性。
gRPC 也是 Google 开源出来的包,不过,Go 语言官方也提供了自己的 RPC 包

net/rpc 包

远程过程调用协议(Remote Procedure Call Protocal, RPC)是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议

简单来说,与远程访问或者 Web 请求差不多,都是一个客户端向远程服务端请求服务返回结果,但是 Web 请求使用的网络协议是高层协议 HTTP,RPC 所使用的协议多为 TCP,是网络层协议,这减少了信息的包装,加快了处理速度