Загрузка…
Загрузка…
HTTP / REST · middle · сложность 6
За LB любой request может попасть на любой server — проектируйте stateless: state в shared storage, не на local disk одного инстанса.
// The client-side reality of "any request can hit any server":
// design STATELESS. Never assume server memory between requests.
// ❌ Assumes the upload and the "commit" hit the same server's local temp dir.
await fetch('/upload/chunk', { method: 'POST', body: chunk }); // → server A's disk
await fetch('/upload/commit'); // → maybe server B: chunk isn't there. Fails under LB.
// ✅ Stateless: every request carries what it needs; state lives in shared storage.
const id = await startUpload(); // returns an id backed by S3/Redis
await fetch(`/upload/${id}/chunk`, { method: 'POST', body: chunk }); // any server
await fetch(`/upload/${id}/commit`); // any server — state is shared// Real-time: a WebSocket lives on ONE server, so the LB must be sticky for it
// AND the client must be able to reconnect (it may land on a different server).
function connect() {
const ws = new WebSocket('wss://api.app.com/live');
ws.onclose = () => setTimeout(connect, backoff()); // deploy drains → reconnect elsewhere
return ws;
}Chunked upload на local temp dir ломается под round-robin. Shared id (S3/Redis) — fix. WebSocket sticky, но client всё равно должен reconnect после deploy с backoff.
Stateless HTTP через shared storage; WebSocket — sticky + client-owned reconnect с backoff.