【实践】goland中使用protobuf实现高效率的RPC调用
【实践】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快速实现服务和客户端,实现高效率的分布式系统。