zoukankan      html  css  js  c++  java
  • grpc的微服务探索实践

    对于微服务的实践,一般都是基于Java和Golang的,博主最近研究了下基于Python的微服务实践,现在通过一个简单的服务来分析Python技术栈的微服务实践

    技术栈:Python3 + grpc + Zookeeper

    服务API:通过学科获取相应的题型

    grpc:由Google公司开源的高性能RPC框架,消息协议使用Google自家开源的Protocol Buffers协议机制,传输使用HTTP2.0标准,支持双向流和连接多路复用

     Protocol Buffers部分:

    syntax = "proto3";
    
    message Subject {
        string name = 1;
    }
    
    message QuestionType {
        string name = 1;
    }
    
    service SimpleRpcServer {
        // server streaming rpc
        // 客户端发送学科,服务端多次返回该学科包含的题型
        rpc GetSubjectQuestionTypes (Subject) returns (stream QuestionType) {
        }
    }

    这里定义grpc的接口类型为服务器流式RPC,即客户端发起一次请求,服务器可以返回多个响应信息,典型的例子有:客户端向服务端发送一个股票代码,服务端就把该股票的实时数据源源不断的返回给客户端:

    通过protobuf编译器和Protocol Buffers生成代码:

    python3 -m grpc_tools.protoc -I. --python_out=.. --grpc_python_out=.. simple_calculate.proto

    服务端开启服务器,对外提供rpc调用流程:

    客户端rpc调用流程:

    Zookeeper服务注册与发现策略:

    服务注册:

     1 def register_zk(host, port):
     2     """
     3     注册到zookeeper
     4     """
     5     zk = KazooClient(hosts='{host}:{port}'.format(
     6         host=settings_info["zookeeper"]["host"],
     7         port=settings_info["zookeeper"]["port"])
     8     )
     9     zk.start()
    10     zk.ensure_path('/rpc_calc')  # 创建根节点
    11     value = json.dumps({'host': host, 'port': port})
    12 
    13     # 创建服务子节点
    14     zk.create(
    15         '/rpc_calc/calculate_server',
    16         value.encode(),
    17         ephemeral=True,
    18         sequence=True
    19     )

    服务治理发现:

     1     def _get_servers(self, event=None):
     2         """
     3         从zookeeper获取服务器地址信息列表
     4         """
     5         servers = self._zk.get_children(
     6             '/rpc_calc', watch=self._get_servers
     7         )
     8         print(servers)
     9         self._servers = []
    10         for server in servers:
    11             data = self._zk.get('/rpc_calc/' + server)[0]
    12             if data:
    13                 addr = json.loads(data.decode())
    14                 self._servers.append(addr)
    15 
    16     def get_server(self):
    17         """
    18         随机选出一个可用的服务器
    19         """
    20         return random.choice(self._servers)

    服务端实现代码:

     1 class SimpleRpcServerServicer(calculate_grpc.SimpleRpcServerServicer):
     2     """
     3     实现被调用方法的具体代码
     4     """
     5 
     6     def __init__(self):
     7         self.subject_question_type_db = {
     8             'Chinese': ['单选', '多选', '填空', '解答', '问答', '作文'],
     9             'Math': ['单选', '填空', '解答'],
    10             'English': ['单选', '填空', '作文'],
    11             'Physics': ['单选', '多选', '填空', '解答'],
    12             'Chemistry': ['单选', '多选', '填空', '解答'],
    13             'Biology': ['单选', '多选', '填空', '解答'],
    14             'History': ['单选', '多选', '填空', '解答', '问答']
    15         }
    16 
    17     def GetSubjectQuestionTypes(self, request, context):
    18         """
    19         服务器流式RPC调用 根据subject获取question_types
    20         :param request:
    21         :param context:
    22         :return:
    23         """
    24         subject = request.name
    25         question_types = self.subject_question_type_db.get(subject)
    26         for question_type in question_types:
    27             yield calculate_pb2.QuestionType(name=question_type)

    客户端实现代码:

     1 def invoke_get_subject_question_types(stub):
     2     """
     3     根据学科获取题型
     4     Server Streaming RPC 服务器流式RPC  客户端发送,服务器响应多个
     5     :param stub:
     6     :return:
     7     """
     8     subject = calculate_pb2.Subject(name='Chinese')
     9     question_types = stub.GetSubjectQuestionTypes(subject)
    10     for question_type in question_types:
    11         print(question_type.name)

    服务测试:

    开启三个服务,地址分别是 host:8003  host:8005  host:8009,客户端开启两个,client1 和 client2 ,测试结果:

     

    已经成功注册了三个server到Zookeeper,客户端1使用的是8003端口的server,客户端2使用的是8005端口的server;grpc框架对于完整的rpc实现来说,实质上是封装了 网络传输、数据协议的打包解包,使得实现rpc更加简单,其本质仍然是遵守rpc的实现原理的

    完整的代码详见我的git:simple_calculate_service

  • 相关阅读:
    数据类型装换
    变量及数据类型
    27 网络通信协议 udp tcp
    26 socket简单操作
    26 socket简单操作
    14 内置函数 递归 二分法查找
    15 装饰器 开闭原则 代参装饰器 多个装饰器同一函数应用
    12 生成器和生成器函数以及各种推导式
    13 内置函数 匿名函数 eval,exec,compile
    10 函数进阶 动态传参 作用域和名称空间 函数的嵌套 全局变量
  • 原文地址:https://www.cnblogs.com/FG123/p/10391759.html
Copyright © 2011-2022 走看看