【实践】goland中使用protobuf实现高效率的RPC调用 近年来,随着分布式系统和微服务的普及,RPC(远程过程调用)作为一种高效、方便的通信方式开始被广泛应用。其中,Google的protobuf作为一种高效的序列化工具,受到了广泛的青睐。本文将结合goland开发环境,讲解如何使用protobuf实现高效率的RPC调用。 1. 安装protobuf 首先,我们需要安装protobuf的编译器,可以通过以下命令来安装: ``` $ sudo apt-get install protobuf-compiler ``` 安装完成后,我们需要下载protobuf的golang插件,可以通过以下命令来安装: ``` $ go get -u github.com/golang/protobuf/{proto,protoc-gen-go} ``` 2. 编写.proto文件 在使用protobuf进行RPC调用时,我们需要先定义一个.proto文件,来描述我们要传输的数据格式。下面,我们以一个简单的demo为例,来说明.proto文件的编写。 在项目根目录下创建proto文件夹,并在其中创建hello.proto文件,写入以下内容: ``` syntax = "proto3"; package hello; message Request { string name = 1; } message Response { string greeting = 1; } service Greeter { rpc SayHello(Request) returns (Response); } ``` 通过上述代码,我们定义了一个hello.proto文件,其中: - syntax = "proto3":指定使用protobuf的版本为3; - package hello:指定package的名称; - message Request:定义了Request包含一个string类型的参数; - message Response:定义了Response包含一个string类型的参数; - service Greeter:定义了一个服务,包含一个SayHello方法,入参为Request,出参为Response。 3. 编译.proto文件 我们需要使用protobuf的编译器来编译.proto文件,生成相应的go文件。在项目根目录下执行以下命令: ``` $ protoc --go_out=plugins=grpc:. proto/*.proto ``` 执行完成后,我们可以看到在proto文件夹下生成了与.proto文件同名的go文件。 4. 创建服务端 下面,我们将通过golang在服务端实现一个简单的RPC调用。在项目根目录下创建server.go文件,写入以下代码: ``` package main import ( "context" "log" "net" pb "github.com/your/path/proto" // 引入proto生成的go文件 "google.golang.org/grpc" ) const ( port = ":50051" // 服务端口号 ) // server is used to create the hello service. type server struct{} // SayHello implements helloworld.GreeterServer func (s *server) SayHello(ctx context.Context, in *pb.Request) (*pb.Response, error) { log.Printf("Received: %v", in.GetName()) return &pb.Response{Greeting: "Hello " + in.GetName()}, nil } func main() { lis, err := net.Listen("tcp", port) if err != nil { log.Fatalf("failed to listen: %v", err) } s := grpc.NewServer() pb.RegisterGreeterServer(s, &server{}) log.Printf("Server listening at %v", lis.Addr()) if err := s.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) } } ``` 通过上述代码,我们创建了一个服务端,其中: - 引入proto生成的go文件:通过import语句引入生成的go文件; - SayHello方法:用于处理客户端的请求,将客户端传来的名字与“Hello ”进行拼接并返回; - main函数:创建一个监听端口,并启动服务。 5. 创建客户端 下面,我们将通过golang在客户端实现一个简单的RPC调用。在项目根目录下创建client.go文件,写入以下代码: ``` package main import ( "context" "log" "os" "time" pb "github.com/your/path/proto" // 引入proto生成的go文件 "google.golang.org/grpc" ) const ( address = "localhost:50051" // 服务端地址 defaultName = "world" ) func main() { // 建立连接 conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock()) if err != nil { log.Fatalf("did not connect: %v", err) } defer conn.Close() c := pb.NewGreeterClient(conn) // 创建请求 name := defaultName if len(os.Args) > 1 { name = os.Args[1] } ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() r, err := c.SayHello(ctx, &pb.Request{Name: name}) if err != nil { log.Fatalf("could not greet: %v", err) } log.Printf("Greeting: %s", r.GetGreeting()) } ``` 通过上述代码,我们创建了一个客户端,其中: - 引入proto生成的go文件:通过import语句引入生成的go文件; - 建立连接:使用grpc.Dial函数连接服务端; - 创建请求:创建一个携带name参数的Request,向服务端发送请求,并等待返回结果; - 输出结果:输出服务端返回的结果。 6. 运行程序 在完成服务端和客户端的编写后,我们需要在终端窗口中分别运行server.go和client.go,即可看到以下输出结果: 服务端输出: ``` 2021/10/16 17:07:56 Server listening at localhost:50051 2021/10/16 17:08:04 Received: world ``` 客户端输出: ``` 2021/10/16 17:08:04 Greeting: Hello world ``` 通过上述输出结果,我们可以看到,使用protobuf实现RPC调用,可以实现高效率的数据传输,并且使用简单、方便。在实际应用中,我们可以根据.proto文件定义数据结构,并通过golang快速实现服务和客户端,实现高效率的分布式系统。