1. 程式人生 > >【一】從0開始,用flask+mongo打造分散式伺服器監控平臺

【一】從0開始,用flask+mongo打造分散式伺服器監控平臺

閱讀本文,代表你將和 奎因 一起,從 0 開始快速入門 flask 開發以及 mongodb 的使用,打造一個穩定、健壯的分散式多機伺服器資源監控平臺

在前面一篇文章《 Python 系統資源資訊獲取工具,你用過沒?》中,我們學習瞭如何使用 Python 中的第三方庫 psutil 來獲取系統的資源資訊,比如 cpu 佔用率、記憶體使用情況、硬碟以及程序情況等。並且奎因在文章的末尾還大言不慚、信誓旦旦的說可以用 psutil 打造一個分散式伺服器監控平臺

德萊厄斯:哼!好大的口氣!!!

我們翻翻舊帳,看看 奎因 上一篇文章末尾說的分散式伺服器監控平臺是什麼:

德萊文:德瑪西亞的人為什麼要打造這麼一個監控平臺呢?莫非有什麼陰謀?

專案開始之前的故事

現在 奎因 的手上有 N 臺 Linux 伺服器,上面部署了很多的爬蟲以及爬蟲依賴的服務,德瑪西亞陣營 希望 奎因 能夠儘量節省開銷,畢竟上次跟 諾克薩斯 一戰之後軍費就很緊張。奎因 臨危受命, 負責爬蟲專案的優化。

但是在必須在優化之前,記錄伺服器上的資源峰值以及對應的爬蟲程序數,以估算爬蟲數量與資源消耗量的關聯關係。市面上的伺服器監控平臺很多,而且功能強大無比,為什麼 奎因 要自己打造,而不用現成的呢?

這個專案的需求並不大、也不復雜,而且定製化程度較高,如果使用成熟的伺服器監控平臺未免也太浪費了,而且需要頻繁的記錄伺服器峰值情況,恐怕還得更改程式碼 -- 奎因

考慮到這些問題,心中覺得不如重寫來的實在,畢竟只有造輪子,才能夠進步得更快。

造一個什麼樣的輪子

上面的專案圖是在假設需求的情況下製作的,但是現在有了真正的需求,那麼就應該將上面圖的進行調整和細化,想到這裡,奎因不禁皺了皺眉頭:要是 華洛 在這裡就好了,至少還有個可以商量的人,但是 華洛 被派出去執行任務,奎因 也只好自己操刀了:

首先,這個模組完成的任務是獲取伺服器資源資訊,包括當前 cpu、記憶體和磁碟的佔用率以及當前 python (因為爬蟲是 python 編寫的,所以監控 python 程序資訊)相關程序的列表,它的名字似乎不太合適,應該改為 系統資源資訊獲取模組。

然後在儲存中心這裡,redis 似乎不太適合,如果要用 nosql 的話,mongodb 可能更適合。而且還要考慮分散式的問題。 奎因 心中很清楚,分散式不過是使用一箇中心儲存,將不同端的資料共同儲存在資料中心而已,那麼這就衍生了三種情況:

  • A).對等分散式 -- 每臺伺服器上的程式碼都一樣,功能也都相同
  • B).主從分散式之推模式 -- 多臺從機將資料推給主機,由主機負責儲存和其他操作。
  • C).主從分散式之拉模式 -- 由主機主動向從機索要資料,形象的理解為拉。

奎因 腦海中閃過一個很形象的畫面:

這不就是早上他去 召喚師峽谷 打野時候路過的 三狼 米粉店門口的貼紙嗎,太適合這個場景了!

推模式與拉模式的選擇

推與拉,看似方向相同,但是卻需要不同的操作(你能夠說 紅 Buff藍 Buff 一樣嗎?)。

首先要考慮的是主機所在的環境,如果主機不在公網當中,而從機都在公網中(比如阿里雲伺服器),這個情況下主機可以訪問從機,但是從機卻無法訪問主機,推拉模式當中的 顯然是不適用的,反之亦然。

奎因 諮詢了峽谷先鋒,得知目前 德瑪西亞陣營 的伺服器中主機不在公網,而從機都在公網,所以很適合 模式。根據經驗得出, 模式在程式碼中的表現通常是主機 request.get(從機)。

所以,儲存中心只需要提供給主機即可,從機不需要訪問到儲存中心,那麼圖就可以改為:

警報中心

奎因 是一名優秀的戰士,甚至警報的重要性,這麼大的專案怎麼能沒有警報功能呢?

泰隆:就算你再小心也沒有用!

根據以往對抗 諾克薩斯 的經驗,他們的人都比較實在而且又猛又蠢,所以警報中心需要即時又準確,那麼警報中心就分為兩部分:發現警情和通知。也就是閾值檢測以及郵件傳送功能

資料處理與視覺化

要讓大家相信,必須拿出真憑實據,所以資料的處理與視覺化是必不可少的,但是由於 華洛 外出執行任務,所以對於資料的呈現這部分 奎因 也沒有什麼頭緒,那就暫且保留原樣吧。

所以整個伺服器資訊監控平臺的結構圖如下:

臨陣磨槍

既然已經規劃好了,那麼差不多就可以開始動工了。奎因 最擅長使用的就是工具,他擁有有整個聯盟最強的弓弩,必定知道工具選擇的重要性。

既然這是一個平臺,那麼就需要 WEB 服務作為支撐,縱觀 Python 領域,最受歡迎的莫過於 Django 和 Flask,由於專案並不大,而且要求輕量、快速,所以 奎因 選擇了他從未使用過的 Flask restful 點選前往文件

剛才探討到資料儲存中心,那就選定 Mongodb,但是為了快速開發,還需要選定一個能夠將 Flask 和 Mongodb 連線在一起的中間工具。目前有幾種可以選擇:

  • A).Pymongo -- mongodb 的 Python 連線庫
  • B).Flask-pymonggo -- 在 A 的基礎上封裝了一層
  • C).MongoEngine -- 一個成熟的 Mongodb ORM 框架

三種都是可以完成任務的,華洛 曾經跟 奎因 說過:從速度、程式碼結構完整性、易用性以及可維護性幾個方面來考慮的話,ORM 當然是最合適的,所以這裡選擇 MongoEngine 點選前往文件

雖然 Flask restful 和 MongoEngine 是 奎因 之前很少接觸的工具,但是 奎因 相信 華洛 的推薦,也相信自己的快速學習能力

最重要的能力

奎因 經歷過大大小小几百場戰鬥,無論是對陣強大的 諾克薩斯陣營 還是召喚師峽谷出沒的那些 怪物,心裡深知:你永遠無法學會所有的知識,但是如果你學會了如何快速學習,那麼你就會變得很強。

開始

經過上面的分析和規劃 『專案似瞭然於胸 又飄渺於峽谷之中』

奎因: 動手吧!

工具的安裝

如果你真的從 0 開始,那麼所有的學習都可以從官方文件開始。相比那些流傳在峽谷和迷霧中的謠言(筆者指的是網上胡亂抄襲的斷頭文章),官方文件當然是更可靠的選擇,就像 奎因 選擇與 華洛 並肩作戰一樣。

根據 Flask restful 文件

MongoEngine

以及 Mongodb 文件

的安裝介紹

Mongodb 視覺化工具 Robt 3T

的安裝介紹

由於有官方文件,所以奎因很快就將他們安裝好了

執行 Flask

Flask restful 文件中的 快速開始 部分,給出了一個簡單的示例程式碼,我們可以通過這段程式碼來啟動 Flask。當然 奎因 從來都不會這麼做,因為直接複製貼上文件是不可能快速學習的,必須立即將文件轉為自己的知識:

from flask import Flask
from flask_restful import Resource, Api

app = Flask(__name__)
api = Api(app)


class Home(Resource):
    
    def get(self):
        return {'status': 'success', 'message': 'Flask restful is running'}


api.add_resource(Home, '/')

if __name__ == '__main__':
    # 崔慶才丨靜覓、韋世東丨奎因 邀請你關注微信公眾號【進擊的Coder】
    app.run(debug=True)
複製程式碼

然後我們執行程式碼

得到 Flask 已經啟動的提示資訊,接著我們可以點選連結,到瀏覽器上看一看輸出了什麼內容:

如程式碼所寫,正確輸出了剛才的內容,說明適當的改動是可以的,不怕不怕。

Flask 與 MongoEngine

通過 MongoEngine 文件 Connecting to MongoDB 部分的介紹:

我們很快就學會了如何用程式碼連線 Mongodb 資料庫(將剛才的程式碼改為):

from flask import Flask
from flask_restful import Resource, Api
from mongoengine import *

connect(
    host='mongodb://localhost/server_resource'
)

app = Flask(__name__)
api = Api(app)


class Home(Resource):

    def get(self):
        return {'status': 'success', 'message': 'Flask restful is running'}


api.add_resource(Home, '/')

if __name__ == '__main__':
    # 崔慶才丨靜覓、韋世東丨奎因 邀請你關注微信公眾號【進擊的Coder】
    app.run(debug=True)

複製程式碼

資料模型

資料模型可以讓我們很輕鬆的操作資料庫,而且還能夠保證程式碼的整潔性和美觀程度 -- 就像士兵總喜歡將自己的武器擦亮一樣 奎因 就經常這麼做。

文件 上面清楚的寫著應該如何建立資料模型,並且用一些例子告訴我們欄位的設定和定義應該如何選擇。

我們現在想一想,需要定義哪一些資料模型呢?

首先,回到那個推拉的模式,我們已經確定使用 模式(不是龍龜 拉莫斯 ),所以意味著主機要從從機上拉取資料,主機如何在資料記錄中確定資料到底是來自於哪一臺從機呢?

所以,我們需要一個伺服器佇列,佇列中記錄了從機的名稱、ip 地址以及備註資訊等,那麼資料模型就可以定義了。

在程式碼中新增一個數據模型類:

class ResourceModel(Document):
    """ 伺服器佇列模型 """
    name = StringField(max_length=255, required=True)
    address = StringField(max_length=160, required=True)
    description = StringField(max_length=255)
複製程式碼

執行程式碼後,你就可以開啟 Mongodb 視覺化工具,檢視新生成的 Collection 了。

小結

除了編寫程式碼之外,開發專案過程中的需求分析、規劃以及技術手段確認也是非常重要的,今天我們的學習就先到這裡,因為 奎因 要外出執行任務了

下一次我們再完善這個分散式多機的監控平臺