浅谈RPC协议

article/2025/9/19 5:21:23

RPC协议

  • RPC简介
  • 为啥需要RPC
  • RPC的调用过程
  • gRPC
  • ProtoBuffer
  • gRPC实战

RPC简介

RPC(Remote Procedure Call Protocol)远程过程调用协议,目标就是让远程服务调用更加简单、透明。RPC 框架负责屏蔽底层的传输方式(TCP 或者 UDP)、序列化方式(XML/Json/ 二进制)和通信细节,服务调用者可以像调用本地接口一样调用远程的服务提供的接口,而不需要关心底层通信细节和调用过程。
在这里插入图片描述
其大致过程如上图所示。

为啥需要RPC

当我们的业务越来越多、应用也越来越多时,自然的,我们会发现有些功能已经不能简单划分开来或者划分不出来。我们平时写的项目大多数所有的模块都在一起,部署一台服务器上来,但是这也有几个问题:

  • 单台服务器的硬件资源有限,能够承受的并发量并不高
  • 任意模块的修改,都会导致整个项目代码重写编译,有可能你你只修改了只行代码并且至少一个模块的,当然你肯定只想编译这一个模块的代码就行,但是事实上整个项目需要重新编译。
  • 系统当中有些模块属于CPU密集型,有些模块是I/O密集型的,造成各模块对硬件资源的需求不一样的.当我们把这些模块打包发在同一台机器上,我们就只能综合整个模块选择内存和CPU以及网路带宽,没有办法针对每个模块选择其合适的硬件资源。

此时可以将公共业务逻辑抽离出来以及将服务进行模块拆分,将之组成独立的服务 Service 应用,而原有的、新增的应用都可以与那些独立的 Service 应用 交互,以此来完成完整的业务功能,所以我们急需一种高效的应用程序之间的通讯手段来完成这种需求,RPC 大显身手的时候来了。
但是这也有一些我们需要思考的点:

  • 大软件的模块怎么进行划分,各个模块之间可能会实现大量重复的代码
  • 各个模块之间改怎么访问?这使用的就是RPC来实现。

RPC的调用过程

要让网络通信细节对使用者透明,我们需要对通信细节进行封装,我们先看下一个 RPC 调用的流程涉及到哪些通信细节:
在这里插入图片描述

  • 服务消费方(client)调用以本地调用方式调用服务;
  • client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
  • client stub找到服务地址,并将消息发送到服务端;
  • server stub收到消息后进行解码;
  • server stub根据解码结果调用本地的服务;
  • 本地服务执行并将结果返回给 server stub;
  • server stub将返回结果打包成消息并发送至消费方;
  • client stub接收到消息,并进行解码;
  • 服务消费方得到最终结果。

而RPC的目标就是要 2~8(上面的2-8) 这些步骤都封装起来,让用户对这些细节透:
在这里插入图片描述

gRPC

1.grpc 的相关概念

什么是gRPC? gRPC 是一个高性能、通用的开源 RPC 框架,其由 Google 2015 年主要面向移动应用开发并基于 HTTP/2 协议标准而设计,基于 ProtoBuf 序列化协议开发,且支持众多开发语言。
由于是开源框架,通信的双方可以进行二次开发,所以客户端和服务器端之间的通信会更加专注于业务层面的内容,减少了对由 gRPC 框架实现的底层通信的关注。

2.gRPC的特点

  • 跨语言使用,支持 C++、Java、Go、Python、Ruby、C#、Node.js、Android Java、Objective-C、PHP 等编程语言;
  • 基于 IDL 文件定义服务,通过 proto3 工具生成指定语言的数据结构、服务端接口以及客户端 Stub;
  • 通信协议基于标准的 HTTP/2 设计,支持双向流、消息头压缩、单 TCP 的多路复用、服务端推送等特性,这些特性使得 gRPC 在移动端设备上更加省电和节省网络流量;
  • 序列化支持 PB(Protocol Buffer)和 JSON,PB 是一种语言无关的高性 能序列化框架,基于 HTTP/2 + PB, 保障了 RPC 调用的高性能;

其交互过程大概如下:
在这里插入图片描述
1.交换机在开启 gRPC 功能后充当 gRPC 客户端的角色,采集服务器充当 gRPC 服务器角色;

2.交换机会根据订阅的事件构建对应数据的格式(GPB/JSON),通过 Protocol Buffers 进行编写 proto 文件,交换机与服务器建立 gRPC 通道,通过 gRPC 协议向服务器发送请求消息;

3.服务器收到请求消息后,服务器会通过 Protocol Buffers 解译 proto 文件,还原出最先定义好格式的数据结构,进行业务处理;

4.数据处理完后,服务器需要使用 Protocol Buffers 重编译应答数据,通过 gRPC 协议向交换机发送应答消息;

5.交换机收到应答消息后,结束本次的 gRPC 交互。

ProtoBuffer

ProtoBuffer 是一种更加灵活、高效的数据格式,与 XML、JSON 类似,在一些高性能且对响应速度有要求的数据传输场景非常适用。
ProtoBuffer 在 gRPC 的框架中主要有三个作用:

  • 定义数据结构和字段
  • 定义服务的接口以及生成客户端的Stub(个人理解就是一个客户端类)
  • 通过序列化和反序列化方式提升传输效率。

为什么 ProtoBuf 会提高传输效率呢?
我们知道使用 XML、JSON 进行数据编译时,数据文本格式更容易阅读,但进行数据交换时,设备就需要耗费大量的 CPU 在 I/O 动作上,自然会影响整个传输速率。
Protocol Buffers 不像前者,它会将字符串进行序列化后再进行传输,即二进制数据。在这里不详细说明,有兴趣的可以看博客的另外一篇博客.

为什么 ProtoBuf 会提高传输效率呢?

我们知道使用 XML、JSON 进行数据编译时,数据文本格式更容易阅读,但进行数据交换时,设备就需要耗费大量的 CPU 在 I/O 动作上,自然会影响整个传输速率。

Protocol Buffers 不像前者,它会将字符串进行序列化后再进行传输,即二进制数据
gRPC 能够做到跨平台,多语言,很大一部分得益于Protobuffer自动的编译器。前面提到的 proto 文件就是通过编译器进行编译的,proto 文件需要编译生成一个类似库文件,基于库文件才能真正开发数据应用。
具体用什么编程语言编译生成这个库文件呢?由于现网中负责网络设备和服务器设备的运维人员往往不是同一组人,运维人员可能会习惯使用不同的编程语言进行运维开发,那么 Protocol Buffers 其中一个优势就能发挥出来——跨语言。

gRPC实战

在这里博主选择go语言进行演示grpc的使用,其他铁子也可以自行选择提前语言进行使用。在使用grpc之前各位铁子要安装好这个protobuf。
安装grpc最核心的库

go get google.golang.org/grpc 

上面安装是安装了这个protocol的编译器,它可以生成各种语言因此除了这个编译器我们还需要配合各个语言的代码生成工具,对于golang来说我们叫做protoc-gen-go

go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2

安装好之后我们就可以开始编写proto文件

syntax="proto3";
option go_package=".;service";//这部分内容是关于生成的go代码,在那个目录的包中,service代表生成的go文件的package是servicemessage  HelloRequest{bytes requestName=1;
}
message  HelloResponse{bytes responseMsg=1;
}
service SayHello{rpc SayHello(HelloRequest)returns(HelloResponse);
}

编写完成proto文件之后我们开始使用这个命令生成代码

protoc --go_out=. hello.proto  
protoc --go-grpc_out=. hello.proto 

在这里插入图片描述
下面我们开始编写客户端的代码

package mainimport ("context""errors""fmt""google.golang.org/grpc""google.golang.org/grpc/metadata"service "http/gRpc/server/proto""net"
)type server struct {*service.UnimplementedSayHelloServer //包含定义的sayHello方法的结构体
}func (s *server) SayHello(ctx context.Context, req *service.HelloRequest) (*service.HelloResponse, error) {//获取源数据信息md, ok := metadata.FromIncomingContext(ctx)if !ok {return nil, errors.New("未传输token")}var appId stringvar appKey stringif v, ok := md["appid"]; ok {appId = v[0]}if v, ok := md["appkey"]; ok {appKey = v[0]}fmt.Println("the appkey is" + appKey)//这里应该要去数据库里面查询,用户id appidif appId != "ksy" || appKey != "122" {return nil, errors.New("错误" + appKey + appId)}return &service.HelloResponse{ResponseMsg: []byte(req.RequestName),}, nil
}func Test() {//开启监听listen, err := net.Listen("tcp", "127.0.0.1:8909")if err != nil {panic(err)}//创建grpc服务器grpcServer := grpc.NewServer()//注册进来,在grpc 服务端当中注册我们编写的服务service.RegisterSayHelloServer(grpcServer, &server{})//启动服务if err := grpcServer.Serve(listen); err != nil {panic(err)}
}func main() {Test()
}

这个客户端对应代码

package mainimport ("context""fmt""google.golang.org/grpc""google.golang.org/grpc/credentials/insecure"service "http/gRpc/server/proto"
)func Test() {//链接server端,此处禁用安全链接conn, err := grpc.Dial(":8909", grpc.WithTransportCredentials(insecure.NewCredentials()))if err != nil {panic(err)}defer conn.Close()//建立链接client := service.NewSayHelloClient(conn)//发起远程过程调用resp, err := client.SayHello(context.Background(), &service.HelloRequest{RequestName: []byte("ksy")})fmt.Println(resp)
}type ClientTokenAuth struct {}// GetRequestMetadata 重写接口
func (c *ClientTokenAuth) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {return map[string]string{"appid":  "ksy","appKey": "122",}, nil
}func (c *ClientTokenAuth) RequireTransportSecurity() bool {//不开启安全传输return false
}// TestToke token认证
func TestToke() {var opts []grpc.DialOption//选项opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))opts = append(opts, grpc.WithPerRPCCredentials(new(ClientTokenAuth)))conn, err := grpc.Dial(":8909", opts...)if err != nil {panic(err)}defer conn.Close()//建立链接client := service.NewSayHelloClient(conn)//发起远程过程调用resp, err := client.SayHello(context.Background(), &service.HelloRequest{RequestName: []byte("ksy")})fmt.Println(err)fmt.Println(resp)
}
func main() {TestToke()
}

下面我们可以把客户端和服务端启动起来,就可以进行通信了。


http://chatgpt.dhexx.cn/article/jLj0hb7k.shtml

相关文章

网络协议——RPC协议综述

拿最简单的场景,客户端调用一个加法函数,将两个整数加起来,返回它们的和。 如果放在本地调用,那是简单的不能再简单了,。但是一旦变成了远程调用,门槛一下子就上去了。 如何解决这五个问题? …

RPC(远程过程调用协议)简介

RPC框架解释 谁能用通俗的语言解释一下什么是 RPC 框架? - 远程过程调用协议RPC(Remote Procedure Call Protocol) 首先了解什么叫RPC,为什么要RPC,RPC是指远程过程调用,也就是说两台服务器A,B&#xff0…

RPC和HTTP

一、为什么需要RPC,而不是简单的HTTP接口? RPC(即Remote Procedure Call,远程过程调用),主要是基于TCP/IP协议;而HTTP服务主要是基于HTTP协议的。我们都知道HTTP协议是在传输层协议TCP之上的&a…

RPC入门总结(一)RPC定义和原理

转载:深入浅出 RPC - 浅出篇 转载:RPC框架与Dubbo完整使用 转载:深入浅出 RPC - 深入篇 转载:远程调用服务(RPC)和消息队列(Message Queue)对比及其适用/不适用场合分析 一、RPC 1. RPC是什么 RPC(Remote Proced…

RPC协议与Http协议区别

RPC调用 RPC是远程过程调用(Remote Procedure Call)的缩写形式。SAP系统RPC调用的原理其实很简单,有一些类似于三层构架的C/S系统,第三方的客户程序通过接口调用SAP内部的标准或自定义函数,获得函数返回的数据进行处理…

RPC——RPC协议介绍及原理详解

common wx:CodingTechWork 介绍 RPC框架 概念 RPC(Remote Procedure Call Protocol) 远程过程调用协议。RPC是一种通过网络从远程计算机程序上请求服务,不需要了解底层网络技术的协议。RPC主要作用就是不同的服务间方法调用就…

RPC协议简述

RPC是指远程过程调用,也就是说两台服务器,一个应用部署在其中一台服务器上,想要调用另外一台服务器上应用提供的函数(方法),由于不在一个内存空间,不能直接调用,需要通过网络来表达调…

一文带你搞懂HTTP和RPC协议的异同

1 什么是RPC协议 1.1 简介 这是老生常谈的协议了,RPC即远程过程调用(Remote Procedure Call), RPC协议是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。 1.2 原理及模型 RPC协议广泛的…

关于RPC协议的通俗理解

根据网上搜索的一些资料摘抄汇总的,如果有误,欢迎斧正。 作者:肖继潮 链接:http://www.zhihu.com/question/25536695/answer/31046384 来源:知乎 著作权归作者所有,转载请联系作者获得授权。 早期单机时代&…

NLP之中文命名实体识别

在MUC-6中首次使用了命名实体(named entity)这一术语,由于当时关注的焦点是信息抽取(information extraction)问题,即从报章等非结构化文本中抽取关于公司活动和国防相关活动的结构化信息,而人名…

命名实体识别(biLSTM+crf)

本文是翻译的github这个项目的博客https://guillaumegenthial.github.io/sequence-tagging-with-tensorflow.html。 为什么要用biLSTM?为了使特征提取自动化。当使用CRF工具来进行命名实体识别时,需要自定义模板(或者使用默认的模板)。 任…

命名实体识别(NER)算法

文章目录 标注方案问题建模评价指标常用的NER方法深度学习方法(in survey)输入的分布式表示上下文编码解码器**先说MLPsoftmax和CRF**softmax 延伸至多标签解码 **RNN**Pointer Networks 实践Bert SoftmaxBert CRF 参考 之前做了NER的相关工作&#xf…

命名实体识别(NER):BiLSTM-CRF原理介绍+Pytorch_Tutorial代码解析

本文较全面的介绍了命名实体识别(NER),包括NER定义、BiLSTM-CRF模型、Pytorch代码实现,未来将继续完善本文,以求涵盖NER众多方面。 文章目录 命名实体识别任务(NER)定义BiLSTM-CRF模型模型输入L…

命名实体识别代码阅读

中文命名实体识别 BERT中文任务实战 18分钟快速实战_哔哩哔哩_bilibili 注意注释 from transformers import AutoTokenizer import time # 时间start time.time() #加载分词器 tokenizer AutoTokenizer.from_pretrained(hfl/rbt6) #中文bertprint(tokenizer)#分词测试&am…

命名实体识别详解

1.命名实体识别定义 例如: 2.常用开源的中英文NER工具 这些工具的缺点是:只提供通用型的实体类别如 人名,地方,组织,时间等,对于特定领域,可能很难提取出你需要的实体。 2.1 代码实践 代码来…

命名实体识别(NER – Named-entity recognition) 总结

1. 什么是命名实体识别? 命名实体识别(Named Entity Recognition,简称NER),又称作“专名识别”,是指识别文本中具有特定意义的实体,主要包括人名、地名、机构名、专有名词等。简单的讲&#xf…

命名实体识别学习笔记

1 命名实体识别概述 1.1 定义 命名实体识别(Name Entity Recognition,NER),也称作“专名识别”,是指识别文本中具有特定意义的实体,包括人名、地名、机构名、专有名词等。 1.2 形式化定义 给定标识符集…

命名实体识别的难点与现状

https://baijiahao.baidu.com/s?id1566811969925699&wfrspider&forpc 命名实体识别(Named Entities Recognition, NER)是自然语言处理(Natural Language Processing, NLP)的一个基础任务,其目的是识别语料中人名、地名、组织机构名等命名实体&…

命名实体识别研究综述

命名实体识别研究进展综述 1 引 言 命名实体识别(Named Entity Recognition,NER)的主要任务是识别出文本中的人名、地名等专有名称和有意义的时间、日期等数量短语并加以归类[ 1]。命名实体识别技术是信息抽取、信息检索、机器翻译、问答系统等多种自然语言处理技术必不可少的…

命名实体识别(基于规则-无监督学习-机器学习-深度学习)

文章目录 1 简介2 NER标注语料库3 NER工具库4 序列标注标签方案5 四类NER方法(规则-无监督学习-机器学习-深度学习)5.1 基于规则的NER5.2 基于无监督学习方法5.2 基于机器学习(含特征的有监督学习)5.3 基于深度学习方法1、输入层2…