Files
chongming-core/README.md
T

359 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Chongming-Zenoh
基于 **FastAPI + Zenoh + MQTT + Vue 3** 的**配置驱动微服务网关平台**。
核心理念:通过 TOML 配置文件定义 RPC 端点,自动生成 Pydantic 模型,同时暴露 **HTTP** 和 **MQTT** 双通道。
底层通过 Zenoh 分布式消息协议进行 RPC 通信,Worker 插件可独立开发、热加载、水平扩展。
---
## 核心特性
- **FastAPI + Uvicorn**:高性能异步 Web 框架,自动生成 OpenAPI 文档
- **Zenoh 服务发现**:基于 Zenoh liveliness 的 Worker 注册与 RPC 调用,负载均衡 + 超时重试
- **MQTT 集成**:内嵌 amqtt Broker,MQTT 消息自动桥接到 Worker 插件,支持请求/响应与单向上报
- **动态路由生成**:扫描 `config/workers` TOML 配置自动生成 HTTP 路由,`[MQTT]` 节单独处理
- **Worker 框架**:`@rpc_method` 装饰器定义 RPC 方法,自动参数解析与 Pydantic 模型绑定
- **自动化模型生成**:`gen_models` 脚本根据 TOML 配置生成请求/响应 Pydantic 模型(含 MQTT)
- **JWT 鉴权**:Rust 实现,路由级别 `auth_required` 控制
- **Argon2id 密码哈希**:Rust 实现的高性能密码安全方案
- **文件存储**:本地文件系统上传/下载
- **构建打包**:支持 PyInstaller / Nuitka 一键打包为独立可执行文件
- **Vue 3 前端**:Element Plus UI、Pinia 状态管理、自动生成类型安全的 API 客户端
---
## 项目结构
```text
chongming-zenoh/
├── config.toml # 应用主配置(含 MQTT、Zenoh、DB 等)
├── pyproject.toml # 项目依赖与工具配置
├── config/ # 配置文件目录
│ ├── zenoh_config.json5 # Zenoh 会话配置
│ └── workers/ # Worker 路由定义(TOML)
│ ├── config.toml # 插件注册列表
│ ├── auth/ # 鉴权插件(login / register / me / …)
│ ├── doubao/ # 豆包视觉理解插件
│ └── example/ # 示例插件(add / heartbeat / …)
├── src/
│ ├── chongming/ # 核心应用
│ │ ├── app/
│ │ │ ├── core/ # WorkerManager, RouteGenerator, MQTTBridge, auth
│ │ │ └── routes/ # 内置路由(存储上传等)
│ │ └── scripts/ # build, gen_models
│ ├── chongming-web/ # Vue 3 前端
│ │ └── src/
│ │ ├── api/generated/ # 自动生成 API 客户端
│ │ ├── views/ # 页面组件
│ │ └── router/ # Vue Router 配置
│ └── plugins/ # Worker 插件源码
│ ├── auth/ # JWT 鉴权
│ ├── doubao/ # 豆包 AI
│ └── example/ # 示例(含 MQTT 端点)
├── utils/ # 7 个独立工具包
│ ├── config/ database/ jwt/ lock/
│ ├── password/ request/ worker/
├── test_mqtt_e2e.py # MQTT 端到端测试脚本
├── publisher.py # MQTT 发布示例
├── subscriber.py # MQTT 订阅示例
├── test_amqtt.py # amqtt Broker 独立测试
├── data/storage/chongming/ # 本地数据存储
├── logs/ # 日志目录
└── resources/ # 模块银行打包资源
```
---
## 快速开始
### 环境要求
- Python >= 3.12
- Rust 工具链(用于编译 `jwt` / `password` 扩展)
- Node.js >= 22(前端开发)
- [uv](https://docs.astral.sh/uv/) 包管理器
### 安装与启动
```bash
uv sync # 安装依赖 + 编译 Rust 扩展
uv run serve # 启动服务(开发模式,热重载)
```
服务启动后可用:
| 通道 | 地址 | 说明 |
| ------- | ---------------------------- | ------------------------ |
| HTTP | `http://localhost:8000` | REST API + Swagger 文档 |
| MQTT | `mqtt://localhost:1883` | 内嵌 Broker,Worker 桥接 |
| Swagger | `http://localhost:8000/docs` | OpenAPI 文档 |
### 前端开发
```bash
cd src/chongming-web
npm install && npm run dev # http://localhost:5173
```
---
## 架构与数据流
```mermaid
graph TB
HTTP[HTTP 客户端] -->|REST API| FastAPI[FastAPI 路由<br/>自动生成]
MQTT[MQTT 客户端] -->|chongming/+/+| Bridge[MQTT Bridge<br/>内嵌 Broker]
FastAPI --> WM[WorkerManager]
Bridge --> WM
WM -->|Zenoh Query| W1[Worker 副本 1]
WM -->|负载均衡| W2[Worker 副本 2]
WM -->|超时重试| W3[Worker 副本 N]
W1 & W2 & W3 -->|插件业务逻辑| DB[(SQLite)]
W1 & W2 & W3 -->|AI 调用| AI[豆包 API]
```
启动流程:
```
uv run serve → FastAPI lifespan:
1. setup_storage() — 本地文件系统存储
2. setup_zenoh() — Zenoh peer 会话
3. setup_worker_manager() — WorkerManager + liveliness 刷新
4. load_workers() — 动态 import 插件 → 启动 Worker 协程
5. register_routes() — 扫描 config/workers/ 生成 HTTP 路由
6. setup_mqtt() — 内嵌 Broker + MQTT→Worker 桥接
```
---
## MQTT 集成
### 协议约定
| 方向 | Topic | Payload |
| ---- | -------------------------------- | ------------------------------------------ |
| 请求 | `chongming/<type>/<op>` | `{"_method":"MQTT","param1":"value1",...}` |
| 响应 | `chongming/<type>/<op>/response` | 由 Worker 返回(`None` 则跳过) |
### 快速测试
```bash
# 终端 1: 启动服务
uv run serve
# 终端 2: 端到端测试
python test_mqtt_e2e.py
# 或手动测试
python subscriber.py # 监听所有响应
python publisher.py example add '{"a":3,"b":5,"_method":"MQTT"}' # 有响应
python publisher.py example heartbeat '{"worker_id":"node-1","_method":"MQTT"}' # 无响应
```
### 无响应模式(心跳上报等)
Worker 返回 `None` 时,MQTT Bridge 自动跳过响应发布:
```python
@rpc_method(subject="example.heartbeat", method="MQTT")
async def heartbeat(worker_id: str = "") -> None:
return None # Bridge 跳过发布
```
### 配置
```toml
# config.toml — 按环境区分
[development.mqtt]
enabled = true # false 禁用 MQTT
host = "localhost"
port = 1883
[development.mqtt.broker]
# 可选:amqtt Broker 高级参数
```
---
## 开发指南
### 端点类型说明
TOML 文件中的节类型决定端点暴露方式:
| 节类型 | HTTP 路由 | OpenAPI | MQTT | 请求模型命名 | 备注 |
| -------- | --------- | ------- | ---- | ------------------------- | ------------------- |
| `[GET]` | ✅ | ✅ | ✅ | `XxxGetRequest/Response` | |
| `[POST]` | ✅ | ✅ | ✅ | `XxxPostRequest/Response` | |
| `[MQTT]` | ❌ | ❌ | ✅ | `XxxMqttRequest` | 无 `response_model` |
```toml
# config/workers/example/add.toml
[GET]
summary = "Add via HTTP GET"
params = ["a: float", "b: float"]
[POST]
summary = "Add via HTTP POST"
params = ["a: float", "b: float"]
[MQTT]
summary = "Add via MQTT"
params = ["a: float", "b: float"]
```
### 两种路由注册方式
本项目支持两种路由注册方式,根据场景选用:
#### 方式一:TOML 动态路由(标准 JSON 端点)
通过 `config/workers/<插件>/*.toml` 定义 `[GET]` / `[POST]` 节,网关自动生成 FastAPI 路由。
适用于参数和响应可被 Pydantic 模型描述的标准 JSON 接口。
- 路由生成流程:`TOML 配置 → 自动生成 Pydantic 模型 → 注册 FastAPI 路由`
- 底层 RPC:`FastAPI 路由 → WorkerManager.call() → Zenoh Query → Worker @rpc_method → 响应`
```toml
# config/workers/example/add.toml
[GET]
summary = "加法"
params = ["a: float", "b: float"]
[GET.response_model]
result = { type = "float", required = true }
```
#### 方式二:插件自定义路由(特殊端点)
当端点无法用 TOML 描述时(如 `multipart/form-data` 文件上传),插件可在模块顶层暴露
一个 `APIRouter` 实例,网关在 `load_workers()` 阶段自动发现并注册(无需修改网关代码)。
**约定**:插件模块(`__init__.py`)需导入并暴露一个名为 `router` 的 `APIRouter` 实例:
```python
# src/plugins/<name>/__init__.py
from .routes import router # 暴露给网关自动发现
```
```python
# src/plugins/<name>/routes.py
from fastapi import APIRouter, UploadFile, File, Form
router = APIRouter(prefix="/<prefix>", tags=["<worker_type>"])
@router.post("/upload")
async def upload(
file: UploadFile = File(...),
param1: str = Form(...),
):
...
return {"result": "ok"}
```
- 全局前缀(如 `/api/v1`)由网关自动注入,插件无需关心
- tags 应与 TOML 自动生成的端点保持一致(使用 worker_type)
- TOML 配置中对应端点应设 `internal = true`,避免重复注册
### HTTP / MQTT 调用路径
同一端点通过**不同通道**到达 Worker 的路径对比:
| 通道 | 调用路径 | 适用场景 |
| -------- | --------------------------------------------------------------------------------------- | ------------------------------ |
| **HTTP** | `客户端 → FastAPI 路由 → WorkerManager.call() → Zenoh Query → Worker` | REST API、Web 前端、文件上传 |
| **MQTT** | `MQTT 客户端 → 内嵌 Broker → MQTT Bridge → WorkerManager.call() → Zenoh Query → Worker` | IoT 设备上报、心跳、低带宽环境 |
HTTP 和 MQTT 最终都通过 Zenoh RPC 调用 Worker 的 `@rpc_method` 处理函数,业务逻辑完全共享。
```
┌──────────────────────────────┐
│ WorkerManager │
│ (负载均衡 / 超时重试) │
└──────────┬───────────────────┘
│ Zenoh Query
┌──────────▼───────────────────┐
│ Worker 副本池 │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ W1 │ │ W2 │ │ W3 │ │
│ └──┬──┘ └──┬──┘ └──┬──┘ │
│ │ │ │ │
│ @rpc_method 处理函数 │
└────────────────────────────────┘
HTTP 请求到达 ▲ ▲ MQTT 消息到达
┌───────┘ └───────┐
FastAPI 路由(TOML 自动生成) MQTT Bridge
插件自定义路由(router 约定) (chongming/+/+)
```
### 添加新 Worker 插件
1. 创建 `src/plugins/<name>/` — `__init__.py`, `global_var.py`, `router/`, `models/`
2. 注册到 `config/workers/config.toml`
3. 创建 `config/workers/<name>/*.toml` 端点定义
4. `uv run gen_models config/workers/<name>/ src/plugins/<name>/`
5. 实现 `router/<op>.py`,引用生成的模型
6. 更新 `router/__init__.py` 导入
详见 [插件开发指南](src/plugins/README.md)。
### 常用命令
```bash
uv run serve # 启动开发服务器
uv run python -m chongming.scripts.gen_models # 生成 Pydantic 模型
uv run build pyinstaller # PyInstaller 打包
uv run build nuitka # Nuitka 打包
uv pip install -e utils/<name> # 安装/更新工具包子包
```
### TOML 配置字段速查
| 字段 | 位置 | 说明 |
| -------------------- | --------------------- | --------------------------------------- |
| `count` | `workers/config.toml` | Worker 副本数 |
| `router_prefix` | `<插件>/config.toml` | API 路由前缀 |
| `defaults.timeout` | `<插件>/config.toml` | 默认超时(秒) |
| `defaults.cacheable` | `<插件>/config.toml` | 是否缓存 RPC 结果 |
| `params` | `<操作>.toml` | 参数列表(`"name: type"` 格式) |
| `auth_required` | `<操作>.toml` | 是否需要 JWT 鉴权 |
| `internal` | `<操作>.toml` | `true` 则仅限内部 RPC,不注册 HTTP 路由 |
| `cacheable` | `<操作>.toml` | 端点是否可缓存 |
| `summary` | `<操作>.toml` | 端点描述(用于 OpenAPI / 日志) |
---
## 内置插件
| 插件 | HTTP 前缀 | MQTT 主题前缀 | 说明 |
| ------------------------ | --------- | ------------------------ | ------------------------------------ |
| **auth** | `/auth` | `auth.*` | 注册、登录、JWT 鉴权、个人信息、改密 |
| **doubao** | `/doubao` | `doubao.*` | 火山引擎豆包视觉理解模型 |
| **example** | `/calc` | `example.*` | 四则运算 + 访问计数 + MQTT 心跳示例 |
| **aibox_sophon_adapter** | `/aibox` | `aibox_sophon_adapter.*` | AI Box 设备心跳适配 + 视频上传 |
---
## 工具包
| 包名 | 说明 | 技术栈 |
| -------------------- | --------------------------------------------- | ----------- |
| `chongming-config` | TOML 配置加载、TypedDict 类型定义 | Python |
| `chongming-database` | 异步 SQLite(aiosqlite + SQLModel) | Python |
| `chongming-jwt` | JWT 编码/验证(HS256/384/512, RS256/384/512) | Rust + PyO3 |
| `chongming-password` | Argon2id 密码哈希与验证 | Rust + PyO3 |
| `chongming-request` | Zenoh Worker 客户端(负载均衡、超时重试) | Python |
| `chongming-worker` | Worker 框架核心(`@rpc_method`、运行时) | Python |
---
## 更多文档
- [配置说明](config/README.md)
- [插件开发指南](src/plugins/README.md)
- [前端开发指南](src/chongming-web/README.md)
- [Worker 框架](utils/worker/README.md)