GRPC (1) : 基本概念

作者: adm 分类: go 发布时间: 2023-09-24

Go gRPC 简介gRPC 是由 Google 开源的基于 HTTP/2 协议的开源远程过程调用(RPC)框架,使用 Protocol Buffers 序列化协议。相比于传统的 HTTP+JSON 的通信方式,gRPC 更轻量、更快速,拥有更多的优点。Go gRPC 安装
首先,你需要安装Go gRPC环境。可以打开你的终端,输入以下命令进行安装:

go get -u google.golang.org/grpc
安装完成后,你需要安装 Protocol Buffer 编译器。:
mac

brew install protobuf

CentOS

yum install -y protobuf
protoc --version

Ubuntu

apt install -y protobuf-compiler
protoc --version  # Ensure compiler version is 3+

接下来,你需要安装 Go 的 Protocol Buffer 插件。可以使用以下命令安装:

//go get -u github.com/golang/protobuf/protoc-gen-go
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

Go gRPC 开发准备工作
一般来说,gRPC 包含服务端和客户端两部分。服务端主要包含 Proto 文件定义和服务实现;客户端主要包含服务调用和响应处理。

在开始之前,我们需要做一些准备工作:

定义 protobuf文件
首先,我们需要定义protobuf文件。protobuf是一种跨平台、语言无关的序列化协议,它能够将数据结构转换成二进制格式,以实现基于TCP、UDP等协议的跨服务通信, 通常以.proto结尾
protobuf 文件是 gRPC 的核心部分,用于描述服务所需要的数据类型、请求参数和服务方法等信息, 新建一个文件 example.proto

syntax = "proto3";

package example;

message Message {
  string data = 1;
}

service Greeter {
    rpc SayHello (Message) returns (Message) {};
}

在该示例中,protobuf 文件定义了一个名为 example 的包,包含了一个名为 Message 的消息类型,以及一个名为 Greeter 的服务,该服务中包含了一个名为 SayHello 的方法。

生成go代码
接下来,我们将使用 protocol buffer 编译器 protoc 命令将刚刚新建的文件编译成 Go 代码。打开终端,输入以下命令:

$ protoc -I. --go_out=plugins=grpc:. ./example.proto

该命令将根据 example.proto 文件生成一个名为 example.pb.go 的 Go 代码文件,并将 grpc 标志作为参数传递,以支持 gRPC 功能。实现服务端

go_out详细解读
大家在使用时,遇到过这些写法:–go_out=paths=import:.、–go_out=paths=source_relative:.,或者–go_out=plugins=grpc:.。

--go_out参数是用来指定 protoc-gen-go 插件的工作方式和Go代码的生成位置,而上面的写法正是表明该插件的工作方式。

--go_out主要的两参数为plugins和paths,分别表示生成Go代码所使用的插件,以及生成的Go代码的位置。
--go_out的写法是,参数之间用逗号隔开,最后加上冒号来指定代码的生成位置,比如--go_out=plugins=grpc,paths=import:.。

paths参数有两个选项,imports和 source_relative, 默认为 import,表示按照生成的Go代码的包的全路径去创建目录层级,source_relative 表示按照 proto源文件的目录层级去创建Go代码的目录层级,如果目录已存在则不用创建。

plugins参数有不带grpc和带grpc两种(应该还有其它的,目前知道的有这两种),两者的区别如下,带grpc的会多一些跟gRPC相关的代码,实现gRPC通信.

导入其它proto文件
有时候我们可能有多份proto文件,且每份proto文件不一定是完全独立,它们之间会互相引用,这时候该怎么做呢?

└── proto2
    ├── common.proto
    └── greeter
        └── greeter.proto

greeter.proto内容如下:

syntax = "proto3";

package greeter;

import "proto2/common.proto";

option go_package="proto2/greeter";

service Greeter {
    rpc SayHello (common.Request) returns (common.Response) {}
}

以上述内容为例,假设我们有一个共用的 proto 文件 common.proto,此时 greeter.proto 如果想引用里面的message,就可以使用 import 关键字进行导入。
编译指令如下:

protoc –proto_path=. –go_out=. proto2/greeter/greeter.proto proto2/common.proto
关于protoc-gen-go的多包问题
假设目前的proto文件存放如下:

└── proto
    ├── common.proto
    ├── greeter
    │   └── greeter.proto
    └── user
        └── user.proto

如果你想编译所有proto文件(假设生成Go语言),正常的命令应该是这样的:

protoc --proto_path=. --go_out=. proto/*.proto proto/user/*proto proto/greeter/*proto

在服务端,我们需要在 gRPC 的基础上实现我们的服务。以下是一个简单的示例:

package main

import (
	"context"
	"net"

	"google.golang.org/grpc"

	"example.pb" // 引入刚刚生成的
)

type server struct{}

func (s *server) SayHello(ctx context.Context, in *example.Message) (*example.Message, error) {
	return &example.Message{Data: "Hello " + in.GetData()}, nil
}

func main() {
	lis, err := net.Listen("tcp", ":50051")
	if err != nil {
		panic(err)
	}
	s := grpc.NewServer()
	example.RegisterGreeterServer(s, &server{})
	if err := s.Serve(lis); err != nil {
		panic(err)
	}
}

在该示例中,我们定义了一个名为 server 的结构体,该结构体实现了 example.GreeterServer 接口中的 SayHello 方法,该方法会接收一个名为 Message 的请求,并返回一个 Message 类型的响应。

实现客户端
在客户端,我们需要调用服务端的服务,并处理服务端的响应。以下是一个简单的示例:

package main

import (
	"context"
	"log"

	"google.golang.org/grpc"

	"example.pb" // 引入刚刚生成的
)

func main() {
	conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
	if err != nil {
		panic(err)
	}
	defer conn.Close()

	c := example.NewGreeterClient(conn)
	response, err := c.SayHello(context.Background(), &example.Message{Data: "World"})
	if err != nil {
		panic(err)
	}
	log.Printf("Response: %s", response.GetData())
}

在该示例中,我们使用 grpc.Dial 方法连接服务端,创建了一个名为 GreeterClient 的客户端,然后调用了 SayHello 方法。

启动服务端和客户端
现在,我们已经完成整个项目的代码编写,可以开始启动服务端和客户端了。首先,我们需要在终端中启动服务端:

go run server.go
接下来,在另一个终端中启动客户端:

go run client.go
如果一切顺利,你应该可以在客户端终端中看到以下信息:

Response: Hello World
结论
Go gRPC 是一个快速、轻量、高效、易于使用的RPC框架,能够提供出色的性能和灵活性,在 Go Web 开发中应用广泛。本文介绍了 Go gRPC 的安装、开发和使用方法,并通过一个简单的示例来展示了如何在 Go 中使用 gRPC。

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!