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文件即可实现互相调用
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?