using grpc in Python
gRPC是基於http/2的RPC框架,使用ProtoBuf作為底層數據序列化。Nginx服務器2018年3月17日引入gRPC支持。
gRPC 是用來實現跨語言通信的。比如在你的某個功能里需要用的同事寫的接口,而你們倆又不是同一種語言。此時有兩種方案,一是使用.so 文件;另一種則是使用 RPC 框架。
創建一個grpc_demo項目,結構如下
grpc_demo/
├── client
│ └── client.py
├── example
│ └── data.proto
└── server
└── server.py
- client目錄下的client.py實現了客戶端用於發送數據並打印接收到server端處理后的數據
- server目錄下的server.py實現了server端用於接收客戶端發送的數據,並對數據進行簡單處理后返回給客戶端
- example包用於編寫proto文件並生成data接口
grpc安裝
-
安裝gRPC
pip install grpcio
-
安裝 ProtoBuf 相關的 python 依賴庫
pip install protobuf
-
安裝 python grpc 的 protobuf 編譯工具
pip install grpcio-tools
定義gRPC接口
data.proto文件,service關鍵字就是定義接口,message定義數據結構
syntax = "proto3";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
string message = 2;
string location = 3;
string ip = 4;
}
message HelloReply {
string name = 1;
string message = 2;
string location = 3;
string ip = 4;
}
編譯protobuf生成所需文件(服務端和客戶端都需要)
# mkdir gen-py
# python -m grpc_tools.protoc --proto_path=./ --python_out=./gen_py --grpc_python_out=./gen_py ./data.proto
在gen-py目錄下生成data_pb2_grpc.py和data_pb2.py兩個文件。
生成后完整目錄結構:
grpc_demo
├── client
│ └── client.py
├── example
│ ├── data.proto
│ └── gen_py
│ ├── data_pb2_grpc.py
│ └── data_pb2.py
└── server
└── server.py
服務端實現
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
sys.path.append('../example/gen_py')
import grpc
import time
from concurrent import futures
import data_pb2
import data_pb2_grpc
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
_HOST = "127.0.0.1"
_PORT = "19999"
class HelloWorld(data_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
print("request: " + str(request))
return data_pb2.HelloReply(message='%s, %s!' % (request.message, request.name))
def server():
grpcServer = grpc.server(futures.ThreadPoolExecutor(max_workers=4))
data_pb2_grpc.add_GreeterServicer_to_server(HelloWorld(), grpcServer)
grpcServer.add_insecure_port("{0}:{1}".format(_HOST, _PORT))
grpcServer.start()
try:
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
grpcServer.stop(0)
if __name__ == '__main__':
server()
客戶端實現
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
sys.path.append("../example/gen_py")
import grpc
import data_pb2
import data_pb2_grpc
_HOST = '127.0.0.1'
_PORT = '19999'
def run():
with grpc.insecure_channel("{0}:{1}".format(_HOST, _PORT)) as channel:
client = data_pb2_grpc.GreeterStub(channel=channel)
response = client.SayHello(data_pb2.HelloRequest(name='you', message='hey guys'))
print("received: " + response.message)
if __name__ == '__main__':
run()
#channel = grpc.insecure_channel("{0}:{1}".format(_HOST, _PORT))
#client = data_pb2_grpc.GreeterStub(channel=channel)
#response = client.SayHello(data_pb2.HelloRequest(name='you', message='hey guys'))
#print("received: " + response.message)
參考:
https://blog.codeship.com/using-grpc-in-python/