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

前言

大家好,这里是白泽,之前最近在阅读字节跳动开源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.mzph.cn/news/620994.shtml

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

相关文章

RXJS中Subject, BehaviorSubject, ReplaySubject, AsyncSubject的区别?

在RxJS(Reactive Extensions for JavaScript)中,Subject、BehaviorSubject、ReplaySubject和AsyncSubject都是Observable的变体,它们用于处理观察者模式中的不同场景。以下是它们之间的主要区别: 1、Subject: 是一种特…

在ubuntu平台上安装minecraft

一、获取minecraft启动器安装包 登陆minecraft官网Welcome to the Minecraft Official Site | Minecraft,使用已经购买minecraft的microsoft或者mojang账号登陆。 点击Download Launcher 对于ubuntu系统,使用点击debian版本 此后便会自动下载Minecraft.…

gcc -l 参数说明

gcc -l 参数说明 -l参数就是用来指定程序要链接的库,-l参数紧接着就是库名,那么库名跟真正的库文件名有什么关系呢? 就拿数学库来说,他的库名是m,他的库文件名是libm.so,很容易看出,把库文件名…

【STM32】FLASH闪存

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

Spring Cloud整体架构解析

Spring Cloud整体架构 本文已收录至我的个人网站:程序员波特,主要记录Java相关技术系列教程,共享电子书、Java学习路线、视频教程、简历模板和面试题等学习资源,让想要学习的你,不再迷茫。 Spring Cloud的中文名我们就…

pytorch学习笔记(八)

Sequential 看看搭建了这个能不能更容易管理,CIFAR-10数据集进行 看一下网络模型CIFAR-10模型 1 2 3 4 5 6 7 8 9 输入进过一次卷积,然后经过一次最大池化&#…

YOLOv7基础 | 手把手教你简化网络结构之yolov7.yaml(包括源码+封装步骤+网络结构图)

前言:Hello大家好,我是小哥谈。通过下载YOLOv7源码可知,原始的yolov7.yaml文件是拆开写的,比较混乱,也不好理解,并且为后续改进增添了很多困难。基于此种情况,笔者就给大家介绍一种将yolov7.yam…

企业如何判断定岗定编是否合理?

定岗定编是一项最为基础的人力资源管理工作。定岗是指明确企业所需要的岗位;定编是指明确企业需要多少适合企业发展的个人。在企业组织结构确定之后,紧接着的问题就是定岗定编。定岗定编涉及企业业务目标的落实、员工能力和数量的匹配,科学合…

已解决java.lang.NoSuchFieldException异常的正确解决方法,亲测有效!!!

已解决java.lang.NoSuchFieldException异常的正确解决方法,亲测有效!!! 文章目录 问题分析 报错原因 解决思路 解决方法 总结 问题分析 NoSuchFieldException是一个常见异常,它通常与反射(Reflectio…

深入理解 Spark(三)SparkTask 执行与 shuffle 详解

SparkTask 的分发部署与启动流程分析 Spark Action 算子触发 job 提交 Spark 当中 Stage 切分源码详解 Task 的提交与执行 SparkShuffle 机制详解 MapReduceShuffle 全流程深度剖析 MapReduce 全流程执行过程中参与工作的组件以及他们的执行先后顺序:InputFormat …

【AIGC】电影风格的一组绝美高清图提示词解析

实际示例 女人主角,以时尚电影风格为灵感,追求照片般的逼真度,运用伦勃朗式光线,创造奇幻且细节丰富的场景,充满象征意义,使用3D渲染技术达到8K超高清晰度。 分类相关信息主角女人风格时尚电影风格逼真度…

LLM漫谈(三)| 使用Chainlit和LangChain构建文档问答的LLM应用程序

一、Chainlit介绍 Chainlit是一个开源Python包,旨在彻底改变构建和共享语言模型(LM)应用程序的方式。Chainlit可以创建用户界面(UI),类似于由OpenAI开发的ChatGPT用户界面,Chainlit可以开发类似…

5 个适用的免费数据恢复软件【2024 年 版本】

互联网上有许多免费的数据恢复软件产品。有些产品是免费软件,而其他产品则提供该工具的免费试用下载以进行评估。我们列出了2024 年 5 款最佳数据恢复工具 ,可以免费下载和试用。 5 个适用的免费数据恢复软件 1.奇客数据恢复(Windows和Mac&am…

Apache-Common-Pool2中对象池的使用方式

最近在工作中,对几个产品的技术落地进行梳理。这个过程中发现一些朋友对如何使用Apache的对象池存在一些误解。所以在写作“业务抽象”专题的空闲时间里,本人觉得有必要做一个关于对象池的知识点和坑点讲解。Apache Common-Pool2 组件最重要的功能&#…

中仕公考:2024年上半年中小学教师资格考试(笔试)报名已开始

2024年上半年中小学教师资格考试(笔试)报名工作于1月12日开始,此次笔试在31个省(自治区、直辖市)举办,各省(自治区、直辖市)的报名公告将陆续上网。 个别地区报名截止时间有所差异,上海1月13日报名截止,浙江、天津、河南1月14日截…

负荷预测 | Python基于CEEMDAN-VMD-BiGRU的短期电力负荷时间序列预测

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 提出一种分解去噪、重构分解的 CEEMDAN-VMD-BiGRU组合预测方法: 1 采用CEEMDAN将原始电力负荷数据分解成一组比较稳定的子序列,联合 小波阈值法将含有噪声的高频分量去噪,保留含有信…

微服务技术要点

一、服务注册到nacos 1.下载nacos,修改nacos启动模式为单机模式,另外需要在环境变量配置JAVA_HOME,否则启动不起来。 2.启动类加注解EnableDiscoveryClient 3.application.yml配置nacos地址 spring:cloud:nacos:discovery:server-addr: 127.0.0.1:884…

springboot怎样设置全局的traceId(包括MQ)

一、Controller打印TraceId 1、拦截所有的controller,输入输出将traceId放入MDC中: package com.perkins.ebicycle.mobile.trace;import java.util.Arrays; import java.util.List; import java.util.UUID; import java.util.stream.Collectors;import…

华为设备登录安全配置案例

知识改变命运,技术就是要分享,有问题随时联系,免费答疑,欢迎联系! 厦门微思网络​​​​​​ https://www.xmws.cn 华为认证\华为HCIA-Datacom\华为HCIP-Datacom\华为HCIE-Datacom Linux\RHCE\RHCE 9.0\RHCA\ Oracle O…

Python+甘特图及标签设置

图示 甘特图代码 import matplotlib.pyplot as plt import numpy as npclass ProjectEmement:def __init__(self, name_, starttime_: float, endtime_: float, fact_endtime_: float, grade_, rootlist_: list, keylist_: list, isover_=-1):self.name = name_self.starttime…