Code前端首页关于Code前端联系我们

Golang工程组件:高性能分布式RPC框架gRPC使用protobuf来定义服务

terry 2年前 (2023-09-24) 阅读数 59 #后端开发

在分布式系统中,RPC(Remote procedure Call)是一种常见的通信方式。它使不同语言编写的应用程序之间能够进行高效网络通信,实现分布式服务架构。

gRPC是一个基于protocol buffer的高性能RPC框架,支持多种编程语言和平台。本文将介绍如何在gRPC中使用protocol buffers来定义服务,并提供相应的示例代码来帮助读者理解这些概念。

1。什么是Protocol Buffers

Protocol Buffers(简称protobuf)是一个轻量级的、儒家的、可扩展的、与语言无关的序列化协议。它可以将结构化数据序列化为二进制格式,并在不同平台和语言之间交换数据。

与其他序列化协议相比,protobuf有以下优点:

  • 简单:只需定义一个结构体即可。
  • 高效:压缩后的消息体积很小。
  • 可扩展:支持添加和删除字段,兼容转发。
  • 平台和语言中:Java、C++、Python等都有对应的库。

下面是proto的buf结构定义的一个简单例子:

syntax = "proto3";

message Person {
    string name = 1;
    int32 age = 2;
    bool is_student = 3;
}

在这个例子中,我们定义了一个消息结构,名为Person,它包含三个字段: name: 年龄和is_a_student。每个数组都有一个唯一的标识符,用于序列化和反序列化期间的匹配。

2。 gRPC 中的协议缓冲区定义服务

gRPC 使用 proto buf 来定义 RPC 服务和消息格式。通过proto的buf文件定义服务,您可以轻松生成客户端和服务器端代码并​​实现远程过程调用。

以下是 gRPC 服务定义的简单示例:

syntax = "proto3";

package example;

service Greeter {
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
    string name = 1;
}

message HelloReply {
    string message = 1;
}

在此示例中,我们定义了一个名为 Greeter 的 gRPC 服务,其中包含一个名为 ⓙHelloSay 的服务。此方法接受类型为 HelloRequest 的参数并返回类型为 HelloReply 的响应。

同时,我们还定义了两种消息类型:HelloRequestHelloReply。它们代表客户端请求和服务器端响应中的数据格式。

3。使用protoc工具生成代码

使用protobuf文件定义gRPC服务后,我们需要使用protoc工具生成相应的客户端和服务端代码。 gRPC支持多种编程语言(如C++、Java、Python、Go等),因此需要选择合适的插件来生成所需的代码。

下面是使用proto c工具生成Go客户端代码和服务器端代码的示例:

# 安装 protoc 工具。
$ wget https://github.com/protocolbuffers/protobuf/releases/download/v3.17.1/protoc-3.17.1-linux-x86_64.zip
$ unzip protoc-3.17.1-linux-x86_64.zip
$ export PATH=$PATH:/path/to/protoc/bin

# 安装 go-grpc 插件。
$ go get google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.38.0

# 使用 protoc 工具生成 Go 语言代码。
$ protoc --go_out=plugins=grpc:. *.proto

在这个例子中,我们首先下载并安装了proto c工具,然后使用命令go get安装了插件go-grpc,可以将proto的buf文件编译成Go gRPC代码。最后我们使用命令proto c生成对应的客户端和服务端代码。

4。 gRPC服务的实现

定义完gRPC服务并生成相应的客户端和服务端代码后,我们就可以开始实现gRPC服务了。

以下是实现 gRPC 服务的简单示例:

package main

import (
    "context"
    "log"
    "net"

    pb "example/proto"

    "google.golang.org/grpc"
)

type server struct{}

func (s *server) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) {
    return &pb.HelloReply{Message: "Hello " + req.Name}, nil
}

func main() {
    lis, err := net.Listen("tcp", ":8080")
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterGreeterServer(s, &server{})
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

在这个示例中,我们首先实现了一个名为 server 的 gRPC 服务器。服务器包含一个名为 SayHello 的方法,该方法接受类型为 *pb.HelloRequest 类型的参数并返回类型为 .reply*❝.*reply

然后在 main 函数中,我们创建 TCP 侦听器,并使用方法 grpc.NewServer() 我们创建一个新的 gRPC 服务器对象。接下来,我们在服务器对象中注册已实现的 gRPC 服务,并通过调用 s.Serve(lis) 启动服务器。

5。 gRPC客户端实现

除了gRPC服务器实现之外,我们还需要编写相应的客户端代码来发送请求和接收响应。 gRPC 提供自动生成的客户端存根代码以方便远程过程调用。

以下是一个简单的 gRPC 客户端示例:

package main

import (
	"context"
	"log"

	pb "example/proto"

	"google.golang.org/grpc"
)

func main() {
	conn, err := grpc.Dial(":8080", grpc.WithInsecure())
	if err != nil {
		log.Fatalf("failed to connect: %v", err)
	}
	defer conn.Close()

	client := pb.NewGreeterClient(conn)
	resp, err := client.SayHello(context.Background(), &pb.HelloRequest{Name: "World"})
	if err != nil {
		log.Fatalf("failed to call SayHello: %v", err)
	}

	log.Printf("response message: %s", resp.Message)
}

在此示例中,我们首先创建一个使用 grpc.Dial() 方法连接到服务器的 gRPC 客户端。接下来,我们使用 pb.NewGreeterClient() 方法创建一个新的 gRPC 客户端对象,并调用其 SayHello() 方法来发送请求并接收响应。

6。总结

gRPC是一个基于protocol buffer的高性能RPC框架,支持多种编程语言和平台。通过proto的buf文件定义服务和消息格式,并使用proto的c工具生成相应的客户端和服务端代码。在实现gRPC服务时,我们需要编写相应的服务器代码来处理客户端请求,并编写相应的客户端代码来发送请求和接收响应。 gRPC 提供自动生成的客户端存根代码以方便远程过程调用。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门