RPC简介和grpc的使用

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 函数类似,都执行了本地函数调用。不同的是它底层实现上不是进行操作系统调用读取本地文件来提供数据,而是将参数打包成网络消息,并将此网络消息发送到远程服务器,交由远程服务执行对应的方法,在发送完调用请求后,客户端存根随即阻塞,直到收到服务器发回的响应消息为止。

下图展示了远程方法调用过程中的客户端和服务端各个阶段的操作。
    
在这里插入图片描述

总结下RPC执行步骤:

  1. 调用客户端句柄,执行传递参数。
  2. 调用本地系统内核发送网络消息。
  3. 消息传递到远程主机,就是被调用的服务端。
  4. 服务端句柄得到消息并解析消息。
  5. 服务端执行被调用方法,并将执行完毕的结果返回给服务器句柄。
  6. 服务器句柄返回结果,并调用远程系统内核。
  7. 消息经过网络传递给客户端。
  8. 客户端接受数据。

安装gRPC和Protobuf

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

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

安装

  • go get github.com/golang/protobuf/proto
  • go get google.golang.org/grpc(无法使用,用如下命令代替)
    • git clone https://github.com/grpc/grpc-go.git $GOPATH/src/google.golang.org/grpc
    • git clone https://github.com/golang/net.git $GOPATH/src/golang.org/x/net
    • git clone https://github.com/golang/text.git $GOPATH/src/golang.org/x/text
    • go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
    • git clone https://github.com/google/go-genproto.git $GOPATH/src/google.golang.org/genproto
    • cd $GOPATH/src/
    • go install google.golang.org/grpc
    • go get github.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服务器以后,就可以像调用本地函数一样操作远程服务器。

代码仓库

https://github.com/onenewcode/mygrpc.git

也可以直接下载绑定的资源。

  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
回答: RPC(Remote Procedure Call)和 gRPC 是两种不同的远程过程调用协议。RPC是一种通过网络从远程计算机程序上请求服务的协议,它可以实现不同节点之间的通信。而gRPC是一种基于RPC协议的框架,它使用了Google开发的Protocol Buffers作为序列化和协议编解码器,以及HTTP/2作为网络传输协议。\[1\]\[2\]\[3\] 区别在于,gRPC相比传统的RPC框架具有以下特点: 1. 序列化和协议编解码器:gRPC使用Protocol Buffers作为默认的序列化和协议编解码器,它可以高效地序列化和传输数据。 2. 网络传输协议:gRPC使用HTTP/2作为网络传输协议,可以提供更高的性能和更低的延迟。 3. 多语言支持:gRPC支持多种编程语言,包括C++、Java、Python等,可以方便地在不同的语言之间进行通信。 4. 异步支持:gRPC支持异步调用,可以提高系统的并发性能。 5. 服务定义:gRPC使用Protocol Buffers定义服务接口和消息类型,可以自动生成客户端和服务端的代码,简化开发过程。 总之,gRPC是一种基于RPC协议的框架,通过使用Protocol Buffers和HTTP/2等技术,提供了更高效、更灵活的远程过程调用方式。 #### 引用[.reference_title] - *1* *2* *3* [RpcgRpc 简介汇总](https://blog.csdn.net/Jailman/article/details/126056469)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

过去日记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值