AI News HubLIVE
站内改写4 分钟阅读

同时运行1500个AI智能体得到的六个数字

本文介绍了在单个AWS c6i.metal实例上同时运行1500个完全KVM隔离的虚拟机进行AI任务时,测量到的关键性能指标,包括启动时间、内存密度、DNS缓存、网络延迟、TLS会话复用和吞吐量,展示了轻量级隔离架构的实际成本与收益。

来源Hacker News AI作者: amitlimaye

本文是系列文章的第四篇。前三篇奠定基础:第一篇展示了如何在加载时重写二进制文件的每个系统调用,使客户程序无法绕过运行时;第二篇解释了为何不运行客户内核,仅用一个36KB的垫片处理智能体实际需要的约30个系统调用;第三篇介绍了池守护进程:虚拟机如何预热、连接如何预先建立、运行时如何位于每个智能体的路径上。

第四篇来得比预期晚。不是写作障碍,而是工作本身——让1500个虚拟机真正稳定运行,让池守护进程在真实负载下保持TLS会话,追踪那些直到从开发机迁移到AWS不同CPU系列才出现的快照可移植性缺陷。这篇博客的存在是因为系统现在足够稳定,可以可靠地测量。

本文介绍的是利用所有这些技术能实现什么——大规模运行的实际面貌。

每个数字均来自在单个AWS c6i.metal实例上同时运行1500个完全KVM隔离的虚拟机。不是容器,不是共享内核的进程。每个智能体拥有自己的虚拟机,自己的硬件隔离边界。

我试图回答的问题是:这实际上要付出什么代价?内存、延迟、吞吐量——隔离模型是否让其中一些变得不可测量,还是你处处都要为此付出代价?

以下是运营仪表板显示的数据。

  1. 暖启动虚拟机时间——0.42秒

在任何事情之前,池必须就绪。

以朴素方式预热1500个KVM虚拟机——fork、exec、boot、import——每个智能体运行依次耗时约200毫秒。第一个作业运行前就要五分钟。

我们的做法是:将Python通过完整导入序列运行一次,在那一刻冻结虚拟机,并将结果保存为快照。99MB的非零页面——解释器状态、加载的模块、预解析的导入。在池启动时,所有1500个虚拟机并行从该快照恢复。物理页面在虚拟机之间共享,直到某个智能体写入。每个智能体无需支付导入成本。

需要澄清一点:该快照仅包含Python标准库。用户级导入——anthropic、openai、requests,无论智能体使用什么——仍在智能体启动时发生。我们可以在启动序列后期(这些导入之后)拍摄快照,进一步缩短调度时间。但代价是,你会得到按智能体类型不同的快照,而不是整个集群共享的通用Python镜像。我们选择了通用镜像——0.42秒已经够快,而且一个镜像操作更简单。

条形图显示了1500个虚拟机在100毫秒时间桶中的分布。大多数落在前两个桶中。总墙钟时间:0.42秒。

我们没有客户内核。垫片只有约36KB。没有其他东西。

  1. 运行密度——10.8个智能体/GB

这是我最常被问到的数字。

1500个KVM隔离的虚拟机——每个都在向LLM API发起活跃TLS调用——适配在139GB物理内存中。即每GB 10.8个智能体,不是空闲,不是静态,而是在真实负载下。该数字包括智能体运行时累积的一切:Python堆、打开的TLS会话、传输中的请求缓冲区、栈帧、系统调用状态。

ps RSS显示更高——所有VMM进程总和约290GB。这个数字具有误导性:99MB的Python快照在所有1500个工作者之间共享,RSS会计将其计入每个进程一次,而非每个物理页面一次。仪表板上的139GB是物理内存,直接从宿主机测量。

10.8个智能体/GB是在真实负载下测量的。一个空闲虚拟机成本为3MB(上文)。你的数字将介于两者之间,取决于你的智能体做什么以及运行时累积多少堆。

  1. DNS缓存——100%命中率,260,700次命中

原生Linux进程获得操作系统级DNS缓存。将该进程移入拥有自己内核的虚拟机,你通常会失去它——客户机运行自己的解析器,发出自己的上游查询,支付自己的延迟。

我们的客户机没有内核。DNS查询通过池守护进程退出,它位于UDP数据包离开宿主机之前的路径上。池在所有1500个智能体之间维护一个共享缓存——因此每个客户机获得与原生进程完全相同的效果,甚至更强:一次上游查询服务整个集群。

如果50个智能体同时冷缺失同一个名称,只发出一个查询,所有50个都得到答案。上游解析器在TTL窗口内每个名称每窗口只看到一个查询,无论集群大小。

如果你一直关注本系列,这听起来会熟悉:对于池无法解析或处理的任何内容——奇异记录类型、DNSSEC、任何非标准的东西——查询会降级到原生Linux栈。与系统调用设计相同的原则。常见情况走快速路径,真正的东西作为后备。

100%命中率,260,700次缓存命中。在这次运行中,所有1500个智能体都命中相同的两个端点——api.anthropic.com和本地Postman mock——因此缓存迅速饱和。在更多样化的集群中,命中率会降低,但合并效益无论如何随智能体数量扩展。隔离没有让智能体失去DNS缓存——他们得到了更好的。

  1. 首次网络调用时间——p50 44ms,p99 105ms

智能体代码是确定性的。同一任务每次都在相同点触及网络。因此从调度到首次网络调用的时间几乎完全是基础设施开销——智能体等待就绪的时间,而非工作时间。

调度到首次系统调用: p50: 44ms p95: 86ms p99: 105ms n: 1500

连接到首次发送(预建立TLS): p50: 70ms p99: 1.6s n: 1500

调度数字是纯基础设施开销——虚拟机恢复到首次系统调用。连接数字是直到第一个字节通过预建立TLS会话到达线路的时间。连接上的p99尾延迟反映了在首次发送前遭遇Anthropic速率限制的智能体。

对于一项工作而言,44ms微不足道。但对于连续运行的1500个智能体,这决定了基础设施是否可测量。

  1. TLS缓存——持有338个会话

每次HTTPS调用通常以TCP握手(10-50ms)和TLS握手(50-150ms)开始。在1500个智能体都访问同一端点的情况下,每次冷连接都会支付大量延迟。

池守护进程位于每个智能体与每个上游目的地之间的网络路径中——这意味着它也可以拥有TLS层。

在池启动时,守护进程建立到配置的上游端点的持久TLS会话。当智能体发起HTTPS请求时,它向环形缓冲区写入明文。守护进程代表它处理TLS,进入已建立的会话。无需握手,无需往返。

整个集群持有338个会话。1500个智能体共享338个上游连接。API看到338个连接。智能体看到零握手延迟。

需要直说一点:池守护进程读取每个智能体请求的明文。这是有意的——同一接缝使得策略执行、凭证注入和响应检查成为可能。这是否是你想要的取决于你的威胁模型。这是一个设计选择,而非副作用。

  1. 网络吞吐量——入站33.2 MB/s,出站37.0 MB/s

截至此快照时刻,已完成138,972次LLM调用——自池启动以来累积,1500个智能体每个大约每秒发起一次调用。

入站33.2 MB/s,出站37.0 MB/s。这些数字随集群动态变化——这是实时运行的快照,不是上限。在1500个智能体时,运行时远未达到c6i.metal的网络限制。此处约束是LLM API——在我们的案例中是Anthropic速率限制。智能体大部分时间在等待,而非移动字节。

这些数字加起来意味着什么

将它们放在一起,你得到在运行中的KVM集群上一个作业的生命周期:

池预热:1500个虚拟机在0.42秒内完成,密度每GB 10.8个智能体

作业到达:首次网络调用44ms

智能体解析端点:<1µs DNS缓存命中,0ms TCP(预建立)

智能体发起HTTPS调用:0ms TLS——持有338个会话,智能体写入明文

响应流回:集群持续吞吐量33.2 MB/s

每一层的工作原理相同:运行时已经位于路径中,因此它缓存DNS响应、保持TLS会话、共享快照页面。无需单独系统。实施隔离的同一机制也在进行优化。

KVM隔离不一定意味着沉重。这些数字是证据。

在1500个智能体时,节省是可测量的。在10000个时,它们变得结构性——区别在于是否需要更多机器。

下一篇内容将探讨,当运行时同时看到主机上每个智能体的每个系统调用、每个DNS查询、每个TLS会话、每个模型调用时,什么变得可能。

如果你在生产中运行智能体,且其中任何一点是实际问题——请在LinkedIn上联系我。