前言
看到这个标题,你可能会有一些问题:
- 什么是 RPC,是解决什么问题;
- 什么是 Service Mesh,现代的 RPC 形态和它有什么关系。
让我们通过下面这些内容来理解他们。
- 服务架构的演化史;
- 如何完成一次基本的 RPC 调用;
- 一些扩展需求:服务容错、监控和治理;
- 基于 Docker 与 Service Mesh 之上的现代化 RPC 形态
服务架构的演化史
服务架构大体分为这么几个阶段:
- 单体架构时代;
- HTTP 接口通信架构时代;
- "RPC", “消息队列” 承载的微服务架构时代;
单体架构
相信在几年前有过服务开发经验的同学,都有这样一段经历。那是个应用部署方式还比较匮乏的年代,大部分互联网公司开发、发布应用的方式是这样的。
所有的项目开发者会在一个项目中开发,通过 git 管理版本历史,在完成代码开发后,将代码编译打包,通过 scp 传递到云主机上,然后 ssh 到云主机上执行启动命令来完成发布。
项目还小的时候,这样的方式既快又省事。但随着项目逐渐变大,慢慢就会发现了一些问题:
- 系统庞大时,任何一次小改动都需要长时间的编译;
- 每次小功能的调整,都需要发布整个项目,增大引入问题的风险;
- 前后端的代码在一个项目中部署,前端页面更新也需要整个项目重新发布,增大引入问题的风险;
- 如果应用宕机,所有服务都将不可用。
似乎发现了这些问题,所以开发者也试图做一些改造。
HTTP 接口通信架构
最初的改造,是将单体服务按照大的模块进行拆分,然后模块与模块之间暴露出一些 HTTP 的服务,提供互相之间的功能调用的能力。
比如,一个电商网站的开发,将它拆成商品模块,订单模块和库存模块等等,这些服务分别启动在各自的域名之上,提供出 HTTP 的访问协议。
那么,用户完成一次下单操作,需要以 HTTP 的形式调用订单模块、商品模块和库存模块提供出来的 API。
这其实已经是微服务架构的原型了,但仍有一些问题:
- 每次 HTTP 接口调用,都包含域名解析和 LB 层转发的过程,增加了调用链路以及复杂度;
- HTTP 协议比较灵活,URL、headers(Cookies 和其他 headers)、body 都可以作为数据承载的载体,影响最终的服务调用结果,且出现问题时不容易追溯;
- 性能上,HTTP 1.0 的不复用连接的形式,也会给性能造成一些负担。
微服务架构
总结 HTTP 接口通信架构的一些问题:
- 域名解析与 LB 层转发带来的调用链路增加与 Response Time 的影响;
- HTTP 协议灵活,所以需要一套规范化传输方式;
- 连接不复用对于内网环境的服务调用不是一个好选择。
看起来问题的根因,是 HTTP 从设计之出,不是为服务间调用量身定制的。所以解决问题的方式,似乎就是设计一套专门用于内网之间服务调用的方案了。
这个方案其实早在 1988 年就有人在 RFC 中提出,即 RPC,全称 "Remote Procedure Call Protocol"。
完成一次基本的 RPC 调用
理解 RPC 调用,可以类比本地的函数调用。
function Add(a: number, b: number) {
return a + b;
}
const methods = {
Add
};
function call(method: string, args: []) {
return methods[method](...args);
}
call('Add', ['hello', 'world']);
而 RPC 做的事情,就是按照一定协议,允许你的程序调用