使用 psutil 和 MongoDB 做系统监控
admin
2023-07-31 00:47:52
0

这篇入门文章描述了怎样创建一系列的图表来监控一台或多台服务器的负载。使用 Python(psutil 和 bottle),MongoDB 和 jquery。不管你使用什么样的数据库或 WEB 框架,思路都是一样的。

在最后,你将有一个 web 页面为每台服务器展示图表,图表中显示了 cpu, memory, 和 disk usage。

大纲

  • Part 0: Get the Tools
  • Part 1: Get the Data
    • About the MongoDB Collection.
    • The Data Gathering Code
  • Part 2: Set up the bottle Server
  • Part 3: Display the Data with jqplot
    • The HTML Page
    • The JavaScript (jqplot) Code

我们需要监控两台 FreeBSD 服务器来确保它们是正常的,运行期间没有内存和磁盘使用率问题。 为了这篇文章的目的,这两台服务器的名字是 example01 和 example02。

注意:这些恰好是相同的机器运行 MongoDB 副本集,它们中的一台运行 web 服务。没有理由它们必须是相同的机器 – 你完全可以让 MongoDB 运行在一台不同的服务器上,而不是你想监控的其中一台。这对于 web 服务也是一样的 – 可以在任何服务器上,不是必须得在你监控的其中一台服务器上。

我不想登录每台服务器,然后运行 topds 来找出发生了什么。我想要一个有最新图表的 web 页面可以看一眼,每台服务器一个页面。

整个工作流遵循以下三个步骤:

  • 获取系统数据存入 MongoDB(使用 psutilcron
  • 设置一个 Web 服务器来查询 MongoDB 的数据(使用 bottle
  • 编写一个简单的 Web 页面来展示这些数据(jqplot + AJAX)

你可以在 GitHub 工程 psmonitor 上获取所有的代码。在这篇文章中,我使用一些代码片段。

在第一部分,你在一个 cron 任务中使用 psutil Python 包每五分钟写系统信息到 MongoDB 的一个 capped collection 中。这 5 分钟是完全任意的 – 你可以选择你喜欢的任意时段。我正在监控的系统,几分钟提供足够细的粒度。这部分把数据存入 MongoDB。

在第二部分, bottle 应用程序发出一个请求给 MongoDB,然后得到一个 JSON 数据格式的响应。这是在客户端的 HTML 页面和 MongoDB 数据直接创建了一个代理。

在第三部分,你有一个 HTML 文件匹配到你想监控的每台服务器上。该文件加载 jqplot 并发出一个 AJAX 请求给 bottle 应用程序。这部分是波动的原因 – 我们获取存储在 MongoDB 中的负载数据的时间序列图表。

这个我们创建的其中一个图表的示例:

你可以为你想要的任何数据创建图表。我为每台机器使用的图表是:

  • cpu user percent
  • cpu system percent
  • cpu irq
  • cpu nice percent
  • disk space free
  • memory free

Part 0: Get the Tools

以下的工具需要通过安装来实现,但是你可以使用一个不同的数据库或是 Web 框架,如果你已经有的话。

psutil 是一个非常好用的跨平台的系统监控工具,如果想了解更多,请移步至其项目主页,你可以通过 pip 安装它。

NoSQL 数据库 MongoDB 是一个开源的文档型数据库。如果你有自然适合 JSON 结构的数据,MongoDB 会是一款非常适合存储数据的工具。对我来说,它已经成为了首选的工具,当我随时发现需要存储 JSON 格式数据的时候。有趣的是,我越使用它,越能找到新的用途。MongoDB 的文档型结构是惊人的有用,并且可以为许多信息类型提供 map 。

bottle Web 框架是一个用 Python 写的没有任何依赖的小型框架。你可以通过 pip 安装它。你可以使用包括开发服务器让事情继续,稍后把它放在一个不同的后端服务器。我把我的放在 Apache 服务器,一旦我得到我希望他们的。我稍后将写一篇文章关于这个的设置。

jqplot jquery 插件使得生产图表更容易,加上它们看起来也不错,并且它们是统一的很容易的比较图表。比如,当一个进程波动起来的时候,在图表中很容易看出来,因为你可以同时看到 cpu 和 内存飙升,这两个图表是同样的 X 轴位置。你可以使用这个插件做很多事情,这个练习仅仅只是皮毛。

Part 1: Get the Data

当我们想遵循这样的模式创建一个数据结构的时候,在这步中你可以添加和删除任何 psutil 支持的数据。终点是会看 jqplot 图表的用户,因此在你的脑海里保持数据结构,jqplot 想要的是一个双元素列表的列表,其中一个是时间,像这样:

12 [[datetime1, yvalue1], [datetime2, yvalue2], and so on.] 

那个结构不是收集数据的最有效方式,但是记住你的初心是什么一直是很重要的。我们将收集数据并且改变数据结构以便给 jqplot 需要的数据结构。

当第一步我不知道我需要什么和使用什么,我有更多一些测量。我认为,随着时间的流逝,我看到机器的实际需求将改变,并且它非常容易改变。

12345678 {  \’server\’: servername,  \’datetime\’: datetime.now(),  \’disk_root\’: ,  \’phymem\’:,  \’cpu\’: {\’user\’:, \’nice\’:, \’system\’:, \’idle\’:, \’irq\’:,},} 

下面是 python 代码从系统获取数据(使用 psutil )到 MongoDB 数据库。我在 MongoDB 中为每个被检测到的机器创建了一个集合。

你可以在 MongoDB 中创建一个单独的 document,包含了每台机器的数据;这个依赖于你的需求。因为我想每台机器有一个单独的页面,我用同样的方式拆分数据。如果你想把所有机器的图表渲染到一个页面中的话,你或许想让所有机器的数据在一个 document 中。

About the MongoDB Collection

我有一个三个成员的 MongoDB 副本,设置名为 rs1。保存数据的机器恰巧是我监控的服务器,example01 和 example02。这第三个是一个仲裁者,不保存数据。这些 mongoDB 服务器不需要监控,它们可以在任何地方。

我有一个数据库 reports,我们将把新的 collections 放入这个数据库。对于每台机器,我将有一个 collection 来包含它的负载数据:1440 分每天,每 5 分组抽样一次,并保存 2 天的数据,我们需要 576 条记录(documents)。

12 (1440/5)*2 = 576 records per server 

我不确定我最后要使用多少数据,因此我预估了 2k 每个 document,我为每个 document 预估一个比较大的大小, 因为这仅仅是个开始,后面我需要收集更多的数据,结果是 2k 真的是非常慷慨了,每个记录的平均大小是 200 bytes 左右,但是我没有包含任何的网络数据(并且 disk space 是低耗的)。

12 576 documents @ 2048 bytes per doc = 1,179,648 bytes 

对于每一台机器需要监控的机器,我创建了一个固定集合的最大大小上限 1179648 和一个最大的数量上限 576 documents:

1234 use reportsdb.createCollection(\’example01\’, {capped:true, size:1179648, max:576})db.createCollection(\’example02\’, {capped:true, size:1179648, max:576}) 

通过使用一个固定集合,我们将保证数据是以插入顺序保存的,随着时间流逝,老的 documents 会自动删除,因此我们始终有最新的 48 小时数据。

The Data Gathering Code

首先,做必须的 imports 并且连接到 MongoDB 实例:

1234567891011 from datetime import datetimeimport psutilimport pymongoimport socket conn = pymongo.MongoReplicaSetClient(    \’example01.com, example02.com\’,    replicaSet=\’rs1\’,)db = conn.reports 

现在为你想要的每一个数据调用 psutil

12345 def main():    cpu = psutil.cpu_times_percent()    disk_root = psutil.disk_usage(\’/\’)    phymem = psutil.phymem_usage() 

创建一个字典包含你需要的时间序列结构数据。

1234567891011121314     doc = dict()    doc[\’server\’] = socket.gethostname()    doc[\’date\’] = datetime.now()    doc[\’disk_root\’] = disk_root.free,     doc[\’phymem\’] = phymem.free     doc[\’cpu\’] = {        \’user\’: cpu.user,         \’nice\’: cpu.nice,        \’system\’: cpu.system,         \’idle\’: cpu.idle,        \’irq\’: cpu.irq    } 

最后,把这个字典作为一个 document 添加进匹配的 MongoDB 集合中。它将被转换成一个 BSON document 当它被插入数据库的时候,但是结构是一样的。

12345     if doc[\’server\’] == \’example01.com\’:        db.example01.insert(doc)    elif doc[\’server\’] == \’example02\’:        db.example02.insert(doc) 

这里你有代码来获取数据并且存储进数据库集合中。所有剩下的部分是运行代码自动完成的。

在你想监控的每台服务器上设置一个定时任务,每 5 分钟运行一次:

12 */5 * * * * /path/to/psutil_script 

每个 MongoDB 集合包含 48 小时的系统性能数据,随你操弄。

Part 2: Set up the bottle Server

创建一个 bottle 应用程序来查询 MongoDB集合。

连接 MongoDB,在收到每个请求服务器的数据后,给每个对应的服务器响应格式化的数据。

12345678910 from bottle import Bottleimport pymongoload = Bottle() conn = pymongo.MongoReplicaSetClient(    \’example01.com, example02.com\’,    replicaSet=\’rs1\’,)db = conn.reports 

这是一个路由,一个 url 连接。当一个请求进来,从 url 中获取服务器的名字,然后创建并返回一个合适的数据结构(jqplot 需要的)。

123456789101112131415161718192021222324252627282930313233343536 @load.get(\’/\’)def get_loaddata(server):    data_cursor = list()    if server == \’example02\’:        data_cursor = db.example02.find()    elif server == \’example01\’:        data_cursor = db.example01.find() 

相关内容

热门资讯

500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
python绘图库Matplo... 本文简单介绍了Python绘图库Matplotlib的安装,简介如下: matplotlib是pyt...
Prometheus+Graf... 一,Prometheus概述 1,什么是Prometheus?Prometheus是最初在Sound...