0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

RPC的机制的诞生和基础概念

马哥Linux运维 来源:马哥Linux运维 2024-03-11 10:06 次阅读

【摘要】 Rpc基本概念RPC(Remote Procedure Call)远程过程调用,是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议,简单的理解是一个节点请求另一个节点提供的服务。RPC只是一套协议,基于这套协议规范来实现的框架都可以称为 RPC 框架,比较典型的有 有阿里巴巴的 Dubbo、Google 的 gRPC、Facebook 的 Thrift 和 Twitt...

Rpc基本概念

RPC(Remote Procedure Call)远程过程调用,是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议,简单的理解是一个节点请求另一个节点提供的服务。RPC只是一套协议,基于这套协议规范来实现的框架都可以称为 RPC 框架,比较典型的有 有阿里巴巴的 Dubbo、Google 的 gRPC、Facebook 的 Thrift 和 Twitter 的 Finagle 等。

RPC 机制和实现过程

RPC 是远程过程调用的方式之一,涉及调用方和被调用方两个进程的交互。因为 RPC 提供类似于本地方法调用的形式,所以对于调用方来说,调用 RPC 方法和调用本地方法并没有明显区别。

RPC的机制的诞生和基础概念

1984 年,Birrell 和 Nelson 在 ACM Transactions on Computer Systems 期刊上发表了名为“Implementing remote procedure calls”的论文,该文对 RPC 的机制做了经典的诠释:

RPC 远程过程调用是指计算机 A 上的进程,调用另外一台计算机 B 上的进程的方法。其中A 上面的调用进程被挂起,而 B 上面的被调用进程开始执行对应方法,并将结果返回给 A,计算机 A 接收到返回值后,调用进程继续执行。

发起 RPC 的进程通过参数等方式将信息传送给被调用方,然后被调用方处理结束后,再通过返回值将信息传递给调用方。这一过程对于开发人员来说是透明的,开发人员一般也无须知道双方底层是如何进行消息通信和信息传递的,这样可以让业务开发人员更专注于业务开发,而非底层细节。

RPC 让程序之间的远程过程调用具有与本地调用类似的形式。比如说某个程序需要读取某个文件的数据,开发人员会在代码中执行 read 系统调用来获取数据。

当 read 实际是本地调用时,read 函数由链接器从依赖库中提取出来,接着链接器会将它链接到该程序中。虽然 read 中执行了特殊的系统调用,但它本身依然是通过将参数压入堆栈的常规方式调用的,调用方并不知道 read 函数的具体实现和行为。

当 read 实际是一个远程过程时(比如调用远程文件服务器提供的方法),调用方程序中需要引入 read 的接口定义,称为客户端存根(client-stub)。远程过程 read 的客户端存根与本地方法的 read 函数类似,都执行了本地函数调用。不同的是它底层实现上不是进行操作系统调用读取本地文件来提供数据,而是将参数打包成网络消息,并将此网络消息发送到远程服务器,交由远程服务执行对应的方法,在发送完调用请求后,客户端存根随即阻塞,直到收到服务器发回的响应消息为止。

下图展示了远程方法调用过程中的客户端和服务端各个阶段的操作。

469a3e84-dec9-11ee-a297-92fbcf53809c.png

总结下RPC执行步骤:

调用客户端句柄,执行传递参数。

调用本地系统内核发送网络消息。

消息传递到远程主机,就是被调用的服务端。

服务端句柄得到消息并解析消息。

服务端执行被调用方法,并将执行完毕的结果返回给服务器句柄。

服务器句柄返回结果,并调用远程系统内核。

消息经过网络传递给客户端。

客户端接受数据。

安装gRPC和Protobuf

gRPC由google开发,是一款语言中立、平台中立、开源的远程过程调用系统
gRPC客户端和服务端可以在多种环境中运行和交互,例如用java写一个服务端,可以用go语言写客户端调用
在gRPC中,我们可以一次性的在一个 proto文件中定义服务并使用任意的支持gRPC的语言去实现客户端和服务端,整个过程操作变得简单,就像调用本地函数一样。

通过 proto生成服务端代码,也就是服务端的骨架,提供低层通信抽象
通过 proto生成客户端代码,也就是客户端的存根,隐藏了不同语言的差异,提供抽象的通信方式,就像调用本地函数一样。

安装

go getgithub.com/golang/protobuf/proto

go getgoogle.golang.org/grpc(无法使用,用如下命令代替)

git clonehttps://github.com/grpc/grpc-go.git$GOPATH/src/google.golang.org/grpc

git clonehttps://github.com/golang/net.git$GOPATH/src/golang.org/x/net

git clonehttps://github.com/golang/text.git$GOPATH/src/golang.org/x/text

go get -ugithub.com/golang/protobuf/{proto,protoc-gen-go}

git clonehttps://github.com/google/go-genproto.git$GOPATH/src/google.golang.org/genproto

cd $GOPATH/src/

go installgoogle.golang.org/grpc

go getgithub.com/golang/protobuf/protoc-gen-go

上面安装好后,会在GOPATH/bin下生成protoc-gen-go.exe

但还需要一个protoc.exe,windows平台编译受限,很难自己手动编译,直接去网站下载一个,地址:https://github.com/protocolbuffers/protobuf/releases/tag/v3.9.0,同样放在GOPATH/bin下

proto 服务定义

gRPC 使用protocol buffer 来定义服务接口,protocol buffer和 XML、JSON一样是一种结构化数据序列化的可扩展存储结构,protocol buffer是一种语言中立,结构简单高效,比XML更小更简单,可以通过特殊的插件自动生成代码来读写操作这个数据结构。

import "myproject/other_protos.proto";// 导入其他 proto文件
syntax = "proto3"; // 指定proto版本
package hello;     // 指定默认包名

// 指定golang包名
option go_package = "hello";

message SearchRequest 
{
  required string query = 1;// 必须赋值字段
  optional int32 page_number = 2 [default = 10];// 可选字段
  repeated int32 result_per_page = 3;// 可重复字段 
}

message SearchResponse 
{
  message Result // 嵌套定义
  {
    required string url = 1;
    optional string title = 2;
    repeated string snippets = 3;
  }
  repeated Result result = 1;
}

message SomeOtherMessage 
{
  optional SearchResponse.Result result = 1;// 使用其他消息的定义
}

service List{// 定义gRPC服务接口
rpc getList(SearchRequest) returns (SearchResponse);
}
// 插件自动生成gRPC骨架和存根
protoc --go_out=plugins=grpc: ./ *.proto

后面需要实现服务端具体的逻辑就行,然后注册到gRPC服务器
客户端在调用远程方法时会使用阻塞式存根,所以gRPC主要使用同步的方式通信,在建立连接后,可以使用流的方式操作。
客户端编排为protocol buffer的格式,服务端再解排执行,以HTTP2 传输

gRPC 优势

更高效的进程通信:使用基于protocol buffer在Http2 中以二进制协议通信,而不是JSON、XML文本格式

简单定义的服务接口、易扩展

强类型、跨语言

一元RPC、服务端流、客户端流、双工流

gRPC入门

简单使用

protocol buffer

syntax = "proto3";
package hello;
// 第一个分割参数,输出路径;第二个设置生成类的包路径

option go_package = "./proto/hello";
// 设置服务名称
service Greeter {
  // 设置方法
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// 请求信息用户名.
message HelloRequest {
  string name = 1;
}

// 响应信息
message HelloReply {
  string message = 1;
}

服务端

package main

import (
"context"
"flag"
"fmt"
"log"
"net"

"google.golang.org/grpc"
pb "mygrpc/proto/hello"
)

var (
port = flag.Int("port", 50051, "The server port")
)

type server struct {
pb.UnimplementedGreeterServer
}

func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
log.Printf("Received: %v", in.GetName())
return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}

func main() {
flag.Parse()
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
// 开启rpc
s := grpc.NewServer()
// 注册服务
pb.RegisterGreeterServer(s, &server{})
log.Printf("server listening at %v", lis.Addr())
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}

客户端

package main

import (
"context"
"flag"
"log"
"time"

"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
pb "mygrpc/proto/hello" // 引入编译生成的包
)

const (
defaultName = "world"
)

var (
addr = flag.String("addr", "localhost:50051", "the address to connect to")
name = flag.String("name", defaultName, "Name to greet")
)

func main() {
flag.Parse()
// 与服务建立连接.
conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
// 创建指定服务的客户端
c := pb.NewGreeterClient(conn)

// 连接服务器并打印出其响应。
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
// 调用指定方法
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: *name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetMessage())
}

客户端连接gRPC服务器以后,就可以像调用本地函数一样操作远程服务器。

审核编辑:黄飞

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 计算机
    +关注

    关注

    19

    文章

    7137

    浏览量

    86990
  • 服务器
    +关注

    关注

    12

    文章

    8656

    浏览量

    84400
  • JAVA
    +关注

    关注

    19

    文章

    2942

    浏览量

    103985
  • RPC
    RPC
    +关注

    关注

    0

    文章

    110

    浏览量

    11471

原文标题:RPC简介和grpc的使用

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    HarmonyOS跨进程通信—IPC与RPC通信开发

    一、IPC与RPC通信概述 基本概念 IPC(Inter-Process Communication)与RPC(Remote Procedure Call)用于实现跨进程通信,不同的是前者
    的头像 发表于 02-02 17:47 1058次阅读
    HarmonyOS跨进程通信—IPC与<b class='flag-5'>RPC</b>通信开发

    聊聊Dubbo - Dubbo可扩展机制实战

    摘要: 在Dubbo的官网上,Dubbo描述自己是一个高性能的RPC框架。今天我想聊聊Dubbo的另一个很棒的特性, 就是它的可扩展性。1. Dubbo的扩展机制在Dubbo的官网上,Dubbo描述
    发表于 06-04 17:33

    RPC的结构原理是什么?

    远程过程调用(RPC)是一个协议,程序可以使用这个协议请求网络中另一台计算机上某程序的服务而不需知道网络细节。(过程调用有时也称作函数调用,或子例行程序调用。)RPC使用client/server模型。请求程序是client,而服务提供程序则为server。
    发表于 10-12 10:43

    直连设备怎么rpc双向控制

    Thing***oard提供非常强大的可视化部件,除了图表、地图车联网外,还有控制部件,通过mqtt rpc可以轻松实现平台 -- 设备端 设备到平台双向数据传输及控制。Thingboard 连接
    发表于 07-12 06:55

    RPC是什么

    RPC是什么?RabbitMQ又是什么?
    发表于 10-08 09:24

    【学习打卡】OpenHarmony的RPC连接介绍

    常规过程调用返回一样。注意:RPC特别适合客户端-服务器(例如查询-响应)交互,其中控制流在调用者和被调用者之间交替。从概念上讲,客户端和服务器不会同时执行。相反,执行线程从调用者跳转到被调用者,然后再
    发表于 07-28 18:13

    什么是RPC

    什么是RPC   英文原义:Remote Procedure Call Protocol 中文释义:(RFC-1831)远过程调用协议 注  解:一种通过
    发表于 02-23 11:48 897次阅读

    什么是RPC?为什么需要RPC

    首先要明确一点:RPC可以用HTTP协议实现,并且用HTTP是建立在 TCP 之上最广泛使用的 RPC,但是互联网公司往往用自己的私有协议,比如鹅厂的JCE协议,私有协议不具备通用性为什么还要用呢?因为相比于HTTP协议,RPC
    的头像 发表于 04-16 12:49 1.5w次阅读
    什么是<b class='flag-5'>RPC</b>?为什么需要<b class='flag-5'>RPC</b>?

    RPC的JAVA实现工作原理

    在传统的开发模式中,我们通常将系统的各个服务部署在单台机器,随着服务的扩展,这种方式已经完全无法满足系统大规模的扩展需要,分布式系统由此诞生,在分布式系统中,最重要就是各个服务之间的 RPC 调用。
    的头像 发表于 05-05 23:39 3410次阅读
    <b class='flag-5'>RPC</b>的JAVA实现工作原理

    为什么需要RPC接口

    论复杂度,RPC框架肯定是高于简单的HTTP接口的。但毋庸置疑,HTTP接口由于受限于HTTP协议,需要带HTTP请求头,导致传输起来效率或者说安全性不如RPC
    发表于 07-13 17:46 2554次阅读

    解析操作系统的概念、结构和机制

    全面。解析操作系统的概念、结构和机制
    发表于 03-26 14:19 8次下载

    OpenDaylight中的RPC &amp; Notification是什么

    我们将介绍RPC和Notification,并从进程内外的通信开始,着重介绍远程过程调用和发布-订阅机制,然后分析MD-SAL的通信交互过程。
    的头像 发表于 02-14 15:15 793次阅读
    OpenDaylight中的<b class='flag-5'>RPC</b> &amp; Notification是什么

    RPC 和 REST 区别是什么

    01. 既 REST ,何 RPC ? 在 OpenStack 里的进程间通信方式主要有两种,一种是基于HTTP协议的RESTFul API方式,另一种则是RPC调用。 那么这两种方式在应用场景上有
    的头像 发表于 11-02 10:40 2626次阅读
    <b class='flag-5'>RPC</b> 和 REST 区别是什么

    鸿蒙开发通信与连接:ohos.rpc RPC通信

    本模块提供进程间通信能力,包括设备内的进程间通信(IPC)和设备间的进程间通信(RPC),前者基于Binder驱动,后者基于软总线驱动。
    的头像 发表于 06-21 09:40 275次阅读
    鸿蒙开发通信与连接:ohos.<b class='flag-5'>rpc</b> <b class='flag-5'>RPC</b>通信

    Dubbo源码浅析(一)—RPC框架与Dubbo

    一、什么是RPC 1.1 RPC概念 RPC,Remote Procedure Call 即远程过程调用,与之相对的是本地服务调用,即LPC(Local Procedure Call)
    的头像 发表于 08-16 15:18 206次阅读
    Dubbo源码浅析(一)—<b class='flag-5'>RPC</b>框架与Dubbo