gRPC in Python

weixin_33922672發表於2018-10-09

gRPC 是 Google 開放的一款 RPC (Remote Procedure Call) 框架,建立在 HTTP2 之上,使用 Protocol Buffers。

Protocol Buffers 簡介

protocol buffers 是 Google 公司開發的一種資料描述語言,採用簡單的二進位制格式,比 XML、JSON 格式體積更小,編解碼效率更高。用於資料儲存、通訊協議等方面。

通過一個 .proto 檔案,你可以定義你的資料的結構,並生成基於各種語言的程式碼。目前支援的語言很多,有 Python、golang、js、java 等等。

gRPC 簡介

有了 protocol buffers 之後,Google 進一步推出了 gRPC。通過 gRPC,我們可以在 .proto 檔案中也一併定義好 service,讓遠端使用的 client 可以如同呼叫本地的 library 一樣使用。

2733312-a6c2967311afc8e8.png

可以看到 gRPC Server 是由 C++ 寫的,Client 則分別是 Java 以及 Ruby,Server 跟 Client 端則是通過 protocol buffers 來資訊傳遞。

1. 定義功能函式

calculate.py

# -*- coding: utf-8 -*-
import math


# 求平方
def square(x):
    return math.sqrt(x)
2. 建立 .proto 檔案

在這裡描述我們要使用的 message 以及 service

calculate.proto

syntax = "proto3";

message Number {
    float value = 1;
}

service Calculate {
    rpc Square(Number) returns (Number) {}
}
3. 生成 gRPC 類

這部分可能是整個過程中最“黑盒子”的部分。我們將使用特殊工具自動生成類。

$ pip install grpcio grpcio-tools
$ python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. calculate.proto

你會看到生成來兩個檔案:

  • calculate_pb2.py  —  包含 message(calculate_pb2.Number)
  • calculate_pb2_grpc.py  —  包含 server(calculate_pb2_grpc.CalculatorServicer) and client(calculate_pb2_grpc.CalculatorStub)
4. 建立 gRPC 服務端

server.py

# -*- coding: utf-8 -*-
import grpc
import calculate_pb2
import calculate_pb2_grpc
import calculate
from concurrent import futures
import time


# 建立一個 CalculateServicer 繼承自 calculate_pb2_grpc.CalculateServicer
class CalculateServicer(calculate_pb2_grpc.CalculateServicer):
    def Square(self, request, context):
        response = calculate_pb2.Number()
        response.value = calculate.square(request.value)
        return response


# 建立一個 gRPC server
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
# 利用 add_CalculateServicer_to_server 這個方法把上面定義的 CalculateServicer 加到 server 中
calculate_pb2_grpc.add_CalculateServicer_to_server(CalculateServicer(), server)
# 讓 server 跑在 port 50051 中
print 'Starting server. Listening on port 50051.'
server.add_insecure_port('[::]:50051')
server.start()

# 因為 server.start() 不會阻塞,新增睡眠迴圈以持續服務
try:
    while True:
        time.sleep(24 * 60 * 60)
except KeyboardInterrupt:
    server.stop(0)

啟動 gRPC server:

$ python server.py
Starting server. Listening on port 50051.
5. 建立 gRPC 客戶端

client.py

# -*- coding: utf-8 -*-
import grpc
import calculate_pb2
import calculate_pb2_grpc

# 開啟 gRPC channel,連線到 localhost:50051
channel = grpc.insecure_channel('localhost:50051')
# 建立一個 stub (gRPC client)
stub = calculate_pb2_grpc.CalculateStub(channel)
# 建立一個有效的請求訊息 Number
number = calculate_pb2.Number(value=16)
# 帶著 Number 去呼叫 Square
response = stub.Square(number)
print response.value

啟動 gRPC client:

$ python client.py
4.0

最終的檔案結構:


2733312-79268e6a80810cd8.png

相關文章