golang工程组件篇:高性能分布式系统RPC框架gRPC之使用protobuf定义服务

2023-05-2409:37:30后端程序开发Comments736 views字数 3237阅读模式

分布式系统中,RPC(Remote Procedure Call)是一种常见的通信方式。它可以让不同语言编写的应用程序之间进行高效的网络通信,从而实现分布式服务架构。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

gRPC 是一个基于 Protocol Buffers 的高性能 RPC 框架,支持多种编程语言和平台。本文将介绍如何使用 gRPC 中的 Protocol Buffers 定义服务,并给出相应的示例代码帮助读者理解这些概念。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

1. 什么是 Protocol Buffers

Protocol Buffers(简称 protobuf)是一种轻量级、高效、可扩展且语言无关的序列化协议。它可以将结构化数据序列化为二进制格式,在不同平台和语言之间进行数据交换。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

与其他序列化协议相比,protobuf 具有以下优点:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

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

以下是一个简单的 protobuf 结构体定义示例:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

syntax = "proto3";

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

在这个例子中,我们定义了一个名为 Person 的消息结构体,它包含三个字段:nameage 和 is_student。每个字段都有一个唯一的标识符,用于在序列化和反序列化时进行匹配。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

2. gRPC 中的 Protocol Buffers 定义服务

gRPC 使用 protobuf 来定义 RPC 服务和消息格式。通过 protobuf 文件定义服务,可以轻松地生成客户端和服务器端代码,并实现远程过程调用。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

以下是一个简单的 gRPC 服务定义示例:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

syntax = "proto3";

package example;

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

message HelloRequest {
    string name = 1;
}

message HelloReply {
    string message = 1;
}

在这个例子中,我们定义了一个名为 Greeter 的 gRPC 服务,它包含一个名为 SayHello 的 RPC 方法。该方法接受一个类型为 HelloRequest 的参数,并返回一个类型为 HelloReply 的响应。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

同时,我们还定义了两个消息类型:HelloRequest 和 HelloReply。它们分别表示客户端请求和服务器端响应中的数据格式。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

3. 使用 protoc 工具生成代码

使用 protobuf 文件定义好 gRPC 服务之后,我们需要使用 protoc 工具来生成对应的客户端和服务器端代码。gRPC 支持多种编程语言(例如 C++、Java、Python、Go 等),因此需要选择相应的插件来生成所需的代码。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

以下是一个使用 protoc 工具生成 Go 语言客户端和服务器端代码的示例:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

# 安装 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

在这个例子中,我们首先下载并安装了 protoc 工具。然后,我们使用 go get 命令安装了 go-grpc 插件,该插件可以将 protobuf 文件编译为 Go 语言的 gRPC 代码。最后,我们使用 protoc 命令来生成对应的客户端和服务器端代码。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

4. 实现 gRPC 服务

在定义好 gRPC 服务之后,并生成对应的客户端和服务器端代码之后,我们就可以开始实现 gRPC 服务了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

以下是一个简单的 gRPC 服务实现示例:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

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 的参数,并返回一个类型为 *pb.HelloReply 的响应。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

然后,在主函数中,我们创建了一个 TCP 监听器,并使用 grpc.NewServer() 方法创建了一个新的 gRPC 服务器对象。接着,我们将实现好的 gRPC 服务注册到该服务器对象上,并通过调用 s.Serve(lis) 启动该服务器。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

5. 实现 gRPC 客户端

除了实现 gRPC 服务端之外,我们还需要编写对应的客户端代码来发送请求和接收响应。gRPC 提供了自动生成的客户端 stub(存根)代码,可以方便地进行远程过程调用。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

以下是一个简单的 gRPC 客户端示例:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

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() 方法来发送请求并接收响应。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

6. 总结

gRPC 是一种基于 Protocol Buffers 的高性能 RPC 框架,支持多种编程语言和平台。通过 protobuf 文件定义服务和消息格式,并使用 protoc 工具生成对应的客户端和服务器端代码。在实现 gRPC 服务时,我们需要编写对应的服务端代码来处理客户端请求,并编写对应的客户端代码来发送请求和接收响应。gRPC 提供了自动生成的客户端 stub(存根)代码,可以方便地进行远程过程调用。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/41801.html

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/bc/41801.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定