Skip to content

Commit 3334879

Browse files
committed
docs: add symmetric server architecture pages (pipeline, engines, extending)
1 parent e9518bb commit 3334879

4 files changed

Lines changed: 652 additions & 3 deletions

File tree

docs/.vitepress/config.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,9 @@ export default defineConfig({
9797
{
9898
text: 'Server Architecture',
9999
items: [
100-
{ text: 'Handler Design', link: '/architecture/handlers' },
101-
{ text: 'E2E Scenarios', link: '/architecture/scenarios' },
102-
{ text: 'Hosting & Actor Lifecycle', link: '/server/hosting' },
100+
{ text: 'Request Pipeline', link: '/architecture/server-pipeline' },
101+
{ text: 'Protocol Engines', link: '/architecture/server-engines' },
102+
{ text: 'Extending the Pipeline', link: '/architecture/server-extending' },
103103
],
104104
},
105105
],
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
# Server Protocol Engines
2+
3+
Each server engine is responsible for decoding incoming request bytes and encoding response bytes for a specific HTTP version. The `ProtocolRouter` selects the appropriate engine based on ALPN negotiation (TLS) or auto-detection (plaintext).
4+
5+
---
6+
7+
## Protocol Router
8+
9+
When a connection arrives, `ProtocolRouter` inspects the initial bytes to select the correct engine:
10+
11+
| Protocol | Detection Method | Server Engine |
12+
| -------- | --------------------------------------------------------- | ---------------------------- |
13+
| HTTP/1.0 | First line is `METHOD /path HTTP/1.0` (ASCII) | `Http10ServerEngine` |
14+
| HTTP/1.1 | First line is `METHOD /path HTTP/1.1` (ASCII) | `Http11ServerEngine` |
15+
| HTTP/2 | First bytes are `PRI * HTTP/2.0` preface or `SETTINGS` | `Http20ServerEngine` |
16+
| HTTP/3 | Connection over QUIC (UDP); ALPN or auto-detect | `Http30ServerEngine` |
17+
18+
With TLS, ALPN negotiation happens during the TLS handshake. The client sends advertised protocols (`h2`, `h3`, `http/1.1`, `http/1.0`), and the server selects one. Without TLS, the router auto-detects from the first bytes received.
19+
20+
---
21+
22+
## HTTP/1.0 Server Engine
23+
24+
<ClientOnly>
25+
<LikeC4Diagram viewId="serverHttp10Engine" :height="300" />
26+
</ClientOnly>
27+
28+
`Http10ServerEngine` handles the simplest protocol: one request per connection, then close.
29+
30+
**Characteristics:**
31+
- Each connection handles exactly one request
32+
- After sending the response, the connection closes
33+
- No keep-alive, no pipelining
34+
- Response body length determined by `Content-Length` header
35+
36+
**Transport:**
37+
- `TcpListenerFactory` — TCP listener binds to configured port
38+
- `TcpConnectionStage` — transport reads/writes bytes
39+
40+
---
41+
42+
## HTTP/1.1 Server Engine
43+
44+
<ClientOnly>
45+
<LikeC4Diagram viewId="serverHttp11Engine" :height="340" />
46+
</ClientOnly>
47+
48+
`Http11ServerEngine` adds **persistent connections** and **keep-alive control**.
49+
50+
**Characteristics:**
51+
- Connections persist after each response (`Connection: keep-alive`)
52+
- Supports pipelining — multiple requests queued for sequential processing
53+
- Chunked transfer encoding for streaming responses
54+
- Keep-alive timeout configurable via `TurboServerOptions.Http1.IdleTimeout`
55+
56+
**Transport:**
57+
- `TcpListenerFactory` — TCP listener binds to configured port
58+
- `TcpConnectionStage` — transport reuses connections across multiple requests
59+
60+
**Keep-Alive Handling:**
61+
62+
After encoding each response, `Http11ServerEngine` evaluates the `Connection` header:
63+
64+
- `Connection: keep-alive` (or HTTP/1.1 default) → the connection remains open for the next request
65+
- `Connection: close` → the connection closes after sending the response
66+
- Idle timeout → if no new request arrives within the idle timeout, the connection closes
67+
68+
---
69+
70+
## HTTP/2 Server Engine
71+
72+
<ClientOnly>
73+
<LikeC4Diagram viewId="serverHttp2Engine" :height="380" />
74+
</ClientOnly>
75+
76+
`Http20ServerEngine` provides **stream multiplexing** — many logical requests share a single TCP connection.
77+
78+
**Characteristics:**
79+
- Single TCP connection carries multiple concurrent streams
80+
- Each stream has a unique stream ID allocated by the client
81+
- HPACK header compression with synchronized dynamic tables
82+
- Connection-level and stream-level flow control
83+
- Server push support
84+
85+
**Transport:**
86+
- `TcpListenerFactory` — TCP listener binds to configured port
87+
- ALPN negotiation — client advertises `h2`; server selects it
88+
89+
**Internal Features:**
90+
91+
- **Frame parsing** — decodes 9-byte frame headers + payloads
92+
- **HPACK decoding** — decompresses request headers using the dynamic table
93+
- **Flow control** — tracks connection-level and per-stream receive windows; applies backpressure
94+
- **Connection frames**`SETTINGS`, `PING`, `GOAWAY`, `WINDOW_UPDATE`
95+
- **Stream correlation** — assembles `HEADERS` + `DATA` frames per stream into `HttpRequestMessage`
96+
97+
**Configuration:**
98+
99+
```csharp
100+
var options = new TurboServerOptions
101+
{
102+
Http2 = new Http2Options
103+
{
104+
MaxFrameSize = 16 * 1024, // default 16KB
105+
MaxHeaderListSize = 32 * 1024, // default 32KB
106+
InitialWindowSize = 65_535, // stream-level flow control window
107+
InitialConnectionWindowSize = 1 * 1024 * 1024, // connection-level window
108+
}
109+
};
110+
```
111+
112+
---
113+
114+
## HTTP/3 Server Engine
115+
116+
<ClientOnly>
117+
<LikeC4Diagram viewId="serverHttp3Engine" :height="380" />
118+
</ClientOnly>
119+
120+
`Http30ServerEngine` runs over **QUIC** (UDP-based transport), eliminating head-of-line blocking.
121+
122+
**Characteristics:**
123+
- QUIC (UDP) replaces TCP, providing built-in encryption (TLS)
124+
- Each request uses its own QUIC stream — lost packets don't block other streams
125+
- QPACK header compression (adapted for out-of-order delivery)
126+
- Connection-level flow control only (stream flow control handled by QUIC)
127+
128+
**Transport:**
129+
- `QuicListenerFactory` — QUIC listener binds to configured port (UDP)
130+
- ALPN negotiation — client advertises `h3`; server selects it
131+
132+
**Internal Features:**
133+
134+
- **Frame parsing** — uses QUIC variable-length integer encoding
135+
- **QPACK decoding** — decompresses request headers with decoder instruction streams
136+
- **Stream management** — per-stream lifecycle independent of other streams
137+
- **Connection frames**`SETTINGS`, `GOAWAY`
138+
139+
**Configuration:**
140+
141+
```csharp
142+
var options = new TurboServerOptions
143+
{
144+
Http3 = new Http3Options
145+
{
146+
MaxFrameSize = 16 * 1024, // default 16KB
147+
MaxHeaderListSize = 32 * 1024, // default 32KB
148+
InitialMaxStreamDataBidiLocal = 1 * 1024 * 1024, // per-stream flow control
149+
InitialMaxData = 10 * 1024 * 1024, // connection-level flow control
150+
}
151+
};
152+
```
153+
154+
---
155+
156+
## Per-Protocol Configuration
157+
158+
Each protocol has its own configuration section on `TurboServerOptions`:
159+
160+
```csharp
161+
var options = new TurboServerOptions
162+
{
163+
Binding = new BindingOptions
164+
{
165+
Port = 8080,
166+
EnableHttp1 = true,
167+
EnableHttp2 = true,
168+
EnableHttp3 = true,
169+
},
170+
Http1 = new Http1Options { IdleTimeout = TimeSpan.FromSeconds(120) },
171+
Http2 = new Http2Options { MaxFrameSize = 32 * 1024 },
172+
Http3 = new Http3Options { MaxHeaderListSize = 64 * 1024 },
173+
};
174+
```
175+
176+
::: tip
177+
For most applications, the default configuration works well. Only adjust these settings if you have specific protocol requirements or are tuning for a particular workload.
178+
:::
179+
180+
---
181+
182+
## ALPN Negotiation (TLS)
183+
184+
When TLS is enabled, the client advertises supported protocols during the handshake:
185+
186+
```
187+
Client TLS ClientHello
188+
189+
application_layer_protocol_negotiation (ALPN)
190+
supported_protocols: ["h3", "h2", "http/1.1"]
191+
192+
Server TLS ServerHello
193+
194+
application_layer_protocol_negotiation (ALPN)
195+
selected_protocol: "h2"
196+
197+
Client & Server both use HTTP/2
198+
```
199+
200+
If no ALPN is advertised or negotiation fails, the server defaults to **HTTP/1.1**.
201+
202+
---
203+
204+
## Related Guides
205+
206+
- [HTTP/2 & Multiplexing](/client/http2) — client-side HTTP/2 configuration
207+
- [HTTP/3 & QUIC](/client/http3) — client-side HTTP/3 configuration
208+
- [Server Configuration](/server/configuration) — server protocol settings
209+
- [Hosting & Lifecycle](/server/hosting) — connection management

0 commit comments

Comments
 (0)