Hermes-Studio 企业级分布式部署改造方案
Hermes-Agent 企业级分布式部署方案
版本:v1.0 | 适用场景:多租户 / 多团队 / 规模化 AI Agent 平台
基于 Hermes Studio 原生架构,企业仅需扩展用户表 + 新增路由映射表即可落地
一、方案概述
1.1 背景与挑战
Hermes Studio 原生采用单实例 + SQLite架构,适合个人或小团队使用。当企业需要将 AI Agent 能力开放给数十到数百名用户时,单实例面临以下瓶颈:
| 瓶颈 | 表现 |
|---|---|
| 并发上限 | SQLite 写锁导致高并发下请求排队 |
| 数据隔离 | 所有用户共享同一数据库,无法做会话隔离 |
| 扩展困难 | 无法水平扩容,单点故障影响全员 |
| 资源争抢 | 某用户的大量 Agent 会话影响其他用户体验 |
1.2 设计目标
低成本 — 无中间件依赖(不需要 Redis/MySQL/K8s),纯 Docker + SQLite 水平扩展 高可用 — 任一实例故障仅影响该实例用户,全局兜底保证零中断 易落地 — 企业只需改两处:用户表加一个字段 + 新增一张路由映射表 零侵入 — 不修改 Hermes Studio 源码,通过反向代理层透明路由1.3 核心架构
┌──────────────────────────────────────────┐ │ 企业后端 (Proxy Layer) │ │ │ ┌──────┐ HTTP/API │ ┌───────────────────────────────┐ │ │ 用户A │──────────────┼─►│ 路由决策引擎 │ │ └──────┘ │ │ ① 查用户绑定的实例 │ │ ┌────────────────┐ │ │ ② 未绑定 → 自动分配 │ │────►│ Hermes 实例 A │ ┌──────┐ HTTP/API │ │ ③ 都不可用 → 全局默认兜底 │ │ │ :30001 │ │ 用户B │──────────────┼─►│ │──┬──►│ SQLite (~20用户) │ └──────┘ │ └───────────────────────────────┘ │ └────────────────┘ │ │ ┌────────────────┐ ┌──────┐ HTTP/API │ │ │ Hermes 实例 B │ │ 用户C │──────────────┼─► ├──►│ :30002 │ └──────┘ │ │ │ SQLite (~15用户) │ │ │ └────────────────┘ │ │ ┌────────────────┐ │ │ │ Hermes 实例 C │ │ └──►│ :30003 │ │ │ SQLite (~10用户) │ │ └────────────────┘ └──────────────────────────────────────────┘关键设计决策:
- 一用户一实例:每个用户的所有请求(HTTP API + WebSocket/SSE)自动路由到固定实例
- 实例自治:每个 Hermes 实例独立运行,拥有自己的 SQLite 数据库,用户间数据天然隔离
- 代理透明:前端无需感知多实例,所有请求通过企业后端统一代理转发
二、数据库设计(最小改动)
企业只需做两件事:① 新增一张路由映射表 ② 用户表加一个外键字段
2.1 新增表:hermes_instances(实例路由映射表)
CREATETABLEhermes_instances(idSERIALPRIMARYKEY,nameVARCHAR(100)NOTNULL,-- 实例名称,如 "hermes-prod-01"base_urlVARCHAR(500)NOTNULLUNIQUE,-- 实例地址,如 "http://10.0.1.50:30001"statusVARCHAR(20)NOTNULLDEFAULT'active',-- active = 正常服务-- maintenance = 维护中(不分配新用户)-- inactive = 已下线max_usersINTEGERNOTNULLDEFAULT20,-- 最大承载用户数(按 SQLite 并发能力设定)priorityINTEGERNOTNULLDEFAULT100,-- 自动分配优先级(数值越大越优先)remarkTEXTDEFAULT'',created_atTIMESTAMPDEFAULTNOW(),updated_atTIMESTAMPDEFAULTNOW());字段说明:
| 字段 | 用途 | 运维场景 |
|---|---|---|
status | 控制实例生命周期 | 下线前先改maintenance→ 迁移用户 → 再改inactive |
max_users | 防止单实例过载 | 根据服务器配置调整,一般 15-30 |
priority | 灰度发布 | 新实例可设高优先级优先接收用户,老实例逐步迁移 |
2.2 用户表扩展字段
ALTERTABLEusersADDCOLUMNhermes_instance_idINTEGERREFERENCEShermes_instances(id)ONDELETESETNULL;-- NULL 含义:该用户未绑定实例,走全局默认地址(完全向下兼容)设计原则:
hermes_instance_id允许为 NULL → 未绑定的老用户自动走全局默认实例,零中断ON DELETE SET NULL→ 删除实例时用户自动回退到全局默认,不会悬空- 不修改任何现有字段 → 对现有业务逻辑完全透明
2.3 初始化迁移(向下兼容)
-- 1. 将现有全局地址注册为第一个实例INSERTINTOhermes_instances(name,base_url,status,max_users,priority,remark)VALUES('hermes-prod-01','http://<当前全局地址>:30001','active',20,100,'初始实例')ONCONFLICTDONOTHING;-- 2. 将已有 Hermes 凭证的用户绑定到初始实例UPDATEusersSEThermes_instance_id=(SELECTidFROMhermes_instancesORDERBYidLIMIT1)WHEREhermes_usernameISNOTNULLANDhermes_instance_idISNULL;三、路由决策引擎
3.1 路由优先级
请求进入 │ ▼ ┌─────────────────────────────────┐ │ ① 用户已绑定实例? │ │ → YES → 查询实例 base_url │ │ → 实例存在且 active? │ │ → YES → 路由到该实例 │ │ → NO → 降级到 ② │ │ → NO → 进入 ② │ └─────────────────────────────────┘ │ ▼ ┌─────────────────────────────────┐ │ ② 全局默认地址是否可用? │ │ → YES → 路由到全局默认实例 │ │ → NO → 返回 503 │ └─────────────────────────────────┘3.2 路由函数(伪代码)
asyncdefget_remote_base(user,db)->str:""" 路由决策核心 — 每个代理请求的入口 返回该用户应该被转发到的 Hermes 实例地址 """# 优先级 1:用户绑定的实例ifuser.hermes_instance_id:instance=db.query(hermes_instances).get(user.hermes_instance_id)ifinstanceandinstance.status=='active':returninstance.base_url# 实例不存在或已下线,降级# 优先级 2:全局默认地址(兜底)returnGLOBAL_HERMES_BASE_URL3.3 Token 缓存隔离
多实例场景下,同一用户在不同实例上的认证 Token 不同,缓存键需包含实例地址:
改前:cache_key = username 改后:cache_key = {base_url}::{username}这确保了:
- 用户切换实例后自动获取新 Token(旧 Token 自然过期)
- 不同实例的 Token 互不干扰
四、自动分配算法
4.1 分配策略:优先级加权最低负载
新用户注册时,系统自动选择最优实例:
算法流程: 1. 查询所有 status = 'active' 的实例 2. 按 priority DESC 排序(高优先级先考虑) 3. 统计每个实例当前绑定的用户数 4. 过滤出 current_users < max_users 的实例(未满载) 5. 在候选集中选 load_ratio = current_users / max_users 最低的实例 6. 无可分配实例时返回 NULL(用户走全局默认)4.2 分配示例
| 实例 | 优先级 | 当前用户 | 最大用户 | 负载比 | 是否选中 |
|---|---|---|---|---|---|
| hermes-prod-01 | 100 | 18 | 20 | 90% | |
| hermes-prod-02 | 100 | 12 | 20 | 60% | ✅ 最低负载 |
| hermes-prod-03 | 200 | 5 | 20 | 25% | ✅ 高优先级 + 低负载 |
| hermes-prod-04 | 100 | 20 | 20 | 100% | 已满 |
优先级为 200 的 hermes-prod-03 会被优先选中,即使它的绝对负载不是最低。
4.3 何时触发自动分配
| 触发时机 | 行为 |
|---|---|
| 新用户注册 | 自动分配一个可用实例 |
| 管理员手动分配 | 覆盖自动分配结果 |
| 管理员清除绑定 | 用户回退到全局默认 |
五、Hermes Studio 实例部署
5.1 单实例部署(Docker)
每个 Hermes 实例是一个独立的 Docker 容器:
# 实例 A — 端口 30001dockerrun-d\--namehermes-prod-01\-p30001:3000\-v/data/hermes/instance-01:/app/data\--restartunless-stopped\hermes-studio:latest# 实例 B — 端口 30002dockerrun-d\--namehermes-prod-02\-p30002:3000\-v/data/hermes/instance-02:/app/data\--restartunless-stopped\hermes-studio:latest要点:
- 每个实例挂载独立的数据目录 → SQLite 文件互不干扰
- 使用
--restart unless-stopped保证进程级高可用 - 同一台服务器可运行多个实例(端口区分),也可分布在不同服务器
5.2 服务器规划(低成本方案)
┌───────────────────────────────────────────────────────────────┐ │ 服务器 A (4C8G, 云服务器 ~¥200/月) │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Hermes 实例 1 │ │ Hermes 实例 2 │ │ Hermes 实例 3 │ │ │ │ :30001 │ │ :30002 │ │ :30003 │ │ │ │ ≤20 用户 │ │ ≤20 用户 │ │ ≤20 用户 │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Hermes 实例 4 │ │ Hermes 实例 5 │ │ Hermes 实例 6 │ │ │ │ :30004 │ │ :30005 │ │ :30006 │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ 共承载 ~120 用户 │ └───────────────────────────────────────────────────────────────┘容量估算:
- 单实例 Hermes Studio 内存占用约 200-500MB(取决于 Agent 数量和活跃度)
- 4C8G 服务器可安全运行 6-8 个实例
- 每实例推荐 15-25 用户(取决于使用频率)
- 单台服务器可承载 100-150 用户
5.3 Docker Compose 模板(推荐)
version:"3.8"services:hermes-01:image:hermes-studio:latestports:["30001:3000"]volumes:["./data/instance-01:/app/data"]restart:unless-stoppedenvironment:-HERMES_INSTANCE_NAME=hermes-prod-01hermes-02:image:hermes-studio:latestports:["30002:3000"]volumes:["./data/instance-02:/app/data"]restart:unless-stoppedenvironment:-HERMES_INSTANCE_NAME=hermes-prod-02hermes-03:image:hermes-studio:latestports:["30003:3000"]volumes:["./data/instance-03:/app/data"]restart:unless-stoppedenvironment:-HERMES_INSTANCE_NAME=hermes-prod-03# 按需增加更多实例...六、代理层改造要点
代理层是企业后端与 Hermes 实例之间的桥梁,负责将请求路由到正确的实例。
6.1 需要改造的代理接口
| 接口类型 | 说明 | 改造内容 |
|---|---|---|
| REST API 代理 | 所有 Hermes CRUD 操作的透传 | _get_remote_base(user)替代硬编码地址 |
| WebSocket/SSE 代理 | Agent 对话的流式响应 | 连接时使用用户实例地址建立上游连接 |
| 认证代理 | Hermes 登录/Token 获取 | Token 缓存键加实例前缀 |
| MCP 工具调用 | Agent 工具链执行 | 工具调用请求路由到用户实例 |
6.2 代理层改造清单
改前(所有请求 → 同一地址): def get_remote_base() -> str: return settings.HERMES_STUDIO_BASE_URL 改后(按用户路由): async def get_remote_base(user, db) -> str: if user.hermes_instance_id: instance = await db.get(HermesInstance, user.hermes_instance_id) if instance and instance.status == 'active': return instance.base_url return settings.HERMES_STUDIO_BASE_URL # 兜底6.3 所有调用点统一改造
代理层中每个调用 Hermes 的位置都需要:
- 获取当前用户对象(从 JWT/Session 中解析)
- 调用路由函数获取实例地址
- 传递实例地址到下游 HTTP 客户端
需要改造的典型调用点:
| 调用点 | 改造方式 |
|---|---|
| 通用 API 代理(catch-all) | 传入current_user+db,调用get_remote_base |
| 流式对话代理 | 从请求 Header 解析 JWT → 获取用户 → 路由 |
| 认证代理 | 路由到用户实例后登录,Token 缓存键含实例地址 |
| WebSocket 代理 | 用路由后的地址建立上游连接 |
七、管理后台设计
7.1 实例管理页面
面向超级管理员,提供完整的实例生命周期管理:
┌─────────────────────────────────────────────────────────────┐ │ Hermes 实例管理 [+ 新增] │ ├─────────────────────────────────────────────────────────────┤ │ 名称 地址 状态 用户数 负载 操作 │ │ ─────────────────────────────────────────────────────────── │ │ hermes-prod-01 http://...:30001 ✅活跃 18/20 90% 编辑 │ │ hermes-prod-02 http://...:30002 ✅活跃 12/20 60% 编辑 │ │ hermes-prod-03 http://...:30003 🔧维护 5/20 25% 编辑 │ │ hermes-prod-04 http://...:30004 ❌停用 0/20 0% 编辑 │ └─────────────────────────────────────────────────────────────┘功能列表:
| 功能 | 说明 |
|---|---|
| 新增实例 | 填写名称、地址、最大用户数、优先级 |
| 编辑实例 | 修改状态(活跃/维护/停用)、调整容量上限 |
| 删除实例 | 前置校验:实例下必须无用户才能删除 |
| 查看用户 | 查看某实例下绑定的所有用户列表 |
| 预览分配 | 模拟自动分配算法,预览新用户会被分到哪个实例 |
7.2 用户管理页面增强
在现有的用户管理页面中,Hermes 配置弹窗增加实例选择:
┌─────────────────────────────────┐ │ Hermes 账号配置 │ │ │ │ 用户:zhangsan (张三) │ │ │ │ Hermes 实例: │ │ ┌─────────────────────────────┐│ │ │ hermes-prod-02 ││ ← 下拉选择 │ │ 12/20 用户 ✅活跃 ││ │ └─────────────────────────────┘│ │ 留空则使用全局默认实例 │ │ │ │ Hermes 账号:[zhangsan ] │ │ Hermes 密码:[•••••••• ] │ │ │ │ [取消] [保存] │ └─────────────────────────────────┘用户列表表格中可选展示实例名称列,便于管理员一目了然。
八、运维操作流程
8.1 扩容:新增 Hermes 实例
Step 1 部署新实例 docker-compose 增加一个 service → docker compose up -d Step 2 注册到路由表 管理后台 → Hermes 实例管理 → 新增实例 填写:名称、地址、端口、最大用户数、优先级 Step 3 自动生效 后续新注册用户会自动分配到新实例 (无需重启任何服务)8.2 迁移:用户实例切换
Step 1 管理员操作 用户管理 → 找到目标用户 → Hermes 配置 → 切换实例 → 保存 Step 2 即时生效 用户的下一次请求自动路由到新实例 Token 缓存自动刷新(旧 Token 自然过期) Step 3 数据说明 ⚠️ 旧实例上的会话/消息数据不会自动迁移 (这是 SQLite 方案的特性,也是数据隔离的优势) 如用户需要历史数据,可保留旧实例一段时间供查阅8.3 下线:实例退役
Step 1 停止分配 将实例状态改为 maintenance(不再接收新用户) Step 2 迁移用户 查看实例下的用户列表 → 逐个或批量迁移到其他实例 (可通过管理后台操作,也可直接更新数据库) Step 3 确认清空 确认实例下用户数为 0 Step 4 下线 将实例状态改为 inactive 或直接删除实例记录(有用户时删除会被拒绝) Step 5 清理 docker compose 移除对应 service 可选:备份并删除数据目录8.4 批量迁移脚本
当需要大规模迁移时(如服务器更换),可通过 SQL 批量操作:
-- 将实例 A 的所有用户迁移到实例 BUPDATEusersSEThermes_instance_id=(SELECTidFROMhermes_instancesWHEREname='hermes-prod-02')WHEREhermes_instance_id=(SELECTidFROMhermes_instancesWHEREname='hermes-prod-01');九、高可用保障
9.1 多层次容错
层级 1 — 进程级 Docker restart: unless-stopped → 实例崩溃自动重启 层级 2 — 路由级 实例不可达时,代理层返回明确的错误信息 管理员可将故障实例标记为 inactive → 用户切换到其他实例 层级 3 — 全局兜底 所有路由失败时降级到全局默认地址 保证至少有基础服务可用 层级 4 — 数据级 定期备份各实例的 SQLite 文件 单实例数据损坏不影响其他实例9.2 实例健康检查(可选增强)
# 定时任务:每 60 秒检测各实例健康状态asyncdefhealth_check():forinstanceinactive_instances:try:resp=awaithttpx.get(f"{instance.base_url}/api/health",timeout=5)ifresp.status_code!=200:alert(f"实例{instance.name}健康检查异常: HTTP{resp.status_code}")excepthttpx.ConnectError:alert(f"实例{instance.name}无法连接")# 可选:自动将状态改为 maintenance9.3 监控指标
| 指标 | 采集方式 | 告警阈值 |
|---|---|---|
| 实例可用性 | /api/health探活 | 连续 3 次失败 |
| 用户负载比 | 数据库统计 | > 90% |
| 请求延迟 | 代理层日志 | P99 > 10s |
| SQLite 文件大小 | 文件系统监控 | > 500MB |
| 连接错误率 | 代理层统计 | > 5% |
十、安全设计
10.1 网络隔离
┌──────────────────────────────────────────────────┐ │ 公网 / 企业内网 │ │ ┌──────────┐ │ │ │ 前端应用 │ │ │ └─────┬────┘ │ │ │ 仅访问企业后端 │ │ ▼ │ │ ┌──────────────────┐ │ │ │ 企业后端 (代理层) │ ← 唯一入口,JWT 认证 │ │ └─────┬────────────┘ │ │ │ 仅后端可访问 │ │ ▼ │ │ ┌──────────────────────────────┐ │ │ │ Hermes 实例集群 (内网/容器网) │ ← 不暴露公网 │ │ └──────────────────────────────┘ │ └──────────────────────────────────────────────────┘10.2 权限控制
| 操作 | 所需权限 |
|---|---|
| 查看实例列表 | 已登录用户 |
| 查看实例详情 | 已登录用户 |
| 新增/编辑/删除实例 | 超级管理员 |
| 切换用户绑定的实例 | 管理员 |
| 查看实例下的用户 | 管理员 |
10.3 凭证管理
- 每个用户在每个实例上有独立的 Hermes 账号/密码
- 企业后端统一代管凭证,前端不直接暴露
- Token 缓存在服务端,按实例+用户隔离
- 代理转发时自动附加认证信息
十一、成本估算
11.1 基础设施成本
| 用户规模 | 服务器配置 | 月成本(约) | 实例数 |
|---|---|---|---|
| 1-20 人 | 2C4G 云服务器 | ¥100 | 1 |
| 20-60 人 | 4C8G 云服务器 | ¥200 | 3 |
| 60-120 人 | 8C16G 云服务器 | ¥400 | 6 |
| 120-200 人 | 2×4C8G 云服务器 | ¥400 | 10 |
| 200+ 人 | 按需扩展 | 线性增长 | N |
11.2 对比方案
| 方案 | 月成本 | 复杂度 | 数据隔离 | 扩展性 |
|---|---|---|---|---|
| 本方案(多实例 SQLite) | ¥200-400 | ⭐ 极低 | ✅ 天然隔离 | 水平扩展 |
| 单实例 + MySQL | ¥300-500 | ⭐⭐ 中等 | ❌ 需开发 | 需改 Hermes 源码 |
| K8s + 共享存储 | ¥1000+ | ⭐⭐⭐⭐ 高 | 需设计 | 弹性 |
| 每用户独立部署 | ¥极高 | ⭐⭐⭐ 高 | ✅ | 运维成本大 |
十二、落地检查清单
Phase 1:基础设施(1 天)
- 确认当前 Hermes Studio 单实例运行正常
- 确定新实例的部署服务器和端口规划
- 通过 Docker Compose 部署第 2 个实例并验证可用性
Phase 2:数据库改造(0.5 天)
- 创建
hermes_instances路由映射表 - 用户表新增
hermes_instance_id字段 - 执行初始化迁移(将现有全局地址注册为实例)
- 验证现有用户不受影响(向下兼容)
Phase 3:代理层改造(1-2 天)
- 实现路由决策函数
get_remote_base(user, db) - 改造所有代理调用点(REST/WebSocket/认证/MCP)
- Token 缓存键加实例隔离
- 测试:不同用户路由到不同实例
- 测试:未绑定用户走全局默认
Phase 4:管理后台(1 天)
- 实现实例 CRUD API
- 实现自动分配算法 API
- 前端实例管理页面
- 用户配置弹窗增加实例选择
Phase 5:验证上线(0.5 天)
- 管理员手动分配/切换实例 → 验证路由正确
- 新用户注册 → 验证自动分配
- 实例设为 maintenance → 验证不分配新用户
- 实例宕机 → 验证降级到全局默认
- 灰度发布:先迁移少量用户到新实例观察
十三、FAQ
Q1:为什么不直接改 Hermes 源码,换成 MySQL/PostgreSQL?
修改 Hermes 源码意味着每次官方更新都需要合并冲突,维护成本极高。本方案在代理层做路由,对 Hermes 零侵入,可以随时升级 Hermes 版本。
Q2:用户切换实例后,旧数据怎么办?
旧实例上的会话/消息数据保留在旧实例的 SQLite 中。企业可根据业务需求选择:① 保留旧实例一段时间供查阅 ② 通过导出工具迁移关键数据 ③ 直接丢弃(适合会话型场景)。
Q3:能否做到实例间的负载均衡?
可以。自动分配算法在用户注册时选择最优实例,实现了"注册时均衡"。如果需要运行时再均衡,管理员可手动迁移用户。不建议做请求级负载均衡,因为 SQLite 不支持跨实例数据共享。
Q4:单个实例最多支持多少用户?
取决于使用模式。一般建议 15-25 用户/实例。如果用户主要做轻量对话,可以放宽到 30-40;如果频繁使用复杂 Agent 工作流,建议 10-15。
Q5:如何做到零停机升级?
① 部署新版本 Hermes 实例 ② 在路由表中注册新实例 ③ 逐步迁移用户到新实例 ④ 确认所有用户迁移完毕 ⑤ 下线旧实例。全程无需停机。
Q6:前端需要改动吗?
前端无需感知多实例。所有请求走企业后端代理,代理层透明路由。可选优化:前端从后端获取
instance_url后直连实例(需 CORS 配置),减少代理层压力。
十四、架构演进路线
当前阶段(本方案) 未来可选演进 ───────────────── ───────────── 多实例 SQLite + 代理路由 ──► 实例健康检查 + 自动故障转移 │ ├──► 实例用量看板 + Grafana 监控 │ ├──► 实例自动扩缩容(Docker API) │ └──► 数据导出/迁移工具总结:本方案以最小代价将 Hermes Studio 从单实例扩展为多实例分布式架构。企业仅需一张路由映射表 + 用户表一个字段 + 代理层路由改造,即可实现低成本、高可用、数据隔离的企业级 AI Agent 平台。方案对 Hermes Studio 零侵入,可随时跟随官方版本升级。
