六个Actor部署下去,只有两个Worker在跑。第三个请求发出去,等来的不是响应,是一个504超时。

这不是配置写错了,也不是网络出了问题。是内存不够——每个Worker只有1Gi的额度,每个Actor要吃掉768Mi,第二个Actor想挤进去需要1536Mi,放不下。

打开网易新闻 查看精彩图片

Agent Substrate这套调度逻辑里,放不下的Actor不会报错退出,而是进入一种"停靠"状态,等有Worker腾出空间再自动接上。

停靠不是关机,是待命

所有Actor部署之后,默认就是挂起状态。挂起意味着它们没有真正在跑,不占CPU也不占内存。只有当你建立一个会话指向某个Actor时,它才会被唤醒。

这种设计解决的是一个很实际的问题:Actor不是每时每刻都需要算力。没有会话的时候让它跑着,纯粹是浪费。

但挂起不等于冷启动。Actor处于一种"温热"状态,恢复不需要等好几秒。你发请求过去,不会感觉它像刚从冰柜里拿出来一样迟钝。

在这个实验环境里,六个Actor被创建出来,全部处于挂起状态。它们此刻只是记录,加上GCS里的一份快照。

两个Worker,六个Actor,3:1的账

WorkerPool的配置把每个Worker的内存上限卡在1Gi,Actor模板则要求每个Actor占768Mi。调度器只会把Actor放到内存还装得下的Worker上,所以第二个Actor永远挤不进同一个Worker。

六个Actor、两个Worker,比例是3:1。这意味着两个Actor能被调度,剩下四个只能停靠,等Worker空出来。

验证的方式很直接:先把路由端口转发出来,然后用curl依次唤醒前两个Actor。两个Worker各接一个,状态变成活跃,内存占用显示768Mi/1Gi。

接着试第三个。请求发出去,返回504,超时。原因不复杂——两个Worker都没有足够内存再塞下一个Actor。

这时候把第一个Actor挂起,再发一次同样的请求。第三个Actor立刻被调度上去。

整个过程中,Actor没有重启,Worker没有重建,只是内存账本上腾出了一格。

HPA要解决的是Worker不够,不是Actor太多

前面这个场景暴露的瓶颈在Worker侧。两个Worker的池子,撑不住三个同时活跃的Actor。

但要注意,多个Actor是可以共享一个Worker的,前提是内存够。真正需要HPA介入的时刻,是Worker内存耗尽、必须新建一个Worker(也就是Pod副本)的时候。

换句话说,HPA在这里扩的不是Actor,是Worker。当WorkerPool里的Worker因为内存压力扛不住时,HPA负责把Worker的数量撑开,让停靠的Actor有地方落。

这套机制的完整链路是:Actor先停靠,Worker腾出内存或新建Worker,Actor自动调度上去,Actor开始运行。

想让Actor共享Worker也有办法——把WorkerPool的内存上限调高,或者把Actor模板的内存需求调低。两个方向动一个,原本挤不进去的Actor就能共用一个Worker了。

回到开头那个504。它不是故障,是这套调度系统在说:资源不够了,先排队。