# 分布式网关部署方法

## 使用场景

当你需要在多台机器上部署 Jarvis Web Gateway，并通过统一的入口访问所有节点上的 Agent 时，可以使用分布式网关部署模式。这种模式适用于以下场景：

- **多机资源利用**：将计算任务分散到多台机器上执行，充分利用集群资源
- **异地协作**：团队成员在不同地点访问统一的 Jarvis 服务入口
- **负载分担**：将不同类型的 Agent 分配到不同的节点上运行
- **环境隔离**：不同节点可以配置不同的运行环境或工具集

## 架构概述

```
┌─────────────────────────────────────────────────────────────────┐
│                         客户端层                                  │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐           │
│  │   Web 浏览器  │  │  VSCode 插件  │  │   其他客户端  │           │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘           │
└─────────┼────────────────┼────────────────┼─────────────────────┘
          │                │                │
          └────────────────┴────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────────┐
│                      主节点 (Master)                             │
│  ┌──────────────────────────────────────────────────────┐      │
│  │              Jarvis Web Gateway                       │      │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐   │      │
│  │  │  Agent 管理  │  │  节点注册表  │  │  路由转发   │   │      │
│  │  └─────────────┘  └─────────────┘  └─────────────┘   │      │
│  └──────────────────────────────────────────────────────┘      │
└─────────────────────────────────────────────────────────────────┘
          │                │                │
          ▼                ▼                ▼
┌──────────────┐  ┌──────────────┐  ┌──────────────┐
│   子节点 1    │  │   子节点 2    │  │   子节点 N    │
│  (Child 1)   │  │  (Child 2)   │  │  (Child N)   │
│ ┌──────────┐ │  │ ┌──────────┐ │  │ ┌──────────┐ │
│ │  Agent 1 │ │  │ │  Agent 3 │ │  │ │  Agent 5 │ │
│ │  Agent 2 │ │  │ │  Agent 4 │ │  │ │  Agent 6 │ │
│ └──────────┘ │  │ └──────────┘ │  │ └──────────┘ │
└──────────────┘  └──────────────┘  └──────────────┘
```

**工作原理**：

- 主节点负责对外提供统一的访问入口，维护所有子节点的注册信息
- 子节点通过 WebSocket 长连接接入主节点，上报自身状态
- 客户端只需连接主节点，主节点会根据 Agent 所属节点自动转发请求
- 创建 Agent 时可以指定目标节点，Agent 将在指定节点上运行

## 前置要求

- 所有节点（主节点和子节点）必须安装 Jarvis 并配置好 LLM 平台
- 主节点需要能够被客户端和子节点访问（网络可达）
- 建议为所有节点配置相同的节点密钥（`--node-secret`）以确保安全通信

## 操作步骤

### 1. 启动主节点

在主节点机器上执行：

```bash
jarvis-service --node-mode master --gateway-host 0.0.0.0 --gateway-port 8000 --gateway-password your_password
```

**参数说明**：

- `--node-mode master`：指定以主节点模式运行
- `--gateway-host 0.0.0.0`：监听所有网络接口（如需仅本地访问，可使用 `127.0.0.1`）
- `--gateway-port 8000`：监听端口
- `--gateway-password`：可选，设置网关访问密码
- `--node-secret`：可选，设置节点间通信的共享密钥

**获取节点密钥**：

主节点启动时会自动生成节点密钥并保存到 `~/.jarvis/node_mode/master_node_secret` 文件中。首次启动后，可通过以下方式查看密钥：

```bash
# 查看已生成的节点密钥
cat ~/.jarvis/node_mode/master_node_secret
```

子节点启动时需要使用相同的密钥。如果主节点未指定 `--node-secret` 参数，系统会自动生成；如果指定了，则使用指定的密钥。

### 2. 启动子节点

在每台子节点机器上执行：

```bash
jarvis-service --node-mode child \
    --node-id worker-01 \
    --master-url ws://master-host:8000 \
    --node-secret your_secret_key
```

**参数说明**：

- `--node-mode child`：指定以子节点模式运行
- `--node-id worker-01`：子节点的唯一标识（必填）
- `--master-url`：主节点的 WebSocket 地址（必填）
  - 格式：`ws://host:port` 或 `wss://host:port`（如果使用 HTTPS）
  - 例如：`ws://192.168.1.100:8000`
- `--node-secret`：节点间通信的共享密钥（必填）

**启动多个子节点示例**：

```bash
# 子节点 1
jarvis-service --node-mode child --node-id worker-01 --master-url ws://192.168.1.100:8000 --node-secret my_secret

# 子节点 2
jarvis-service --node-mode child --node-id worker-02 --master-url ws://192.168.1.100:8000 --node-secret my_secret

# 子节点 3（指定不同端口避免冲突）
jarvis-service --node-mode child --node-id worker-03 --master-url ws://192.168.1.100:8000 --node-secret my_secret --gateway-port 8001
```

### 3. 验证节点接入

启动子节点后，可以通过以下方式验证接入状态：

1. **查看主节点日志**：成功接入时会显示子节点信息
2. **通过 Web 界面查看**：
   - 连接主节点后打开"创建 Agent"对话框
   - 在"目标节点"下拉框中应该能看到所有已接入的子节点
3. **通过 VSCode 插件查看**：
   - 连接主节点后，Agent 列表会显示每个 Agent 所属的节点

### 4. 创建并运行分布式 Agent

#### 通过 Web 界面

1. 浏览器访问主节点地址（如 `http://master-host:8000`）
2. 点击"创建 Agent"
3. 在"目标节点"下拉框中选择要运行 Agent 的子节点
4. 完成创建后，Agent 将在指定子节点上运行

#### 通过 VSCode 插件

1. 在插件中连接主节点
2. 点击"创建 Agent"
3. 在节点选择器中选择目标子节点
4. Agent 创建后将运行在选定的子节点上

### 5. 子节点上的 Agent 管理

- **查看运行状态**：在主节点的 Web 界面或 VSCode 插件中，可以看到所有节点上的 Agent 列表，每个 Agent 都会显示其所属节点
- **交互通信**：与子节点上的 Agent 通信时，消息会自动通过主节点转发到对应的子节点
- **会话恢复**：子节点上的 Agent 会话同样支持恢复功能

## 你会看到的提示与反馈

### 主节点启动时

```
🚀 启动 Jarvis Web Gateway

  地址: 0.0.0.0
  端口: 8000
  密码: 已设置
  节点模式: master
  节点ID: master
  节点密钥: 已设置
```

### 子节点启动时

```
🚀 启动 Jarvis Web Gateway

  地址: 127.0.0.1
  端口: 8000
  密码: 未设置
  节点模式: child
  节点ID: worker-01
  节点密钥: 已设置
```

子节点成功连接到主节点后，会显示连接成功的信息。

### Web 界面中的节点标识

- 在 Agent 列表中，每个 Agent 会显示其所属节点的标识（如 `master`、`worker-01` 等）
- 创建 Agent 时，节点选择器会列出所有可用的节点

## 配置文件方式部署（推荐用于生产环境）

对于生产环境的部署，建议使用配置文件配合 systemd/supervisor 等进程管理工具。

### 主节点配置示例

创建启动脚本 `/opt/jarvis/start-master.sh`：

```bash
#!/bin/bash
export JARVIS_GATEWAY_PASSWORD="your_secure_password"
export JARVIS_NODE_SECRET="your_secret_key"
jarvis-service --node-mode master --gateway-host 0.0.0.0 --gateway-port 8000
```

### 子节点配置示例

创建启动脚本 `/opt/jarvis/start-worker.sh`：

```bash
#!/bin/bash
export JARVIS_NODE_SECRET="your_secret_key"
jarvis-service --node-mode child \
    --node-id "$(hostname)" \
    --master-url "ws://master-host:8000" \
    --node-secret "${JARVIS_NODE_SECRET}" \
    --gateway-port 8000
```

### 使用 systemd 管理（Linux）

**主节点服务文件** `/etc/systemd/system/jarvis-master.service`：

```ini
[Unit]
Description=Jarvis Web Gateway Master
After=network.target

[Service]
Type=simple
User=jarvis
Environment="JARVIS_GATEWAY_PASSWORD=your_password"
Environment="JARVIS_NODE_SECRET=your_secret_key"
ExecStart=/usr/local/bin/jarvis-service --node-mode master --gateway-host 0.0.0.0 --gateway-port 8000
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
```

**子节点服务文件** `/etc/systemd/system/jarvis-worker.service`：

```ini
[Unit]
Description=Jarvis Web Gateway Worker
After=network.target

[Service]
Type=simple
User=jarvis
Environment="JARVIS_NODE_SECRET=your_secret_key"
ExecStart=/usr/local/bin/jarvis-service --node-mode child --node-id %H --master-url ws://master-host:8000 --node-secret ${JARVIS_NODE_SECRET}
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
```

**启用服务**：

```bash
# 主节点
sudo systemctl enable jarvis-master
sudo systemctl start jarvis-master

# 子节点
sudo systemctl enable jarvis-worker
sudo systemctl start jarvis-worker
```

## 使用 Docker Compose 部署

对于容器化部署，可以使用 Docker Compose：

**`docker-compose.master.yml`**（主节点）：

```yaml
version: "3.8"
services:
  jarvis-master:
    image: ghcr.io/skyfireitdiy/jarvis:latest
    ports:
      - "8000:8000"
    environment:
      - JARVIS_GATEWAY_PASSWORD=${JARVIS_GATEWAY_PASSWORD}
      - JARVIS_NODE_SECRET=${JARVIS_NODE_SECRET}
    command: >
      jarvis-service --node-mode master 
          --gateway-host 0.0.0.0 
          --gateway-port 8000
          --gateway-password ${JARVIS_GATEWAY_PASSWORD}
          --node-secret ${JARVIS_NODE_SECRET}
    volumes:
      - ~/.jarvis:/home/jarvis/.jarvis
```

**`docker-compose.worker.yml`**（子节点）：

```yaml
version: "3.8"
services:
  jarvis-worker:
    image: ghcr.io/skyfireitdiy/jarvis:latest
    environment:
      - JARVIS_NODE_SECRET=${JARVIS_NODE_SECRET}
      - NODE_ID=${NODE_ID}
      - MASTER_URL=${MASTER_URL}
    command: >
      jarvis-service --node-mode child 
          --node-id ${NODE_ID}
          --master-url ${MASTER_URL}
          --node-secret ${JARVIS_NODE_SECRET}
    volumes:
      - ~/.jarvis:/home/jarvis/.jarvis
```

**启动命令**：

```bash
# 主节点
docker-compose -f docker-compose.master.yml up -d

# 子节点
export NODE_ID=worker-01
export MASTER_URL=ws://master-host:8000
docker-compose -f docker-compose.worker.yml up -d
```

## 注意事项

### 安全性

1. **密码保护**：生产环境建议设置 `--gateway-password` 防止未授权访问
2. **节点密钥**：所有节点应配置相同的 `--node-secret`，用于节点间通信的安全校验
3. **网络安全**：确保主节点和子节点之间的网络通信安全，必要时使用 VPN 或私有网络
4. **HTTPS/WSS**：如果部署在公网，建议使用反向代理（如 Nginx）启用 HTTPS/WSS

### 网络要求

1. **端口开放**：确保主节点的监听端口对客户端和子节点开放
2. **防火墙配置**：检查防火墙规则，允许节点间的 WebSocket 通信
3. **长连接保持**：子节点与主节点之间保持 WebSocket 长连接，网络不稳定时可能断线重连

### 高可用性

1. **当前限制**：目前只支持单主节点架构，主节点是单点
2. **故障恢复**：子节点断线后会自动重连，Agent 状态会重新同步
3. **数据持久化**：建议配置持久化存储以保存 Agent 会话数据

### 版本兼容性

1. 主节点和子节点应使用相同版本的 Jarvis
2. 版本不一致可能导致通信协议不兼容

### 资源管理

1. 每个子节点可以承载多个 Agent，但应根据机器资源合理分配
2. 注意监控子节点的 CPU、内存使用情况
3. 大型任务建议分配到资源更充足的节点上执行

## 故障排查

### 子节点无法连接到主节点

1. 检查主节点地址和端口是否正确
2. 确认主节点防火墙是否允许子节点 IP 访问
3. 检查 `--node-secret` 是否在所有节点上一致
4. 查看主节点和子节点的日志输出

### Agent 创建失败

1. 确认目标子节点已正确接入主节点
2. 检查子节点是否有足够的资源创建新 Agent
3. 查看子节点的日志获取详细错误信息

### 消息转发失败

1. 检查子节点与主节点的连接状态
2. 确认 Agent ID 和节点 ID 的映射关系正确
3. 重启相关服务尝试恢复

## 相关文档

- [启动 Web Gateway 服务](./启动_Web_Gateway_服务.md)
- [Node 模式部署与联调手册](./Node_模式部署与联调手册.md)
- [在 Web 界面中查看 Agent 所属节点](./在_Web_界面中查看_Agent_所属节点.md)
- [在 VSCode 插件中创建 Agent 并选择目标节点](../07_VSCode_插件/在_VSCode_插件中创建_Agent_并选择目标节点.md)
