影刀RPA进阶:我写了一套调度引擎,500个店铺同时跑,内存稳得像条直线
一、五百个店铺,一跑脚本就蓝屏,老板差点把电脑砸了
去年年底,一个做Shopee跨境的兄弟阿杰通过公众号找到我,上来就发了一段视频。
视频里,他的电脑屏幕上密密麻麻全是浏览器窗口,数了一下,大概有四十几个。然后画面突然卡住,鼠标不动了,紧接着蓝屏。
他发了一串语音:“林哥你看到没?我五百个Shopee店铺,光每天领个签到奖励就要搞死个人。想用影刀写个流程批量跑,一开二十个窗口就开始卡,开三十个直接蓝屏。我32G内存,i7处理器,这配置还不够?”
我问他具体怎么跑的。
他说,就是用Python写了个循环,读取店铺列表,然后多线程调影刀流程。一开始开了10个线程,勉强能跑,但是五百个店得跑七八个小时。他贪快,把线程数调到30,结果电脑直接罢工。
“而且,”他补充,“跑着跑着,一些窗口明明流程结束了,浏览器却不关,像僵尸一样在后台吃内存。我得手动去任务管理器里一个一个杀进程。这么搞下去,别说自动化了,人都要疯了。”
我听完,感觉他的问题根本不是电脑配置的事。
是没有调度。
大多数店群老板对“并发”的理解就是“开更多窗口”,但并发的精髓是控制。没有控制的并发,就是一场内存泄漏的灾难。
店群矩阵自动化突破运营极限!
我对阿杰说:“你给我两周时间,我帮你把执行层从根上重构一遍。保证你以后跑五百个店,电脑稳得像块石头。”
这就是我后来在Alien系统里重点打磨的高并发调度引擎的故事。
二、店群并发的最大误区:多开窗口就是快
阿杰的问题非常典型,几乎每一个从“几十个店”扩张到“几百个店”的店群老板都会遇到。
他们的自动化思路往往很简单:
一个店铺跑一个流程,十个店铺就开十个窗口,一百个店铺就开一百个窗口。
速度确实上去了,但三分钟就崩。
核心矛盾在哪儿?
浏览器是内存大户。
一个Chromium实例,启动就要两三百兆,加载完页面轻松上G。
如果你一口气启动三十个浏览器窗口,30G内存瞬间吃光,系统开始疯狂换页,CPU上下文切换飙升,蓝屏只是时间问题。
进程管理是失控的。
脚本跑完一个店铺,有时候浏览器窗口关了,但渲染进程、GPU进程还挂在后台。
这些“僵尸进程”不断积压,内存越吃越多,直到系统崩溃。
阿杰手动杀进程的场景,我太熟悉了。
任务调度是裸奔的。
没有任何排队机制,线程之间互相抢资源,一个任务卡住了,后面全堵死。
更致命的是,代理IP可能复用,Cookie路径可能串,店铺环境互相污染。
用一句话总结:
没有调度和隔离的“高并发”,就是给电脑上刑。
三、我的思路:把五百个店铺的执行变成“银行排队”
Alien系统的并发调度引擎,设计灵感其实很朴素——银行排队。
你去银行办业务,不是所有人一起涌到窗口,而是取号,然后在等候区坐着。
窗口就那几个,叫到你了,你去办,办完了,窗口空出来,下一个补上。
在Alien里,我把每个“店铺+任务”组合,封装成一个任务对象,丢进一个异步队列。
系统维护一个固定大小的槽位池,比如20个槽位。
任何时刻,只有拿到槽位的任务才能启动浏览器,去执行影刀的流程。
执行完毕,浏览器优雅关闭,槽位释放,下一个排队任务自动补上。
这样一来,不管你有500个店铺还是1000个店铺,
系统同时占用的资源,永远限制在20个浏览器窗口以内。
内存稳定,CPU平稳,跑一整夜都不会崩。
我在Alien的“自动化编排流”面板里,把这个能力包装成了一个极其简单的操作。
temu店群自动化报活动案例
阿杰只需要:
- 把“Shopee签到领券”流程卡片拖到编排区
- 勾选全部500个店铺
- 设置最大并发窗口数为20
- 点击“开始执行”
然后去睡觉。
- 点击“开始执行”
系统在后台自动排队、叫号、执行、回收,
第二天早上他打开运行监控面板,绿色一排成功,红色几个失败(基本都是代理波动),
点一下“重试失败项”,五分钟收工。
四、调度器的心脏:槽位控制 + 超时强杀 + 看门狗
这个银行排队模型,在代码层面是怎么落地的?
我用了Python的asyncio来构建整个调度核心。asyncio.Semaphore做槽位控制,asyncio.Queue做任务队列,
每个任务包一层asyncio.wait_for做超时控制。
但这还不够。
真正让我踩过坑之后才加上的,是一个资源看门狗。
当时第一次线上压测,我想试试极限,把槽位开到了25。
前半个小时跑得非常丝滑,内存曲线平稳。
然后突然,内存从8G开始往上涨,12G,15G,18G……
我赶紧看任务管理器,发现有几个浏览器窗口明明已经跑完流程了,
但进程还挂在那里,每个占着三四百兆。
我查日志才找到根因:有两个店铺的签到流程,跑完后页面弹了个“评价本次服务”的弹窗,
流程逻辑里没处理这个弹窗,浏览器就一直等,进程退不出。
这些僵尸进程越积越多,内存就爆了。
那天晚上,我给调度器加了一个看门狗协程。
它每10秒巡检一次所有正在执行的任务,
如果发现某个任务已经标记为“已完成”,但它对应的浏览器进程树还活着,
看门狗会直接调用系统命令,把这个进程树从根上杀掉。
有了看门狗,再也没出现过内存泄漏。
下面这段代码,是Alien调度器的核心骨架,
槽位控制、超时强杀、看门狗巡检,全在里面了:
importasyncioclassAlienScheduler:""" Alien 高并发调度引擎 固定槽位 + 任务队列 + 超时回收 + 看门狗清僵尸 """def__init__(self,max_slots:int=20,task_timeout:int=3600):self.semaphore=asyncio.Semaphore(max_slots)self.queue=asyncio.Queue()self.task_timeout=task_timeout self._active_tasks={}# 记录当前占用槽位的任务asyncdefsubmit(self,task):awaitself.queue.put(task)asyncdef_worker(self,worker_id:int):whileTrue:task=awaitself.queue.get()asyncwithself.semaphore:self._active_tasks[task.uid]=tasktry:# 超时控制:任务超过指定时长未完成,强制终止awaitasyncio.wait_for(task.execute(),timeout=self.task_timeout)exceptasyncio.TimeoutError:print(f"[超时]{task.name}超过{self.task_timeout}s,强制终止")task.kill()exceptExceptionase:print(f"[异常]{task.name}:{e}")task.kill()finally:self._active_tasks.pop(task.uid,None)self.queue.task_done()asyncdef_watchdog(self,interval:int=10):""" 看门狗:每 interval 秒巡检一次, 杀掉那些已完成但进程还活着的僵尸任务 """whileTrue:zombies=[]foruid,taskinself._active_tasks.items():iftask.is_finished()andtask.is_process_alive():zombies.append(uid)foruidinzombies:print(f"[看门狗] 发现僵尸进程:{self._active_tasks[uid].name},强制清理")self._active_tasks[uid].kill()delself._active_tasks[uid]awaitasyncio.sleep(interval)asyncdefstart(self,worker_count:int=20):workers=[asyncio.create_task(self._worker(i))foriinrange(worker_count)]watchdog=asyncio.create_task(self._watchdog())awaitself.queue.join()watchdog.cancel()forwinworkers:w.cancel()``` 在这个调度器里,`task.kill()` 不是简单发个终止信号, 而是会递归查找这个任务启动的所有子进程, 调用系统命令把它们全部终止。 确保不留下任何一个在后台偷内存的幽灵。## 五、高并发的另一半:隔离,不然跑得再快也是白跑你可能会问:调度这么稳,那环境串了怎么办? 这是我在Alien里把**调度引擎**和**环境隔离矩阵**设计成一体的原因。 每一个任务在执行之前,都会从环境管理中心拉取对应店铺的独立Profile。 这个Profile包含:*独立的浏览器用户数据目录(物理路径不同,Cookie、缓存完全隔离)**独立的代理IP(带认证,支持HTTP/SOCKS5)**独立的浏览器指纹(基于上百套真实设备模板,创建时随机微调Canvas、WebGL、字体列表)**窗口标题强制注入店铺名和ID(防止手滑) 即使20个窗口并发跑, 每一个窗口都是完全独立的数字身份, 平台看到的是20个来自不同设备、不同网络、不同指纹的独立用户。 调度负责“不乱”,隔离负责“不串”, 两者结合,才是真正能扛住几百个店铺的商业级系统。## 六、阿杰的Shopee矩阵,从“蓝屏日常”到“稳如磐石”系统交付给阿杰后,他当天晚上就跑了一次。500个Shopee店铺,全部执行“自动签到领券”流程, 并发窗口设20个,总耗时4小时23分钟。 期间内存占用最高12G,CPU温度没超过65度, 一次蓝屏都没出现。 第二天早上他给我发了一条消息: “林哥,我昨晚终于睡了一个踏实觉。电脑在那自己跑,风扇声音都小了。这要是放在以前,我得坐旁边盯着,随时准备按重启键。” 他后来还跟我说,他算了一笔账: 以前500个店铺的签到领券,如果让人工做,需要3个人干一整天。 现在一个人,下班前设置好任务,第二天早上看报告,全自动。 “这不是省了几个人的钱,是把我从焦虑里救出来了。”## 七、给想自己搞高并发调度的兄弟三点建议写了这么多,总结三个最核心的点:**第一,并发不是越多越好。**一个槽位一个坑,资源上限卡死,比无限制开窗口要稳定十倍。 银行排队模型,是店群自动化最好的并发范式。**第二,进程回收必须做绝。**不要相信任何“自动退出”,要有自己的看门狗。 任务完成 ≠ 进程退出,这是血的教训。**第三,调度和隔离是绑在一起的。**没有隔离的并发,跑得越快,封得越快。 一定要让每个任务带着自己独立的浏览器环境去执行。## 八、结语Alien这套系统,从环境隔离到并发调度,再到打包交付, 每个模块都是我林焱RPA在店群自动化的泥潭里摸爬滚打, 用最朴素的工程方法,一行一行代码抠出来的。 它没有什么花哨的AI,也没有什么融资加持, 它就是一款实打实能帮店群老板解决并发卡死、环境串号、人力黑洞的生产力工具。 如果你也在被几百个店铺的批量执行折磨, 电脑一开脚本就蓝屏, 欢迎来找我聊聊。 我是林焱RPA, 一个用调度器和看门狗,硬刚店群并发痛点的独立开发者。 (全文完)