[ PROMPT_NODE_24042 ]
Containers 设计模式
[ SKILL_DOCUMENTATION ]
## 路由模式
### 会话亲和性(有状态)
typescript
export class SessionBackend extends Container {
defaultPort = 3000;
sleepAfter = "30m";
}
export default {
async fetch(request: Request, env: Env) {
const sessionId = request.headers.get("X-Session-ID") || crypto.randomUUID();
const container = env.SESSION_BACKEND.getByName(sessionId);
await container.startAndWaitForPorts();
return container.fetch(request);
}
};
**用途:** 用户会话、WebSocket、有状态游戏、每用户缓存。
### 负载均衡(无状态)
typescript
export default {
async fetch(request: Request, env: Env) {
const container = env.STATELESS_API.getRandom();
await container.startAndWaitForPorts();
return container.fetch(request);
}
};
**用途:** 无状态 HTTP API、CPU 密集型工作、只读查询。
### 单例模式
typescript
export default {
async fetch(request: Request, env: Env) {
const container = env.GLOBAL_SERVICE.getByName("singleton");
await container.startAndWaitForPorts();
return container.fetch(request);
}
};
**用途:** 全局缓存、集中式协调器、单一事实来源。
## WebSocket 转发
typescript
export default {
async fetch(request: Request, env: Env) {
if (request.headers.get("Upgrade") === "websocket") {
const sessionId = request.headers.get("X-Session-ID") || crypto.randomUUID();
const container = env.WS_BACKEND.getByName(sessionId);
await container.startAndWaitForPorts();
// ⚠️ 必须使用 fetch(),不要使用 containerFetch()
return container.fetch(request);
}
return new Response("Not a WebSocket request", { status: 400 });
}
};
**⚠️ 关键:** WebSocket 请始终使用 `fetch()`。
## 优雅停机
typescript
export class GracefulContainer extends Container {
private connections = new Set();
onStop() {
// 收到 SIGTERM,距离 SIGKILL 还有 15 分钟
for (const ws of this.connections) {
ws.close(1001, "Server shutting down");
}
this.ctx.storage.put("shutdown-time", Date.now());
}
onActivityExpired(): boolean {
return this.connections.size > 0; // 如果有连接则保持存活
}
}
## 并发请求处理
typescript
export class SafeContainer extends Container {
private initialized = false;
async fetch(request: Request) {
await this.ctx.blockConcurrencyWhile(async () => {
if (!this.initialized) {
await this.st