You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-**Weighted Load Balancing**: distribute requests across backends by configurable weight; unhealthy backends are automatically excluded.
10
10
-**Method-Based Routing**: pin specific RPC methods (e.g. `getSlot`) to designated backends.
11
-
-**WebSocket Proxying**: separate WS server (HTTP port + 1) with the same auth, rate limiting, and weighted backend selection.
11
+
-**WebSocket Proxying**: upgrade on the main HTTP port or a dedicated WS port (HTTP port + 1), with the same auth, rate limiting, and weighted backend selection.
12
12
-**Health Checks**: background loop calls a configurable RPC method per backend; consecutive-failure / consecutive-success thresholds control status transitions.
13
13
-**Prometheus Metrics**: `GET /metrics` exposes request counts, latencies, and backend health gauges.
14
14
-**Admin CLI** (`rpc-admin`): create, list, inspect, and revoke API keys in Redis.
@@ -74,6 +74,62 @@ getSlot = "mainnet-primary"
74
74
-`proxy.timeout_secs` must be > 0.
75
75
-`method_routes` values must reference existing backend labels.
76
76
77
+
## WebSocket Handling
78
+
79
+
The proxy supports Solana WebSocket subscriptions (e.g. `accountSubscribe`, `logsSubscribe`) with the same authentication and load-balancing guarantees as HTTP.
80
+
81
+
### Connection Lifecycle
82
+
83
+
```mermaid
84
+
sequenceDiagram
85
+
participant Client
86
+
participant Router
87
+
participant Redis
88
+
participant Backend
89
+
90
+
Client->>Router: GET / (Upgrade: websocket) + API Key
91
+
Router->>Redis: Validate Key
92
+
Redis-->>Router: OK (Owner info)
93
+
Router->>Router: Select Healthy Backend
94
+
Router->>Backend: Connect (WS Handshake)
95
+
Backend-->>Router: 101 Switching Protocols
96
+
Router-->>Client: 101 Switching Protocols
97
+
98
+
Note over Client,Backend: Bi-directional Message Pipe
99
+
100
+
Client->>Router: Message
101
+
Router->>Backend: Forward
102
+
Backend->>Router: Message
103
+
Router->>Client: Forward
104
+
```
105
+
106
+
1.**Upgrade** — Clients open a WebSocket to the main HTTP port (`GET /` with `Upgrade: websocket`) or the dedicated WS port (HTTP port + 1). Both accept `?api-key=` as a query parameter.
107
+
2.**Authentication** — The API key is validated against Redis (same flow as HTTP: lookup, cache check, rate-limit enforcement). Failures return `401 Unauthorized` or `429 Too Many Requests` before the upgrade completes.
108
+
3.**Backend Selection** — `select_ws_backend()` picks a healthy backend that has a `ws_url` configured, using the same weighted-random algorithm as HTTP requests.
109
+
4.**Bi-directional Piping** — After the upgrade, the proxy opens a second WebSocket to the chosen backend (via `tokio-tungstenite`). Two concurrent tasks forward frames in each direction (client ↔ backend). Text, Binary, Ping, and Pong frames are relayed transparently. When either side sends a Close frame or errors out, `tokio::select!` shuts down the other direction.
110
+
5.**Cleanup** — On disconnect the active-connection gauge is decremented and the total session duration is recorded.
|`ws_connection_duration_seconds`| Histogram |`backend`, `owner`| Session duration from upgrade to close |
120
+
121
+
### Configuration
122
+
123
+
Backends that should accept WebSocket traffic must include a `ws_url` field. Backends without `ws_url` are excluded from WebSocket routing but still serve HTTP requests.
124
+
125
+
```toml
126
+
[[backends]]
127
+
label = "mainnet-primary"
128
+
url = "https://api.mainnet-beta.solana.com"
129
+
ws_url = "wss://api.mainnet-beta.solana.com"# enables WS for this backend
130
+
weight = 10
131
+
```
132
+
77
133
## API Key Management CLI
78
134
79
135
```bash
@@ -103,10 +159,11 @@ Redis URL can be set via `--redis-url` flag or `REDIS_URL` env var (default `red
103
159
| Endpoint | Method | Description |
104
160
|----------|--------|-------------|
105
161
|`/`| POST | Proxy JSON-RPC requests (requires `?api-key=`) |
162
+
|`/`| GET (Upgrade) | WebSocket proxy on main port (requires `?api-key=`) |
0 commit comments