python3和grpc的微服務探索實踐

對於微服務的實踐,通常都是基於Java和Golang的,博主最近研究了下基於Python的微服務實踐,如今經過一個簡單的服務來分析Python技術棧的微服務實踐python

技術棧:Python3 + grpc + Zookeepergit

服務API:經過學科獲取相應的題型github

grpc:由Google公司開源的高性能RPC框架,消息協議使用Google自家開源的Protocol Buffers協議機制,傳輸使用HTTP2.0標準,支持雙向流和鏈接多路複用json

 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生成代碼:app

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

 

服務端開啓服務器,對外提供rpc調用流程:框架

 

 

客戶端rpc調用流程:dom

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

相關文章
相關標籤/搜索