【GeeRPC】7天用 Go 从零实现 RPC 框架 GeeRPC

7天用 Go 从零实现 RPC 框架 GeeRPC

这部分内容来自于 Golang 大佬 Geektutu 的七天用 Go 从零实现系列,仅做学习之用,原项目链接在此

1. 谈谈 RPC 框架

RPC(Remote Procedure Call,远程过程调用)是一种计算机通信协议,允许调用不同进程空间的程序。RPC 的客户端和服务器可以在一台服务器上,也可以在不同的机器上。程序员在使用时,可以像调用本地程序一样使用,而无需关注内部的实现细节

不同的应用程序之间通信方式有很多,比如浏览器和服务器之间广泛使用的基于 HTTP 协议的 Restful API【来自 DeepSeek:RESTful API 是一种基于 REST(Representative State Transfer,表述性状态转移)架构风格设计的 API。它使用 HTTP 协议进行通信,通常用于 Web 服务开发】。与 RPC 相比,Restful API 有相对统一的标准,因而更加通用,兼容性更好,支持不同的语言(因为它基于 http 协议)。HTTP 协议是基于纯文本的,一般具备更好的可读性。但是缺点也很明显:

  • Restful 接口需要额外定义,而 RPC 相当于直接调用;
  • 基于 HTTP 协议的 Restful 报文冗余,承载了过多的无效信息,而 RPC 通常使用自定义的协议格式(比如 protobuf),减少报文冗余;
  • RPC 可以采用更高效的序列化协议,将文本转为二进制数据(因此需要处理序列化和反序列化),获得更高的性能;
  • 因为 RPC 的灵活性,所以更容易扩展和集成诸如注册中心(比如 consul)、负载均衡等功能。

2. 重点:RPC 框架需要解决什么问题?

不如换一个问法:为什么需要 RPC 框架?

首先我们想象两台机器,两个应用程序之间需要通信,那么首先我们需要确定采用何种传输协议。如果这两个程序位于不同的机器,那么一般会选择 TCP 或 HTTP 协议;如果两个应用程序位于相同的机器,也可以采用 Unix Socket 协议【也即,首先需要确定两个应用程序之间的通信方式(通过什么协议)】。传输协议确定之后,还需要确定报文的编码格式,比如 JSON/XML,当报文较大时,还可能会选择 protobuf 等其它编码方式【确定传输协议之后,还需要确定报文的编码格式,JSON 是最常见的编码方式,protobuf 是比较新的编码方式,通常与 gRPC 相结合】。

解决了传输协议和报文编码的问题,接下来还需要解决一系列可用性问题,例如,连接超时了怎么办?是否支持异步请求和并发?【传输协议确定了两个应用程序之间的通信方式,而编码格式确定了两个应用程序之间传递数据的格式。在二者之上,还需要解决连接超时、异步请求、并发等可用性问题】

如果服务器的实例很多。客户端并不关心这些实例的地址和部署位置,只关心自己能否获取到期待的结果,这就引出了注册中心(registry)和负载均衡(load balance)的问题。简单来说,就是客户端和服务端互相感知不到对方的存在,服务端启动时将自己注册到注册中心,客户端调用时从注册中心获取所有可用的实例(这些实例对于客户端而言就像是可以直接调用的函数一样),选择一个来调用。这样客户端和服务端只需要感知注册中心的存在就足够了。注册中心通常还需要实现服务动态添加、删除,使用心跳确保服务处于可用状态等功能。【总结一下,在确定传输协议和报文编码的基础上,一个 RPC 框架还应该具有注册中心和负载均衡,注册中心比较重要,它通常应该进一步实现服务动态添加、删除、使用心跳来确保服务处于可用状态等功能】

再进一步,加入服务端由不同的团队提供,如果没有统一的 RPC 框架,各个团队的服务提供方就需要各自实现一套消息编解码、连接池、收发线程、超时处理等"业务之外"的重复技术劳动,造成整体的低效。因此,"业务之外"的这部分公共能力,是 RPC 框架所需要具备的能力。

3. 关于 GeeRPC

Golang 广泛地应用于云计算和微服务,成熟的 RPC 框架和微服务框架汗牛充栋。grpcrpcxgo-micro等都是非常成熟的框架。一般地,RPC 是微服务框架的一个子集,微服务框架可以自己实现 RPC 部分,当然,也可以选择不同的 RPC 框架作为通信基座。

考虑性能和功能,上述成熟的框架代码量庞大,且通常与第三方库(最典型的就是 gRPC 和 protobuf 的联合使用)有比较深的耦合。GeeRPC 的目的是以最少的代码,实现 RPC 框架中最重要的部分。

综上,GeeRPC 从零开始以 Golang 官方标准库的 net/rpc 为基础,新增了协议交换(protocol exchange)、注册中心(registry)、服务发现(service discovery)、负载均衡(load balance)、超时处理(timeout processing)等特性。分七天完成,代码量在 1000 行左右。

相关推荐
科技道人7 小时前
记录 默认置灰/禁用 app ‘Search Engine Selector‘ 的disable按钮
开发语言·前端·javascript
逝水无殇9 小时前
C# 异常处理详解
开发语言·后端·c#
玖玥拾11 小时前
C# 语言进阶(十五)C# 游戏服务端 MySQL 数据库
服务器·开发语言·网络·数据库·mysql·c#
铅笔侠_小龙虾11 小时前
Rust 学习目录
开发语言·学习·rust
云泽80812 小时前
从零吃透 C++ 异常:抛出捕获、栈展开、异常重抛与编码规范详解
开发语言·c++·代码规范
灯澜忆梦12 小时前
GO---可见性规则
开发语言·golang
逝水无殇12 小时前
C# 文件的输入与输出详解
开发语言·数据库·后端·c#
这是个栗子13 小时前
前端开发中的常用工具函数(八)
开发语言·前端·javascript
凤凰院凶涛QAQ13 小时前
《Java版数据结构 & 集合类剖析》栈与队列:“push/pop 是栈的灵魂,offer/poll 是队列的骨架——四组 API,两种人生”
java·开发语言·数据结构
研☆香13 小时前
为什么变量声明在赋值前也能使用?—— 深入理解 JavaScript 变量提升与作用域
开发语言·前端·javascript