佛山网站建设科技公司,用开源源码做淘宝客网站,主题字体wordpress,企业建站流程前言
大家好#xff0c;这里是白泽#xff0c;之前最近在阅读字节跳动开源RPC框架Kitex的源码#xff0c;分析了如何借助命令行#xff0c;由一个IDL文件#xff0c;生成client和server的脚手架代码#xff0c;也分析了Kitex的日志组件klog。当然Kitex还有许多其他组件这里是白泽之前最近在阅读字节跳动开源RPC框架Kitex的源码分析了如何借助命令行由一个IDL文件生成client和server的脚手架代码也分析了Kitex的日志组件klog。当然Kitex还有许多其他组件服务注册、发现、负载均衡、熔断、限流等等后续我也会继续分析。
我希望借助这篇文章用尽可能少的语言配合分析Go原生net/rpc包的部分核心代码帮助你贯通RPC的知识梳理RPC的运作流程让你对RPC有一个比较全面的认识。
以此为基础将有助于你在阅读其他开源RPC框架源码时对比发掘开源RPC框架具体做了哪些提高。
RPC的流程
远程过程调用 (Remote Procedure CallRPC) 是一种计算机通信协议。允许运行在一台计算机的程序调用另一个地址空间的子程序一般是开放网络中的一台计算机而程序员就像调用调用本地程序一样无需额外做交互编程。 假设你要调用一个Add(a int, b int) int方法实现求和功能但是这个方法部署在另一台机器上该如何调用 这就是一次RPC的流程甚至和HTTP请求/响应流程很像眼下我先侧重于介绍RPC的概念以后会介绍其与HTTP的区别。
并且这里暂时没有涉及所谓的服务注册、发现、负载均衡、熔断、限流等字眼这些都是一个成熟的RPC框架应该具备的功能组件用于确保一个RPC框架的高可用但是却不是一个RPC框架所必需的。
RPC协议本质上定义了一种通信的流程而具体的实现技术是没有约束的每一种RPC框架都有自己的实现方式比如你可以规定自己的RPC请求/响应包含消息头和消息体使用gob/json/pb/thrift来序列化/反序列化消息内容使用socket/http2进行网络通信只要client和server消息的发送和解析能对应即可。希望读者仔细体会——“约定”这个概念这将贯穿始终。
分析net/rpc
先讲解一下流程图中的序列化和网络传输部分这是RPC的核心。
消息编码/解码序列化 上面的RPC通信流程图其中很重要的一环就是消息的编解码消息只有序列化之后才能高效地参与网络传输。通过实现上图net/rpc包定义的接口可以指定使用的编解码方式比如net/rpc包默认使用了gob二进制编码 服务端负责序列化的结构gobServerCodec的实现了ServerCodec接口服务端需要编解码消息的地方都会调用gobServerCodec的对应方法客户端也是类似的实现也是一样使用gob编解码。
消息的网络传输
消息序列化之后是需要用于网络传输的涉及到客户端与服务端的通信方式。 这是服务端的接受链接的逻辑和大部分网络应用相同server监听了一个ip:port
然后accept一个连接之后会开启一个go协程处理请求与响应。 这是客户端发起请求的方式也印证了socket网络编程的通信模型。
理解了RPC的各个流程之后就能梳理清楚RPC框架的各种组件是作用在哪个层面的例如Kitex的网络库netpoll虽然我未曾看过其源码实现但是有理由猜测其是在网络通信/传输部分做了提高。
Server端的设计 这是service的结构可以看到一个服务通过Map可以绑定多个名称的方法提供调用且对应service需要提前注册到服务端这样在客户端请求达到时才能准确调用。 服务注册主要参数是serviceName和service实体。
reflect.xxx()主要的工作就是通过反射的机制解析所绑定的服务的名称、类型等。 suitableMethods()解析一个service绑定的所有method。 serviceMap.LoadOrStore()将service注册到服务端server的Map如下是Server的结构 Client端的设计 这是Client的结构
codec编解码的具体实现。seqRPC的序列号每发起一个就计数增加加入Map且完成或失败后从Map中移除。pending配合seq工作的Map。 这是客户端具体发起一次RPC请求的过程当然一次具体的RPC请求可以是同步的也可以是异步的 client.Go()是异步的。client.Call()是同步的且其内部就是调用了client.Go()但是因为其调用之后在调用完成之前会被阻塞在chan上因此后续的RPC请求必须等待发送。
小结
到此为止我们粗浅的分析了net/rpc的一些核心源码借此梳理了RPC的工作流程主要包括
RPC的编解码序列化协议选择RPC的网络通信/传输模型Socket编程RPC的请求发起/响应接受同步/异步
RPC的功能组件 一个成熟的RPC框架只实现基本的通信功能是不够的否则它将十分的脆弱没有任何应对服务宕机的能力在高并发场景下也难堪重任因此需要增加很多的功能组件来提高服务的可靠性
超时控制请求重试负载均衡熔断器限流器日志监控链路追踪…
Go原生net/rpc包也有很多提高可靠性的设计本文没有过多展开
结束语
这篇文章我借助Go原生net/rpc包的部分核心源码梳理了RPC的工作流程试图帮助你建立RPC的全局观念希望你明白RPC框架是对RPC通信流程的具体实现每一个框架为提高自身的可靠性又延伸出了多种功能组件。 感兴趣可以关注公众号 「白泽talk」白泽目前也打算打造一个氛围良好的行业交流群文章的更新也会提前预告欢迎加入622383022。