Python微服務框架nameko的簡單使用
推薦一款 Python 微服務框架 - Nameko
微服務框架有Istio、Dubbo和nameko三種:
一、Istio
Istio是一個用來連接、管理和保護微服務的開放平台,使用Istio可以建立已部署服務網絡,且Istio具備負載均衡、服務間認證、監控等功能。
二、Dubbo
Dubbo是一個利用同步通信實現的分布式微服務框架,其致力於提供高性能和透明化的RPC遠程服務調用方案,以及SOA服務治理方案。
三、nameko
nameko是一個利用異步通信方式實現的微服務框架,其采用RabbitMQ消息隊列作為消息中間件,原理簡單,使用方便。
在後端開發方面,Java的使用呢要遠比Python廣泛,所以Java的微服務框架非常流行,但Python的微服務框架卻很少有人問津。在大多數需要微服務的場合下直接用Java的各種工具就可以解決問題,但如果業務代碼使用Python寫的,那麼使用Java工具就不太方便了。
其實Python也有自己的微服務框架,其中用的最多的就是nameko,nameko框架輕便,使用簡單,易上手,是一個很不錯的微服務框架。
首先假設要做一款簡化版的微信產品,它只有如下幾個功能。那麼你的初期系統設計應該是這樣的:
(1)微信單體架構
隨著時間的遷移,跨年夜,同一時刻,很多人都在發朋友圈,朋友圈接口訪問量很大,服務器訪問峰值瞬間沖頂,那麼我們可以開始做集群操作,也就是整一個服務器做集群操作。
那麼我們的注冊登錄接口、支付接口、聊天接口也有了一個復制集,但此刻這幾個接口其實並沒有很大的訪問量,那我們能不能只將朋友圈的接口做擴容呢?答案當然是可以的,基於微服務架構進行擴容。
(2)微服務架構
直接水平擴展朋友圈服務,如下圖,峰值壓力有所緩解。
然而在各個功能拆解成一個個的服務之後,由客戶端直接訪問各個微服務,這樣就直接將我們的服務暴露了出來,客戶端也需要定制相應的訪問策略。這樣的設計還是沒有那麼友好。那麼,我們能不能將所有微服務統一到一起呢?且看下圖:
(3)微服務架構Plus
在這張示例圖中,多了一個API Gateway模塊,那API網關是用來干嘛的呢?一般情況下 API 網關有以下任務:路由,安全,限流,緩存,日志,監控,重試,熔斷等,然後服務層就純粹的做業務,也能夠很好的保證業務代碼的干淨,不用關心安全,壓力等方面的問題。
(4)微服務的特征與優勢
微服務特征:單一職責;輕量級的通信;隔離性,運行在自己的進程中,不會相互干擾;有自己的數據,數據的獨立性,每個微服務都有自己的數據庫;技術的多樣性,選用適合的技術做合適的事。
一個微服務就負責某一個職責,就像朋友圈服務,它就只負責朋友圈的增刪查功能,與其他服務獨立開來,可以選用不同的技術語言,來滿足不同的需求。
微服務的優勢:獨立性、敏捷性、技術棧靈活、高效團隊。
(5)微服務的不足
額外的工作、數據一致性、溝通成本、debug 單元測試困難、需要額外工作。
微服務架構最重要的就是使用什麼方式進行服務間通信(也稱作服務調用),按照通信方式的不同,主要可以分為同步通信和異步通信兩種方式:
同步調用比較簡單,一致性強,但是容易出調用問題,性能體驗上也會差些。同步通信最常用的兩種協議是RESTful和RPC,而目前使用最廣泛,最有名的兩種微服務框架Spring Cloud和Dubbo分別使用了RESTful和RPC協議。RESTful和RPC兩種協議各有優勢,具體使用要看業務場景。
Dubbo框架是一個非常流行的采用同步通信的分布式微服務框架,下圖就是Dubbo框架的工作原理圖:
首先一個微服務應用程序需要有服務的生產者和服務的消費者,另外還需要一個注冊中心(常見的有zookeeper和RabbitMQ等)來管理和調度服務。
微服務架構的程序運行的一般步驟為:
(1)服務提供方,即生產者啟動服務,並將服務提交到注冊中心注冊服務。
(2)服務需求方,即消費者連接到注冊中心,向注冊中心發出請求,申請需要的服務。
(3)注冊中心根據消費者發出的請求來調度服務,將對應的服務提供者(生產者)的信息發送給消費者。
(4)消費者和生產者之間建立連接,消費者調用服務。
(5)記錄服務調用過程中的信息。
異步通信一般通過消息中間件來進行服務間通信,消息中間件能為調用之間提供的緩沖,確保消息積壓不會沖垮被調用方,同時能保證調用方的服務體驗,繼續干自己該干的活,不至於被後台性能拖慢。不過需要付出的代價是一致性的減弱。
Nameko框架就是一個采用異步通信方式的微服務框架,采用RabbitMQ消息隊列作為消息中間件,原理非常簡單,使用起來也很方便。
Nameko采用RabbitMQ作為注冊中心,所以使用Nameko必須要先安裝RabbitMQ。
以docker容器的方式運行RabbitMQ是最為簡便快捷的方式,兩行命令就搞定了,這裡介紹如何使用docker運行RabbitMQ。
第一步:從DockerHub拉取rabbitmq鏡像
docker pull rabbitmq:management
第二步:運行RabbitMQ容器
docker run -d --hostname my-rabbit --name rabbit -p 15672:15672 -p 5672:5672 rabbitmq:management
參數分析如下docker run -d
--hostname my-rabbit
--name rabbit
-p 15672:15672 控制台Web訪問端口號
-p 5672:5672 應用訪問端口
rabbitmq:management
如果需要設置用戶名和密碼,則使用這條命令
docker run -d --hostname my-rabbit --name rabbit -e RABBITMQ_DEFAULT_USER=user -e RABBITMQ_DEFAULT_PASS=password -p 15672:15672 -p 5672:5672 rabbitmq:management
參數分析如下docker run -d
--hostname my-rabbit
--name rabbit
-e RABBITMQ_DEFAULT_USER=user
-e RABBITMQ_DEFAULT_PASS=password
-p 15672:15672 控制台Web訪問端口號
-p 5672:5672 應用訪問端口
rabbitmq:management
我運行容器時沒有設置用戶名和密碼,所以使用用戶名guest,密碼guest登錄。
http://localhost:15672/
http://192.168.1.10:15672/
在浏覽器中通過下面的連接進入到MQ後台Web管理頁面
登錄成功界面
pip install nameko
create_service.py發布服務,服務名稱為“helloservice”。
from nameko.rpc import rpc
class hello_service:
name = "helloservice"
@rpc
def hello(self):
print("hello world")
@rpc
def hi(self):
print("my name is lucy")
使用nameko框架的run命令啟動微服務。
nameko run create_service --broker amqp://guest:[email protected]
如果顯示信息如下則表示服務成功啟動
invoke_service.py調用服務進行消費。
from nameko.standalone.rpc import ClusterRpcProxy
CONFIG = {
'AMQP_URI': "amqp://guest:[email protected]"}
def compute():
with ClusterRpcProxy(CONFIG) as rpc:
rpc.helloservice.hello()
if __name__ == '__main__':
compute()
運行invoke_service.py調用服務後在命令行打印出“hello world”,服務被成功調用。
自定一個類,使用name屬性定義服務的名稱為generate_service。然後使用裝飾器rpc注冊服務中具體的方法。
from nameko.rpc import rpc
class GenerateService(object):
# 定義微服務名稱
name = "generate_service"
@rpc
def hello_world(self, msg):
print('hello,I am been called by customer(消費者),返回消息:{}'.format(msg))
# 返回結果
return "Hello World!I Am a msg from producer!"
使用nameko命令在終端將目標文件中的服務注冊到MQ中。
# 注冊服務
nameko run producer_service --broker amqp://guest:[email protected]:5672/
參數分析如下
producer_service:目標文件名稱
guest:guest:MQ用戶名及密碼
ip地址:5672:MQ服務器ip地址及應用端口號
為了演示方便,這裡使用Flask編寫一個簡單的API。
(1)首先,定義MQ連接信息
(2)然後,編寫一個API接口,請求方式為GET。
(3)最後,使用nameko中的ClusterRpcProxy拿到消費者對象去調用服務中的具體方法。
from flask import Flask
from nameko.standalone.rpc import ClusterRpcProxy
app = Flask(__name__)
# MQ配置
config_mq = {
'AMQP_URI': "amqp://guest:[email protected]"}
@app.route('/hello_world', methods=['GET'])
def call_service():
with ClusterRpcProxy(config_mq) as rpc:
# 消費者調用微服務(生產者),獲取服務(生產者)的返回值
# rpc.服務名.方法名
result = rpc.generate_service.hello_world(msg="xag msg")
# 返回結果
return result, 200
if __name__ == '__main__':
app.run(debug=True)
使用Postman調用上面的API接口,就能完成消費者調用生成者服務中的方法,拿到返回結果的完整流程。
http://127.0.0.1:5000/hello_world。
上面以Flask為例講解了微服務的搭建的完整流程,如果是其他Web框架(比如Django、FastAPI等)集成微服務流程是類似的。