grpc python使用记录

rpc

RPC是远程过程调用(Remote Procedure Call)的缩写形式, 在python中, 有 基于 xml , json ,mq(zeromq) 的rpc 框架, 现在记录grpc 在 python中的使用

grpc

grpc 是一个跨语言的通用rpc框架, 比 SimpleXMLRPCServer, jsonrpclib 性能要高, 比zerorpc 支持的语言多, grpc 传输协议用的是http2 , 序列化用的是protobuf, grpc中有一元调用,单向流式调用,双向流式调用这3种调用方式

一元调用: 客户端获取调用请求, 服务器返回数据
单向流式调用: 某一端源源不断的给另一端发送数据
双向流式调用: 客户端请求服务器建立链接后,两端都可以源源不断的给对方发送数据

protobuf

protobuf 协议压缩数据比 xml json 性能高(序列化出来的二进制数据比 xml,json的小)

proto
syntax = "proto3";

option go_package = "./;proto";

message Request {
  string data = 1;
}

message Reply {
  string result = 1;
}

service StreamGrpc{

  // 一元调用
  rpc GetServerResult(Request) returns (Reply){}
  // 单向流 服务器返回流数据
  rpc ServerStream(Request) returns (stream Reply){}
  // 单向流 客户端发送流数据
  rpc ClientStream(stream Request) returns (Reply){}
  // 双向流 服务器和客户端都发送流数据
  rpc ServerClientStream(stream Request) returns (stream Reply){}
}
protobuf生成python rpc文件命令
python -m grpc_tools.protoc --python_out=. --grpc_python_out=. -I. stream_grpc.proto
server
import time
from concurrent import futures
from threading import Thread
import grpc

from rpc.stream_grpc.proto import streamGrpc_pb2_grpc, streamGrpc_pb2


def server_send_stream():
    for i in range(10):
        yield streamGrpc_pb2.Reply(result="server send stream {}".format(i))
        time.sleep(1)


def server_recv_stream(request_iterator):
    for i in request_iterator:
        print("server 接收到的数据是: ", i)


class StreamServer(streamGrpc_pb2_grpc.StreamGrpcServicer):

    def GetServerResult(self, request, context):
        print("接收到grpc 请求数据是: ", request.data)
        return streamGrpc_pb2.Reply(result="这是一元调用")

    def ServerStream(self, request, context):
        print("serverstream 接收到的数据是: ", request.data)
        for i in range(10):
            yield streamGrpc_pb2.Reply(result="hello {}".format(i))
            time.sleep(1)

    def ClientStream(self, request_iterator, context):
        for i in request_iterator:
            print("clientStream 接收到的数据是: ", i)
        print("client stream end")
        return streamGrpc_pb2.Reply(result="client stream end ")

    def ServerClientStream(self, request_iterator, context):
        # 创建服务器接收流数据线程, 通过多线程的方式实现同时发送和接收数据
        t = Thread(target=server_recv_stream, args=(request_iterator,))
        t.start()

        for i in range(2):
            yield streamGrpc_pb2.Reply(result="server send stream {}".format(i))
            time.sleep(1)
        t.join()


def main():
    g = grpc.server(thread_pool=futures.ThreadPoolExecutor(max_workers=10))
    g.add_insecure_port("0.0.0.0:9966")
    streamGrpc_pb2_grpc.add_StreamGrpcServicer_to_server(StreamServer(), g)
    g.start()
    g.wait_for_termination()


if __name__ == '__main__':
    main()

client
import time
from concurrent import futures

import grpc

from rpc.stream_grpc.proto import streamGrpc_pb2, streamGrpc_pb2_grpc


# 迭代器生成数据
def ClientSendStream():
    for i in range(10):
        yield streamGrpc_pb2.Request(data="client send: {}".format(i))
        time.sleep(1)


class ClientRpc:

    def __init__(self):
        self.channel = grpc.insecure_channel("127.0.0.1:9966")
        self.client = streamGrpc_pb2_grpc.StreamGrpcStub(channel=self.channel)

    def GetServerResult(self):
        result = self.client.GetServerResult(streamGrpc_pb2.Request(data="test"))
        print(result.result)

    # 单向流式调用, 接收服务器流数据
    def ServerStream(self):
        result = self.client.ServerStream(streamGrpc_pb2.Request(data="test"))
        for i in result:
            print("server stream result: ", i)

    # 单向流式调用, 给服务器发送流式数据, 通过迭代器的方式发送
    def ClientStream(self):
        # 执行到这里的时候会堵塞
        result = self.client.ClientStream(ClientSendStream())
        print("Client stream result: ", result)

    # 双向流式调用, 服务器可以给客户端发送,客户端也可以给服务器发送流式数据
    def ServerClientStream(self):
        # 这里 grpc 应该是生成了一个线程用来发送数据
        result = self.client.ServerClientStream(ClientSendStream())
        for i in result:
            print("client server stream result : ", i)


if __name__ == '__main__':
    client = ClientRpc()

    th = futures.ThreadPoolExecutor(max_workers=10)
    f1 = th.submit(client.GetServerResult)
    f2 = th.submit(client.ServerStream)
    f3 = th.submit(client.ClientStream)
    f4 = th.submit(client.ServerClientStream)
    task_list = [f1, f2, f3, f4]
    futures.wait(task_list)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值