rpc的正确打开方式|读懂Go原生net/rpc包

news2025/4/22 21:17:07

前言

大家好,这里是白泽,之前最近在阅读字节跳动开源RPC框架Kitex的源码,分析了如何借助命令行,由一个IDL文件,生成clientserver的脚手架代码,也分析了Kitex的日志组件klog。当然Kitex还有许多其他组件:服务注册、发现、负载均衡、熔断、限流等等,后续我也会继续分析。

我希望借助这篇文章,用尽可能少的语言,配合分析Go原生net/rpc包的部分核心代码,帮助你贯通RPC的知识,梳理RPC的运作流程,让你对RPC有一个比较全面的认识。

以此为基础,将有助于你在阅读其他开源RPC框架源码时,对比发掘开源RPC框架具体做了哪些提高。

RPC的流程

远程过程调用 (Remote Procedure Call,RPC) 是一种计算机通信协议。允许运行在一台计算机的程序调用另一个地址空间的子程序(一般是开放网络中的一台计算机),而程序员就像调用调用本地程序一样,无需额外做交互编程。

image-20220609093210634

假设你要调用一个Add(a int, b int) int方法,实现求和功能,但是这个方法部署在另一台机器上,该如何调用?

image-20220610092554101

这就是一次RPC的流程,甚至和HTTP请求/响应流程很像,眼下我先侧重于介绍RPC的概念,以后会介绍其与HTTP的区别。

并且这里暂时没有涉及所谓的服务注册、发现、负载均衡、熔断、限流等字眼,这些都是一个成熟的RPC框架应该具备的功能组件,用于确保一个RPC框架的高可用,但是却不是一个RPC框架所必需的。

RPC协议本质上定义了一种通信的流程,而具体的实现技术是没有约束的,每一种RPC框架都有自己的实现方式,比如你可以规定自己的RPC请求/响应包含消息头和消息体,使用gob/json/pb/thrift来序列化/反序列化消息内容,使用socket/http2进行网络通信,只要clientserver消息的发送和解析能对应即可。希望读者仔细体会——“约定”这个概念,这将贯穿始终。

分析net/rpc

先讲解一下流程图中的序列化和网络传输部分,这是RPC的核心。

消息编码/解码(序列化)

image-20220610105909770

上面的RPC通信流程图,其中很重要的一环就是消息的编解码,消息只有序列化之后,才能高效地参与网络传输。通过实现上图net/rpc包定义的接口,可以指定使用的编解码方式,比如net/rpc包默认使用了gob二进制编码:

image-20220610110656762

服务端负责序列化的结构gobServerCodec的实现了ServerCodec接口,服务端需要编解码消息的地方,都会调用gobServerCodec的对应方法(客户端也是类似的实现,也是一样使用gob编解码)。

消息的网络传输

消息序列化之后,是需要用于网络传输的,涉及到客户端与服务端的通信方式。

image-20220610120204483

这是服务端的接受链接的逻辑,和大部分网络应用相同,server监听了一个ip:port

,然后accept一个连接之后,会开启一个go协程处理请求与响应。

image-20220610121926769

这是客户端发起请求的方式,也印证了socket网络编程的通信模型。

理解了RPC的各个流程之后,就能梳理清楚RPC框架的各种组件是作用在哪个层面的,例如Kitex的网络库netpoll,虽然我未曾看过其源码实现,但是有理由猜测其是在网络通信/传输部分做了提高。

Server端的设计

image-20220610122814954

这是service的结构,可以看到一个服务通过Map可以绑定多个名称的方法,提供调用,且对应service需要提前注册到服务端,这样在客户端请求达到时才能准确调用。

image-20220610212015865

服务注册主要参数是serviceNameservice实体。

  • reflect.xxx():主要的工作就是通过反射的机制,解析所绑定的服务的名称、类型等。
  • suitableMethods():解析一个service绑定的所有method
  • serviceMap.LoadOrStore():将service注册到服务端serverMap,如下是Server的结构:

image-20220610212541601

Client端的设计

image-20220610214204785

这是Client的结构:

  • codec:编解码的具体实现。
  • seqRPC的序列号,每发起一个就计数增加,加入Map,且完成或失败后从Map中移除。
  • pending:配合seq工作的Map

image-20220610215611554

这是客户端具体发起一次RPC请求的过程,当然一次具体的RPC请求可以是同步的,也可以是异步的:

image-20220610220356234

  • client.Go()是异步的。
  • client.Call()是同步的,且其内部就是调用了client.Go(),但是因为其调用之后,在调用完成之前,会被阻塞在chan上,因此后续的RPC请求必须等待发送。

小结

到此为止我们粗浅的分析了net/rpc的一些核心源码,借此梳理了RPC的工作流程,主要包括:

  • RPC的编解码(序列化)协议选择
  • RPC的网络通信/传输模型(Socket编程
  • RPC的请求发起/响应接受(同步/异步)

RPC的功能组件

image-20220610223730023

一个成熟的RPC框架只实现基本的通信功能是不够的,否则它将十分的脆弱,没有任何应对服务宕机的能力,在高并发场景下也难堪重任,因此需要增加很多的功能组件来提高服务的可靠性:

  • 超时控制|请求重试|负载均衡|熔断器|限流器|日志|监控|链路追踪|…

Go原生net/rpc包也有很多提高可靠性的设计,本文没有过多展开)

结束语

这篇文章,我借助Go原生net/rpc包的部分核心源码,梳理了RPC的工作流程,试图帮助你建立RPC的全局观念,希望你明白,RPC框架是对RPC通信流程的具体实现,每一个框架为提高自身的可靠性,又延伸出了多种功能组件。

感兴趣可以关注公众号 「白泽talk」,白泽目前也打算打造一个氛围良好的行业交流群,文章的更新也会提前预告,欢迎加入:622383022。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1382717.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

sqlilabs第五十三五十四关

Less-51(GET - GET - Error based - ORDER BY CLAUSE-String- Stacked injection) 手工注入 单引号闭合,和上一关一样堆叠注入解决 自动注入 和上一关一样 Less-52(GET - challenge - Union- 10 queries allowed -Variation 1) 手工注入 这一关开始后面的可以看…

Linux 内核如何根据设备树文件来匹配内核

一. 简介 上一篇文章学习了 Linux内核如何确定是否支持此设备,如果支持,设备就会启动 Linux 内核。 文章地址如下: 设备树根节点下的compatile属性的作用-CSDN博客 本文继上面文章的学习。这里简单看一下, Linux 内核是如何根…

学习资料: uni-app HBuilderX

编译器:HBuilderX HBuilderX-高效极客技巧 uni-app介绍:uni-app官网 uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序&#…

2023.1.13 关于在 Spring 中操作 Redis 服务器

目录 引言 前置工作 前置知识 实例演示 String 类型 List 类型 Set 类型 Hash 类型 ZSet 类型 引言 进行下述操作的前提是 你的云服务器已经配置好了 ssh 端口转发即已经将云服务器的 Redis 端口映射到本地主机 注意: 此处我们配置的端口号为 8888 可点击下…

C++力扣题目617--合并二叉树

给你两棵二叉树: root1 和 root2 。 想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠&#…

【STM32】FLASH闪存

1 FLASH闪存简介 本节所指STM32内部闪存,即下载程序的时候,程序存储的地方。(非易失性) STM32F1系列的FLASH包含程序存储器、系统存储器(bootloader,不允许修改)和选项字节三个部分&#xff0…

JavaScript学习笔记——变量、作用域、var、const和let

JavaScript学习笔记——变量、作用域、var、const和let 学习链接(原链接)变量变量声明的三种方式 作用域作用域介绍作用域分类全局作用域局部作用域(函数作用域)块级作用域块级作用域和局部(函数)作用域区别 varvar的作用域(全局函…

【elastic search】详解elastic search集群

目录 1.与集群有关的一些概念 2.集群搭建 3.集群搭建 4.kibana链接集群 5.选举流程 6.请求流程 7.master的作用 1.与集群有关的一些概念 数据分片: 数据分片(shard),单台服务器的存储容量是有限的,把一份数据…

LINUX基础培训七之进程管理

前言、本章学习目标 了解LINUX中进程和程序掌握进程管理的作用和方法熟悉进程调度优先级了解LINUX信号 一、了解LINUX进程和程序 进程是正在执行的一个程序或命令,每个进程都是一个运行的实体,都有自己的地址空间,并占用一定的系统资源。 …

【Python学习】Python学习15-模块

目录 【Python学习】Python学习15-模块 前言创建语法引入模块from…import 语句from…import* 语句搜索路径PYTHONPATH 变量-*- coding: UTF-8 -*-导入模块现在可以调用模块里包含的函数了PYTHONPATH 变量命名空间和作用域dir()函数globals() 和 locals() 函数reload() 函数Py…

pytest -- 基本使用详解

1. pytest基本介绍 pytest 是一个功能强大且易于使用的 Python 测试框架,用于编写单元测试、集成测试和功能测试。 它提供了丰富的功能和灵活的用法,使得编写和运行测试变得简单而高效。 --------------->>>>> pytest框架优点&#xff1a…

C语言之字符串和指针

目录 用数组实现的字符串和用指针实现的字符串 █用数组实现的字符串str █用指针实现的字符串ptr 注意 用数组和指针实现字符串的不同点 字符串数组 用数组实现的字符串的数组——二维数组 用指针实现的字符串数组——指针数组 注意 字符串和指针有着紧密的联系&#…

C#中对浮点数NaN,PositiveInfinity,NegativeInfinity的特殊处理

NAN NAN 整体意思为Not a Number 不是一个数, NaN(Not a Number,非数)是计算机科学中数值数据类型的一类值,表示未定义或不可表示的值。常在浮点数运算中使用。首次引入NaN的是1985年的IEEE 754浮点数标准。 EEE 75…

AI-图片转换绚丽动漫人物-UGATIT

​​​​​​ 🏡 个人主页:IT贫道-CSDN博客 🚩 私聊博主:私聊博主加WX好友,获取更多资料哦~ 🔔 博主个人B栈地址:豹哥教你学编程的个人空间-豹哥教你学编程个人主页-哔哩哔哩视频 目录 ​​​​…

代码随想录算法训练营第五天天| 总结数组专题

数组:二分查找、双指针(包括快慢指针)、滑动窗口、模拟 链表:双指针、三指针、虚拟头指针、复杂指针操作画图明确每一步(标好次序) 数组 代码随想录总结的很好,如下图。我再结合自己的一些理解…

当使用WSL下载运行Docker可视化界面的镜像,使用报错

Traceback (most recent call last): File “app.py”, line 345, in root tk.Tk() File “/usr/lib/python3.8/tkinter/init.py”, line 2270, in init self.tk _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use) _tkinter.T…

java基础知识点系列——运算符(四)

java基础知识点系列——运算符(四) 算术运算符 运算符和表达式 运算符:对常量或者变量进行操作的符号表达式:用运算符把常量或者变量链接起来符合java语法的式子就可以称为表达式。不同运算符连接的表达式体现的是不同类型的表…

数据结构排序——计数排序和排序总结(附上912. 排序数组讲解)

数据结构排序——计数排序和排序总结 现在常见算法排序都已讲解完成,今天就再讲个计数排序。再总结一下 文章目录 1.计数排序2.排序总结3.排序oj(排序数组)题目详情代码思路 1.计数排序 计数排序是一种非基于比较的排序算法,它通…

苹果电脑清理内存 怎么清理删不掉的软件

苹果电脑是很多人的首选,因为它有着优秀的性能和设计。但是,随着时间的推移,你可能会发现你的苹果电脑变得越来越慢,或者出现一些奇怪的问题。这可能是因为你的电脑内存不足,或者有一些删不掉的软件占用了你的空间和资…