今天偶尔刷到Http Arena 的排行榜, https://www.http-arena.com/,这个是TechEmpower 榜单不再更新后,一个相对全的性能测评榜单。
所以看见C# 的GenHTTP登顶了多个榜单很是震惊,不是单项强,是综合都很强。
很多细分榜单第一,大多不是第一的也排名靠前或者和第一差距很小的情形。 大家可以自行判断下。
这个是介绍:
GenHTTP 11 on .NET 11 on a custom io_uring server engine (the ioxide runtime) instead of the default socket engine. Built from the GenHTTP 11 preview 24 packages, which carry the merged ioxide engine branch (PR #887): TLS is terminated in the engine itself, with HTTP/2 and HTTP/3: :8080 is HTTP/1.1, :8082 h2c, :8081 HTTP/1.1 over TLS, and :8443 serves HTTP/1.1 and HTTP/2 over TCP plus HTTP/3 over QUIC on the same port. Static is served by IoxideFiles, which reads bodies positionally off the io_uring ring through a per-reactor descriptor snapshot; responses go through GenHTTP's own routing + serialization; Postgres rides ioxide.pg (per-reactor ring-native pool).
https://github.com/Kaliumhexacyanoferrat/GenHTTP
稍微研究了一下发现几个事实:
-
达到这个成绩基于.net的io_turing引擎, i
oxide是一个专门为 .NET 做的高性能 Linux I/O Runtime 。它不是普通的 HTTP Server,也不是io_uring本身;更准确地说,它是在 .NET 上重新实现了一套基于 Linuxio_uring的 shared-nothing reactor 网络执行模型。 -
HttpArena 对这个版本的描述非常明确:
GenHTTP 11 + .NET 11 + custom io_uring server engine(ioxide),而不是默认 socket engine。
而且 HTTP/2、HTTP/3、TLS 都是在这个 engine 上跑的。
所以实际上可以把架构理解成:
┌──────────────────────┐
│ GenHTTP │
│ │
│ Router │
│ Handler │
│ Serialization │
│ Middleware │
└──────────┬───────────┘
│
HTTP abstraction
│
┌──────────▼───────────┐
│ ioxide │
│ │
│ HTTP/1.1 │
│ HTTP/2 │
│ HTTP/3 │
│ TLS │
└──────────┬───────────┘
│
io_uring
│
┌──────────▼───────────┐
│ Linux │
│ Kernel │
└──────────────────────┘
而传统 ASP.NET Core/Kestrel 更接近:
Application
│
ASP.NET Core
│
Kestrel
│
Socket APIs
│
.NET ThreadPool / async infrastructure
│
Linux
3. 最大的杀手锏:Shared-Nothing
这是我认为整个项目最值得研究的地方。
ioxide 的设计原则非常激进:
one reactor per core
每一个 CPU core 有自己的 reactor:
CPU Core 0
└── Reactor 0
├── io_uring ring
├── connections
├── clients
├── connection state
└── handlers
CPU Core 1
└── Reactor 1
├── io_uring ring
├── connections
├── clients
└── handlers
CPU Core 2
└── Reactor 2
...
关键是:
一个 request 尽可能始终留在它进入的 CPU core 上。
ioxide 官方描述的设计就是:
- 每个 reactor 一个 io_uring ring
- 每个 reactor 一个 core
- 每个 reactor 自己拥有 connections
- 每个 reactor 自己拥有 clients
- 请求不会跨 core
- 尽量不需要 lock
成绩相关截图:
HTTP 1.1 相关:
HTTP/2:
H3:
WebSocket: