# {{app_name}} 基于 **chongming 网关**的宿主项目(由 chongming 项目模板初始化): - **网关本体**:`chongming-gateway` 包(FastAPI + Zenoh),从私有源按版本依赖,不在本仓库 - **本仓库负责**:宿主骨架(`public/`,可执行文件入口)、内置插件(`src/plugins/`)、 配置(`config/`)、构建与交付产物 ## 快速开始 ```bash uv sync # 同步依赖(网关与 chongming-* 工具包从私有源安装) uv run serve # 启动服务(开发模式,热重载) ``` | 通道 | 地址 | 说明 | | ---- | ---- | ---- | | HTTP | `http://localhost:8000` | REST API(`config.toml` 的 `prefix` 为 `/api/v1`) | | Swagger | `http://localhost:8000/docs` | OpenAPI 交互文档(调试模式开启) | | MQTT | `mqtt://localhost:1883` | 内嵌 Broker(`use_embedded_broker = true`) | 开箱示例(内置插件 `example`): ```bash curl 'http://localhost:8000/api/v1/example/hello?name=world' # {"message":"hello, world!","count":1} curl -X POST http://localhost:8000/api/v1/example/hello \ -H 'Content-Type: application/json' -d '{"name":"world"}' ``` ## 目录结构 ```text ├── config.toml # 应用主配置(环境、服务器、缓存、MQTT、打包清单) ├── pyproject.toml # 宿主依赖(chongming-gateway 等) ├── plugins_deps.toml # 内置插件专属依赖(打包收集用) ├── public/ # 可执行文件打包骨架:main.py / server.py / utils / 运行时 config.toml ├── config/ # 项目配置 │ ├── zenoh_config.json5 # Zenoh 会话配置 │ └── workers// # 插件注册(config.toml)与端点定义(.toml) ├── src/plugins/ # 内置插件源码(inline,网关进程内加载) │ └── example/ # 最小示例:Plugin 生命周期 + @rpc_method + 模型 ├── workers/ # 进程插件本地开发目录(external,不入库;生产独立容器) └── resources/ # 构建产物(plugins.mbank 等) ``` ## 新增插件 / 端点 ```bash uv run gen_plugin [operation ...] # 一键生成内置插件骨架(含 config/ 注册与端点 TOML) uv run gen_models config/workers/ src/plugins/ # 改 TOML 后重新生成模型 ``` 手写流程(参考 `src/plugins/example/` 的四个文件): 1. `config/workers//config.toml`:`[workers]` 注册(`type` / `module = "plugins."` / `factory` / `cleanup` / `count` / `load_mode`)+ `[worker]` 路由前缀与端点默认值 2. `config/workers//.toml`:端点定义(`[GET]` / `[POST]` / `[MQTT]` 分节 + `params` + `response_model`) 3. `uv run gen_models ...` 生成 `models/pydantic.py` 4. `router/.py`:`@rpc_method(subject=".", method=...)` 实现; 在 `router/__init__.py` 导入 启动时网关会做**契约校验**:TOML 里的 HTTP 路由缺少对应 `@rpc_method` 会直接启动失败。 进程插件(`load_mode = "external"`,独立进程/容器部署): ```bash uv run gen_plugin --process # 生成自包含插件项目 workers// cd workers/ && uv run chongming-worker --type # 本地调试 uv run build_plugin # 打包 → dist/.zip(容器入口 start.sh) ``` ## 配置 - **应用配置**:根 `config.toml`(开发读 `[development]`;`[default].env` 切换环境) - **插件注册与端点**:`config/workers//config.toml`、`config/workers//.toml` - **Zenoh**:`config/zenoh_config.json5` 常用开关: | 配置 | 位置 | 说明 | | ---- | ---- | ---- | | `cache.backend` | 根 `config.toml` | `sqlite`(单机默认)/ `redis`(多实例共享) | | `mqtt.use_embedded_broker` | 根 `config.toml` | `true` 自带 Broker;`false` 连外部 Broker | | `workers.count` | 插件 `config.toml` | 副本数(多网关共享 cache 时按在线网关分摊) | | `workers.load_mode` | 插件 `config.toml` | `inline`(默认)/ `external` | ## 打包与部署 ```bash uv run build pyinstaller # 打包可执行文件 → build/chongming uv run build nuitka # Nuitka 打包(Linux 需宿主 patchelf) uv run build --encrypt --license # 对外分发:加密插件模块 + 注入授权公钥 uv run build --only mbank # 只重新生成 plugins.mbank(插件热更新只需替换该文件) ``` - `--encrypt --license` 需要厂商授权公钥(未提供会直接构建失败):先 `uv run chongming-license keygen -o license_private.pem` 生成密钥对(一次性;私钥离线保管, 绝不进仓库/产物),把输出的公钥写入根目录 `license_public.key`(或用 `CHONGMING_LICENSE_PUBKEY` / `CHONGMING_LICENSE_PUBKEY_FILE` 指定),再构建 - 无前端时跳过 vue 步骤:`uv run build pyinstaller --only mbank,prepare,pack` (`--only` 对**所有**步骤划界:加密构建还要显式带上 `obfuscate`,如 `uv run build --encrypt --license --only mbank,prepare,obfuscate,pack,license_guard`, 否则 PyArmor 混淆会被静默跳过) - 插件代码在 `plugins.mbank` 里 → 换文件即可热更新;**网关本体是普通依赖** → 升级网关需改 `pyproject.toml` 版本(或 `uv lock --upgrade-package chongming-gateway`) 并重新 `uv run build` - 新增插件用了新第三方包时:`pyproject.toml` 追加依赖 + `plugins_deps.toml` 声明 (否则打包产物运行到加载插件时才报 ImportError) ## 进一步文档 网关主体、插件开发、进程插件、Worker 运维等完整文档在 chongming-core(chongming-zenoh)仓库的 `README.md` 与 `docs/`;本仓库的管理端点、实例定向、MQTT 协议等用法与之一致。