ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

从零搭建监控系统:用 WxPusher 实现微信告警

从零搭建监控系统:用 WxPusher 实现微信告警 从零搭建监控系统用 WxPusher 实现微信告警背景之前做了个系统监控 API能看 CPU、内存、磁盘也能存历史、画图表。但它有个问题——只能看不能主动告诉你。CPU 跑满了我得自己打开页面才知道。我想要的是服务器出问题微信直接收到通知。试过的方案一开始想用 PushPlus注册简单接口也简单但实名认证要收 3.9 元。不是嫌贵是觉得为一个告警功能花这个钱不值。然后试企业微信的群机器人。注册了企业微信建了群加了机器人结果发现个人版不支持群机器人的 Webhook只能聊天不能推送。折腾了一下午放弃。最后用了 WxPusher。免费、不用实名接口跟 PushPlus 差不多。扫码登录创建应用拿到 AppToken 和 UID就能推了。实现过程在 api_flask.py 里加了两个函数。第一个是推送函数defsend_alert(title,content):urlhttps://wxpusher.zjiecode.com/api/send/messagepayload{appToken:WXPUSHER_TOKEN,content:content,summary:title,contentType:1,uids:[WXPUSHER_UID]}requests.post(url,jsonpayload,verifyFalse,timeout10)verifyFalse是必须的因为 CentOS 7 的证书过期了不加会报 SSL 错误。第二个是告警检查函数defcheck_alerts(cpu_1min,mem_percent,disk_percent):...ifcpu_value0.8:lastlast_alert_time.get(cpu,0)ifnow-last1800:send_alert(CPU 告警,fCPU 负载过高{cpu_value})save_alert_to_db(cpu,fCPU 负载过高{cpu_value})last_alert_time[cpu]now冷却机制为什么不能报一次就完事一开始我根本没想过冷却这件事。逻辑很简单CPU 超过 0.8 就推一条微信就这样。上线第一天我就被自己坑了。crontab 每 5 分钟调一次/report/report里会检查告警。如果 CPU 一直高那每 5 分钟就推一条。一小时 12 条一晚上 100 多条。第二天早上打开微信全是CPU 负载过高。这在运维里有个专门的说法叫告警风暴。听着挺吓人其实原理很简单——你没告诉系统什么时候该闭嘴。告警风暴的危害比没告警还大。因为一旦消息太多人会本能地忽略所有通知。真正出事的那条反而被淹了。老运维都懂一个道理告警不是越多越好是越准越好。怎么加冷却思路很直接记住上次报警是什么时候如果离现在太近就先别报。用字典存因为我有三种告警每种都要独立记时间last_alert_time{}# 全局字典存每种告警上次推送的时间戳判断的时候nowtime_module.time()# 当前时间秒ifcpu_value0.8:# 第一层先看超没超阈值lastlast_alert_time.get(cpu,0)# 取上次 CPU 报警的时间没有就当 0ifnow-last1800:# 第二层离上次报警超过 30 分钟才报send_alert(CPU 告警,fCPU 负载过高{cpu_value})save_alert_to_db(cpu,fCPU 负载过高{cpu_value})last_alert_time[cpu]now# 记下这次报警时间为什么要两层判断只判断阈值不行——CPU 一直高就一直报。只判断时间差也不行——CPU 明明正常每 30 分钟也给你来一条。两层合起来才是对的真的超了而且距离上次报警够久了才报。为什么用 time.time() 不用 datetime因为要算时间差。time.time()返回的是秒数比如 1758400000两个秒数相减就是秒差直接跟 1800 比。datetime.now()返回的是日期对象相减得到的是 timedelta 对象还得再转成秒麻烦。为什么要用字典不用一个变量假设我只用一个last_alert_time变量CPU 刚报警 → last_alert_time 现在 内存接着超阈值了 → 判断现在 - last_alert_time结果是 0不报内存告警被 CPU 的冷却时间误伤了。它们明明是两回事。用字典分三个 keycpu、memory、disk三种告警各记各的互不干扰。1800 秒是怎么定的30 分钟。这不是标准答案是我自己拍脑袋定的。太短还是会被刷屏。太长真的持续出问题你可能错过。如果按运维的常规做法一般会按问题严重程度分级CPU 短暂飙升可以 15 分钟磁盘满这种致命问题可能 5 分钟就报一次。我这边先用 30 分钟统一处理够用。告警记录入库让告警留得住微信推送是即时消息。推完就过去了翻聊天记录得翻很久。想要过去一周报了几次 CPU光靠微信根本查不到。所以我建了第二张表。之前只有一张monitor_history存的是每 5 分钟采集一次的原始数据。现在加一张alert_historyCREATETABLEIFNOTEXISTSalert_history(idINTEGERPRIMARYKEYAUTOINCREMENT,timestampTEXT,alert_typeTEXT,messageTEXT)四个字段id主键自动递增timestamp告警发生的时间alert_type类型cpu / memory / diskmessage告警内容为什么不和 monitor_history 合一张表字段不一样。采集记录需要memory_total这种字段告警记录不需要。硬塞一起一半字段是空的乱。数据库设计有个基本原则一类数据一张表。每次告警做两件事send_alert(CPU 告警,fCPU 负载过高{cpu_value})# 推微信给人看save_alert_to_db(cpu,fCPU 负载过高{cpu_value})# 存数据库给系统记一个负责实时通知一个负责历史可查。为什么 alert_type 存英文 cpu 不存中文因为后面可能要根据类型筛选。SELECT * FROM alert_history WHERE alert_type cpu比WHERE alert_type CPU告警更稳。展示的时候再翻译成中文就行。页面展示在/dashboard的dashboard()函数里多查一次告警表cursor.execute(SELECT timestamp, alert_type, message FROM alert_history ORDER BY id DESC LIMIT 10)alert_rowscursor.fetchall()ORDER BY id DESC让最新的排前面LIMIT 10只取 10 条。查出来的是元组列表转成字典列表方便 HTML 里用alerts[]forrowinalert_rows:alerts.append({time:row[0],type:row[1],message:row[2]})然后传给模板returnrender_template(index.html,...,alertsalerts)HTML 里用 Jinja2 循环生成表格{% for alert in alerts %}trtd{{ alert.time }}/tdtd{{ alert.type }}/tdtd{{ alert.message }}/td/tr{% endfor %}每次循环生成一行页面上就能看到最近 10 条告警。踩的坑PushPlus 实名要 3.9 元一开始看 PushPlus 文档接口简单几乎零学习成本。结果调接口时报了个错{code:905, msg:账户未进行实名认证}去实名页面一看要收 3.9 元。不贵但我觉得为个告警功能花这个钱不值就换了。企业微信个人版没有群机器人注册了企业微信建了群加了机器人看起来一切正常。但点机器人详情发现只有一个发消息按钮和添加到群聊没有 Webhook 地址。Webhook 是代码推送消息的入口没有它就没法用。查了半天才确认企业微信个人注册的账号不支持群机器人的 Webhook 功能。折腾了一下午放弃。CentOS 7 的证书过期WxPusher 的接口测试通了但 Python 里调的时候报 SSL 错误SSL: CERTIFICATE_VERIFY_FAILED原因是 CentOS 7 太老系统里的根证书过期了不认识 WxPusher 的证书。加个参数跳过验证requests.post(url,jsonpayload,verifyFalse,timeout10)verifyFalse意思是别验证证书了直接连。这不是安全做法只适合本地测试和老系统。生产环境应该更新证书而不是关掉验证。Token 硬编码被 GitGuardian 警告最开始图方便Token 直接写在代码里WXPUSHER_TOKENAT_Cde2Y...推到 GitHub 之后第二天收到 GitGuardian 的邮件检测到你的仓库里暴露了 Bearer 令牌。那一刻挺懵的因为之前完全没意识到这个问题。后来查资料才知道API Key 等于账号密码提交到公开仓库等于公开你的身份。改法是改成从环境变量读WXPUSHER_TOKENos.environ.get(WXPUSHER_TOKEN,)然后在自己机器的.bashrc里设置exportWXPUSHER_TOKENAT_Cde2Y...这样代码里只有变量名值存在操作系统里推到 GitHub 也不会泄露。以后再写任何项目Token 都不能写死在代码里。忘了加冷却差点被自己刷屏上面讲过了第一天就被自己坑。一晚上 100 多条消息。当时的心理感受是这东西比没告警还烦。后来加了冷却才正常。效果现在系统在跑CPU 超过 0.8单核负载内存使用率超过 90%磁盘使用率超过 90%任意一个超了微信直接收到推送。30 分钟内不重复推同样的。打开/dashboard能看到三个卡片实时状态、一条 CPU 历史趋势图最近 10 次、一张告警历史表格最近 10 条告警记录。整个项目从最早的check_system.py脚本变成了一个能采集、能存库、能画图、能告警的小系统。下一步现在的告警还比较粗糙能优化的方向多级告警轻微、严重、致命不同级别不同的冷却时间和推送频率告警恢复通知问题修好后发一条已恢复加登录/dashboard现在谁都能看应该加身份验证换 MySQLSQLite 单机够用但如果多人访问SQLite 会锁表先做到这一步剩下的慢慢迭代。GitHubhttps://github.com/zzp-03/monitor
返回列表