【一】从0开始,用flask+mongo打造分布式服务器监控平台

3,426 阅读9分钟

阅读本文,代表你将和 奎因 一起,从 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 了。

小结

除了编写代码之外,开发项目过程中的需求分析、规划以及技术手段确认也是非常重要的,今天我们的学习就先到这里,因为 奎因 要外出执行任务了

下一次我们再完善这个分布式多机的监控平台