HiHuo
首页
博客
手册
工具
关于
首页
博客
手册
工具
关于
  • 代理技术全栈手册

    • 代理技术全栈手册 - HiHuo
    • 原理篇

      • 第01章 代理是什么:正向 / 反向 / 透明 / 隧道的统一模型
      • 第02章 代理与网络层级:L3 / L4 / L5 / L7 在哪里截断流量
      • 第03章 一个请求穿过代理的一生:连接生命周期全景
    • 协议篇

      • 第04章 HTTP 代理协议:绝对 URI、CONNECT 隧道、转发头与连接池
      • 第05章 HTTPS 与 TLS 代理:终止 / 透传 / MITM / SNI / mTLS
      • 第06章 SOCKS 协议:SOCKS4/4a/5 与 UDP ASSOCIATE 报文级解析
      • 第07章 HTTP/2、gRPC 与 HTTP/3(QUIC) 代理的挑战
      • 第08章 代理自动配置:PAC / WPAD / 系统代理 / NO_PROXY
    • 层级与转发篇

      • 第09章 L4 代理:TCP/UDP 转发与连接级负载均衡
      • 第10章 L7 代理:协议感知与基于内容的路由
      • 第11章 透明代理:iptables REDIRECT/DNAT、TPROXY 与 eBPF 劫持
      • 第12章 数据搬运的艺术:splice / sendfile / 零拷贝 / io_uring
    • 组件横评篇

      • 第13章 Nginx / OpenResty:反向代理、upstream 与 Lua 可编程
      • 第14章 HAProxy:L4/L7、ACL、健康检查与 stick table
      • 第15章 Envoy:xDS 动态配置与 filter chain,为何是云原生数据面
      • 第16章 Traefik / Caddy:自动服务发现与自动 HTTPS
      • 第17章 Squid 与正向/缓存代理:企业出网、缓存与审计
      • 第18章 mitmproxy:抓包、改包、脚本化调试
      • 第19章 内网穿透与隧道:frp / gost / SSH 隧道 / ngrok
      • 第20章 科学上网生态的技术原理(技术中立)
    • 多语言手写篇

      • 第21章 Go:100 行手写 HTTP/CONNECT + SOCKS5 代理
      • 第22章 Rust:基于 tokio 的高性能 TCP 代理
      • 第23章 Python:asyncio 实现,适合调试与脚本
      • 第24章 C:epoll 裸写与零拷贝,及语言选型对比
    • 容器与K8s篇

      • 第25章 Docker 里的代理:HTTP_PROXY、build/pull 与 daemon 配置
      • 第26章 Sidecar 与流量劫持:Istio init-container 的 iptables 原理
      • 第27章 Ingress 与南北流量:Ingress-nginx 与 Gateway API
      • 第28章 Egress 与出网治理:出口网关、registry mirror、审计
      • 第29章 Service Mesh 数据面:Envoy Sidecar 全链路
    • 进阶篇

      • 第30章 可编程代理:Lua / Wasm / eBPF / xDS,代理的"软件定义"
      • 第31章 性能调优:并发模型、连接池、超时与重试、压测
      • 第32章 排错决策树:502 / 504 / 握手失败 / 环路 / 泄漏
      • 第33章 代理安全:开放代理、SSRF、凭证泄漏与攻击面
    • 底层机制篇

      • 第34章 代理的背压与流控:一个代理最难的部分
      • 第35章 socket 与 TCP 状态机:半关闭、超时、连接生命周期
      • 第36章 HTTP/2 帧、流控与 HPACK:h2 代理的内部机制
      • 第37章 负载均衡算法推导与韧性状态机
      • 第38章 Capstone:把玩具代理改造成生产级骨架
    • 综合实战篇

      • 第39章 企业多跳转发链:拓扑、协议矩阵与贯穿性难题
      • 第40章 端到端实战:把 6 类流量全代理通
      • 第41章 更刁钻的流量:gRPC、长轮询、WebRTC、大文件、双向流
      • 第42章 可落地完整参考实现:一套能跑的多协议转发栈
    • 附录

      • 附录 A:代理协议报文速查(HTTP / SOCKS / PAC / PROXY protocol)
      • 附录 B:组件选型决策树
      • 附录 C:抓包与命令速查

第30章 可编程代理:Lua / Wasm / eBPF / xDS,代理的"软件定义"

学习目标

  • 理解代理从"静态配置"到"可编程逻辑"的演进,及四个可编程层次
  • 分清 Lua / Wasm / eBPF / xDS 各自在哪运行、用什么语言、什么场景
  • 理解 Proxy-Wasm 如何让你用任意语言写跨代理的插件
  • 知道何时选 Lua、何时选 Wasm、何时下沉到 eBPF

前置知识

  • 第13章 OpenResty/Lua、第15章 Envoy filter/xDS、第11章/第12章 eBPF

原理

为什么代理要"可编程"

声明式配置(proxy_pass、ACL、路由规则)能覆盖通用需求,但业务的定制逻辑——按某个自定义 Header 鉴权、调用外部服务决定路由、改写特定字段、埋自定义指标——是无法穷举的。于是代理提供扩展点,让你注入代码。这就是"软件定义代理":数据面行为由可热更新的程序决定,而非写死的配置。

四个可编程层次

  抽象高 ┌─────────────────────────────────────────────┐ 灵活/重
        │ ① 声明式 DSL    ACL / 路由规则 / RBAC          │ 配置即代码
        │ ② 嵌入脚本 Lua  OpenResty / HAProxy / Kong      │ 运行时逻辑
        │ ③ Wasm 插件     Proxy-Wasm(多语言、沙箱)       │ 安全可扩展
        │ ④ eBPF          内核层(Cilium,数据路径/L4)     │ 极致性能
  抽象低 └─────────────────────────────────────────────┘ 性能/底层

② Lua:嵌入式脚本(最成熟)

在代理进程内嵌一个 Lua 解释器,在请求处理各阶段跑你的脚本:

  • OpenResty(第13章):access_by_lua/content_by_lua/balancer_by_lua,Kong、APISIX 的插件机制之基
  • Envoy Lua filter、HAProxy Lua

优点:成熟、热更新、生态广;缺点:单一语言(Lua)、需小心别写阻塞调用堵事件循环。

③ Wasm:多语言、沙箱化的插件

Proxy-Wasm 是新一代扩展标准:你用 Rust/Go/C++/AssemblyScript 写 filter,编译成 WebAssembly,由代理在沙箱里加载执行:

  你的逻辑(Rust/Go/...)──编译──▶ filter.wasm ──加载──▶ Envoy/APISIX 沙箱执行

相比 Lua 的优势:

  • 多语言:用你擅长的语言写,不限于 Lua
  • 安全隔离:Wasm 沙箱,插件崩溃/越界不影响代理本体
  • 可移植:Proxy-Wasm ABI 是标准,同一个 wasm 能跑在 Envoy、APISIX 等多种代理上
  • 动态加载:不重启换插件

Istio 用 WasmPlugin CRD 给 mesh 数据面动态下发 wasm 扩展(第29章)。代价:比原生稍慢、ABI 仍在演进。

④ eBPF:内核层可编程(极致性能)

Lua/Wasm 在用户态代理进程里跑;eBPF 把可编程能力下沉到内核(第11章、第12章)。Cilium 用它做 L3/L4 策略、负载均衡、可观测、sockmap 加速——数据不进用户态,性能最高,但只适合 L4 级逻辑(看不懂 L7 应用语义那么细)。

① xDS:配置层面的"可编程"

第15章 的 xDS 也是一种"可编程"——控制面用代码动态生成配置、热推数据面。它不改"每个请求怎么处理"的逻辑,但能动态改"路由/集群/证书",是声明式的动态化。

四层对比:选哪个

层运行在语言性能安全隔离热更新适合
DSL/xDS配置层YAML/规则——✅通用路由/策略
Lua用户态代理内Lua中高弱✅鉴权/改写/限流(成熟)
Wasm用户态沙箱Rust/Go/C++中高强✅复杂/多语言/安全扩展
eBPF内核C/eBPF最高内核校验✅L4 策略/加速/可观测

选择心法:简单逻辑用 Lua;复杂/多语言/要隔离用 Wasm;L4 级、要极致性能用 eBPF;只是动态改配置用 xDS。


️ 实现 / 命令

实验一:Envoy Lua filter 改写头

http_filters:
- name: envoy.filters.http.lua
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
    inline_code: |
      function envoy_on_request(handle)
        handle:headers():add("x-via-lua", "1")          -- 注入请求头
      end
      function envoy_on_response(handle)
        handle:headers():replace("server", "redacted")   -- 抹掉响应的 server 头
      end
- name: envoy.filters.http.router
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

实验二:OpenResty Lua 动态限流(呼应第13章)

location /api/ {
    access_by_lua_block {
        local limit = require "resty.limit.req"
        local lim = limit.new("my_limit_store", 100, 50)   -- 100r/s,突发50
        local delay, err = lim:incoming(ngx.var.binary_remote_addr, true)
        if not delay then
            if err == "rejected" then return ngx.exit(429) end  -- 限流返回 429
        end
    }
    proxy_pass http://backend;
}

实验三:Istio WasmPlugin(多语言扩展)

# 给 mesh 数据面动态加载一个 wasm 扩展(用 Rust/Go 写并编译)
apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata: { name: my-auth }
spec:
  selector: { matchLabels: { app: myapp } }
  url: oci://registry.example.com/my-auth-wasm:1.0    # wasm 镜像
  phase: AUTHN

实验四:对比三层"加一个头"的代价

Lua  :进程内解释执行,几微秒级,热更新
Wasm :沙箱执行,略高于 Lua,但安全隔离 + 多语言
eBPF :内核执行,最快,但只能做 L4 级(加不了 L7 业务头)

排错

现象根因解决
Lua 拖慢整个代理脚本里有阻塞调用用非阻塞 API(resty.*),别在热路径做重活
Wasm 插件不生效ABI 版本/编译目标不符对齐 Proxy-Wasm SDK 与代理版本
Wasm 加载失败镜像拉取/签名检查 OCI 仓库可达、imagePullPolicy
eBPF 程序加载失败内核版本太老升级内核(Cilium 有最低版本要求)
扩展崩溃影响代理用了无隔离的扩展优先 Wasm 沙箱,而非裸 C 模块

本章小结

  • "软件定义代理"四层:DSL/xDS(配置)→ Lua(脚本)→ Wasm(沙箱多语言)→ eBPF(内核)。
  • Lua 成熟(OpenResty/Kong/APISIX);Wasm(Proxy-Wasm)多语言+沙箱+可移植,Istio 用 WasmPlugin 下发。
  • eBPF 下沉内核,性能最高但限 L4;xDS 是配置层的动态化。
  • 选型:简单 Lua、复杂/隔离 Wasm、L4 极致 eBPF、动态配置 xDS。

下一章 第31章 性能调优,从可编程回到"快"——并发模型、连接池、超时重试、内核参数与正确的压测方法。

Next
第31章 性能调优:并发模型、连接池、超时与重试、压测