Linux中國

用 Python、 RabbitMQ 和 Nameko 實現微服務

"微服務是一股新浪潮" - 現如今,將項目拆分成多個獨立的、可擴展的服務是保障代碼演變的最好選擇。在 Python 的世界裡,有個叫做 「Nameko」 的框架,它將微服務的實現變得簡單並且強大。

微服務

在最近的幾年裡,「微服務架構」如雨後春筍般湧現。它用於描述一種特定的軟體應用設計方式,這種方式使得應用可以由多個獨立部署的服務以服務套件的形式組成。 - M. Fowler

推薦各位讀一下 Fowler 的文章 以理解它背後的原理。

好吧,那它究竟意味著什麼呢?

簡單來說,微服務架構可以將你的系統拆分成多個負責不同任務的小的(單一上下文內) 功能塊 responsibilities blocks ,它們彼此互無感知,各自只提供用於通訊的 通用指向 common point 。這個指向通常是已經將通訊協議和介面定義好的消息隊列。

這裡給大家提供一個真實案例

案例的代碼可以通過 github: http://github.com/rochacbruno/nameko-example 訪問,查看 service 和 api 文件夾可以獲取更多信息。

想像一下,你有一個 REST API ,這個 API 有一個端點(LCTT 譯註:REST 風格的 API 可以有多個端點用於處理對同一資源的不同類型的請求)用來接受數據,並且你需要將接收到的數據進行一些運算工作。那麼相比阻塞介面調用者的請求來說,非同步實現此介面是一個更好的選擇。你可以先給用戶返回一個 "OK - 你的請求稍後會處理" 的狀態,然後在後台任務中完成運算。

同樣,如果你想要在不阻塞主進程的前提下,在計算完成後發送一封提醒郵件,那麼將「郵件發送」委託給其他服務去做會更好一些。

場景描述

用代碼說話

讓我們將系統創建起來,在實踐中理解它:

環境

我們需要的環境:

  • 運行良好的 RabbitMQ(LCTT 譯註:RabbitMQ 是一個流行的消息隊列實現)
  • 由 VirtualEnv 提供的 Services 虛擬環境
  • 由 VirtualEnv 提供的 API 虛擬環境

Rabbit

在開發環境中使用 RabbitMQ 最簡單的方式就是運行其官方的 docker 容器。在你已經擁有 Docker 的情況下,運行:

docker run -d --hostname my-rabbit --name some-rabbit -p 15672:15672 -p 5672:5672 rabbitmq:3-management

在瀏覽器中訪問 http://localhost:15672 ,如果能夠使用 guest:guest 驗證信息登錄 RabbitMQ 的控制面板,說明它已經在你的開發環境中運行起來了。

服務環境

現在讓我們創建微服務來滿足我們的任務需要。其中一個服務用來執行計算任務,另一個用來發送郵件。按以下步驟執行:

在 Shell 中創建項目的根目錄

$ mkdir myproject
$ cd myproject

用 virtualenv 工具創建並且激活一個虛擬環境(你也可以使用 virtualenv-wrapper)

$ virtualenv service_env
$ source service_env/bin/activate

安裝 nameko 框架和 yagmail

(service_env)$ pip install nameko
(service_env)$ pip install yagmail

服務的代碼

現在我們已經準備好了 virtualenv 所提供的虛擬環境(可以想像成我們的服務是運行在一個獨立伺服器上的,而我們的 API 運行在另一個伺服器上),接下來讓我們編碼,實現 nameko 的 RPC 服務。

我們會將這兩個服務放在同一個 python 模塊中,當然如果你樂意,也可以把它們放在單獨的模塊里並且當成不同的服務運行:

在名為 service.py 的文件中

import yagmail
from nameko.rpc import rpc, RpcProxy

class Mail(object):
    name = "mail"

    @rpc
    def send(self, to, subject, contents):
        yag = yagmail.SMTP('myname@gmail.com', 'mypassword')
        # 以上的驗證信息請從安全的地方進行讀取
        # 貼士: 可以去看看 Dynaconf 設置模塊
        yag.send(to=to.encode('utf-8), 
                 subject=subject.encode('utf-8), 
                 contents=[contents.encode('utf-8)])

class Compute(object):
    name = "compute"
    mail = RpcProxy('mail')    

    @rpc
    def compute(self, operation, value, other, email):
        operations = {'sum': lambda x, y: int(x) + int(y),
                      'mul': lambda x, y: int(x) * int(y),
                      'div': lambda x, y: int(x) / int(y),
                      'sub': lambda x, y: int(x) - int(y)}
        try:
            result = operations[operation](value, other)
        except Exception as e:
            self.mail.send.async(email, "An error occurred", str(e))
            raise
        else:
            self.mail.send.async(
                email, 
                "Your operation is complete!", 
                "The result is: %s" % result
            )
            return result

現在我們已經用以上代碼定義好了兩個服務,下面讓我們將 Nameko RPC service 運行起來。

注意:我們會在控制台中啟動並運行它。但在生產環境中,建議大家使用 supervisord 替代控制台命令。

在 Shell 中啟動並運行服務

(service_env)$ nameko run service --broker amqp://guest:guest@localhost
starting services: mail, compute
Connected to amqp://guest:**@127.0.0.1:5672//
Connected to amqp://guest:**@127.0.0.1:5672//

測試

在另外一個 Shell 中(使用相同的虛擬環境),用 nameko shell 進行測試:

(service_env)$ nameko shell --broker amqp://guest:guest@localhost
Nameko Python 2.7.9 (default, Apr  2 2015, 15:33:21) 
[GCC 4.9.2] shell on linux2
Broker: amqp://guest:guest@localhost
>>>

現在你已經處在 RPC 客戶端中了,Shell 的測試工作是通過 n.rpc 對象來進行的,它的使用方法如下:

>>> n.rpc.mail.send("name@email.com", "testing", "Just testing")

上邊的代碼會發送一封郵件,我們同樣可以調用計算服務對其進行測試。需要注意的是,此測試還會附帶進行非同步的郵件發送。

>>> n.rpc.compute.compute('sum', 30, 10, "name@email.com")
40
>>> n.rpc.compute.compute('sub', 30, 10, "name@email.com")
20
>>> n.rpc.compute.compute('mul', 30, 10, "name@email.com")
300
>>> n.rpc.compute.compute('div', 30, 10, "name@email.com")
3

在 API 中調用微服務

在另外一個 Shell 中(甚至可以是另外一台伺服器上),準備好 API 環境。

用 virtualenv 工具創建並且激活一個虛擬環境(你也可以使用 virtualenv-wrapper)

$ virtualenv api_env
$ source api_env/bin/activate

安裝 Nameko、 Flask 和 Flasgger

(api_env)$ pip install nameko
(api_env)$ pip install flask
(api_env)$ pip install flasgger

注意: 在 API 中並不需要 yagmail ,因為在這裡,處理郵件是服務的職責

創建含有以下內容的 api.py 文件:

from flask import Flask, request
from flasgger import Swagger
from nameko.standalone.rpc import ClusterRpcProxy

app = Flask(__name__)
Swagger(app)
CONFIG = {'AMQP_URI': "amqp://guest:guest@localhost"}

@app.route('/compute', methods=['POST'])
def compute():
    """
    Micro Service Based Compute and Mail API
    This API is made with Flask, Flasgger and Nameko
        parameters:
      - name: body
        in: body
        required: true
        schema:
          id: data
          properties:
            operation:
              type: string
              enum:
                - sum
                - mul
                - sub
                - div
            email:
              type: string
            value:
              type: integer
            other:
              type: integer
    responses:
      200:
        description: Please wait the calculation, you'll receive an email with results
    """
    operation = request.json.get('operation')
    value = request.json.get('value')
    other = request.json.get('other')
    email = request.json.get('email')
    msg = "Please wait the calculation, you'll receive an email with results"
    subject = "API Notification"
    with ClusterRpcProxy(CONFIG) as rpc:
        # asynchronously spawning and email notification
        rpc.mail.send.async(email, subject, msg)
        # asynchronously spawning the compute task
        result = rpc.compute.compute.async(operation, value, other, email)
        return msg, 200

app.run(debug=True)

在其他的 shell 或者伺服器上運行此文件

(api_env) $ python api.py 
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

然後訪問 http://localhost:5000/apidocs/index.html 這個 url,就可以看到 Flasgger 的界面了,利用它可以進行 API 的交互並可以發布任務到隊列以供服務進行消費。

注意: 你可以在 shell 中查看到服務的運行日誌,列印信息和錯誤信息。也可以訪問 RabbitMQ 控制面板來查看消息在隊列中的處理情況。

Nameko 框架還為我們提供了很多高級特性,你可以從 https://nameko.readthedocs.org/en/stable/ 獲取更多的信息。

別光看了,擼起袖子來,實現微服務!

via: http://brunorocha.org/python/microservices-with-python-rabbitmq-and-nameko.html

作者: Bruno Rocha 譯者: mr-ping 校對: wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的電子郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國