写给脚本加了向量提取后,云服务器内存每天悄悄涨满的排查过程

举报
yd_243285056 发表于 2026/10/24 00:18:22 2026/10/24
【摘要】 前阵子给自己的资讯聚合脚本加了个新功能:把抓回来的文章标题和摘要转成向量,做个简单的余弦相似度计算,用来过滤掉不同来源的重复新闻。这套脚本挂在一台华为云2核4G的机器上跑,每天定时抓几十次。 刚上线前两天看着挺正常,去控制台看监控,CPU不高,内存也才吃了40%左右。但到了第四天早晨,我发现定时推送断了,连上SSH一查,后台那个Python守护进程直接没了,翻dmesg看日志,清清楚楚写着O...

前阵子给自己的资讯聚合脚本加了个新功能:把抓回来的文章标题和摘要转成向量,做个简单的余弦相似度计算,用来过滤掉不同来源的重复新闻。这套脚本挂在一台华为云2核4G的机器上跑,每天定时抓几十次。

刚上线前两天看着挺正常,去控制台看监控,CPU不高,内存也才吃了40%左右。但到了第四天早晨,我发现定时推送断了,连上SSH一查,后台那个Python守护进程直接没了,翻dmesg看日志,清清楚楚写着Out of memory,被系统的OOM Killer给掐死了。

当时觉得很奇怪,因为我每次处理的文章批次都不大,一次也就三四十条文本,按理说算完之后内存就该释放掉,不至于把4G内存全吃光。为了找出是哪里在漏,我在机器上重新起了进程,挂着监控看了两天,记录一下排查和解决的过程。

第一个问题是Python本身的垃圾回收机制并没有把内存还给操作系统。
最开始我以为是自己写了循环引用,导致对象没被释放。于是我特意在每轮批量计算完后手动调了gc.collect(),并且把存储中间结果的列表全部del清空。
但在终端里用top一直盯常驻内存(RES),发现根本没用。跑完一轮批处理,内存涨上去两三百兆,gc触发后,虽然Python内部的对象确实被回收了,但进程占用的系统物理内存几乎纹丝不动。
查了资料才搞明白,Linux下glibc的内存分配器(ptmalloc)在面对大量频繁申请、释放小内存块时,很容易产生内存碎片。哪怕Python把内存标记为空闲,底层内存池也往往不会立即通过brk或mmap把这部分物理内存交还给Linux内核,表现出来的就是进程占用的内存只会单调递增,日积月累直到爆掉。

第二个解决办法是把常驻计算改成“阅后即焚”的子进程。
既然Python长进程在Linux下释放内存这么墨迹,我索性不让它以长驻线程的方式做模型推理了。
原本是在主循环里直接调用模型计算,我改成了用multiprocessing起一个独立的短暂子进程。每次脚本抓完一批数据,主进程把文本丢给子进程,子进程加载量化模型、跑完推理、把向量矩阵写回共享队列,然后立刻退出销毁。
这种做法的好处非常明显:子进程一结束,操作系统会瞬间把该进程占用的所有物理内存强制回收得干干净净,从根源上绕过了glibc的内存碎片问题。虽然每次唤起子进程有一两秒的模型初始化开销,但对于我这种间隔几十分钟才跑一次的定时任务来说,这点时间完全微不足道。

第三个调整是顺手配置了华为云主机的Swap交换分区。
买这台机器的时候图省事,系统装好后默认是没有开Swap分区的,内存只要达到4G的物理上限,Linux内核没有任何退路,只能直接触发OOM杀进程。
针对这种情况,我直接在云硬盘上划了一个2G大小的swapfile挂载上去,并且把系统的vm.swappiness调到了10。
这样设置的意思是,让系统平时依然优先使用物理内存保证运行速度,但当遇到突发的瞬时高负载、内存快见顶时,允许把极低频的数据临时换出到磁盘上顶一下,防止进程被直接抹杀。

第四个细节是限制了底层矩阵计算库的并发线程。
在子进程里跑向量提取时,底层调用的numpy和onnx默认会根据CPU核数拉起多个线程去跑并行矩阵乘法。两个核本来就不富裕,线程一多不仅争抢CPU,还会在各自的线程栈里申请额外的临时缓冲区。
我在脚本入口处硬性加了环境变量,把OMP_NUM_THREADS和OPENBLAS_NUM_THREADS都锁死为1。
单线程跑几十条短文本的耗时其实也就多了不到一秒,但运行期间的瞬时内存峰值直接被砍掉了一半还多,对小机器来说稳妥得多。

改完这套方案之后,这台服务器已经连续跑了三周。
现在主守护进程常驻内存常年稳定在70M左右,每次批处理触发时唤起子进程跑上几秒,处理完内存瞬间回落。
在小规格云主机上跑数据处理或者小模型任务,不要把长生命周期和高密集计算混在一个进程里。用完即丢的子进程模式虽然看起来不够优雅,但面对有限的硬件资源,它往往是成本最低、也最皮实稳定的解决办法。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。