网站监控源码
凌晨三点,网站我盯着终端里滚动的监控日志,一个404状态码跳了出来。源码那是网站我自己的服务器,某个爬虫正试图访问一个不存在的监控路径。没人会在这个点手动敲URL,源码除非是网站脚本在扫描漏洞。监控源码的监控价值,在这一刻变得具体——它让你看见那些看不见的源码访问者。
写监控系统,网站核心就一句话:定时请求,监控记录响应,源码异常告警。网站但真做起来,监控坑比想象多。源码第一版我用了Python的requests库,每五分钟GET一次首页,检查状态码是不是200。简单粗暴,跑了一周,发现服务器宕机两小时都没察觉——因为那两小时里,网站恰好返回200(缓存页面)。你看,监控本身也会骗人。
后来改成检查页面里的关键字符,比如
标签内容。要是返回的HTML里没有“我的博客”四个字,就算HTTP 200也当故障处理。这个改动救了两次命,一次是数据库连接池耗尽导致页面白屏,一次是CDN回源失败返回了默认欢迎页。监控要监控“业务成功”,不是“请求成功”。
代码结构其实很朴素。一个主循环,里面塞三个函数:fetch_url()负责请求,设置10秒超时;parse_response()提取状态码、响应时间、页面大小;compare_with_threshold()把结果和预设规则比对。规则存在JSON文件里,比如{ "url": "https://example.com", "max_response_time": 2000, "expected_string": "欢迎"}。改规则不用动代码,改配置就行。
告警部分最折腾。邮件太慢,短信要钱,最后选了Telegram Bot——免费,推送快,还能带截图。代码里就几行:requests.post(f"https://api.telegram.org/bot{ token}/sendMessage", data={ "chat_id": chat_id, "text": message})。但有个坑:Telegram在某些网络环境下会被墙,所以告警通道本身也得监控,不然服务器挂了,告警也发不出去,等于白搭。
存储这块,我没用数据库,直接写JSON文件。每天一个文件,按时间戳命名,记录每次检查的结果。文件大小一天也就几百KB,攒一年才几百MB,硬盘完全扛得住。真出了事,用grep搜时间戳,比查数据库还快。有人觉得这不够“工程化”,可个人站长要的是实用,不是架构评审。
还有个细节容易被忽略——监控脚本本身会崩。Python进程被OOM killer干掉,或者服务器重启后没设开机自启,监控就静默失效了。我的解决办法是crontab里写两行:一行跑监控,一行检查监控进程是否活着,死了就重启。虽然笨,但管用。
现在这套源码跑在树莓派上,功耗五瓦,已经连续运行了214天。偶尔半夜收到告警,爬起来看,多数是某个外部API超时,不是自己网站的问题。但那种“知道发生了什么”的感觉,比睡个安稳觉踏实。监控源码的价值不在于代码多漂亮,而在于它把不确定性变成了可处理的日志。
说到底,写监控就是写一种对失控的恐惧。你越清楚系统会怎么挂,就越能在它挂之前做点什么。源码里没有魔法,只有对HTTP协议的敬畏,和对“一切都会出问题”这个事实的坦然接受。