gRPC入门

Posted 落雷

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了gRPC入门相关的知识,希望对你有一定的参考价值。

1. gRPC简介

gRPC是一种高性能、开源和通用的远程过程调用(RPC)框架,由Google开源并维护。它使用Protocol Buffers(protobuf)作为接口定义语言(IDL),提供跨平台、跨语言的RPC调用支持。gRPC具有以下几个特点:

  1. 高性能:使用HTTP/2协议,支持多路复用和流控制等特性,能够在客户端和服务器之间高效地传输大量数据。同时,gRPC还使用了基于平台优化的序列化和反序列化技术,提高了通信的效率。
  2. 简单易用:gRPC的IDL语言简单易懂,同时提供了自动生成代码的工具,方便用户进行开发。用户只需要定义好IDL,并生成代码后即可在代码中使用类似于本地函数调用的方式进行远程过程调用。
  3. 多语言支持:gRPC支持多种编程语言,如C++, Java, Python, Go, Ruby等,可以在不同编程语言之间进行RPC调用。
  4. 可扩展性:gRPC支持各种扩展,包括拦截器、负载均衡、认证和授权等,可以满足不同场景下的需求。
  5. 安全性:gRPC支持SSL/TLS安全传输,同时还提供了基于Token的认证机制,确保通信的安全性。

总之,gRPC提供了一种高效、可扩展、多语言、安全的RPC框架,适用于大规模分布式系统中的服务间通信,如微服务架构。

本文以go为例,介绍如何使用gRPC开发一个简单服务。

2. 准备工作

2.1 安装protoc

github系统对应的protoc预编译版,解压到/usr/local/下,以v22.3为例,具体操作如下:

wget https://github.com/protocolbuffers/protobuf/releases/download/v22.3/protoc-22.3-linux-x86_64.zip
unzip protoc-22.3-linux-x86_64.zip -d /usr/local/
ldconfig 
protoc --version
# libprotoc 22.3

2.2 安装go相关插件

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

3. 实践

3.1 编写proto文件

syntax = "proto3";

option go_package = "./;hello";

package hello;

message HelloRequest
    string name = 1;


message HelloResponse
    string message = 1;


service ExampleService
    rpc SayHi (HelloRequest) returns (HelloResponse);

service ExampleService就是我们定义的服务,rpc SayHi (HelloRequest) returns (HelloResponse);就是服务中提供的接口,protoc会根据我们定义的proto文件生成相应的代码。

3.2 使用protoc生成代码

终端下执行以下命令即可生成我们需要的代码:

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

--go_out指定go文件的生成目录,--go-grpc_out指定grpc文件的生成目录

此时打开生成的go文件大概率会发现飘红报错,此时可以在当前目录下执行go mod tidy同步下依赖即可。

3.3 编写服务端代码

示例只是简单实现一个echo服务,服务端代码如下:

package main

import (
	"context"
	"net"

	pb "github.com/mengbin92/hello/protos/hello"
	"google.golang.org/grpc"
)

// 服务实体
type HelloService struct 
	pb.UnimplementedExampleServiceServer


// 实现我们proto文件定义的接口
func (sv *HelloService) SayHi(ctx context.Context, in *pb.HelloRequest) (*pb.HelloResponse, error) 
	return &pb.HelloResponseMessage: "hello " + in.Name, nil


func main() 
	// 创建grpc服务示例
	sv := grpc.NewServer()
	// 注册我们的服务
	pb.RegisterExampleServiceServer(sv, new(HelloService))

	// 绑定端口,提供服务
	lis, err := net.Listen("tcp", ":50001")
	if err != nil 
		panic(err)
	
	// 启动服务
	sv.Serve(lis)

启动服务后,服务端会一直阻塞等待客户端的链接,直到收到kill信号:

go run server.go

3.4 实现客户端

package main

import (
	"context"
	"fmt"

	pb "github.com/mengbin92/hello/protos/hello"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
)

func main() 
	// 创建grpc连接
	conn, err := grpc.Dial("localhost:50001", grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil 
		panic(err)
	
	defer conn.Close()

	// 实例化客户端
	client := pb.NewExampleServiceClient(conn)

	// 发送请求
	req := &pb.HelloRequestName: "world"
	resp, err := client.SayHi(context.TODO(), req)
	if err != nil 
		panic(err)
	
	fmt.Printf("get response from server: %s\\n", resp.Message)

客户端启动后向服务端发送world,服务端返回hello world

go run client.go
# get response from server: hello world

至此,一个简单的gRPC服务就已经搞定了。


声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意


gRPC学习入门

grpc框架

参考资料:

GRPC是Google公司基于Protobuf开发的跨语言的、高性能的、通用的开源RPC框架。GRPC基于HTTP/2协议设计,可以基于一个HTTP/2链接提供多个服务,对于移动设备更加友好。

在 gRPC里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法,使得您能够更容易地创建分布式应用和服务。与许多 RPC系统类似, gRPC也是基于以下理念:

  • 定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。
  • 在服务端实现这个接口,并运行一个 gRPC服务器来处理客户端调用。

本来是按照b站上视频学习,但是发现其大多在跟着实战的时候因为版本的原因,导致产生各种问题,所以自己又打开官网,跟着官网,参照视频和百度资料进行学习了。
简单介绍了一下,后面就一起开始实战吧!

1 先决条件

可以使用以下两个命令安装

go install google.golang.org/protobuf/cmd/protoc-gen-go
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc

配置环境变量

export PATH="$PATH:$(go env GOPATH)/bin"

这里配置完了,环境就OK了。此时gopath/bin目录下会有以下两个文件

2 实战环节

在这个grpc-practice项目中,目标是实现一个功能,客户端可以调用服务端,服务端的函数,服务端收到消息后,返回响应给客户端。
创建新的工程目录,结构如下:
grpcPrac
├── client
│ └── client.go
├── message
│ └── message.proto
└── server
└── server.go

2.1 proto文件创建

message用来编写.proto格式文件,server目录编写服务器代码,client目录编写客户端代码。
首先在message文件夹目录下创建message.proto文件,写入内容如下
syntax = "proto3";

option go_package = ".;message";

message MessageResponse 
 string responseSomething = 1;


message MessageRequest 
 string saySomething = 1;


service MessageSender 
 rpc Send(MessageRequest) returns (MessageResponse) 

option go_package = ".;message"这里是制定后面编译后所在的包。

从proto文件可以看出,我们定义了一个service,称为MessageSender,这个服务中有一个rpc方法,名为Send。这个方法会发送一个MessageRequest,然后返回一个MessageResponse。

在message文件夹目录下执行如下命令:

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

此时会把message.proto文件转译为两个.go文件,如下:

在网上的一些教程中,有这样的生成方式:

protoc --go_out=plugins=grpc:. helloworld.proto

这种生成方式,使用的就是github版本的protoc-gen-go,而目前这个项目已经由Google接管了。

并且,如果使用这种生成方式的话,并不会生成上图中的xxx_grpc.pb.go与xxx.pb.go两个文件,只会生成xxx.pb.go这种文件。

此外,你也可能遇到这种错误:
protoc-gen-go-grpc: program not found or is not executable Please specify a program using absolute path or make sure the program is available in your PATH system variable --go-grpc_out: protoc-gen-go-grpc: Plugin failed with status code 1.
这是因为你没有安装protoc-gen-go-grpc这个插件,这个问题在本文中应该不会出现。

你还可能会遇到这种问题:

--go_out: protoc-gen-go: plugins are not supported; use 'protoc --go-grpc_out=...' to generate gRPC

这是因为你安装的是更新版本的protoc-gen-go,但是你却用了旧版本的生成命令。

2.2 服务端编码

在server文件夹下建立server.go文件,

package main

import (
	"context"
	"google.golang.org/grpc"
	msg "grpcPrac/message"
	"log"
	"net"
)

const (
	address = "localhost:12345"
)

type server struct 
	msg.UnimplementedMessageSenderServer


//实现 message接口Send方法
func (this *server)Send(ctx context.Context,in *msg.MessageRequest) (*msg.MessageResponse, error) 
	log.Printf("Received: %v", in.GetSaySomething())
	return &msg.MessageResponseResponseSomething: "Hello " + in.GetSaySomething(),nil


func main() 
	//设置监听端口
	lis, err := net.Listen("tcp", address)
	if err!= nil
		log.Fatalf("Fail to listen:%v", err)
	
	// 获取grpc服务端对象
	srv := grpc.NewServer()
 	
 	//注册grpc服务
	msg.RegisterMessageSenderServer(srv, &server)
	log.Printf("server listening at %v\\n",lis.Addr())
	
	//在指定端口上提供grpc服务
	if err:= srv.Serve(lis);err!=nil
		log.Fatalf("failed to serve:%v",err)
	


2.3 客户端

在Client文件夹创建client.go文件,代码如下:

package main

import (
	"context"
	"google.golang.org/grpc"
	msg "grpcPrac/message"
	"log"
	"time"
)

const (
	address = "localhost:12345"
	defaultName = "world"
)
func main() 
	//和grpc服务建立连接
	conn, err := grpc.Dial(address,grpc.WithInsecure(),grpc.WithBlock())
	if err!= nil
		log.Fatalf("Did not connect :%v\\n",err)
	
	defer conn.Close()
	c := msg.NewMessageSenderClient(conn)

	//contact the server
	name := defaultName
	ctx ,cancel := context.WithTimeout(context.Background(),time.Second)
	defer cancel()
	r, err := c.Send(ctx,&msg.MessageRequestSaySomething: name)
	if err!= nil
		log.Fatalf("Could not Send :%v\\n",err)
	
	log.Printf("Response : %s\\n",r.GetResponseSomething())


用终端进入server和client目录下各自运行代码,效果如下

由此看到咱们通过客户端调用服务端函数成功。

最后

其中一个坑值得记录一下,在.proto文件转译为go后,message_grpc.pb.go中多了这么一行代码,这是为了向前兼容
所以在服务端定义结构体的时候,一定不要忘了加入这一行

以上是关于gRPC入门的主要内容,如果未能解决你的问题,请参考以下文章

grpc教程grpc入门

gRPC C++从入门到无敌教程gRPC核心概念

gRPC学习入门

gRPC学习入门

Python gRPC 入门

grpc的入门使用