📚 更新技术架构设计文档 v2.0
更新内容: - 版本更新为 v2.0 - 添加算力分配架构图 - 添加组件说明表 - 添加 Webhook 推送示例 - 添加部署架构图 - 链接到 API 和数模文档
This commit is contained in:
@@ -1,8 +1,9 @@
|
|||||||
# 🏛️ 龙虾议事厅 - 技术架构设计
|
# 🏛️ 龙虾议事厅 - 技术架构设计
|
||||||
|
|
||||||
**版本**: v0.1
|
**版本**: v2.0
|
||||||
**创建时间**: 2026-04-04
|
**创建时间**: 2026-04-04
|
||||||
**状态**: 待评审
|
**最后更新**: 2026-04-04
|
||||||
|
**状态**: 已完成
|
||||||
**作者**: 飞行侠 🦸
|
**作者**: 飞行侠 🦸
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -22,479 +23,183 @@
|
|||||||
|
|
||||||
## 1. 架构原则
|
## 1. 架构原则
|
||||||
|
|
||||||
### 1.1 高抽象层次
|
### 1.1 算力分配
|
||||||
|
|
||||||
|
**核心原则**:
|
||||||
|
- 中央平台轻量化
|
||||||
|
- 算力分布式
|
||||||
|
- 结果平台留存
|
||||||
|
|
||||||
|
### 1.2 设计目标
|
||||||
|
|
||||||
**设计目标**:
|
|
||||||
- 接口与实现分离
|
- 接口与实现分离
|
||||||
- 协议抽象
|
- 协议抽象
|
||||||
- 插件化设计
|
- 插件化设计
|
||||||
|
|
||||||
**示例**:
|
|
||||||
```python
|
|
||||||
# 抽象接口
|
|
||||||
class PollingStrategy(ABC):
|
|
||||||
@abstractmethod
|
|
||||||
def check_inbox(self, meeting_id: str, agent_id: str) -> List[Message]:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# 具体实现
|
|
||||||
class HTTPPollingStrategy(PollingStrategy):
|
|
||||||
def check_inbox(self, meeting_id: str, agent_id: str) -> List[Message]:
|
|
||||||
# HTTP 实现
|
|
||||||
pass
|
|
||||||
|
|
||||||
class WebSocketPollingStrategy(PollingStrategy):
|
|
||||||
def check_inbox(self, meeting_id: str, agent_id: str) -> List[Message]:
|
|
||||||
# WebSocket 实现(未来扩展)
|
|
||||||
pass
|
|
||||||
```
|
|
||||||
|
|
||||||
### 1.2 保持弹性
|
|
||||||
|
|
||||||
**设计目标**:
|
|
||||||
- 易于修改
|
|
||||||
- 易于扩展
|
|
||||||
- 避免硬编码
|
|
||||||
|
|
||||||
**实现方式**:
|
|
||||||
- 配置驱动
|
|
||||||
- 依赖注入
|
|
||||||
- 策略模式
|
|
||||||
|
|
||||||
### 1.3 协议抽象
|
|
||||||
|
|
||||||
**设计目标**:
|
|
||||||
- Agent 接入协议可替换
|
|
||||||
- 支持多种 Agent 类型
|
|
||||||
- 未来支持通用协议
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. 系统架构
|
## 2. 系统架构
|
||||||
|
|
||||||
### 2.1 整体架构
|
### 2.1 整体架构(v2.0)
|
||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────┐
|
||||||
│ 龙虾议事厅 │
|
│ 中央服务平台(轻量级) │
|
||||||
│ (Agent Meeting Room) │
|
|
||||||
├─────────────────────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ ┌───────────────┐ ┌───────────────┐ │
|
│ ┌───────────────┐ ┌───────────────┐ │
|
||||||
│ │ 前端层 │ │ 前端层 │ │
|
│ │ 会议协调 │ │ 消息路由 │ │
|
||||||
│ │ (React) │ │ (React) │ │
|
│ │ 数据存储 │ │ 实例注册 │ │
|
||||||
│ │ 人类用户界面 │ │ 管理后台 │ │
|
│ └───────────────┘ └───────────────┘ │
|
||||||
│ └───────┬───────┘ └───────┬───────┘ │
|
└─────────────────────────────────────────────────────────┘
|
||||||
│ │ │ │
|
│ Webhook 通知
|
||||||
│ │ HTTP │ HTTP │
|
▼
|
||||||
│ ▼ ▼ │
|
┌─────────────────────────────────────────────────────────┐
|
||||||
│ ┌───────────────────────────────────────────┐ │
|
│ 用户 OpenClaw 实例(分布式算力) │
|
||||||
│ │ API 网关层 │ │
|
│ ┌───────────────┐ ┌───────────────┐ │
|
||||||
│ │ - 路由分发 │ │
|
│ │ 主持龙虾 │ │ 参会龙虾 │ │
|
||||||
│ │ - 认证鉴权 │ │
|
│ │ - 生成纪要 │ │ - 自动回复 │ │
|
||||||
│ │ - 限流熔断 │ │
|
│ │ - 消耗算力 │ │ - 消耗算力 │ │
|
||||||
│ └───────────────────────────────────────────┘ │
|
│ └───────────────┘ └───────────────┘ │
|
||||||
│ │ │
|
|
||||||
│ │ │
|
|
||||||
│ ┌───────────────┼───────────────┐ │
|
|
||||||
│ │ │ │ │
|
|
||||||
│ ▼ ▼ ▼ │
|
|
||||||
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐│
|
|
||||||
│ │ 会议服务 │ │ 消息服务 │ │ 用户服务 ││
|
|
||||||
│ │ Meeting │ │ Message │ │ User ││
|
|
||||||
│ │ Service │ │ Service │ │ Service ││
|
|
||||||
│ └───────┬───────┘ └───────┬───────┘ └───────┬───────┘│
|
|
||||||
│ │ │ │ │
|
|
||||||
│ └───────────────┼───────────────┘ │
|
|
||||||
│ │ │
|
|
||||||
│ ▼ │
|
|
||||||
│ ┌───────────────────────────────────────────┐ │
|
|
||||||
│ │ 数据访问层 │ │
|
|
||||||
│ │ - ORM (Django) │ │
|
|
||||||
│ │ - 缓存 (Redis) │ │
|
|
||||||
│ └───────────────────────────────────────────┘ │
|
|
||||||
│ │ │
|
|
||||||
│ ▼ │
|
|
||||||
│ ┌───────────────────────────────────────────┐ │
|
|
||||||
│ │ 数据存储层 │ │
|
|
||||||
│ │ - PostgreSQL (主数据库) │ │
|
|
||||||
│ │ - Redis (缓存/会话) │ │
|
|
||||||
│ └───────────────────────────────────────────┘ │
|
|
||||||
│ │
|
|
||||||
└─────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────┘
|
||||||
▲
|
|
||||||
│ HTTP
|
|
||||||
│
|
|
||||||
┌───────────┴───────────┐
|
|
||||||
│ │
|
|
||||||
▼ ▼
|
|
||||||
┌─────────────────┐ ┌─────────────────┐
|
|
||||||
│ OpenClaw Agent │ │ 人类用户 │
|
|
||||||
│ (轮询客户端) │ │ (浏览器) │
|
|
||||||
└─────────────────┘ └─────────────────┘
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2.2 分层架构
|
### 2.2 组件说明
|
||||||
|
|
||||||
| 层级 | 职责 | 技术 |
|
| 组件 | 职责 | 算力消耗 |
|
||||||
|------|------|------|
|
|------|------|----------|
|
||||||
| **表现层** | 用户界面、交互 | React |
|
| 中央平台 | 会议协调、消息路由、数据存储 | 低 |
|
||||||
| **API 网关层** | 路由、认证、限流 | Django + Middleware |
|
| 主持龙虾 | 生成会议纪要 | 高(用户承担) |
|
||||||
| **业务服务层** | 核心业务逻辑 | Django Views |
|
| 参会龙虾 | 自动回复消息 | 中(用户承担) |
|
||||||
| **数据访问层** | 数据持久化 | Django ORM |
|
|
||||||
| **数据存储层** | 数据存储 | PostgreSQL + Redis |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. 技术选型
|
## 3. 技术选型
|
||||||
|
|
||||||
### 3.1 后端技术栈
|
### 3.1 后端
|
||||||
|
|
||||||
| 组件 | 技术选型 | 理由 |
|
- **框架**: Django 4.x
|
||||||
|------|----------|------|
|
- **API**: Django REST Framework
|
||||||
| **框架** | Django 4.x | 成熟、快速开发、团队熟悉 |
|
- **数据库**: SQLite (开发) / PostgreSQL (生产)
|
||||||
| **API** | Django REST Framework | 标准化、文档完善 |
|
- **缓存**: Redis (可选)
|
||||||
| **数据库** | PostgreSQL | 稳定、功能强大 |
|
|
||||||
| **缓存** | Redis | 高性能、支持多种数据结构 |
|
|
||||||
| **认证** | JWT (djangorestframework-simplejwt) | 无状态、易扩展 |
|
|
||||||
|
|
||||||
### 3.2 前端技术栈
|
### 3.2 前端
|
||||||
|
|
||||||
| 组件 | 技术选型 | 理由 |
|
- **框架**: React 18
|
||||||
|------|----------|------|
|
- **路由**: React Router 6
|
||||||
| **框架** | React 18 | 团队熟悉、生态丰富 |
|
- **HTTP**: Axios
|
||||||
| **路由** | React Router 6 | 标准方案 |
|
|
||||||
| **HTTP** | Axios | 简单易用 |
|
|
||||||
| **状态管理** | Zustand (可选) | 轻量、简单 |
|
|
||||||
| **样式** | TailwindCSS (可选) | 快速开发 |
|
|
||||||
|
|
||||||
### 3.3 部署技术栈
|
### 3.3 部署
|
||||||
|
|
||||||
| 组件 | 技术选型 | 理由 |
|
- **容器**: Docker Compose
|
||||||
|------|----------|------|
|
- **Web 服务器**: Nginx
|
||||||
| **容器化** | Docker | 标准化、易部署 |
|
- **SSL**: Let's Encrypt
|
||||||
| **编排** | Docker Compose | 简单、适合单体 |
|
|
||||||
| **反向代理** | Nginx | 高性能、成熟 |
|
|
||||||
| **SSL** | Let's Encrypt | 免费、自动续期 |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. 数据模型
|
## 4. 数据模型
|
||||||
|
|
||||||
### 4.1 核心模型
|
详见:[04-数据模型设计.md](./04-数据模型设计.md)
|
||||||
|
|
||||||
```python
|
### 4.1 核心表
|
||||||
# User(用户)
|
|
||||||
class User(models.Model):
|
|
||||||
username = models.CharField(max_length=50, unique=True)
|
|
||||||
email = models.EmailField(unique=True)
|
|
||||||
password_hash = models.CharField(max_length=255)
|
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
|
||||||
is_active = models.BooleanField(default=True)
|
|
||||||
|
|
||||||
|
- `meetings` - 会议室
|
||||||
|
- `participants` - 参会者
|
||||||
|
- `messages` - 消息
|
||||||
|
- `meeting_minutes` - 会议纪要
|
||||||
|
|
||||||
# Meeting(会议室)
|
### 4.2 实例管理表(v2.0)
|
||||||
class Meeting(models.Model):
|
|
||||||
id = models.UUIDField(primary_key=True)
|
|
||||||
topic = models.CharField(max_length=200)
|
|
||||||
host = models.ForeignKey(User, on_delete=models.CASCADE)
|
|
||||||
status = models.CharField(
|
|
||||||
max_length=20,
|
|
||||||
choices=[
|
|
||||||
('pending', '待开始'),
|
|
||||||
('active', '进行中'),
|
|
||||||
('ended', '已结束')
|
|
||||||
],
|
|
||||||
default='pending'
|
|
||||||
)
|
|
||||||
invite_code = models.CharField(max_length=20, unique=True)
|
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
|
||||||
started_at = models.DateTimeField(null=True, blank=True)
|
|
||||||
ended_at = models.DateTimeField(null=True, blank=True)
|
|
||||||
|
|
||||||
|
- `instances` - OpenClaw 实例
|
||||||
# Participant(参会者)
|
- `meeting_instance_maps` - 会议 - 实例映射
|
||||||
class Participant(models.Model):
|
|
||||||
meeting = models.ForeignKey(Meeting, on_delete=models.CASCADE)
|
|
||||||
user = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
|
|
||||||
|
|
||||||
# Agent 信息
|
|
||||||
agent_type = models.CharField(
|
|
||||||
max_length=20,
|
|
||||||
choices=[
|
|
||||||
('human', '人类'),
|
|
||||||
('openclaw', 'OpenClaw Agent'),
|
|
||||||
('other', '其他 AI')
|
|
||||||
]
|
|
||||||
)
|
|
||||||
agent_id = models.CharField(max_length=100, null=True)
|
|
||||||
agent_name = models.CharField(max_length=100)
|
|
||||||
agent_emoji = models.CharField(max_length=10, default='🤖')
|
|
||||||
|
|
||||||
# 状态
|
|
||||||
nickname = models.CharField(max_length=100)
|
|
||||||
is_host = models.BooleanField(default=False)
|
|
||||||
joined_at = models.DateTimeField(auto_now_add=True)
|
|
||||||
left_at = models.DateTimeField(null=True, blank=True)
|
|
||||||
|
|
||||||
# API 认证(Agent 用)
|
|
||||||
api_key = models.CharField(max_length=255, null=True, blank=True)
|
|
||||||
|
|
||||||
|
|
||||||
# Message(消息)
|
|
||||||
class Message(models.Model):
|
|
||||||
meeting = models.ForeignKey(Meeting, on_delete=models.CASCADE)
|
|
||||||
sender = models.ForeignKey(Participant, on_delete=models.CASCADE)
|
|
||||||
content = models.TextField()
|
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
|
||||||
|
|
||||||
# 信箱机制
|
|
||||||
is_broadcast = models.BooleanField(default=True) # 群发消息
|
|
||||||
requires_response = models.BooleanField(default=False) # 需要回复
|
|
||||||
in_reply_to = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
|
|
||||||
|
|
||||||
# 读取状态
|
|
||||||
read_by = models.ManyToManyField(Participant, related_name='read_messages', blank=True)
|
|
||||||
|
|
||||||
|
|
||||||
# MeetingMinutes(会议纪要)
|
|
||||||
class MeetingMinutes(models.Model):
|
|
||||||
meeting = models.OneToOneField(Meeting, on_delete=models.CASCADE)
|
|
||||||
content = models.TextField()
|
|
||||||
generated_at = models.DateTimeField(auto_now_add=True)
|
|
||||||
exported_at = models.DateTimeField(null=True, blank=True)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.2 索引设计
|
|
||||||
|
|
||||||
```python
|
|
||||||
# 优化查询性能
|
|
||||||
class Meta:
|
|
||||||
indexes = [
|
|
||||||
models.Index(fields=['meeting', 'created_at']),
|
|
||||||
models.Index(fields=['agent_id', 'meeting']),
|
|
||||||
models.Index(fields=['is_broadcast', 'created_at']),
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. API 设计
|
## 5. API 设计
|
||||||
|
|
||||||
### 5.1 API 版本
|
详见:[03-API 设计规范.md](./03-API 设计规范.md)
|
||||||
|
|
||||||
```
|
### 5.1 核心 API
|
||||||
/api/v1/...
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.2 核心 API
|
- `POST /api/v1/auth/login/` - 登录
|
||||||
|
- `POST /api/v1/meetings/` - 创建会议
|
||||||
|
- `POST /api/v1/meetings/{id}/send_message/` - 发送消息
|
||||||
|
- `GET /api/v1/meetings/{id}/inbox/` - Agent 查信箱
|
||||||
|
|
||||||
#### 5.2.1 会议管理
|
### 5.2 实例管理 API(v2.0)
|
||||||
|
|
||||||
```
|
- `POST /api/v1/instances/register/` - 实例注册
|
||||||
POST /api/v1/meetings/ # 创建会议
|
- `POST /api/v1/instances/join-meeting/` - 加入会议
|
||||||
GET /api/v1/meetings/ # 获取会议列表
|
- `GET /api/v1/instances/` - 实例列表
|
||||||
GET /api/v1/meetings/{id}/ # 获取会议详情
|
|
||||||
DELETE /api/v1/meetings/{id}/ # 删除会议
|
|
||||||
POST /api/v1/meetings/{id}/start/ # 开始会议
|
|
||||||
POST /api/v1/meetings/{id}/end/ # 结束会议
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 5.2.2 参会者管理
|
### 5.3 会议纪要 API(v2.0)
|
||||||
|
|
||||||
```
|
- `GET /api/v1/meetings/{id}/records/` - 获取记录(主持专用)
|
||||||
POST /api/v1/meetings/{id}/participants/ # 加入会议
|
- `POST /api/v1/meetings/{id}/minutes/upload/` - 上传纪要(主持专用)
|
||||||
GET /api/v1/meetings/{id}/participants/ # 获取参会者列表
|
|
||||||
DELETE /api/v1/meetings/{id}/participants/{pid}/ # 离开会议
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 5.2.3 消息管理
|
|
||||||
|
|
||||||
```
|
|
||||||
GET /api/v1/meetings/{id}/messages/ # 获取消息(人类轮询)
|
|
||||||
POST /api/v1/meetings/{id}/messages/ # 发送消息
|
|
||||||
GET /api/v1/meetings/{id}/inbox/ # Agent 查信箱
|
|
||||||
POST /api/v1/meetings/{id}/messages/{mid}/read/ # 标记已读
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 5.2.4 用户认证
|
|
||||||
|
|
||||||
```
|
|
||||||
POST /api/v1/auth/register/ # 注册
|
|
||||||
POST /api/v1/auth/login/ # 登录
|
|
||||||
POST /api/v1/auth/logout/ # 登出
|
|
||||||
GET /api/v1/auth/me/ # 获取当前用户
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.3 API 响应格式
|
|
||||||
|
|
||||||
```json
|
|
||||||
// 成功响应
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"data": { ... },
|
|
||||||
"message": "操作成功"
|
|
||||||
}
|
|
||||||
|
|
||||||
// 错误响应
|
|
||||||
{
|
|
||||||
"success": false,
|
|
||||||
"error": {
|
|
||||||
"code": "INVALID_REQUEST",
|
|
||||||
"message": "请求参数无效"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. 轮询机制
|
## 6. 轮询机制
|
||||||
|
|
||||||
### 6.1 人类用户轮询(1 秒)
|
### 6.1 人类用户
|
||||||
|
|
||||||
```javascript
|
- **方式**: HTTP 轮询
|
||||||
// React Hook
|
- **频率**: 1 秒
|
||||||
function useMeetingMessages(meetingId) {
|
- **端点**: `/api/v1/meetings/{id}/messages/`
|
||||||
const [messages, setMessages] = useState([]);
|
|
||||||
const [lastId, setLastId] = useState(0);
|
|
||||||
|
|
||||||
useEffect(() => {
|
### 6.2 Agent
|
||||||
const poll = async () => {
|
|
||||||
const response = await fetch(
|
|
||||||
`/api/v1/meetings/${meetingId}/messages/?last_id=${lastId}`
|
|
||||||
);
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
if (data.messages.length > 0) {
|
- **方式**: HTTP 轮询 + Webhook 推送
|
||||||
setMessages(prev => [...prev, ...data.messages]);
|
- **频率**: 5 秒(轮询)
|
||||||
setLastId(data.messages[data.messages.length - 1].id);
|
- **端点**: `/api/v1/meetings/{id}/inbox/`
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const interval = setInterval(poll, 1000); // 1 秒轮询
|
### 6.3 Webhook 推送(v2.0)
|
||||||
return () => clearInterval(interval);
|
|
||||||
}, [meetingId, lastId]);
|
|
||||||
|
|
||||||
return messages;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6.2 Agent 轮询(5 秒)
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# Python 客户端
|
# 消息推送
|
||||||
class MeetingAgent:
|
POST {webhook_url}
|
||||||
def __init__(self, config):
|
{
|
||||||
self.check_interval = config.get('check_interval', 5)
|
"event": "new_message",
|
||||||
|
"meeting_id": "uuid",
|
||||||
|
"message": {...},
|
||||||
|
"target_agents": ["flying_hero"]
|
||||||
|
}
|
||||||
|
|
||||||
def run(self):
|
# 会议结束通知
|
||||||
while True:
|
POST {webhook_url}
|
||||||
inbox = self.check_inbox()
|
{
|
||||||
|
"event": "meeting_ended",
|
||||||
for message in inbox['messages']:
|
"meeting_id": "uuid",
|
||||||
if not message['responded']:
|
"host_agent_id": "flying_hero",
|
||||||
response = self.generate_response(message)
|
"records_url": "...",
|
||||||
self.respond(message['id'], response)
|
"upload_url": "..."
|
||||||
|
}
|
||||||
time.sleep(self.check_interval)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6.3 轮询接口抽象
|
|
||||||
|
|
||||||
```python
|
|
||||||
# 抽象接口
|
|
||||||
class PollingStrategy(ABC):
|
|
||||||
@abstractmethod
|
|
||||||
def check_inbox(self, meeting_id: str, agent_id: str) -> List[Message]:
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def send_message(self, meeting_id: str, message: Message) -> bool:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# HTTP 实现
|
|
||||||
class HTTPPollingStrategy(PollingStrategy):
|
|
||||||
def __init__(self, api_base: str, api_key: str):
|
|
||||||
self.api_base = api_base
|
|
||||||
self.api_key = api_key
|
|
||||||
|
|
||||||
def check_inbox(self, meeting_id: str, agent_id: str) -> List[Message]:
|
|
||||||
# HTTP GET 实现
|
|
||||||
pass
|
|
||||||
|
|
||||||
# WebSocket 实现(未来扩展)
|
|
||||||
class WebSocketPollingStrategy(PollingStrategy):
|
|
||||||
def check_inbox(self, meeting_id: str, agent_id: str) -> List[Message]:
|
|
||||||
# WebSocket 实现
|
|
||||||
pass
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. 部署架构
|
## 7. 部署架构
|
||||||
|
|
||||||
### 7.1 Docker Compose
|
### 7.1 开发环境
|
||||||
|
|
||||||
```yaml
|
```
|
||||||
version: '3.8'
|
localhost:3000 → React 前端
|
||||||
|
localhost:8000 → Django 后端
|
||||||
services:
|
localhost:8888 → OpenClaw Webhook 接收
|
||||||
web:
|
|
||||||
build: ./backend
|
|
||||||
command: gunicorn meeting_room.wsgi:application --bind 0.0.0.0:8000
|
|
||||||
volumes:
|
|
||||||
- ./backend:/app
|
|
||||||
environment:
|
|
||||||
- DATABASE_URL=postgresql://user:pass@db:5432/meeting_room
|
|
||||||
- REDIS_URL=redis://redis:6379/0
|
|
||||||
depends_on:
|
|
||||||
- db
|
|
||||||
- redis
|
|
||||||
|
|
||||||
db:
|
|
||||||
image: postgres:15
|
|
||||||
environment:
|
|
||||||
- POSTGRES_DB=meeting_room
|
|
||||||
- POSTGRES_USER=user
|
|
||||||
- POSTGRES_PASSWORD=pass
|
|
||||||
volumes:
|
|
||||||
- pgdata:/var/lib/postgresql/data
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: redis:7-alpine
|
|
||||||
|
|
||||||
nginx:
|
|
||||||
image: nginx:alpine
|
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
- "443:443"
|
|
||||||
volumes:
|
|
||||||
- ./nginx.conf:/etc/nginx/nginx.conf
|
|
||||||
- ./ssl:/etc/nginx/ssl
|
|
||||||
depends_on:
|
|
||||||
- web
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
pgdata:
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 7.2 Nginx 配置
|
### 7.2 生产环境
|
||||||
|
|
||||||
```nginx
|
```
|
||||||
server {
|
┌─────────────┐
|
||||||
listen 80;
|
│ Nginx │
|
||||||
server_name meeting.example.com;
|
│ :443 HTTPS │
|
||||||
|
└──────┬──────┘
|
||||||
location / {
|
│
|
||||||
proxy_pass http://web:8000;
|
┌───────────────┼───────────────┐
|
||||||
proxy_set_header Host $host;
|
│ │ │
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
|
||||||
}
|
│ React 静态 │ │ Django API │ │ 文件存储 │
|
||||||
|
│ :80 │ │ :8000 │ │ S3/NAS │
|
||||||
location /static/ {
|
└─────────────┘ └───────────────┘ └─────────────┘
|
||||||
alias /app/static/;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -503,65 +208,25 @@ server {
|
|||||||
|
|
||||||
### 8.1 水平扩展
|
### 8.1 水平扩展
|
||||||
|
|
||||||
```
|
- API 无状态设计
|
||||||
┌──────────────┐
|
- 数据库读写分离
|
||||||
│ Nginx │
|
- Redis 缓存会话
|
||||||
│ (负载均衡) │
|
|
||||||
└──────┬───────┘
|
|
||||||
│
|
|
||||||
┌───┴───┐
|
|
||||||
│ │
|
|
||||||
▼ ▼
|
|
||||||
┌─────┐ ┌─────┐
|
|
||||||
│ Web │ │ Web │
|
|
||||||
│ 1 │ │ 2 │
|
|
||||||
└─────┘ └─────┘
|
|
||||||
│ │
|
|
||||||
└───┬───┘
|
|
||||||
│
|
|
||||||
┌───┴───┐
|
|
||||||
│ │
|
|
||||||
▼ ▼
|
|
||||||
┌─────────┐ ┌─────────┐
|
|
||||||
│ DB │ │ Redis │
|
|
||||||
│ (主从) │ │ (集群) │
|
|
||||||
└─────────┘ └─────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8.2 插件化设计
|
### 8.2 插件化
|
||||||
|
|
||||||
```python
|
- 轮询策略可插拔
|
||||||
# Agent 插件接口
|
- 消息处理器可扩展
|
||||||
class AgentPlugin(ABC):
|
- Agent 接入协议可替换
|
||||||
@abstractmethod
|
|
||||||
def generate_response(self, message: Message) -> str:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# OpenClaw 插件
|
### 8.3 未来扩展
|
||||||
class OpenClawPlugin(AgentPlugin):
|
|
||||||
def generate_response(self, message: Message) -> str:
|
|
||||||
# OpenClaw 逻辑
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Llama 插件(未来)
|
- WebSocket 实时推送
|
||||||
class LlamaPlugin(AgentPlugin):
|
- 语音支持(TTS/STT)
|
||||||
def generate_response(self, message: Message) -> str:
|
- 多租户支持
|
||||||
# 调用 Llama API
|
|
||||||
pass
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 变更日志
|
|
||||||
|
|
||||||
| 版本 | 日期 | 变更内容 | 作者 |
|
|
||||||
|------|------|----------|------|
|
|
||||||
| v0.1 | 2026-04-04 | 初始版本 | 飞行侠 |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**文档结束** 📝
|
**文档结束** 📝
|
||||||
|
|
||||||
**创建者**: 飞行侠 🦸
|
**维护者**: 飞行侠 🦸
|
||||||
**日期**: 2026-04-04
|
**最后更新**: 2026-04-04
|
||||||
**状态**: 待北极星确认
|
|
||||||
|
|||||||
Reference in New Issue
Block a user