Skip to main content
Select language: current language is Simplified Chinese
搜索或询问 Copilot
打开菜单

扩展 Copilot SDK 的部署

设计 GitHub Copilot SDK 部署,以便为多个用户提供服务,处理并发会话,并在基础架构中实现水平扩展。

谁可以使用此功能?

GitHub Copilot SDK 适用于所有 Copilot 计划。

注意

          Copilot SDK 当前处于 技术预览版. 功能和可用性可能会发生更改。

考虑 CLI 会话的不同隔离模式,以及如何在实现应用程序时管理并发会话和资源。

          **最适合:** 平台开发人员、SaaS 构建者和任何为多个并发用户提供服务的部署。

会话隔离模式

在选择模式之前,请考虑三个维度:

  •         **隔离**:谁可以查看哪些会话?
    
  •         **并发**:可以同时运行多少个会话?
    
  •         **持久性**:会话持续多长时间?
    

显示 Copilot SDK 部署的三个缩放维度的关系图:隔离、并发和持久性。

模式 1:每个用户的独立 CLI

每个用户获取自己的 CLI 服务器实例。 这是最强的隔离 - 用户的会话、内存和进程完全分离。

显示每用户隔离 CLI 模式的关系图,其中,每个用户都拥有一个专用的 CLI 服务器实例。

          **何时使用**:
  • 在多租户 SaaS 中,数据隔离至关重要。
  • 具有不同身份验证凭据的用户。
  • 符合性要求,如 SOC 2 或 HIPAA。
// CLI pool manager—one CLI per user
class CLIPool {
    private instances = new Map<string, { client: CopilotClient; port: number }>();
    private nextPort = 5000;

    async getClientForUser(userId: string, token?: string): Promise<CopilotClient> {
        if (this.instances.has(userId)) {
            return this.instances.get(userId)!.client;
        }

        const port = this.nextPort++;

        // Spawn a dedicated CLI for this user
        await spawnCLI(port, token);

        const client = new CopilotClient({
            cliUrl: `localhost:${port}`,
        });

        this.instances.set(userId, { client, port });
        return client;
    }

    async releaseUser(userId: string): Promise<void> {
        const instance = this.instances.get(userId);
        if (instance) {
            await instance.client.stop();
            this.instances.delete(userId);
        }
    }
}

模式 2:共享 CLI,带有会话隔离

多个用户共享一个 CLI 服务器,但通过唯一会话 ID 隔离会话。 它对资源的需求较低,但提供的隔离较弱。

图示 CLI 共享模式,其中多个用户通过隔离会话共享一个 CLI 服务器。

          **何时使用**:
  • 具有受信任用户的内部工具。
  • 资源约束的环境。
  • 降低隔离要求。
const sharedClient = new CopilotClient({
    cliUrl: "localhost:4321",
});

// Enforce session isolation through naming conventions
function getSessionId(userId: string, purpose: string): string {
    return `${userId}-${purpose}-${Date.now()}`;
}

// Access control: ensure users can only access their own sessions
async function resumeSessionWithAuth(
    sessionId: string,
    currentUserId: string
): Promise<Session> {
    const [sessionUserId] = sessionId.split("-");
    if (sessionUserId !== currentUserId) {
        throw new Error("Access denied: session belongs to another user");
    }
    return sharedClient.resumeSession(sessionId);
}

模式 3:共享会话(协作)

多个用户与同一会话进行交互,例如与 Copilot 的共享聊天室。 此模式需要应用程序级会话锁定。

显示共享会话模式的关系图,其中多个用户通过消息队列和会话锁与同一会话进行交互。

          **何时使用**:
  • 团队协作工具。
  • 共享代码评审会话。
  • 配对编程助手。

注意

SDK 不提供内置会话锁定。 必须序列化访问权限,以防止并发写入同一会话。

import Redis from "ioredis";

const redis = new Redis();

async function withSessionLock<T>(
    sessionId: string,
    fn: () => Promise<T>,
    timeoutSec = 300
): Promise<T> {
    const lockKey = `session-lock:${sessionId}`;
    const lockId = crypto.randomUUID();

    // Acquire lock
    const acquired = await redis.set(lockKey, lockId, "NX", "EX", timeoutSec);
    if (!acquired) {
        throw new Error("Session is in use by another user");
    }

    try {
        return await fn();
    } finally {
        // Release lock only if we still own it
        const currentLock = await redis.get(lockKey);
        if (currentLock === lockId) {
            await redis.del(lockKey);
        }
    }
}

// Serialize access to a shared session
app.post("/team-chat", authMiddleware, async (req, res) => {
    const result = await withSessionLock("team-project-review", async () => {
        const session = await client.resumeSession("team-project-review");
        return session.sendAndWait({ prompt: req.body.message });
    });

    res.json({ content: result?.data.content });
});

隔离模式比较

每个用户一个独立的 CLI共享 CLI + 会话隔离共享会话
          **隔离** | 已完成 | Logical | 共享 |

| 资源使用情况 | 高(每个用户的命令行界面) | 低(一个 CLI) | 低(一个命令行接口 (CLI) 和会话) | | 复杂性 | 中等 | 低 | 高 (需要锁定) | | 身份验证灵活性 | 每用户令牌 | 服务令牌 | 服务令牌 | | 最适用于 | 多租户软件即服务 | 内部工具 | 协作 |

水平缩放

负载均衡器后面的多个 CLI 服务器

若要为更多并发用户提供服务,请在负载均衡器后面运行多个 CLI 服务器实例。 会话状态必须位于 共享存储 上,因此任何 CLI 服务器都可以恢复任何会话。

显示负载均衡器后面具有共享存储(用于会话状态)的多个 CLI 服务器的示意图。

// Route sessions across CLI servers
class CLILoadBalancer {
    private servers: string[];
    private currentIndex = 0;

    constructor(servers: string[]) {
        this.servers = servers;
    }

    // Round-robin selection
    getNextServer(): string {
        const server = this.servers[this.currentIndex];
        this.currentIndex = (this.currentIndex + 1) % this.servers.length;
        return server;
    }

    // Sticky sessions: same user always hits same server
    getServerForUser(userId: string): string {
        const hash = this.hashCode(userId);
        return this.servers[hash % this.servers.length];
    }

    private hashCode(str: string): number {
        let hash = 0;
        for (let i = 0; i < str.length; i++) {
            hash = (hash << 5) - hash + str.charCodeAt(i);
            hash |= 0;
        }
        return Math.abs(hash);
    }
}

const lb = new CLILoadBalancer([
    "cli-1:4321",
    "cli-2:4321",
    "cli-3:4321",
]);

app.post("/chat", async (req, res) => {
    const server = lb.getServerForUser(req.user.id);
    const client = new CopilotClient({ cliUrl: server });

    const session = await client.createSession({
        sessionId: `user-${req.user.id}-chat`,
        model: "gpt-4.1",
    });

    const response = await session.sendAndWait({ prompt: req.body.message });
    res.json({ content: response?.data.content });
});

粘滞会话与共享存储

比较 Copilot SDK 部署扩展中的粘滞会话和共享存储方法的图表。

          **粘性会话** 将每个用户绑定到特定的 CLI 服务器。 不需要共享存储,但如果用户流量显著变化,负载分布可能会不均衡。

          **共享存储** 允许任何 CLI 处理任何会话。 负载分布更均匀,但需要网络存储。`~/.copilot/session-state/`

纵向扩展

优化单个 CLI 服务器

单个 CLI 服务器可以处理多个并发会话。 关键是管理会话生命周期,以避免资源耗尽:

显示垂直缩放的资源维度的关系图:CPU、内存、磁盘 I/O 和网络。

// Limit concurrent active sessions
class SessionManager {
    private activeSessions = new Map<string, Session>();
    private maxConcurrent: number;

    constructor(maxConcurrent = 50) {
        this.maxConcurrent = maxConcurrent;
    }

    async getSession(sessionId: string): Promise<Session> {
        // Return existing active session
        if (this.activeSessions.has(sessionId)) {
            return this.activeSessions.get(sessionId)!;
        }

        // Enforce concurrency limit
        if (this.activeSessions.size >= this.maxConcurrent) {
            await this.evictOldestSession();
        }

        // Create or resume
        const session = await client.createSession({
            sessionId,
            model: "gpt-4.1",
        });

        this.activeSessions.set(sessionId, session);
        return session;
    }

    private async evictOldestSession(): Promise<void> {
        const [oldestId] = this.activeSessions.keys();
        const session = this.activeSessions.get(oldestId)!;
        // Session state is persisted automatically—safe to disconnect
        await session.disconnect();
        this.activeSessions.delete(oldestId);
    }
}

临时会话与永久性会话

比较 Copilot SDK 部署的临时会话和持久性会话的关系图。

          **临时会话** 按请求创建,并在使用后销毁。 它们非常适合一次性任务和无状态 API。

          **持久会话** 是可以命名的,在重启后能够继续存在,并且可以恢复。 它们非常适合多轮对话和长工作流。

临时会话

app.post("/api/analyze", async (req, res) => {
    const session = await client.createSession({
        model: "gpt-4.1",
    });

    try {
        const response = await session.sendAndWait({
            prompt: req.body.prompt,
        });
        res.json({ result: response?.data.content });
    } finally {
        await session.disconnect();
    }
});

持久会话

// Start a conversation
app.post("/api/chat/start", async (req, res) => {
    const sessionId = `user-${req.user.id}-${Date.now()}`;

    const session = await client.createSession({
        sessionId,
        model: "gpt-4.1",
        infiniteSessions: {
            enabled: true,
            backgroundCompactionThreshold: 0.80,
        },
    });

    res.json({ sessionId });
});

// Continue the conversation
app.post("/api/chat/message", async (req, res) => {
    const session = await client.resumeSession(req.body.sessionId);
    const response = await session.sendAndWait({ prompt: req.body.message });

    res.json({ content: response?.data.content });
});

// Clean up when done
app.post("/api/chat/end", async (req, res) => {
    await client.deleteSession(req.body.sessionId);
    res.json({ success: true });
});

容器部署

具有持久性存储的 Kubernetes

以下示例部署三个共享 CLI PersistentVolumeClaim 副本,以便任何副本可以恢复任何会话。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: copilot-cli
spec:
  replicas: 3
  selector:
    matchLabels:
      app: copilot-cli
  template:
    metadata:
      labels:
        app: copilot-cli
    spec:
      containers:
        - name: copilot-cli
          image: ghcr.io/github/copilot-cli:latest
          args: ["--headless", "--port", "4321"]
          env:
            - name: COPILOT_GITHUB_TOKEN
              valueFrom:
                secretKeyRef:
                  name: copilot-secrets
                  key: github-token
          ports:
            - containerPort: 4321
          volumeMounts:
            - name: session-state
              mountPath: /root/.copilot/session-state
      volumes:
        - name: session-state
          persistentVolumeClaim:
            claimName: copilot-sessions-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: copilot-cli
spec:
  selector:
    app: copilot-cli
  ports:
    - port: 4321
      targetPort: 4321

显示 Kubernetes 部署的图示,其中有多个 CLI 服务器 Pod 共享同一个持久卷声明用于会话状态。

生产核对清单

关注建议
          **会话清理** | 运行定期清理以删除早于 TTL 的会话。 |

| 运行状况检查 | 定期 Ping CLI 服务器;如果无响应,请重启。 | | 存储 | 装载持久卷~/.copilot/session-state/。 | | 机密 | 使用平台的机密管理器(保管库、Kubernetes Secrets 等)。 | | 监控 | 跟踪活动会话计数、响应延迟和错误率。 | | Locking | 使用 Redis 或类似工具访问共享会话。 | | 关机**** | 停止 CLI 服务器之前,请清空活动会话。 |

局限性

限度详细信息
          **无内置会话锁定** | 实现并发访问的应用程序级锁定。 |

| 无内置负载均衡 | 使用外部负载均衡器或服务网格。 | | 会话状态基于文件 | 多服务器设置需要一个共享文件系统。 | | 30 分钟空闲超时 | 不带活动的会话由 CLI 自动清除。 | | CLI 是单进程 | 通过添加更多 CLI 服务器实例而不是线程进行缩放。 |

后续步骤

Morty Proxy This is a proxified and sanitized view of the page, visit original site.