Python學習筆記-gRPC

gRPC概述

gRPC是一款高性能、開源的 RPC 框架,產自 Google,基於 ProtoBuf 序列化協議進行開發,支持多種語言(Golang、Python、Java等)。gRPC對HTTP2.0協議的支持使其在 Android、IOS 等客戶端後端服務的開發領域具有良好的前景。gRPC 提供了一種簡單的方法來定義服務,同時客戶端可以充分利用HTTP2.0 stream的特性,從而有助於節省帶寬、降低 TCP 的連接次數、節省CPU的使用等。所謂RPC(remote procedure call 遠程過程調用)框架實際是提供了一套機制,使得應用程序之間可以進行通信,而且也遵從server/client模型。使用的時候客戶端調用server端提供的接口就像是調用本地的函數一樣。

gRPC優勢

gRPC和Restful API都提供了一套通信機制,用於server/client模型通信,而且它們都使用http作爲底層的傳輸協議。不過gRPC有些特有的優勢如下:

  • gRPC可以通過protobuf來定義接口,從而可以有更加嚴格的接口約束條件。
  • 通過protobuf可以將數據序列化爲二進制編碼,這會大幅減少需要傳輸的數據量,從而大幅提高性能。
  • gRPC可以方便地支持流式通信。(理論上通過http2.0就可以使用streaming模式, 但是通常web服務的Restful API似乎很少這麼用,通常的流式數據應用如視頻流,一般都會使用專門的協議如HLS,RTMP等,這些就不是我們通常web服務了,而是有專門的服務器應用)

gRPC場景

  • 需要對接口進行嚴格約束的情況。比如我們提供一個公共的服務,很多客戶端可以訪問這個服務,這時對於接口我們希望有更加嚴格的約束,我們不希望客戶端給我們傳遞任意的數據,尤其是考慮到安全性的因素,我們通常需要對接口進行更加嚴格的約束。這時gRPC就可以通過protobuf來提供嚴格的接口約束。
  • 對於性能有更高的要求的情況。有時我們的服務需要傳遞大量的數據,而又希望不影響我們的性能,這個時候也可以考慮gRPC服務,因爲通過protobuf我們可以將數據壓縮編碼轉化爲二進制格式,通常傳遞的數據量要小得多,而且通過http2我們可以實現異步的請求,從而大大提高了通信效率。

gRPC安裝

在線:

pip install grpcio

pip install protobuf

pip install grpcio_tools

離線

https://pypi.org/project/grpcio/#files

https://pypi.org/project/protobuf/#files

https://pypi.org/project/grpcio-tools/#files

gRPC示例

1、protobuf定義接口和數據類型

syntax = "proto3";


package firstmsg;

service FirstMsg {

    rpc firstMsg(FirstMsgRequest) returns (FirstMsgResponse) {}

}

message FirstMsgRequest {

    string body = 1;

}

message FirstMsgResponse {

    string content = 1;

}

python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. first_msg.proto
-I 指定協議文件的查找目錄 設置爲當前目錄./
--python_out 指定 xxxxxx_pb2.py的輸出路徑
--grpc_python_out 指定xxxxxx_pb2_grpc.py文件的輸出路徑

2、gRPC Server 端代碼

# -*- coding:utf-8 -*-

import sys
import json
import time
from concurrent import futures
from mgrpc.proto.first_msg_pb2 import *
from mgrpc.proto.first_msg_pb2_grpc import *

default_encoding = "utf-8"
if sys.getdefaultencoding() != default_encoding:
    reload(sys)
    sys.setdefaultencoding(default_encoding)


class CFirstMsgServicer(FirstMsgServicer):

    def firstMsg(self, request, context):
        request_body = request.body
        print 'receive client request : {}'.format(request_body)
        if request_body:
            data = json.loads(request_body)
            print 'parse client request : {}'.format(data)
            return FirstMsgResponse(content=json.dumps({"code": 200, "data": "success"}))
        else:
            return FirstMsgResponse(content=json.dumps({"code": 500, "data": "failure"}))


def startup():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    add_FirstMsgServicer_to_server(CFirstMsgServicer(), server)
    server.add_insecure_port('127.0.0.1:10080')
    server.start()
    try:
        while True:
            time.sleep(3600)
    except KeyboardInterrupt:
        server.stop(0)

if __name__ == '__main__':
    startup()

3、gRPC Client 端代碼

# -*- coding:utf-8 -*-

import sys
import json
from datetime import datetime
from mgrpc.proto.first_msg_pb2 import *
from mgrpc.proto.first_msg_pb2_grpc import *

default_encoding = 'utf-8'
if sys.getdefaultencoding() != default_encoding:
    reload(sys)
    sys.setdefaultencoding(default_encoding)


def invoke_first_msg_service():
    channel = grpc.insecure_channel('127.0.0.1:10080')
    first_msg_stub = FirstMsgStub(channel)
    msg = {"from": 1, "to": 2, "op_time": datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "msg": "hello"}
    response = first_msg_stub.firstMsg(FirstMsgRequest(body=json.dumps(msg)))
    print 'response content : {}'.format(response.content)
    response = first_msg_stub.firstMsg(FirstMsgRequest(body=None))
    print 'response content : {}'.format(response.content)

if __name__ == '__main__':
    invoke_first_msg_service()

 

 

發佈了119 篇原創文章 · 獲贊 68 · 訪問量 34萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章