• 在Python中使用gRPC的方法示例【h】


    本文介绍了在Python中使用gRPC的方法示例,分享给大家,具体如下:

    使用Protocol Buffers的跨平台RPC系统。

    安装

    使用 pip

    1
    2
    pip install grpcio
    pip install grpcio-tools googleapis-common-protos

    gRPC由两个部分构成,grpcio 和 gRPC 工具, 后者是编译 protocol buffer 以及提供生成代码的插件。

    使用

    编写protocol buffer

    使用 gRPC 首先需要做的是设计 protocol buffer。新建一个 msg.proto 文件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    syntax = "proto3";
     
    service MsgService {
     rpc GetMsg (MsgRequest) returns (MsgResponse){}
    }
     
    message MsgRequest {
      string name = 1;
    }
     
    message MsgResponse {
      string msg = 1;
    }

    以上面的这个消息服务为例,首先是规定语法,这里使用的是 proto3 的语法。接着使用 service 关键字定义服务,gRPC 提供4种 RPC 类型的服务,这里定义的是第一种单一请求单一回应,类似普通的函数调用,其他的使用到了 stream 关键字,将其放在括号里,代表这个数据是流数据。这个以后再来研究,本次先设计一个简单的RPC。

    之后定义两个 message ,一个是请求的结构,一个是回应的结果。 这里表示这个数据结构是字符串,protocol buffer 还可以定义为 int32,int64,double,float 等等。这里赋予的初值可以随便填写,实际使用中,会被赋予新的值。

    生成接口代码

    因为之前安装好了一些辅助插件,使用这里直接可以生成。

    1
    python -m grpc_tools.protoc -I . --pythoout=. --grpc_python_out=. msg.proto

    这里会生成两个文件, msg_pb2.py 和 msg_pb2_grpc.py 。这两个文件是为后续的服务端和客户端所用。前者是定义了一些变量,例如 _MSGREQUEST 中就包含了请求函数的名字,可接受的变量,实际上还是 msg.proto 里定义的东西。

    创建服务端

    首先需要导入 RPC 必备的包,以及刚才生成的两个文件。

    1
    2
    3
    import grpc
    import msg_pb2
    import msg_pb2_grpc

    因为 RPC 应该长时间运行,考虑到性能,还需要用到并发的库。

    1
    2
    3
    4
    from concurrent import futures
    import time
     
    _ONE_DAY_IN_SECONDS = 60 * 60 * 24

    在 Server 中,主要是实现服务,按照 msg.proto 定义的,这里需要写一个服务类 MsgServicer ,这个类需要实现之前定义的 GetMsg 。

    1
    2
    3
    4
    5
    class MsgServicer(msg_pb2_grpc.MsgServiceServicer):
     
      def GetMsg(self, request, context):
        print("Received name: %s" % request.name)
        return msg_pb2.MsgResponse(msg='Hello, %s!' % request.name)

    GetMsg 接收到的请求是在 request 中, msg.proto 中定义的 name 就是 request.name ,接着在 GetMsg 中设计 msg.proto 中定义的 MsgResponse 。

    之后实现启动服务的部分即可。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    def serve():
      server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
      msg_pb2_grpc.add_MsgServiceServicer_to_server(MsgServicer(), server)
      server.add_insecure_port('[::]:50051')
      server.start()
      try:
        while True:
          time.sleep(_ONE_DAY_IN_SECONDS)
      except KeyboardInterrupt:
        server.stop(0)

    通过并发库,将服务端放到多进程里运行。

    完整 msg_server.py 代码如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    import grpc
    import msg_pb2
    import msg_pb2_grpc
     
    from concurrent import futures
    import time
     
    _ONE_DAY_IN_SECONDS = 60 * 60 * 24
     
     
    class MsgServicer(msg_pb2_grpc.MsgServiceServicer):
     
      def GetMsg(self, request, context):
        print("Received name: %s" % request.name)
        return msg_pb2.MsgResponse(msg='Hello, %s!' % request.name)
     
     
    def serve():
      server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
      msg_pb2_grpc.add_MsgServiceServicer_to_server(MsgServicer(), server)
      server.add_insecure_port('[::]:50051')
      server.start()
      try:
        while True:
          time.sleep(_ONE_DAY_IN_SECONDS)
      except KeyboardInterrupt:
        server.stop(0)
     
    if __name__ == '__main__':
      serve()

    创建客户端

    客户端相对简单一些,这里我写了一个简单的客户端。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    import grpc
     
    import msg_pb2
    import msg_pb2_grpc
     
    def run():
      # NOTE(gRPC Python Team): .close() is possible on a channel and should be
      # used in circumstances in which the with statement does not fit the needs
      # of the code.
      with grpc.insecure_channel('localhost:50051') as channel:
        stub = msg_pb2_grpc.MsgServiceStub(channel)
        response = stub.GetMsg(msg_pb2.MsgRequest(name='world'))
      print("Client received: " + response.msg)
     
     
    if __name__ == '__main__':
      run()

    使用 grpc.insecure_channel('localhost:50051') 进行连接 服务端, 接着在这个 channel 上创建 stub , 在 msg_pb2_grpc 里可以找到 MsgServiceStub 这个类相关信息。这个 stub 可以调用远程的 GetMsg 函数。 MsgRequest 中的 name 即 msg.proto 中定义的数据。在回应里可以得到 msg.proto 中定义的 msg 。

    运行

    首先运行 python msg_server.py 启动服务端,接着运行 python msg_client.py 机会看到客户端接收到了服务端传来的消息。以上就是一个简单的 RPC 的使用。

    总结

    这里只是简单的用了一下 gRPC,关于另外三种模式,还在摸索。比起gRPC,我感觉简单 RestFul 更讨我喜欢。

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 相关阅读:
    Linq to OBJECT延时标准查询操作符
    LINQ to XML
    动态Linq(结合反射)
    HDU 1242 dFS 找目标最短路
    HDu1241 DFS搜索
    hdu 1224 最长路
    BOJ 2773 第K个与m互质的数
    ZOJ 2562 反素数
    2016 ccpc 杭州赛区的总结
    bfs UESTC 381 Knight and Rook
  • 原文地址:https://www.cnblogs.com/ExMan/p/12112688.html
Copyright © 2020-2023  润新知