• 【Python】建立gRPC服务端与.Net Core 客户端


    由于需要接入其他平台的OAuth 2.0,还要提供RESTful API获取VMware vSphere的数据,这块内容,.net core我更熟悉,通过上两篇,我们知道这里只能通过python去获取数据了,那么我面临的问题就是python与.net core的数据通信:

    • 方法一:使用Python的web轻量级框架Flask提供api,供aspi.net core调用
    • 方法二:使用Python建立gRPC的服务端,供asp.net core调用

    我选择后者,因为之前有gRPC的基础:

    1.更新pip

    python -m pip install --upgrade pip
    

    2.安装grpc

    python -m pip install grpcio
    

    3.安装gRPC-tool

    python -m pip install grpcio-tools
    

    4.编写.proto文件

    如果对ProtoBuf不熟悉,请参考另外一篇博文【gRPC】ProtoBuf 语言快速学习指南

    主要是要记住几个关键要点:

    • service

      • service Query {
          rpc ListHostStat (google.protobuf.Empty) returns (HostStatReply) {}
        }
        
    • message

      • 作为rpc服务的请求和返回
    syntax = "proto3";
    
    import "google/protobuf/empty.proto";
    
    option csharp_namespace  = "Grpc.VmwareVsphere";
    
    package Vcenter;
    
    service Query {
      rpc ListHostStat (google.protobuf.Empty) returns (HostStatReply) {}
    }
    
    message HostStatReply {
        int32  abnormalHostAmount = 1;
        int32  hostAmount = 2;
        int32  normalHostAmount = 3;
    }
    

    5.生成python服务端代码

    cd python-dir
    python -m grpc_tools.protoc -I ../protos --python_out=. --grpc_python_out=. ../protos/vcenter.proto
    

    这里会生成两个python文件

    [proto-file-name]_pb2.py

    [proto-file-name]_pb2_grpc.py

    6.编写服务端代码

    6.1 引入grpc包与生成的python文件

    import grpc
    import vcenter_pb2
    import vcenter_pb2_grpc
    

    官方还引入了

    from concurrent import futures
    import logging
    

    第一个不知道在干啥,先不细究,第二个应该是写日志的

    6.2 实现服务端类

    class Query(vcenter_pb2_grpc.QueryServicer):
        def ListHostStat(self, request, context):
            hostquery = VmwareHost(host, user, pwd, port)
            hostquery.list_host_state_num()
            return vcenter_pb2.HostStatReply(
                abnormalHostAmount=hostquery.abnormalHostAmount,
                hostAmount=hostquery.hostAmount,
                normalHostAmount=hostquery.normalHostAmount,
            )
    

    类比C#实现服务端类,大概都是继承一个父类,然后重写基类方法:

    class QueryImpl : Query.QueryBase
    {
        public override Task<HostStatReply> ListHostStat(NoPara request, ServerCallContext context)
        {
            return Task.FromResult(new HostStatReply { ... });
        }
    }
    

    整体看下python服务端代码吧

    from concurrent import futures
    import logging
    
    import grpc
    import vcenter_pb2
    import vcenter_pb2_grpc
    from vmware_query import VmwareHost
    
    
    class Query(vcenter_pb2_grpc.QueryServicer):
        def ListHostStat(self, request, context):
            hostquery = VmwareHost(host, user, pwd, port)
            hostquery.list_host_state_num()
            return vcenter_pb2.HostStatReply(
                abnormalHostAmount=hostquery.abnormalHostAmount,
                hostAmount=hostquery.hostAmount,
                normalHostAmount=hostquery.normalHostAmount,
            )
    
    def serve():
        server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
        vcenter_pb2_grpc.add_QueryServicer_to_server(Query(), server)
        server.add_insecure_port('[::]:50051')
        server.start()
        print("grpc server start success..  listen port:50051")
        server.wait_for_termination()
    
    
    host = "192.168.0.110"
    user = "....l"
    pwd = "....!"
    port = 443
    if __name__ == '__main__':
        logging.basicConfig()
        serve()
    
    

    7.启动

    def serve():
        server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
        vcenter_pb2_grpc.add_QueryServicer_to_server(Query(), server)
        server.add_insecure_port('[::]:50051')
        server.start()
        print("grpc server start success..  listen port:50051")
        server.wait_for_termination()
    

    类比C#实现的服务端

    Server server = new Server
    {
        Services = { Query.BindService(new QueryImpl()) },
        Ports = { new ServerPort("localhost", 50051, ServerCredentials.Insecure) }
    };
    server.Start();
    
    Console.WriteLine("Query server listening on port " + 50051);
    Console.WriteLine("Press any key to stop the server...");
    Console.ReadKey();
    
    server.ShutdownAsync().Wait();
    

    8.编写客户端代码

    客户端是Asp.net Core,在Webapi中调用gRPC服务

    8.1 安装nuget包

    参考【gRPC】 在.Net core中使用gRPC 4.1 安装包

    8.2 编辑csproj文件

    引入与服务端相同的proto文件

      <ItemGroup>
        <Protobuf Include="....protos*.proto" GrpcServices="Client" Link="Protos\%(RecursiveDir)%(Filename)%(Extension)" />
      </ItemGroup>
    

    8.3 编码

    [HttpGet]
    [Produces("application/json")]
    public async Task<Host> GetHostAsync()
    {
        AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
        var channel = GrpcChannel.ForAddress("http://localhost:50051");
        var queryClient = new QueryClient(channel);
        var reply = await queryClient.ListHostStatAsync(new Grpc.VmwareVsphere.NoPara());
        Console.WriteLine("StatService 服务返回异常主机数据: " + reply.AbnormalHostAmount);
        Console.WriteLine("StatService 服务返回主机数据: " + reply.HostAmount);
        Console.WriteLine("StatService 服务返回正常主机数据: " + reply.NormalHostAmount);
        return new Host() { 
            AbnormalHostAmount=reply.AbnormalHostAmount,
            HostAmount=reply.HostAmount,
            NormalHostAmount=reply.NormalHostAmount
        };
    }
    

    参考链接

    https://www.velotio.com/engineering-blog/grpc-implementation-using-python

    https://www.grpc.io/docs/languages/python/quickstart/

  • 相关阅读:
    tars framework 源码解读(五) framework 部分章节。PropertyServer,StatServer上报统计服务
    tars framework 源码解读(五) framework 部分章节。NotifyServer 通知服务
    mysql之 percona-xtrabackup 2.4.7安装(热备工具)
    年轻
    C语言整型数据(整数)
    【转】想象5年后的你
    MyBatis学习总结(二)——MyBatis核心配置文件与输入输出映射
    CSS3——前端预处理技术(Less、Sass、CoffeeScript、TypeScript)
    HTML(三)——本地存储
    HTML5(二)——特殊符号、新增属性、表单重写属性、
  • 原文地址:https://www.cnblogs.com/RandyField/p/13430399.html
Copyright © 2020-2023  润新知