1. 概述
gRPC 是由 Google 开源的一个高性能、通用化的开源框架。该框架支持多种编程语言 (比如 C++, Python, Java)并且提供了支持多种操作系统的端点。本文将对 gRPC 在 Python 和 Golang 中的使用进行详细介绍。
2. gRPC的安装
2.1 Python 中安装gRPC
pip install grpcio
注意:gRPC 默认是不支持 Python3 的,如果需要使用 Python3 版本的话需要单独安装grpcio-tools, 并使用 Python3 解释器。
pip3 install grpcio-tools
2.2 Golang 中安装gRPC
在使用 gRPC 之前,需要先安装 Go,安装方式可以参考官方文档。然后使用如下命令安装 gRPC。
go get -u google.golang.org/grpc
3. gRPC的使用示例
3.1 Python 中 gRPC的使用
接下来我们实现一个简单的例子,该例子从 gRPC 的官方例子中修改。
在该例子中,我们创建了一个“Hello, World!”的应用程序,它使用一种在服务器和客户端之间发送包含问候语句的消息协议。
我们首先需要编写服务端的代码,如下所示:
import grpc
from concurrent import futures
import helloworld_pb2
import helloworld_pb2_grpc
class Greeter(helloworld_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
server.add_insecure_port('[::]:50051')
server.start()
server.wait_for_termination()
if __name__ == '__main__':
serve()
在上面的代码中,我们需要首先定义一个“greeter service”,它继承自 helloword_pb2_grpc.GreeterServicer,然后重载其中的 SayHello 方法,使其返回一个刚刚对请求中 name 字段作出回应的新消息。接着定义 Server 的 IP 和 Port,并启动 Server 服务,让它一直运行。
然后我们需要编写客户端代码,如下所示:
import grpc
import helloworld_pb2
import helloworld_pb2_grpc
def run():
channel = grpc.insecure_channel('localhost:50051')
stub = helloworld_pb2_grpc.GreeterStub(channel)
response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'))
print(response.message)
if __name__ == '__main__':
run()
在上面的代码中,我们创建了一个通道以与 Server 通信,并向 Server 发送了一个包含 "you" 字段的消息。最后,我们得到了这个字符串响应,将其输出到控制台。
3.2 Golang 中 gRPC的使用
在 Golang 中使用 gRPC 同样也很简单,我们可以通过以下示例实现 echo 服务器应用程序。
首先,我们需要定义自己的 .proto 文件,内容如下:
syntax = "proto3";
package main;
message Request {
string data = 1;
}
message Response {
string data = 1;
}
service EchoService {
rpc Echo(Request) returns (Response) {}
}
接下来,我们使用 protoc 编译器来生成 Golang 代码(也可以使用 pip 安装 protoc-gen-go),如下所示:
protoc --go_out=. --go-grpc_out=. echo.proto
然后我们就可以编写服务端的代码,如下所示:
package main
import (
"log"
"net"
"google.golang.org/grpc"
pb "github.com/your/repo/echo"
)
type echoServer struct {
pb.UnimplementedEchoServiceServer
}
func (s *echoServer) Echo(ctx context.Context, in *pb.Request) (*pb.Response, error) {
log.Printf("Received: %v", in.GetData())
return &pb.Response{Data: in.GetData()}, nil
}
func main() {
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("Failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterEchoServiceServer(s, &echoServer{})
if err := s.Serve(lis); err != nil {
log.Fatalf("Failed to serve: %v", err)
}
}
在上面的代码中,我们定义了一个 modulename/protos/echo.pb.go 文件,它包含了我们生成的客户端和服务器代码。我们实现了 EchoService 接口,重载其中的 Echo 方法,使其将收到的消息作为回应发送回去。
最后我们需要编写客户端代码,如下所示:
package main
import (
"context"
"log"
"time"
"github.com/your/repo/echo"
"google.golang.org/grpc"
)
func main() {
conn, err := grpc.Dial(":50051", grpc.WithInsecure())
if err != nil {
log.Fatalf("Could not connect: %v", err)
}
defer conn.Close()
c := echo.NewEchoServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.Echo(ctx, &echo.Request{Data: "Hello, World!"})
if err != nil {
log.Fatalf("Could not echo: %v", err)
}
log.Printf("Response: %s", r.GetData())
}
在上面的代码中,我们使用已经生成的代码来连接服务器。然后创建 EchoService 客户端并发送一个简单的请求, 返回 Echo 方法的响应,并输出响应字符串。
4. 总结
gRPC 是一个高性能、可扩展的开源框架,它支持多种语言,包括 Python 和 Golang。本文介绍了 gRPC 的安装方法,以及如何在 Python 和 Golang 中使用 gRPC。我们在实践中发现,在项目中使用 gRPC 的确可以大大提升我们的开发效率。