{"meta":{"title":"缩放和多租户","intro":"将 Copilot SDK 部署设计为可为多个用户提供服务、处理并发会话，并可在整个基础设施中实现横向扩展。 本指南介绍会话隔离模式、缩放拓扑和生产最佳做法。","product":"GitHub Copilot","breadcrumbs":[{"href":"/zh/copilot","title":"GitHub Copilot"},{"href":"/zh/copilot/how-tos","title":"操作方法"},{"href":"/zh/copilot/how-tos/copilot-sdk","title":"Copilot SDK"},{"href":"/zh/copilot/how-tos/copilot-sdk/setup","title":"设置 Copilot SDK"},{"href":"/zh/copilot/how-tos/copilot-sdk/setup/scaling","title":"规模化"}],"documentType":"article"},"body":"# 缩放和多租户\n\n将 Copilot SDK 部署设计为可为多个用户提供服务、处理并发会话，并可在整个基础设施中实现横向扩展。 本指南介绍会话隔离模式、缩放拓扑和生产最佳做法。\n\n<!-- markdownlint-disable GHD046 GHD005 -->\n\n<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->\n\n有关 SDK 级别的选项和模式，请参阅 [多租户与服务器部署](/zh/copilot/how-tos/copilot-sdk/setup/multi-tenancy)。\n\n**最适合：** 平台开发人员、SaaS 生成器，任何为多个并发用户提供服务的部署。\n\n## 核心概念\n\n在选择模式之前，请了解缩放的三个维度：\n\n![图示：显示所述过程的流程图。](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-0.png)\n\n## 会话隔离模式\n\n### 模式 1：每位用户一个独立的 CLI\n\n每个用户获取自己的 CLI 服务器实例。 最强的隔离 — 用户的会话、内存和进程完全分离。\n\n![图示：显示所述过程的流程图。](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-1.png)\n\n**何时使用**：\n\n* 数据隔离要求极高的多租户 SaaS\n* 具有不同身份验证凭据的用户\n* 合规性要求 （SOC 2， HIPAA）\n\n```typescript\n// CLI pool manager — one CLI per user\nclass CLIPool {\n    private instances = new Map<string, { client: CopilotClient; port: number }>();\n    private nextPort = 5000;\n\n    async getClientForUser(userId: string, token?: string): Promise<CopilotClient> {\n        if (this.instances.has(userId)) {\n            return this.instances.get(userId)!.client;\n        }\n\n        const port = this.nextPort++;\n\n        // Spawn a dedicated CLI for this user\n        await spawnCLI(port, token);\n\n        const client = new CopilotClient({\n            cliUrl: `localhost:${port}`,\n        });\n\n        this.instances.set(userId, { client, port });\n        return client;\n    }\n\n    async releaseUser(userId: string): Promise<void> {\n        const instance = this.instances.get(userId);\n        if (instance) {\n            await instance.client.stop();\n            this.instances.delete(userId);\n        }\n    }\n}\n```\n\n### 模式 2：支持会话隔离的共享式 CLI\n\n多个用户共享一个 CLI 服务器，但通过唯一会话 ID 隔离会话。 资源较轻，但隔离较弱。\n\n![图示：显示所述过程的流程图。](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-2.png)\n\n**何时使用**：\n\n* 具有受信任用户的内部工具\n* 资源约束的环境\n* 降低隔离要求\n\n```typescript\nconst sharedClient = new CopilotClient({\n    cliUrl: \"localhost:4321\",\n});\n\n// Enforce session isolation through naming conventions\nfunction getSessionId(userId: string, purpose: string): string {\n    return `${userId}-${purpose}-${Date.now()}`;\n}\n\n// Access control: ensure users can only access their own sessions\nasync function resumeSessionWithAuth(\n    sessionId: string,\n    currentUserId: string\n): Promise<Session> {\n    const [sessionUserId] = sessionId.split(\"-\");\n    if (sessionUserId !== currentUserId) {\n        throw new Error(\"Access denied: session belongs to another user\");\n    }\n    return sharedClient.resumeSession(sessionId);\n}\n```\n\n### 模式 3：共享会话（协作）\n\n多个用户与同一会话进行交互，例如与 Copilot 的共享聊天室。\n\n![图示：显示所述过程的流程图。](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-3.png)\n\n**何时使用**：\n\n* 团队协作工具\n* 共享代码审查会话\n* 配对编程助手\n\n> ⚠️**重要：** SDK 不提供内置会话锁定。 你**必须**将访问串行化，以防止对同一会话的并发写入。\n\n```typescript\nimport Redis from \"ioredis\";\n\nconst redis = new Redis();\n\nasync function withSessionLock<T>(\n    sessionId: string,\n    fn: () => Promise<T>,\n    timeoutSec = 300\n): Promise<T> {\n    const lockKey = `session-lock:${sessionId}`;\n    const lockId = crypto.randomUUID();\n\n    // Acquire lock\n    const acquired = await redis.set(lockKey, lockId, \"NX\", \"EX\", timeoutSec);\n    if (!acquired) {\n        throw new Error(\"Session is in use by another user\");\n    }\n\n    try {\n        return await fn();\n    } finally {\n        // Release lock (only if we still own it)\n        const currentLock = await redis.get(lockKey);\n        if (currentLock === lockId) {\n            await redis.del(lockKey);\n        }\n    }\n}\n\n// Usage: serialize access to shared session\napp.post(\"/team-chat\", authMiddleware, async (req, res) => {\n    const result = await withSessionLock(\"team-project-review\", async () => {\n        const session = await client.resumeSession(\"team-project-review\");\n        return session.sendAndWait({ prompt: req.body.message });\n    });\n\n    res.json({ content: result?.data.content });\n});\n```\n\n## 隔离模式比较\n\n|               | 每个用户的隔离 CLI  | 共享 CLI 与会话隔离 | 共享会话              |\n| ------------- | ------------ | ------------ | ----------------- |\n| **Isolation** |              |              |                   |\n| ✅ 完成          |              |              |                   |\n| ⚠️ 逻辑         |              |              |                   |\n| ❌ 共享          |              |              |                   |\n| **资源使用情况**    | 高（每个用户的 CLI） | 低（一个 CLI）    | 低（一个命令行界面 + 一个会话） |\n| **复杂性**       | 中等           | 低            | 高（锁定）             |\n| **身份验证灵活性**   |              |              |                   |\n| ✅ 每个用户的令牌     |              |              |                   |\n| ⚠️ 服务令牌       |              |              |                   |\n| ⚠️ 服务令牌       |              |              |                   |\n| **最适用于**      | 多租户软件即服务     | 内部工具         | 协作                |\n\n## 水平扩展\n\n### 负载均衡器后面的多个 CLI 服务器\n\n![图示：显示所述过程的流程图。](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-4.png)\n\n**关键要求：** 会话状态必须位于 **共享存储** 上，因此任何 CLI 服务器都可以恢复任何会话。\n\n```typescript\n// Route sessions to CLI servers\nclass CLILoadBalancer {\n    private servers: string[];\n    private currentIndex = 0;\n\n    constructor(servers: string[]) {\n        this.servers = servers;\n    }\n\n    // Round-robin selection\n    getNextServer(): string {\n        const server = this.servers[this.currentIndex];\n        this.currentIndex = (this.currentIndex + 1) % this.servers.length;\n        return server;\n    }\n\n    // Sticky sessions: same user always hits same server\n    getServerForUser(userId: string): string {\n        const hash = this.hashCode(userId);\n        return this.servers[hash % this.servers.length];\n    }\n\n    private hashCode(str: string): number {\n        let hash = 0;\n        for (let i = 0; i < str.length; i++) {\n            hash = (hash << 5) - hash + str.charCodeAt(i);\n            hash |= 0;\n        }\n        return Math.abs(hash);\n    }\n}\n\nconst lb = new CLILoadBalancer([\n    \"cli-1:4321\",\n    \"cli-2:4321\",\n    \"cli-3:4321\",\n]);\n\napp.post(\"/chat\", async (req, res) => {\n    const server = lb.getServerForUser(req.user.id);\n    const client = new CopilotClient({ cliUrl: server });\n\n    const session = await client.createSession({\n        sessionId: `user-${req.user.id}-chat`,\n        model: \"gpt-5.4\",\n    });\n\n    const response = await session.sendAndWait({ prompt: req.body.message });\n    res.json({ content: response?.data.content });\n});\n```\n\n### 粘滞会话与共享存储\n\n![图示：显示所述过程的流程图。](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-5.png)\n\n**粘滞会话** 更简单- 将用户固定到特定的 CLI 服务器。 不需要共享存储，但负载分布不均衡。\n\n**共享存储** 允许任何 CLI 处理任何会话。 负载分布更佳，但 `~/.copilot/session-state/` 需要网络存储。\n\n## 纵向扩展\n\n### 优化单个 CLI 服务器\n\n单个 CLI 服务器可以处理多个并发会话。 关键注意事项：\n\n![图示：显示所述过程的流程图。](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-6.png)\n\n**会话生命周期管理** 是垂直缩放的关键：\n\n```typescript\n// Limit concurrent active sessions\nclass SessionManager {\n    private activeSessions = new Map<string, Session>();\n    private maxConcurrent: number;\n\n    constructor(maxConcurrent = 50) {\n        this.maxConcurrent = maxConcurrent;\n    }\n\n    async getSession(sessionId: string): Promise<Session> {\n        // Return existing active session\n        if (this.activeSessions.has(sessionId)) {\n            return this.activeSessions.get(sessionId)!;\n        }\n\n        // Enforce concurrency limit\n        if (this.activeSessions.size >= this.maxConcurrent) {\n            await this.evictOldestSession();\n        }\n\n        // Create or resume\n        const session = await client.createSession({\n            sessionId,\n            model: \"gpt-5.4\",\n        });\n\n        this.activeSessions.set(sessionId, session);\n        return session;\n    }\n\n    private async evictOldestSession(): Promise<void> {\n        const [oldestId] = this.activeSessions.keys();\n        const session = this.activeSessions.get(oldestId)!;\n        // Session state is persisted automatically — safe to disconnect\n        await session.disconnect();\n        this.activeSessions.delete(oldestId);\n    }\n}\n```\n\n## 临时会话与永久性会话\n\n![图示：显示所述过程的流程图。](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-7.png)\n\n### 临时会话\n\n对于每个请求都是独立的无状态 API 端点：\n\n```typescript\napp.post(\"/api/analyze\", async (req, res) => {\n    const session = await client.createSession({\n        model: \"gpt-5.4\",\n    });\n\n    try {\n        const response = await session.sendAndWait({\n            prompt: req.body.prompt,\n        });\n        res.json({ result: response?.data.content });\n    } finally {\n        await session.disconnect();  // Clean up immediately\n    }\n});\n```\n\n### 持久会话\n\n对于对话式界面或长期运行的工作流：\n\n```typescript\n// Create a resumable session\napp.post(\"/api/chat/start\", async (req, res) => {\n    const sessionId = `user-${req.user.id}-${Date.now()}`;\n\n    const session = await client.createSession({\n        sessionId,\n        model: \"gpt-5.4\",\n        infiniteSessions: {\n            enabled: true,\n            backgroundCompactionThreshold: 0.80,\n        },\n    });\n\n    res.json({ sessionId });\n});\n\n// Continue the conversation\napp.post(\"/api/chat/message\", async (req, res) => {\n    const session = await client.resumeSession(req.body.sessionId);\n    const response = await session.sendAndWait({ prompt: req.body.message });\n\n    res.json({ content: response?.data.content });\n});\n\n// Clean up when done\napp.post(\"/api/chat/end\", async (req, res) => {\n    await client.deleteSession(req.body.sessionId);\n    res.json({ success: true });\n});\n```\n\n## 容器部署\n\n### 具有持久性存储的 Kubernetes\n\n```yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: copilot-cli\nspec:\n  replicas: 3\n  selector:\n    matchLabels:\n      app: copilot-cli\n  template:\n    metadata:\n      labels:\n        app: copilot-cli\n    spec:\n      containers:\n        - name: copilot-cli\n          image: your-registry/copilot-cli:latest  # See backend-services.md for how to build and push this image\n          args: [\"--headless\", \"--host\", \"0.0.0.0\", \"--port\", \"4321\"]\n          env:\n            - name: COPILOT_GITHUB_TOKEN\n              valueFrom:\n                secretKeyRef:\n                  name: copilot-secrets\n                  key: github-token\n          ports:\n            - containerPort: 4321\n          volumeMounts:\n            - name: session-state\n              mountPath: /root/.copilot/session-state\n      volumes:\n        - name: session-state\n          persistentVolumeClaim:\n            claimName: copilot-sessions-pvc\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: copilot-cli\nspec:\n  selector:\n    app: copilot-cli\n  ports:\n    - port: 4321\n      targetPort: 4321\n```\n\n![图示：显示所述过程的流程图。](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-8.png)\n\n### Azure 容器实例\n\n```yaml\ncontainers:\n  - name: copilot-cli\n    image: your-registry/copilot-cli:latest  # See backend-services.md for how to build and push this image\n    command: [\"copilot\", \"--headless\", \"--host\", \"0.0.0.0\", \"--port\", \"4321\"]\n    volumeMounts:\n      - name: session-storage\n        mountPath: /root/.copilot/session-state\n\nvolumes:\n  - name: session-storage\n    azureFile:\n      shareName: copilot-sessions\n      storageAccountName: myaccount\n```\n\n## 生产核对清单\n\n![图示：显示所述过程的流程图。](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-9.png)\n\n| 关注          | Recommendation                      |\n| ----------- | ----------------------------------- |\n| **会话清理**    | 运行定期清理以删除超过 TTL 的会话                 |\n| **运行状况检查**  | 定期 Ping CLI 服务器;如果无响应，请重启           |\n| **存储**      | 为 `~/.copilot/session-state/` 挂载持久卷 |\n| **机密**      | 使用您平台的密钥管理器（Vault、K8s Secrets 等）    |\n| **监控**      | 跟踪活动会话计数、响应延迟、错误率                   |\n| **Locking** | 使用 Redis 或类似方案实现共享会话访问              |\n| 关机\\*\\*\\*\\*  | 在停止 CLI 服务器之前清空活动会话                 |\n\n## 局限性\n\n| Limitation    | 详细信息                      |\n| ------------- | ------------------------- |\n| **无内置会话锁定**   | 实现并发访问的应用程序级锁定            |\n| **无内置负载均衡**   | 使用外部 LB 或服务网格             |\n| **会话状态基于文件**  | 多服务器部署需要共享文件系统            |\n| **30 分钟空闲超时** | 不带活动的会话由 CLI 自动清理         |\n| **CLI 是单进程**  | 通过添加更多 CLI 服务器实例而不是线程进行缩放 |\n\n## 后续步骤\n\n* **[会话恢复和持久性](/zh/copilot/how-tos/copilot-sdk/features/session-persistence)**：深入解析可恢复会话\n* **[后端服务设置](/zh/copilot/how-tos/copilot-sdk/setup/backend-services)**：核心服务器端设置\n* **[GitHub OAuth 设置](/zh/copilot/how-tos/copilot-sdk/setup/github-oauth)**：多用户身份验证\n* **[BYOK （自带密钥）](/zh/copilot/how-tos/copilot-sdk/auth/byok)**：使用您自己的模型提供方"}