跳转到主要内容

按核线程模型

每个 worker 线程绑定一个 CPU 核,并各自打开 SO_REUSEPORT 监听 socket。内核会把新连接自动分发到各个 worker。在请求处理过程中,worker 之间不会共享可变状态。 每个 worker 独占的资源:
资源类型
io_uring ringUring 结构(arc-net)
固定缓冲池FixedBuffers(arc-net)
连接槽位表ConnId 索引(arc-gateway)
上游连接池UpstreamPool(arc-gateway)
插件实例池每池 PluginCatalog(arc-plugins)
一级限流缓存WorkerLimiter(arc-global-rate-limit)
指标计数器WorkerMetrics(arc-observability)
日志 ring bufferSPSC ring(arc-logging)
worker 之间共享(只读或原子)的资源:
资源机制
路由、上游、插件、限流器ArcSwap<Arc<SharedConfig>>,请求周期内通过 acquire load 获取
指标数组AtomicU64 计数;管理线程用 relaxed ordering 读取
全局限流后端GlobalRateLimiter + L2 Redis;worker 异步请求补令牌
XDP BPF map由内核管理;用户态 XdpManager 通过 libbpf 写入

io_uring 数据平面

Arc 直接使用 Linux io_uring,而不是 epoll 或 Tokio 一类 async runtime。这样可以减少每次 I/O 操作的 syscall 开销。Arc 重点使用的 io_uring 特性包括:
  • SQPOLL:内核轮询线程直接消费提交队列,用户态无需为提交再发 syscall
  • Fixed buffers:预注册缓冲池;读写时使用缓冲区索引而非指针
  • Fixed files:预注册 fd 集合,减少 fd 表查找开销
  • Multishot accept:单个 accept SQE 在每次接入后自动重臂,不必反复提交
  • Multishot timeout:单个 timeout SQE 覆盖连接槽定时轮

共享配置与热更新

所有 worker 共享一个 ArcSwap<Arc<SharedConfig>>SharedConfig 内含已编译路由、已编译上游、插件目录、按路由限流器和 TLS 状态。构建完成后即不可变。 热更新流程如下:
Config file
    │ mtime change

Background watcher thread
    │ compile_config() → SharedConfig

ArcSwap::store() (release-store)

    ├── Worker 0: ArcSwap::load() (acquire)
    ├── Worker 1: ArcSwap::load() (acquire)
    └── Worker N: ArcSwap::load() (acquire)
监听地址、worker 数、io_uring ring 尺寸、control plane 绑定地址等字段会被 restart_required_changes() 判定为“需重启字段”。只要这些字段有变化,热更新会被拒绝。 Arc 内部会把 TOML/YAML/JSON 统一标准化为 canonical JSON。具体做法是先解析为 serde_json::Value,再做 key 排序,最终写入 SharedConfigraw_json: Arc<str>。这样可以保证集群节点之间的配置指纹一致且可复现。

请求处理路径

Kernel (io_uring CQE: accept or read)

Worker::run()

    ├── Router::match() — host, method, path, headers
    │       └── MatchResult or 404

    ├── Limiter::try_acquire() — per-route token check

    ├── PluginCatalog::invoke() — on_request() → 0=allow / status=deny

    ├── UpstreamPool — checkout or connect

    ├── io_uring write SQE (fixed buffer → upstream fd)

    ├── io_uring read CQE (upstream response)

    ├── io_uring write SQE (fixed buffer → client fd)

    ├── WorkerMetrics — phase_count.fetch_add

    └── AccessLogContext — emit AccessLogRecord

安全分层

Arc 把安全能力拆为三层,并且互相独立:
Internet traffic


arc-xdp kernel program (XDP hook, pre-TCP-stack)
    │  XDP_PASS or XDP_DROP

L7Protection: SlowlorisGuard, TlsFloodGuard, H2StreamFloodGuard


WorkerLimiter / GlobalRateLimiter (GCRA token bucket)


Upstream proxy / application

安全细节

查看完整安全机制说明。

Crate 依赖图

arc-gateway (binary, state machine)
    ├── arc-net (io_uring, sockets, buffers)
    ├── arc-proto-http1 (HTTP/1.x parsing)
    ├── arc-proto-h2 (HTTP/2 framing)
    ├── arc-router (radix tree matching)
    ├── arc-rate-limit (GCRA token bucket)
    ├── arc-global-rate-limit (Redis two-tier limiter)
    ├── arc-plugins (Wasmtime WASM runtime)
    ├── arc-config (JSON/TOML/YAML, hot reload)
    │       ├── arc-router
    │       ├── arc-rate-limit
    │       └── arc-plugins
    ├── arc-observability (metrics, admin server)
    ├── arc-acme (ACME certificate automation)
    ├── arc-xdp-userspace (XDP/eBPF manager)
    ├── arc-logging (NDJSON logs, ring buffers)
    └── arc-common (error types)

Crate 规模与职责

Crate代码行(约)角色
arc-gateway13,638主代理状态机、连接生命周期、worker 主循环
arc-config3,141配置 schema、编译、ArcSwap 热更新
arc-core2,184共享类型(ArcConfigNodeConfigListenerConfig 等)
arc-net1,642原生 io_uring syscall 封装、缓冲池、socket 操作
arc-router1,089压缩 radix 树、路由编译、O(log n) 匹配
arc-acme1,089ACME challenge 生命周期、TLS-ALPN-01、HTTP-01
arc-global-rate-limit904两级限流、Redis Lua 后端、熔断器
arc-proto-http1591HTTP/1.x 请求/响应解析、chunked 解码
arc-proto-h2542HTTP/2 帧解析、SETTINGS、流控、流状态
arc-logging480NDJSON 编码、SPSC ring、io_uring 批量写、日志轮转
arc-xdp-userspace420XDP/eBPF 用户态管理、BPF map 写入、动态阈值计算
arc-plugins347Wasmtime 集成、实例池、on_request ABI
arc-observability327WorkerMetrics 原子计数、管理服务、/metrics
arc-cli126arc logs tail/query 命令
arc-rate-limit104单层 GCRA 原子限流
arc-common100ArcErrorResult