gRPC学习入门

Posted Demonwuwen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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学习入门的主要内容,如果未能解决你的问题,请参考以下文章

将WCF迁移到gRPC

grpc的入门使用

gRPC入门指南 — 简单RPC

《Go-micro微服务框架入门教程》学习笔记 | gRPC

gRPC 流式传输极简入门指南

gRPC 流式传输极简入门指南