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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章