Rust in Everything
基于 pingora 0.9.0

设计取舍

前八部分按代码讲机制,每一章都顺带碰到一些「这样做换来了什么、付出了什么」。这一部分只有一页,把它们收到一起:每一条先说 pingora 选了什么,再说收益和代价,数字取自本卷某一页的实验,链接指向那一页,这里不重讲机制。对照的对象是 hyper 卷(同样在 tokio 上的 HTTP 实现)、tower 卷(Service 套 Service 的中间件)和 tokio 卷(运行时);nginx 只写 pingora 自己的文档和源码里说了什么。这一页另外补了两组数:同一台机器上 pingora 和用 hyper 搭的代理转发同一组请求,以及从 git 历史里数出的 ProxyHttp 演变和各 crate 的版本变动。

  1. 设计取舍:十条取舍、一份上游问题记录、一张文档与代码不符的表和一节同机实测。自己写 HTTP/1 换来头名大小写原样和框架掌握的复用判断,代价是第一个请求之后不再空闲超时,同机实测每请求比 hyper 搭的代理慢约 3 µs;固定阶段的钩子让一个 GET 调 18 个方法、转发和重试都不用自己写,但不能包住一段;ProxyHttp 从 0.1.0 的 25 个方法长到 42 个,只加不删;默认的工作窃取运行时守得住重请求,NoSteal 下下游 socket 共用 accept 线程的反应器;服务级连接池跨下游连接复用,reuse_hash 漏了 ca;TLS 后端用 cfg 四选一,零分发,开两个就是 E0252;传 fd 的平滑升级只在 Linux 上实现;一组资源默认值不设上限,源码明说「Unlike nginx」;22 个 crate 同一个版本号,6 个 crate 没变也升号,0.8.1 是一条不在 main 历史里的岔路;本卷核对出 28 处文档与代码不符。
flowchart TB
  req["请求主线"] --> h1["自己的 HTTP/1"]
  req --> hook["固定阶段钩子"]
  req --> pool["服务级连接池"]
  req --> tls["cfg 四选一 TLS"]
  srv["服务主线"] --> rt["每服务运行时"]
  srv --> fd["传 fd 升级"]
  cache["缓存主线"] --> dflt["默认不设上限"]
  h1 --> hy["对照 hyper"]
  hook --> tw["对照 tower"]
  rt --> tk["对照 tokio"]

💬 关联讨论

发起讨论
加载中...