Go/Python gRPC实践

gRPC框架 & ProtoBuf

安装相关工具:

pip3 install grpcio
pip3 install grpcio-tools

protobuf3有自己专门的定义的格式,基于此可以生成不同的脚本

编写示例的protobuf3:

syntax = "proto3";
message HelloRequest {
string name = 1;
}

生成代码:

python3 -m grpc_tools.protoc --python_out=. --grpc_python_out=. -I. hello.proto

生成文件:

hello_pb2_grpc.py hello_pb2.py

调用示例:

import hello_pb2
request = hello_pb2.HelloRequest()
request.name = "David"
# 对象生成字符串
res = request.SerializeToString()
print(res)
# 通过字符串反向生成对象
request2 = hello_pb2.HelloRequest()
request2.ParseFromString(res)
print(request2.name)

定义proto文件

syntax = "proto3";
service Greeter {
rpc SayHello(HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}

生成文件:

python3 -m grpc_tools.protoc --python_out=. --grpc_python_out=. -I. hello.proto

示例代码

服务器端:

import hello_pb2
import hello_pb2_grpc
import grpc
from concurrent import futures
class Greeter(hello_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
return hello_pb2.HelloReply(message=f"Hello, {request.name}")
if __name__ == "__main__":
# 实例化server
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
# 注册逻辑到server
hello_pb2_grpc.add_GreeterServicer_to_server(Greeter(),server)
server.add_insecure_port('localhost:50051')
server.start()
server.wait_for_termination()

客户端:

import grpc
import hello_pb2,hello_pb2_grpc
if __name__ == "__main__":
with grpc.insecure_channel("localhost:50051") as channel:
stub = hello_pb2_grpc.GreeterStub(channel)
rsp: hello_pb2.HelloReply = stub.SayHello(hello_pb2.HelloRequest(name="David"))
print(rsp.message)

客户端直接如同调用本地函数一样调用远程函数SayHello,只要写好规则就能自动生成代码

在Go语言中也是同理,将以上proto文件放到一个目录下,使用protoc生成:

protoc --go_out=. --go-grpc_out=. ./*.proto

生成了hello.pb.go文件

服务端代码:

type Server struct{}
func (s *Server) SayHello(ctx context.Context, request *proto.HelloRequest) (*proto.HelloReply, error) {
return &proto.HelloReply{
Message: "hello " + request.Name,
}, nil
}
func main() {
s := grpc.NewServer()
proto.RegisterGreeterServer(s, &Server{})
lis, err := net.Listen("tcp", "0.0.0.0:8080")
if err != nil {
panic("failed to listen:" + err.Error())
}
err = s.Serve(lis)
if err != nil {
panic("failed to start grpc:" + err.Error())
}
}

客户端代码:

func main() {
conn, err := grpc.Dial("127.0.0.1:8080", grpc.WithInsecure())
if err != nil {
panic(err)
}
defer conn.Close()
c := proto.NewGreeterClient(conn)
r, err := c.SayHello(context.Background(), &proto.HelloRequest{Name: "David"})
if err != nil {
panic(err)
}
fmt.Println(r.Message)
}

同时Python和Go是可以互相调用的

也就是说,Python开启服务器时,Go的客户端通过服务器的地址和端口可以使用RPC调用,反之亦然

只要基于同一份proto文件即可实现互相调用

posted @   N3ptune  阅读(126)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示