Wabrix实现无需丢包的热重载有状态WebAssembly,单核达10 Mpps
来源标题:Hot-Reloading Stateful WebAssembly at 10 Mpps Without Dropping Packets
Wabrix展示了在不丢包的情况下热重载有状态WebAssembly网络代码,单核性能可达10 Mpps。其做法是将WASM实例的持久状态放在宿主机共享内存中,替换实例直接挂载同一内存页,并在完成数据包批次边界切换实例,从而省去编译、实例构建、状态快照和运行时拆卸。
以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。
在网络中使用 WebAssembly 的一个优势在于,它显著简化了有状态网络代码热升级这一古老而复杂的问题。本文介绍我们如何在 Wabrix 中实现这一点。同时,我们也想测试这种方法的性能极限:这种方法能否在单核上维持 10 Mpps?网络策略更新有两个连续性要求:数据包必须持续流动,新代码必须接管旧代码留下的状态。丢失一个序列计数器就足以破坏丢包测量。丢失连接表可能导致数千个已建立的会话中断,即使数据包队列完好无损。在重载期间,我们准备一个 WebAssembly(WASM)组件的新的替换实例,同时保持 worker 及其流水线节点(包括旧 WASM 实例、AF_XDP socket 和数据包内存)继续运行。WASM 实例的持久状态存放在宿主机拥有的共享内存中。替换的 WASM 实例挂载到相同的共享内存页上,worker 在已完成的数据包批次之间的边界处切换实例。这种设计将编译、实例构建、状态快照和运行时拆除从切换过程本身移除。这就是我们能够在负载下实现无损更新的方式。维持线速仍然需要足够的处理和队列余量来应对短暂的切换。
在 Wabrix 中,宿主机提供 AF_XDP 数据包 I/O、共享数据包内存、流水线执行和运行时生命周期管理。组件定义处理行为,以及在需要连续性时的持久状态布局。组件制品是部署单元:新版本可以在宿主机的 worker、socket 和帧所有权保持服务的情况下安装。
实测吞吐量:10 Mpps 已生成数据包:30 亿 丢失数据包:0 运行时切换:1.851 µs (在单独运行中测量) 持久状态:约 1 KB 在一次持续 10 Mpps 的数据包处理运行中替换了一个 WASM 组件。一个生成器 worker 和一个检查器 worker 各运行在一个 3.4 GHz 核心上。Turbo 模式已禁用。核心与操作系统任务隔离。Intel Core™ i7-14700K,无超线程,Intel 2x25G E830 网卡,Linux 内核 7.0
小停顿变成大数据包积压 在每秒 1000 万个数据包的速率下,两毫秒的中断对应 20,000 个到达的数据包。在数据包 worker 上重建运行时、等待编译器,或销毁旧的 Wasmtime 实例,都可能将一次普通更新变成队列溢出的突发。复制状态还有第二个问题。在旧组件实例继续处理时拍摄的快照会立即过时。暂停旧实例以序列化其全部状态会引入一个持续时间随状态大小增长的停顿。我们的重载路径将昂贵的准备工作保持在后台,并让持久字节留在原地。重载替换流水线节点持有的组件实例(其 Wasmtime store 和组件绑定)。周围的数据包处理机制保持服务:
在一次迭代中已处理的数据包由活动组件实例完成。激活后的工作使用替换实例。无需关闭 socket、重新注册 UMEM,或将排队的数据包移动到另一个 worker。此热重载在现有图中替换组件实例。需要不同 worker 布局、UMEM 配置或重建流水线图的更改仍然需要完全重启。
我们在数据包 worker 进入处理循环之前启动一个共享的暂存线程和一个运行时回收器。因此,发送重载请求不会从固定核心的 worker 创建新线程。
时间 ---> 控制平面 UpdateConfiguration(wasm_file_path) | 暂存线程 [加载 / 编译 / 实例化 / 初始化]----候选就绪 | 数据包 worker [旧实例:处理批次和定时器......| 下一次定时器轮询 | poll_ready | 检查候选 | 安装候选 [新实例...] 运行时回收器 [销毁旧实例...]
控制平面比较当前配置和目标配置。wasm_file_path 发生变化会变成一个 UpdateConfiguration 事件,发送到承载 WASM 实例的现有 WasmEngine 节点。其 worker 将暂存任务排队,并继续使用活动组件实例处理。
暂存器读取并编译或加载组件制品,创建一个新的组件实例,映射其数据包和状态区域,并调用 init-data 来初始化 WASM 实例。编译、实例化和初始化必须成功,该候选才能被激活。组件缓存使用制品路径和 SHA-256 内容哈希。
后台线程使用控制器允许的 CPU 亲和性——排除 worker 核心——和正常的 SCHED_OTHER 调度。它们不继承数据包 worker 受限的单核掩码或实时策略。
每个 WasmEngine 节点有一个单任务暂存邮箱。较新的排队请求会替换其过时的前驱,代数计数器防止被取代的结果被激活。已在运行的构建可能完成,但其过时的候选会在数据包处理线程之外被丢弃。
UpdateConfiguration 中 wasm_file_path 发生变化会启动异步暂存;接收该事件本身不会切换组件。暂存后台运行时,worker 继续使用活动实例。
在 worker 完成一次迭代的入口批次后,它检查配置的定时器轮询间隔是否已过。在该定时器 tick 上,运行器轮询重载控制器以查看是否有潜在的切换。如果暂存尚未完成,活动实例保持使用,下一次定时器轮询 tick 再次检查。候选就绪不会中断数据包处理或唤醒 worker;激活等待此轮询点。
每个运行有状态组件的 worker 本地流水线节点拥有一个专用的
(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。