模块拆分 init

This commit is contained in:
2026-08-27 14:53:22 +08:00
parent e6ddea33a2
commit 3ea59551db
15 changed files with 2191 additions and 1399 deletions
+908
View File
@@ -0,0 +1,908 @@
# geMoldInsight 后端模块化重构蓝图
> 目标:在**同一 Git 仓库**、**同一数据库**前提下,将当前代码结构整理为**可独立部署的多模块架构**,明确 gemold、inventory、frontend 的边界与演进路径。本文档是后续实施的权威蓝图,不是历史记录。
---
## 1. 背景与目标
当前项目已经从早期单体演进为“双应用 + 共享层”的形态:
- 业务模块:`src/moldinsight/`、`src/inventory/`
- 共享层:`src/shared/`
- 部署入口:`src/entrypoints/moldinsight.py`、`src/entrypoints/inventory.py`
- 前端工程:`frontend/`
从代码现状看,`moldinsight` 与 `inventory` 已基本无直接互引,说明模块边界已经初步形成;但同时,数据库模型、认证、配置、应用工厂等仍集中在 `shared/`,导致当前更接近“**模块化中的单体**”,而不是“**可独立部署的模块化单体**”。
本次蓝图的目标不是拆库、拆仓、微服务化,而是:
1. 保持**单仓库(monorepo)**
2. 保持**单数据库**
3. 将后端正式整理为多个模块:
- **gemold**(模具分析 / moldinsight)
- **inventory**(进销存)
- **identity / platform**(共享基础设施与认证)
4. 保持前端为**独立模块工程**,并增强其对多部署模式的兼容
5. 支持三种部署模式:
- **unified**:gemold + inventory 同时部署
- **gemold-only**:仅部署 gemold
- **inventory-only**:仅部署 inventory
---
## 2. 范围与非目标
### 2.1 本次蓝图覆盖范围
- 后端模块边界
- 共享层职责重新定义
- 单数据库下的模型归属与表所有权
- 独立部署模式设计
- 前端 API 边界强化策略
- 分阶段迁移路径
- 风险与验证方法
### 2.2 非目标
本蓝图**不包含**以下方向:
- 多 Git 仓库拆分
- 多数据库拆分
- 分布式微服务重构
- 全量 DDD 重写
- 全量前端重构
- 事件驱动或消息总线主导的跨服务通信改造
换句话说,目标架构是:
> **单仓库 + 单数据库 + 多模块 + 可独立部署的 modular monolith**
而不是微服务系统。
---
## 3. 当前架构快照
### 3.1 后端现状
当前核心目录结构如下:
```text
src/
entrypoints/
moldinsight.py
inventory.py
shared/
app_factory.py
config/
database/
models/
services/
utils/
moldinsight/
api/
core/
services/
storage/
inventory/
api/
schemas/
services/
```
其中:
- [app_factory.py](../src/shared/app_factory.py) 已统一 CORS、日志中间件、startup/shutdown、认证路由、健康检查与 SPA fallback。
- [moldinsight.py](../src/entrypoints/moldinsight.py) 与 [inventory.py](../src/entrypoints/inventory.py) 已提供独立入口。
- [database.py](../src/shared/models/database.py) 同时包含 identity、moldinsight、inventory 三类模型,是当前最强耦合点。
### 3.2 前端现状
前端已是独立 Vite/Vue 工程:
```text
frontend/
src/
modules/
moldinsight/
inventory/
login/
users/
home/
router/
shared/
stores/
types/
```
特点:
- 已按页面/业务模块组织
- 已有共享 API 层雏形:[api-client.ts](../frontend/src/shared/api-client.ts)
- 已接入 OpenAPI 生成类型:[api.ts](../frontend/src/types/api.ts)
- 当前仍有大量相对路径 `/api/...` 与 raw `fetch()` 的同源假设
### 3.3 现状判断
当前架构可概括为:
> **HTTP 入口已分离,业务代码已分组,但平台层与数据层仍共享。**
因此,它适合继续朝“可独立部署的模块化单体”演进,而不适合直接跳到微服务。
---
## 4. 目标架构:可独立部署的模块化单体
### 4.1 架构原则
目标态采用以下原则:
1. **组合优先于复制**:不同部署模式通过组合不同模块得到,而不是复制多套代码。
2. **平台与业务分离**:`platform` 只承载技术性共享能力,不继续承载业务逻辑。
3. **模块所有权清晰**:每张表、每条 API、每个服务类都应有明确归属。
4. **单数据库但显式边界**:允许共享 DB,但不允许“共享数据库 = 没有边界”。
5. **统一前端,兼容多后端部署形态**:前端继续是一套工程,通过 API client 适配 unified / split deployment。
### 4.2 架构定位
目标架构不是“多个服务各自拥有数据库”的微服务,而是:
- 同一个仓库
- 同一个数据库
- 多个模块
- 多个部署入口
- 同一套迁移历史
- 同一套共享基础设施能力
这是一种适合当前项目阶段的**治理性重构**,而不是组织级拆分。
---
## 5. 目标目录结构
以下结构是**目标态**,不要求一次性到位:
```text
src/
platform/
app/
app_factory.py
lifecycle.py
middleware/
config/
auth/
database/
engine.py
session.py
migrations/
observability/
contracts/
api/
events/
shared_kernel/
types/
exceptions/
utils/
modules/
moldinsight/
application/
services/
use_cases/
domain/
models/
policies/
repositories/
infrastructure/
persistence/
storage/
adapters/
interfaces/
api/
schemas/
module.py
inventory/
application/
services/
use_cases/
domain/
models/
policies/
repositories/
infrastructure/
persistence/
adapters/
interfaces/
api/
schemas/
module.py
identity/
application/
domain/
infrastructure/
interfaces/
module.py
compositions/
unified_app.py
gemold_app.py
inventory_app.py
legacy/
main.py
```
### 5.1 当前目录到目标目录的映射
| 当前路径 | 目标路径 | 说明 |
|---|---|---|
| `src/shared/*` | `src/platform/*` | 共享基础设施重新命名与归位 |
| `src/moldinsight/*` | `src/modules/moldinsight/*` | gemold 业务模块 |
| `src/inventory/*` | `src/modules/inventory/*` | inventory 业务模块 |
| `src/entrypoints/*` | `src/compositions/*` | 部署组合层 |
| `src/main.py` | `src/legacy/main.py` | 过渡期兼容入口 |
### 5.2 为什么要引入 `compositions/`
当前 [entrypoints/](../src/entrypoints/) 已经承担“部署入口”角色,但语义更偏“启动文件”。
引入 `compositions/` 的意义是明确:
- 它不是业务模块
- 它不是平台能力
- 它是“**按部署模式装配模块**”的组合层
例如:
- `gemold_app.py`:平台 + identity + moldinsight
- `inventory_app.py`:平台 + identity + inventory
- `unified_app.py`:平台 + identity + moldinsight + inventory
---
## 6. 模块职责边界
### 6.1 platform
`platform` 是技术共享层,只承载**跨模块公共基础设施能力**。
#### 归属范围
- app factory / middleware / 生命周期
- config
- 数据库 engine / session / Alembic 接线
- auth / JWT / 权限
- 日志 / request_id / observability
- 通用 contracts / utilities
#### 可复用现有实现
- [app_factory.py](../src/shared/app_factory.py)
- [settings.py](../src/shared/config/settings.py)
- [database.py](../src/shared/database/database.py)
- [auth_service.py](../src/shared/services/auth_service.py)
- [auth_routes.py](../src/shared/services/auth_routes.py)
#### 规则
`platform` 不得继续吸收业务规则代码,否则新的 `platform` 会变成旧的 `shared`。
---
### 6.2 moldinsight(gemold)
`moldinsight` 模块负责模具分析、几何处理和分析结果生命周期。
#### 归属范围
- 上传、任务、历史、批量分析、成本估算、CAM、分析结果
- 几何分析、特征检测、模具方案、报告
- RustFS / 对象存储接入
- Celery 异步处理链路
#### 可复用现有实现
- [moldinsight/api/__init__.py](../src/moldinsight/api/__init__.py)
- [processing_service.py](../src/moldinsight/services/processing_service.py)
- [task_query_service.py](../src/moldinsight/services/task_query_service.py)
- [moldinsight/core/](../src/moldinsight/core/)
- [celery_app.py](../src/celery_app.py)
- [celery_tasks.py](../src/celery_tasks.py)
---
### 6.3 inventory
`inventory` 模块负责 ERP / 进销存类业务流程。
#### 归属范围
- 产品、物料、供应商、客户、仓库
- 库存、库存流水
- 销售订单、采购订单、财务、采购建议
- BOM / 采购需求推导
#### 可复用现有实现
- [inventory/api/__init__.py](../src/inventory/api/__init__.py)
- [inventory_service.py](../src/inventory/services/inventory_service.py)
- [sales_order_service.py](../src/inventory/services/sales_order_service.py)
- [purchase_order_service.py](../src/inventory/services/purchase_order_service.py)
- [finance_service.py](../src/inventory/services/finance_service.py)
---
### 6.4 identity
`identity` 负责用户、角色、权限与认证授权。
#### 归属范围
- User / Role / Permission
- 登录、鉴权、管理员接口
- 统一授权能力
在物理目录上,identity 可以先靠近 platform;但逻辑上应从一开始就被视为独立边界,而不是“moldinsight 的一部分”或“inventory 的一部分”。
---
## 7. 允许的依赖方向
这是本蓝图最重要的治理规则之一。
### 7.1 依赖规则
```text
compositions -> platform
compositions -> modules/*
platform -> 不依赖业务模块
modules/*/interfaces -> modules/*/application
modules/*/application -> modules/*/domain
modules/*/infrastructure -> modules/*/domain
modules/*/interfaces -> platform
modules/*/infrastructure -> platform
```
### 7.2 跨模块约束
- `inventory` 不能直接 import `moldinsight.api` / `moldinsight.services`
- `moldinsight` 不能直接 import `inventory.api` / `inventory.services`
- `platform` 不得依赖任一业务模块
- 跨模块协作只能通过:
- 显式 contract / query service
- composition wiring
- 受控的共享数据库引用
### 7.3 当前代码与规则的差距
从代码检查看,当前 `moldinsight` 与 `inventory` 基本没有直接互引,这说明上述规则在业务代码层**已经接近成立**。
当前主要问题集中在:
- [database.py](../src/shared/models/database.py) 集中承载所有 ORM 模型
- [app_factory.py](../src/shared/app_factory.py) 同时知道通用平台逻辑与 moldinsight 专属 startup 行为
因此,后续实施的重点不是“切断业务模块互引”,而是“**把共享层与数据层的边界拉直**”。
---
## 8. 单数据库下的模型与表归属策略
### 8.1 核心原则
数据库继续保持为**一个 PostgreSQL 数据库**,但代码中的模型归属必须显式化。
也就是说:
> **数据库不拆,模型归属要拆。**
### 8.2 当前最强耦合点
当前 [database.py](../src/shared/models/database.py) 同时包含:
- identity / 平台相关模型
- moldinsight 业务模型
- inventory 业务模型
这会带来两个问题:
1. 代码层看不出模型所有权
2. 开发者更容易跨模块直接访问整套 ORM 图谱
因此,后续实施应优先将这个文件按归属拆分。
### 8.3 推荐表归属矩阵
#### platform / identity-owned
- users
- roles
- permissions
- user_roles
- role_permissions
- (可选)system_logs
#### moldinsight-owned
- stp_files
- geometry_data
- mesh_data
- html_files
- processing_tasks
- mold_cavity_data
- feature_detections
- design_recommendations
- analysis_metrics
#### inventory-owned
- products
- product_materials
- material_price_history
- material_suppliers
- suppliers
- customers
- warehouses
- inventory
- stock_movements
- purchase_orders
- purchase_order_items
- sales_orders
- sales_order_items
- finance_transactions
- finance_allocations
### 8.4 目标代码形态
推荐逐步演进到:
```text
platform/database/base.py
modules/identity/infrastructure/persistence/models.py
modules/moldinsight/infrastructure/persistence/models.py
modules/inventory/infrastructure/persistence/models.py
```
同时保持:
- 同一个 SQLAlchemy `Base`
- 同一个 metadata
- 同一条 Alembic 历史链
- 同一个数据库连接
### 8.5 跨模块 FK 的处理策略
当前存在真实跨模块业务桥:
- `STPFile.product_id -> Product.id`
这是合理的,因为它反映了真实业务关系:模具分析结果可以创建成品,并与 inventory 中的产品建立连接。
原则上允许保留这类稳定 FK,但应遵守:
1. 跨模块 FK 是**业务桥**,不是“任意跨模块查询”的许可
2. 模块之间应逐步通过 query service / repository contract 暴露需要的读取能力
3. 避免一个模块直接依赖另一个模块的整套 ORM 图谱
---
## 9. 部署模式设计
本项目必须支持三种部署模式。
### 9.1 unified
#### 组成
- platform + identity + moldinsight + inventory
#### 适用场景
- 本地开发
- 小团队部署
- 集成环境
- 一体化业务场景
#### 说明
新的 unified 组合层应接替旧 [main.py](../src/main.py) 的语义,但应通过 `compositions/unified_app.py` 的方式实现,而不是继续维持旧单体式入口。
---
### 9.2 gemold-only
#### 组成
- platform + identity + moldinsight
#### 适用场景
- 仅开放模具分析能力
- 分析服务独立扩容
- 单独部署算法/文件处理能力
#### 说明
- 只暴露 gemold 路由
- 可保留对共享数据库中 `products` 的受控引用
- RustFS / Celery 等专属基础设施只在该模式启用
当前入口基线:
- [moldinsight.py](../src/entrypoints/moldinsight.py)
---
### 9.3 inventory-only
#### 组成
- platform + identity + inventory
#### 适用场景
- 仅提供 ERP / 进销存能力
- 不需要模具分析链路的后台场景
#### 说明
- 只暴露 inventory 路由
- 不要求启动 RustFS 等 moldinsight 专属基础设施
当前入口基线:
- [inventory.py](../src/entrypoints/inventory.py)
---
### 9.4 当前共享工厂的边界问题
需要特别指出:当前 [app_factory.py](../src/shared/app_factory.py) 通过 `mount_html=True` 分支初始化 RustFS,这说明共享工厂仍然知道 moldinsight 模块专属基础设施。
这意味着:
- `shared` / `platform` 还不够纯
- 模块专属 startup hook 还没有完全从平台层剥离
后续实施时,这应是**优先解决的问题之一**:
> app factory 只负责通用平台装配;模块专属生命周期应由 module hook 或 composition layer 决定。
---
## 10. 前端 API 边界策略
### 10.1 设计原则
前端已经是独立工程,不需要再拆目录或拆仓。后续重点应放在:
- 强化域 API 边界
- 消除对单一同源 `/api/...` 的强依赖
- 兼容 unified / split deployment
### 10.2 当前可复用基础
当前前端已经具备良好基础:
- 域客户端入口:[api-client.ts](../frontend/src/shared/api-client.ts)
- 生成类型:[api.ts](../frontend/src/types/api.ts)
- 模块目录:[frontend/src/modules/moldinsight/](../frontend/src/modules/moldinsight/) 与 [frontend/src/modules/inventory/](../frontend/src/modules/inventory/)
因此,后续策略应是“**边界强化**”,不是“前端重写”。
### 10.3 建议的客户端边界
应继续收敛为:
- `authApi`
- `moldinsightApi`
- `inventoryApi`
并要求:
- 页面/组件尽量不直接写裸 `/api/...` 字符串
- multipart upload / download / export 也尽量通过域客户端封装
- 统一利用 OpenAPI 生成类型,而不是额外维护平行手写类型
### 10.4 支持两类部署配置
#### unified 模式
- `VITE_API_BASE_URL`
#### split 模式
- `VITE_AUTH_API_BASE_URL`
- `VITE_MOLDINSIGHT_API_BASE_URL`
- `VITE_INVENTORY_API_BASE_URL`
客户端实现上应支持:
- unified 下三个 client 指向同一个 base URL
- split 下各 client 指向不同服务
### 10.5 capability-aware UI
在 gemold-only 或 inventory-only 部署模式下,前端不应假设所有模块总是存在。
因此建议:
- 后端通过 `/health` 或单独 capability endpoint 暴露已启用模块信息
- 前端根据 capability 隐藏未部署模块入口或禁用对应页面
这样可避免“前端路由还在,但后端根本没部署”的硬失败场景。
---
## 11. 分阶段迁移计划
### Phase 0:蓝图冻结
目标:冻结目标结构与边界规则,防止迁移过程中继续长出新的耦合。
动作:
- 确认模块边界
- 确认依赖规则
- 确认三种部署模式
- 确认 shared/platform 的使用边界
---
### Phase 1:组合层标准化
目标:将部署模式从“若干入口脚本”升级为“正式的 composition layer”。
动作:
- 将 `entrypoints/*` 升级为 `compositions/*`
- 定义 `unified_app.py` / `gemold_app.py` / `inventory_app.py`
- 将 module-specific startup hooks 从通用 app factory 中迁出
重点问题:
- 当前 `mount_html -> RustFS connect` 属于模块专属逻辑,必须从 shared factory 中剥离
---
### Phase 2:platform 与业务代码分治
目标:把“共享基础设施”从“共享杂项”中真正分离出来。
动作:
- 从 `shared` 语义切换到更清晰的 `platform`
- 归位 config / auth / db / observability / utils
- 禁止新业务逻辑继续沉积到 `shared`
---
### Phase 3:ORM 按归属拆分
目标:解决当前最大的代码耦合源。
动作:
- 拆分 [database.py](../src/shared/models/database.py)
- 保持单 Base / 单 Alembic / 单 DB
- 先完成代码层归属拆分,再处理更深层的业务隔离
这是整个重构中最关键的一步。
---
### Phase 4:模块内部继续分层
目标:让每个模块内部的“路由 / 服务 / 领域 / 基础设施”边界更清晰。
动作:
- inventory:从现有 service 层继续向 `application / domain / infrastructure / interfaces` 拉开
- moldinsight:逐步理顺 `api / services / core / storage` 的边界
原则:
- 不要求一步完成 DDD 化
- 先把层次职责清楚,再考虑更纯粹的领域对象抽象
---
### Phase 5:建立跨模块集成规则
目标:把当前 ad hoc 跨表访问逐步收敛成显式桥接能力。
动作:
- 定义跨模块 query services / repository contracts
- 明确“从分析创建成品”等桥接能力的正式入口
- 收敛直接穿透跨模块 ORM 图谱的做法
重点桥接场景:
- `STPFile.product_id`
- [product_routes.py](../src/inventory/api/product_routes.py) 中的“按 task 创建产品”逻辑
---
### Phase 6:前端边界加固
目标:让前端真正适配 unified / split deployment。
动作:
- 强制域 API client 收口
- 支持 per-module base URL
- 支持 capability-aware UI
- 减少页面中裸 `fetch('/api/...')`
---
### Phase 7:部署与文档收尾
目标:使架构蓝图与部署事实一致。
动作:
- 固化 unified / gemold-only / inventory-only 部署说明
- 更新 README / deployment docs / frontend docs
- 明确旧入口、旧 Dockerfile、旧部署说明的地位(兼容 / 历史 / 废弃)
---
## 12. 风险与缓解措施
### 风险 1:共享模型文件继续隐藏领域归属
**现象**:所有模型集中在 [database.py](../src/shared/models/database.py)
**风险**:边界无法落实,任何模块都能自然跨领域访问
**缓解**:
- 先产出表归属矩阵
- 再拆 ORM 文件
- 拆归属优先于改业务逻辑
---
### 风险 2:`shared` 继续变成杂物间
**风险**:shared/platform 成为“不知道放哪就放这里”的位置
**缓解**:
- 以 `platform` 重新定义共享层
- 明确只有技术性共享能力可进入 platform
- 代码 review 中禁止新增业务逻辑进入 platform
---
### 风险 3:模块专属启动逻辑继续留在 app factory
**现象**:当前 `mount_html` 分支控制 RustFS 连接
**风险**:平台层继续了解业务模块内部基础设施
**缓解**:
- module lifecycle hook
- composition 层控制模块 startup/shutdown
- 通用 app factory 保持纯平台化
---
### 风险 4:独立部署后,前端仍假设所有模块存在
**风险**:前端路由可见,但后端未部署,造成运行时错误
**缓解**:
- capability metadata
- feature gating
- 前端按模块部署形态动态隐藏入口
---
### 风险 5:单数据库导致开发者随意跨模块查表
**风险**:虽然数据库未拆,但代码边界被绕开
**缓解**:
- 表归属规则文档化
- code review 要求说明跨模块访问理由
- 逐步通过 query services 收口
---
### 风险 6:大爆炸式目录迁移导致 import churn
**风险**:一次性移动所有目录,修改面过大,回归成本高
**缓解**:
- 分阶段迁移
- 保留兼容 import 过渡层
- 先稳定组合层与模型层,再做深层目录调整
---
## 13. 验证清单
### 13.1 结构验证
- `platform` 不 import 业务模块
- `moldinsight` / `inventory` 无直接 api/services 互引
- ORM 文件已按归属拆分,或至少表归属矩阵已文档化并被遵守
### 13.2 运行验证
#### unified
- 两类路由都能正常挂载
- 统一 health / auth / request-id 机制生效
#### gemold-only
- inventory 路由未挂载
- gemold 路由可用
- RustFS / Celery 等专属依赖正常初始化
#### inventory-only
- moldinsight 路由未挂载
- inventory 路由可用
- 不依赖 moldinsight 专属基础设施即可启动
### 13.3 数据验证
- 三种部署模式使用同一 migration head
- 单数据库中的跨模块 FK 保持有效
- Alembic 无分叉历史
### 13.4 前端验证
- unified 模式下,一个 base URL 即可跑通
- split 模式下,各模块 base URL 可独立配置
- 未部署模块能被隐藏或优雅失败
---
## 14. 文档联动更新计划
本蓝图批准后,以下文档应逐步对齐:
- [EVOLUTION_ROADMAP.md](./EVOLUTION_ROADMAP.md)
- [LINUX_SETUP.md](./deployment/LINUX_SETUP.md)
- [DEPLOY_PORT.md](./deployment/DEPLOY_PORT.md)
- [PORT_CONFIG.md](./deployment/PORT_CONFIG.md)
- [PORT_REFACTOR_SUMMARY.md](./deployment/PORT_REFACTOR_SUMMARY.md)
- `README.md`
- `frontend/README.md`
其中需要特别注意:
- `README.md` 当前仍主要描述旧单体结构,与当前实际代码已有明显漂移。
- 本文档应作为“当前目标架构”的权威蓝图,路线图与部署文档随后对齐。
---
## 15. 附录:实施热点文件
以下文件是后续实际重构时最关键的热点:
### 平台与组合层
- [app_factory.py](../src/shared/app_factory.py)
- [settings.py](../src/shared/config/settings.py)
- [database.py](../src/shared/database/database.py)
- [init_db.py](../src/shared/database/init_db.py)
- [moldinsight.py](../src/entrypoints/moldinsight.py)
- [inventory.py](../src/entrypoints/inventory.py)
- [main.py](../src/main.py)
### 模型与边界
- [database.py](../src/shared/models/database.py)
- [product_routes.py](../src/inventory/api/product_routes.py)
### gemold 模块
- [moldinsight/api/__init__.py](../src/moldinsight/api/__init__.py)
- [processing_service.py](../src/moldinsight/services/processing_service.py)
- [task_query_service.py](../src/moldinsight/services/task_query_service.py)
### inventory 模块
- [inventory/api/__init__.py](../src/inventory/api/__init__.py)
- [inventory_service.py](../src/inventory/services/inventory_service.py)
- [sales_order_service.py](../src/inventory/services/sales_order_service.py)
- [purchase_order_service.py](../src/inventory/services/purchase_order_service.py)
- [finance_service.py](../src/inventory/services/finance_service.py)
### 前端边界
- [api-client.ts](../frontend/src/shared/api-client.ts)
- [api.ts](../frontend/src/types/api.ts)
### 演进与部署参考
- [EVOLUTION_ROADMAP.md](./EVOLUTION_ROADMAP.md)
- [docker-compose.yml](../docker-compose.yml)
---
## 16. 最终结论
本项目当前最适合的演进路径不是微服务,而是:
> **单仓库 + 单数据库 + 多模块 + 可独立部署的 modular monolith**
它既能保留当前业务闭环(模具分析 → 成品 → BOM → 销售/采购/库存),又能逐步降低共享层和模型层的结构耦合。
后续实施时,应优先按以下顺序推进:
1. 固化组合层(deployment composition)
2. 纯化 platform/shared 边界
3. 拆分共享 ORM 文件
4. 再继续模块内部细分层次
5. 最后收口前端 API 与部署文档
这条路径风险最低、收益最大,也最符合当前代码现状与团队演进成本。
+2 -2
View File
@@ -18,7 +18,7 @@
### P0-1 Celery worker 不连 Redis/RustFS,异步任务全坏
- **现象**:任务进度写进 Celery 私有内存,web 端永远读不到;首次上传 RustFS 直接抛 `RuntimeError("RustFS 未连接")`。
- **证据**:`redis_task_manager.connect()` / `rustfs_manager.connect()` 只在 FastAPI startup 调用(`entrypoints/moldinsight.py:42,48`),Celery 进程不跑 startup;`processing_service.py` 在 celery 内调 `update_task` 时 `is_connected=False` 走 `_fallback_set`;`rustfs_storage.py:125-126` 未连接直接抛错。`deploy/docker-compose.yml` 的 `moldinsight-celery` 服务块缺 `REDIS_PASSWORD`。
- **证据**:`redis_task_manager.connect()` / `rustfs_manager.connect()` 只在 FastAPI startup 调用(`entrypoints/moldinsight.py:42,48`),Celery 进程不跑 startup;`processing_service.py` 在 celery 内调 `update_task` 时 `is_connected=False` 走 `_fallback_set`;`rustfs_storage.py:125-126` 未连接直接抛错。`docker-compose.yml` 的 `moldinsight-celery` 服务块缺 `REDIS_PASSWORD`。
- **修法**:`celery_tasks.py` 加 `@worker_process_init` 信号,显式 `connect()` redis 与 rustfs;补齐 celery 服务的 `REDIS_PASSWORD`/`SECRET_KEY` 等环境变量,与主应用对齐。
- **验证**:上传一个 STP,Celery 路径下任务进度能从 web 端 `/api/status/{task_id}` 读到;上传后 RustFS 中能看到对象。
- **状态**:- [ ]
@@ -70,7 +70,7 @@
### P0 执行结果(2026-07-13)
- ✅ **P0-1 Celery 连接**:`celery_tasks.py` 在任务内显式 `redis_task_manager.reconnect()` + `rustfs_manager.connect()`(Redis 客户端绑定事件循环,每任务 reconnect;RustFS 同步客户端连一次复用);`deploy/docker-compose.yml` celery 服务补 `REDIS_PASSWORD`/`RUSTFS_TIMEOUT`
- ✅ **P0-1 Celery 连接**:`celery_tasks.py` 在任务内显式 `redis_task_manager.reconnect()` + `rustfs_manager.connect()`(Redis 客户端绑定事件循环,每任务 reconnect;RustFS 同步客户端连一次复用);`docker-compose.yml` celery 服务补 `REDIS_PASSWORD`/`RUSTFS_TIMEOUT`
- ✅ **P0-2 LLM NameError**:`llm_service.py:339` `trimmed` -> `features`
- ✅ **P0-3 前端字段错配**:FinanceTab 全字段对齐 schema(summary/statement/product-statement/transaction 共 16 处);`UserResponse` 加 `is_superuser` + 统一 `_build_user_response` 构造(修用户管理菜单不显示);DashboardTab `product_count`->`finished_product_count`;PurchaseOrdersTab `received_at/paid_at`->`received_date/paid_date`;后端 `FinanceTransactionResponse` 补 `partner_name` 并批量查询客户/供应商名称
- ✅ **P0-4 OCC 线程安全**:`geometry_analyzer._detect_features` `max_workers` 4->1
+99 -200
View File
@@ -1,255 +1,154 @@
# 存储架构说明
> 本文档主要解释 geMoldInsight 的存储分层与数据流。其历史中的“本项目自行拉起 PostgreSQL / MinIO 并通过 `python src/main.py` 启动单体”的部分,**已不再代表当前默认部署方式**。
当前默认部署前提是:
- PostgreSQL 由服务器已有服务提供
- Redis 由服务器已有服务提供
- RustFS / MinIO 兼容对象存储由服务器已有服务提供
- 项目自身只部署:`moldinsight` / `moldinsight-celery` / `inventory`
如需查看当前部署方式,请优先参考:
- [README.md](../README.md)
- [LINUX_SETUP.md](./deployment/LINUX_SETUP.md)
- [DEPLOY_PORT.md](./deployment/DEPLOY_PORT.md)
- [BACKEND_MODULARIZATION_BLUEPRINT.md](./BACKEND_MODULARIZATION_BLUEPRINT.md)
---
## 架构概述
本项目采用 **RustFS (S3兼容)** 作为对象存储和 **PostgreSQL** 作为元数据存储的双层存储架构。
本项目采用 **RustFS(S3兼容)对象存储** + **PostgreSQL 元数据存储** 的双层存储架构。
```
```text
┌─────────────────────────────────────────────────────────────┐
│ 应用层 (FastAPI) │
│ 应用层 (gemold / inventory) │
└──────────────────────┬──────────────────────────────────────┘
│
┌──────────────┴──────────────┐
│ │
┌───────▼────────┐ ┌─────────▼─────────┐
│ PostgreSQL │ │ RustFS/S3 │
│ PostgreSQL │ │ RustFS / S3 │
│ (元数据) │ │ (对象存储) │
│ │ │ │
│ - users │ │ - stp-files │
│ - stp_files │ │ - geometry │
│ - geometry_data│ │ - mold-cavities │
│ - mold_cavity │ │ - html-files │
│ - features │ │ - user-files │
│ - logs │ │ │
│ - processing │ │ - html-files │
│ - logs │ │ - user-files │
└────────────────┘ └──────────────────┘
```
## PostgreSQL 数据表
---
## PostgreSQL 数据表(摘要)
### 用户管理
- `users` - 用户信息(用户名、邮箱、密码等)
- `users` - 用户信息
- `roles` / `permissions` - 权限体系
### 文件管理
- `stp_files` - STP文件元数据(文件名、哈希、大小、状态等)
- `html_files` - HTML报告文件元数据
### 几何数据
- `geometry_data` - 几何分析数据(体积、表面积、边界框等)
- `mold_cavity_data` - 模具型腔数据(工艺参数、质量评估等)
- `feature_detections` - 特征检测结果(壁厚、拔模角等)
- `design_recommendations` - 设计建议(优先级、参数等)
### 任务和日志
### gemold 相关
- `stp_files` - STP 文件元数据
- `html_files` - HTML 报告元数据
- `geometry_data` - 几何分析数据
- `mold_cavity_data` - 模具型腔数据
- `feature_detections` - 特征检测结果
- `design_recommendations` - 设计建议
- `processing_tasks` - 处理任务记录
- `user_activities` - 用户活动日志
- `system_logs` - 系统日志
- `analysis_metrics` - 分析指标
## RustFS 存储桶
### inventory 相关
- `products` - 产品/物料
- `product_materials` - BOM
- `inventory` - 库存
- `stock_movements` - 库存流水
- `purchase_orders` / `sales_orders` - 订单
- `finance_transactions` - 财务流水
---
## RustFS / S3 存储桶
| 存储桶名称 | 用途 | 存储内容 |
|-------------|------|---------|
| `moldinsight-stp-files` | STP/STEP文件 | 用户上传的原始3D模型文件 |
| `moldinsight-geometry` | 几何数据 | 几何分析结果的JSON数据 |
| `moldinsight-mold-cavities` | 模具型腔数据 | 模具设计的详细JSON数据 |
| `moldinsight-html` | HTML文件 | 生成的HTML报告文件 |
| `moldinsight-user-files` | 用户文件 | 其他用户上传的文件 |
|---|---|---|
| `moldinsight-stp-files` | STP/STEP 文件 | 用户上传的原始 3D 模型 |
| `moldinsight-geometry` | 几何结果 | 几何分析 JSON |
| `moldinsight-mold-cavities` | 模具结果 | 模具设计 JSON |
| `moldinsight-html` | HTML 报告 | 生成的 HTML 报告文件 |
| `moldinsight-user-files` | 用户文件 | 其他附件/用户文件 |
## 快速开始
---
### 1. 安装依赖
## 当前推荐初始化方式
### 1. 准备环境变量
```bash
pip install -r requirements.txt
```
### 2. 启动 PostgreSQL
使用 Docker Compose(推荐):
```bash
docker-compose up -d postgres
```
或手动启动:
```bash
# 创建数据库
createdb moldinsight
# 运行数据库容器
docker run -d \
--name postgres \
-e POSTGRES_DB=moldinsight \
-e POSTGRES_USER=moldinsight_user \
-e POSTGRES_PASSWORD=your_password \
-p 5432:5432 \
postgres:15
```
### 3. 启动 MinIO
使用 Docker Compose(推荐):
```bash
docker-compose up -d minio
```
或手动启动:
```bash
docker run -d \
--name minio \
-p 9000:9000 \
-p 9001:9001 \
-e MINIO_ROOT_USER=minioadmin \
-e MINIO_ROOT_PASSWORD=minioadmin \
minio/minio server /data --console-address ":9001"
```
### 4. 配置环境变量
```bash
# 复制示例配置
cp .env.example .env
# 编辑 .env 文件,修改数据库和MinIO配置
nano .env
```
### 5. 初始化数据库和存储
确保以下变量指向**服务器上已存在的真实服务**:
```bash
# 初始化数据库
python src/database/init_db.py
```env
DB_HOST=your-db-host
DB_PORT=5432
DB_NAME=moldinsight
DB_USER=moldinsight
DB_PASSWORD=change-me
# 初始化MinIO存储
python src/storage/init_storage.py
REDIS_HOST=your-redis-host
REDIS_PORT=6379
REDIS_PASSWORD=
RUSTFS_ENDPOINT=http://your-storage-host:9000
RUSTFS_ACCESS_KEY=change-me
RUSTFS_SECRET_KEY=change-me
```
### 6. 启动服务
### 2. 初始化数据库
```bash
python src/main.py
```
当前初始化入口参考:
- [init_db.py](../src/shared/database/init_db.py)
## 使用示例
### 3. 启动项目服务
### 保存STP文件
当前推荐通过:
- [docker-compose.yml](../docker-compose.yml)
- 或 [src/entrypoints/](../src/entrypoints/)
```python
from services.storage_integration import storage_integration
from database.database import db_manager
而不是继续使用历史单体 `python src/main.py` 作为默认方式。
async def upload_file(file_path: str):
async with db_manager.get_session() as session:
stp_file = await storage_integration.save_stp_file(
session=session,
file_path=Path(file_path),
original_filename="model.stp",
user_id=1
)
print(f"文件已保存,ID: {stp_file.id}")
```
---
### 保存几何数据
## 监控与维护
```python
async def save_geometry(stp_file_id: int, geometry_data: dict):
async with db_manager.get_session() as session:
geo_data = await storage_integration.save_geometry_data(
session=session,
stp_file_id=stp_file_id,
geometry_json=geometry_data,
analysis_method="pythonocc"
)
print(f"几何数据已保存,ID: {geo_data.id}")
```
### 获取文件数据
```python
async def get_file_data(stp_file_id: int):
async with db_manager.get_session() as session:
data = await storage_integration.get_stp_file_with_data(
session=session,
stp_file_id=stp_file_id
)
# 访问几何数据
geometry = data['geometry_data']
print(f"体积: {geometry['volume']}")
print(f"表面积: {geometry['surface_area']}")
# 访问模具型腔数据
cavity = data['mold_cavity_data']
print(f"模具材料: {cavity['mold_material']}")
# 访问特征和建议
for feature in data['features']:
print(f"特征: {feature['feature_type']}")
```
## 数据清理策略
### MinIO 对象存储
- 设置生命周期策略自动删除旧文件
- 示例:删除30天前的临时文件
### 对象存储
- 检查对象存储服务可达性
- 定期清理历史产物
- 配置生命周期策略
### PostgreSQL
- 定期清理已删除用户的记录
- 归档超过6个月的日志数据
- 定期备份
- 监控连接池与慢查询
- 保持 Alembic 迁移链一致
## 监控和维护
### 检查存储使用情况
```bash
# MinIO控制台
# http://localhost:9001
# 用户名: minioadmin
# 密码: minioadmin
```
### 数据库备份
```bash
# 备份数据库
pg_dump -h localhost -U moldinsight_user moldinsight > backup.sql
# 恢复数据库
psql -h localhost -U moldinsight_user moldinsight < backup.sql
```
## 性能优化
### PostgreSQL
- 创建适当的索引(已在模型中定义)
- 定期运行 VACUUM 和 ANALYZE
- 考虑使用连接池(已配置)
### MinIO
- 启用缓存层
- 配置CDN分发静态文件
- 使用多区域复制
## 安全建议
1. **更改默认密码**:生产环境必须更改所有默认密码
2. **启用TLS**:生产环境启用 HTTPS
3. **访问控制**:配置适当的用户权限
4. **数据加密**:敏感数据加密存储
5. **定期备份**:设置自动备份策略
---
## 故障排除
### 连接MinIO失败
```
错误: 对象存储连接失败
解决: 检查 MINIO_ENDPOINT, MINIO_ACCESS_KEY, MINIO_SECRET_KEY 配置
```
### 对象存储连接失败
- 检查 `RUSTFS_ENDPOINT`
- 检查 access key / secret key
- 检查服务端口与网络策略
### 数据库连接失败
```
错误: 数据库连接失败
解决: 检查 DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD 配置
```
- 检查 `DB_HOST` / `DB_PORT`
- 检查数据库账号密码
- 检查防火墙与白名单
### 文件上传失败
```
错误: STP文件上传失败
解决: 检查磁盘空间、网络连接、MinIO权限
```
- 检查对象存储可用性
- 检查 Celery worker 是否运行
- 检查 Redis 是否可达
+159 -125
View File
@@ -1,170 +1,204 @@
# 部署时端口配置说明
# 模块化部署端口说明
## 生产环境部署端口配置
> 本文档描述的是 **当前模块化部署模式** 下的端口规划,不再以历史单体 `src.main:app` 作为默认前提。
本项目现在使用统一的端口配置文件 `.env`,部署时需要相应调整配置。
当前推荐部署对象:
### Gunicorn 启动配置
- gemold API
- gemold Celery worker(无 HTTP 端口)
- inventory API
**推荐方式(使用 .env 配置):**
以下基础设施默认由服务器现有服务提供,不在本项目 compose 中重复部署:
- PostgreSQL
- Redis
- MinIO / RustFS(gemold 需要)
---
## 1. 推荐端口规划
| 组件 | 默认端口 | 说明 |
|---|---:|---|
| gemold API | 8000 | 模具分析后端 |
| inventory API | 8001 | 进销存后端 |
| PostgreSQL | 5432 | 共享数据库 |
| Redis | 6379 | 共享队列/缓存 |
| MinIO API | 9000 | 对象存储接口 |
| MinIO Console | 9001 | 对象存储控制台 |
> Celery worker 不直接暴露 HTTP 端口。
---
## 2. 三种部署模式下的端口
### 2.1 gemold-only
- 对外开放:`8000`
- 依赖:PostgreSQL、Redis、MinIO/RustFS
- 可选:前置 Nginx 暴露 80/443
### 2.2 inventory-only
- 对外开放:`8001`
- 依赖:PostgreSQL、Redis
- 不要求对象存储
### 2.3 unified
两种常见实现:
1. **统一网关模式**
- 外部只开放 80/443
- 网关转发到 gemold / inventory
2. **统一应用组合模式**
- 统一后端监听单一端口
- 后续组合层重构完成后更适合采用
当前阶段,如果需要统一对外,更推荐**网关统一**而不是继续依赖历史单体入口。
---
## 3. Docker Compose 端口来源
当前主部署文件:
- [docker-compose.yml](../../docker-compose.yml)
关键端口映射:
- `MOLDINSIGHT_PORT` → gemold API 外部端口
- `INVENTORY_PORT` → inventory API 外部端口
示例:
```env
MOLDINSIGHT_PORT=8000
INVENTORY_PORT=8001
```
对应 compose 行为:
- gemold:`${MOLDINSIGHT_PORT:-8000}:8000`
- inventory:`${INVENTORY_PORT:-8001}:8001`
---
## 4. 直接运行时的端口约定
### gemold-only
```bash
# 创建启动脚本
cat > start_production.sh << 'EOF'
#!/bin/bash
cd /opt/moldinsight/moldinsight_project
source venv/bin/activate
# 从 .env 读取端口配置
if [ -f .env ]; then
PORT=$(grep '^PORT=' .env | cut -d'=' -f2)
else
PORT=8000
fi
# 启动服务
gunicorn src.main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:${PORT}
EOF
chmod +x start_production.sh
./start_production.sh
uvicorn src.entrypoints.moldinsight:app --host 0.0.0.0 --port 8000
```
### systemd 服务配置
### inventory-only
创建 `/etc/systemd/system/moldinsight.service`:
```ini
[Unit]
Description=MoldInsight Geometry Analysis Service
After=network.target postgresql.service
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/moldinsight/moldinsight_project
Environment=PATH=/opt/moldinsight/moldinsight_project/venv/bin
Environment="PORT=8000"
ExecStart=/opt/moldinsight/moldinsight_project/venv/bin/gunicorn src.main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:${PORT}
Restart=always
[Install]
WantedBy=multi-user.target
```bash
uvicorn src.entrypoints.inventory:app --host 0.0.0.0 --port 8001
```
**重要:** 在 `[Service]` 部分添加 `Environment="PORT=8000"`,或在 `.env` 文件中配置 `PORT=8000`。
如果改端口:
- gemold 改 `--port`
- inventory 改 `--port`
- 同步更新 Nginx / 防火墙 / 前端 base URL
### Nginx 反向代理配置
---
## 5. 前端联动
如果前端与后端分开部署,需要与前端环境变量保持一致。
建议前端支持:
### unified 模式
```env
VITE_API_BASE_URL=https://api.example.com
```
### split 模式
```env
VITE_AUTH_API_BASE_URL=https://auth.example.com
VITE_MOLDINSIGHT_API_BASE_URL=https://gemold.example.com
VITE_INVENTORY_API_BASE_URL=https://inventory.example.com
```
当前详细策略见:
- [BACKEND_MODULARIZATION_BLUEPRINT.md](../BACKEND_MODULARIZATION_BLUEPRINT.md)
---
## 6. Nginx 示例
### gemold-only
```nginx
upstream moldinsight_backend {
server 127.0.0.1:8000; # 对应 .env 中的 PORT
}
server {
listen 80;
server_name your-domain.com;
server_name gemold.example.com;
location / {
proxy_pass http://moldinsight_backend;
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
location /static {
alias /opt/moldinsight/moldinsight_project/static;
}
### inventory-only
location /html_output {
alias /opt/moldinsight/moldinsight_project/html_output;
```nginx
server {
listen 80;
server_name inventory.example.com;
location / {
proxy_pass http://127.0.0.1:8001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
### Docker 部署
---
Docker 部署自动从 `.env` 读取配置,无需额外设置:
## 7. 防火墙建议
如果不通过 Nginx 统一入口而是直接暴露服务端口,则应显式开放:
```bash
# .env 文件配置
PORT=8000 # 容器内端口
HOST_PORT=8080 # 宿主机端口
# gemold
sudo ufw allow 8000/tcp
# 启动
docker-compose up -d
# inventory
sudo ufw allow 8001/tcp
```
### 修改生产环境端口
生产环境更推荐:
- 外部只开放 80/443
- 内部仅开放 8000/8001 给 Nginx 或内网访问
1. **编辑 .env 文件**
```bash
PORT=9000 # 修改应用端口
```
---
2. **重启服务**
```bash
# systemd
sudo systemctl restart moldinsight
# Docker
docker-compose down && docker-compose up -d
# 手动启动
./start_production.sh
```
3. **更新 Nginx 配置(如果使用)**
```nginx
upstream moldinsight_backend {
server 127.0.0.1:9000; # 更新为新端口
}
```
```bash
sudo nginx -t && sudo nginx -s reload
```
### 防火墙配置
如果修改了端口,需要更新防火墙规则:
## 8. 快速检查
```bash
# UFW (Ubuntu/Debian)
sudo ufw allow 9000/tcp
sudo ufw delete allow 8000/tcp # 删除旧端口
# firewall-cmd (CentOS/RHEL)
sudo firewall-cmd --permanent --add-port=9000/tcp
sudo firewall-cmd --permanent --remove-port=8000/tcp
sudo firewall-cmd --reload
curl http://127.0.0.1:8000/health
curl http://127.0.0.1:8001/health
```
### 健康检查
如果只部署单模块,只检查对应服务即可。
修改端口后,更新健康检查命令:
---
```bash
# 检查服务状态
curl http://localhost:9000/health
curl http://your-domain.com/health
```
## 9. 结论
## 快速参考
在当前模块化架构下:
| 部署方式 | 端口配置位置 | 重启命令 |
|---------|------------|---------|
| 直接运行 | `.env` 中的 `PORT` | Ctrl+C 后重新运行 |
| Gunicorn | `.env` 中的 `PORT` | `systemctl restart moldinsight` |
| Docker | `.env` 中的 `PORT` 和 `HOST_PORT` | `docker-compose restart` |
| Nginx代理 | Nginx配置中的 `proxy_pass` | `nginx -s reload` |
## 注意事项
⚠️ **重要:**
1. 所有端口配置统一在 `.env` 文件中管理
2. 修改端口后需要同步更新相关配置(Nginx、防火墙等)
3. 确保新端口没有被其他服务占用
4. 生产环境建议使用 Nginx 反向代理,对外提供 80/443 端口
5. .env 文件不应提交到版本控制系统,使用 `.env.example` 作为模板
- gemold 与 inventory 应视为**两个独立后端模块**
- 端口应按模块分配,而不是继续沿用单体“一个后端一个端口”的思路
- unified 更适合通过**组合层或网关**实现,而不是继续让历史单体入口承载全部语义
+300 -178
View File
@@ -1,177 +1,315 @@
# MoldInsight Linux 部署指南
# geMoldInsight Linux 部署指南
## 系统要求
- Linux 系统 (Ubuntu 20.04+ / CentOS 8+)
- Python 3.8+
- PostgreSQL 12+
> 本文档描述的是 **当前模块化架构** 下的 Linux 部署方式,而不是历史单体 `src.main:app` 方案。
当前项目支持三种部署模式:
- **unified**:gemold + inventory 统一部署
- **gemold-only**:仅部署模具分析后端
- **inventory-only**:仅部署进销存后端
项目保持:
- **同一 Git 仓库**
- **同一 PostgreSQL 数据库**
- **共享认证体系**
- **按模块独立部署**
- **复用服务器上已存在的 PostgreSQL / Redis / RustFS(或 MinIO 兼容存储)**
详细架构蓝图见:
- [BACKEND_MODULARIZATION_BLUEPRINT.md](../BACKEND_MODULARIZATION_BLUEPRINT.md)
---
## 1. 系统要求
### 基础要求
- Linux(Ubuntu 22.04+ / Debian 12+ / CentOS Stream 9+)
- Python 3.12
- Git
- 服务器上已可访问的 PostgreSQL 15+
- 服务器上已可访问的 Redis 7+
## 1. 环境准备
### 按模块附加要求
#### gemold / unified 需要
- 服务器上已可访问的 MinIO 或 RustFS 兼容对象存储
- PythonOCC 运行环境
- Celery worker(推荐与 gemold 一起部署)
#### inventory-only 需要
- PostgreSQL
- Redis
- 不依赖 MinIO / RustFS
- 不依赖 Celery worker
---
## 2. 代码获取与目录约定
### 安装系统依赖
```bash
# Ubuntu/Debian
sudo apt update
sudo apt install python3 python3-pip python3-venv postgresql postgresql-contrib git
# CentOS/RHEL
sudo yum update
sudo yum install python3 python3-pip postgresql postgresql-server git
```
### 配置PostgreSQL
```bash
# 启动PostgreSQL服务
sudo systemctl start postgresql
sudo systemctl enable postgresql
# 创建数据库和用户
sudo -u postgres psql
```
在PostgreSQL中执行:
```sql
CREATE DATABASE moldinsight;
CREATE USER molduser WITH PASSWORD 'moldpassword';
GRANT ALL PRIVILEGES ON DATABASE moldinsight TO molduser;
\q
```
## 2. 项目部署
### 克隆或复制项目
```bash
# 如果使用Git
cd /opt
sudo git clone <your-repo-url> moldinsight
sudo chown -R $USER:$USER moldinsight
cd moldinsight
# 或者直接复制项目文件到Linux服务器
sudo git clone <your-repo-url> geMoldInsight
sudo chown -R $USER:$USER geMoldInsight
cd geMoldInsight
```
### 创建Python虚拟环境
后续示例默认项目位于:
```bash
cd moldinsight_project
python3 -m venv venv
source venv/bin/activate
/opt/geMoldInsight
```
### 安装依赖
---
## 3. Python 环境准备
```bash
python3.12 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
```
## 3. 环境配置
> 如果需要 gemold 分析能力,请额外准备 PythonOCC 运行环境。该依赖通常通过 conda 或预构建运行镜像提供,而不是直接由 pip 安装。
---
## 4. 环境变量配置
复制模板:
### 修改环境配置文件
编辑 `.env` 文件:
```bash
nano .env
cp .env.example .env
```
修改为Linux环境的配置:
```env
# 数据库配置(Linux环境)
DATABASE_URL=postgresql+asyncpg://molduser:moldpassword@localhost:5432/moldinsight
或部署场景参考:
# 服务配置
DEBUG=false
```bash
cp deploy/.env.example .env
```
至少需要配置(并指向服务器上已存在的基础设施):
```env
HOST=0.0.0.0
PORT=8000
# Redis配置(可选)
REDIS_HOST=localhost
DB_HOST=127.0.0.1
DB_PORT=5432
DB_NAME=moldinsight
DB_USER=moldinsight_user
DB_PASSWORD=change-me
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=
# Kafka配置(可选)
KAFKA_BOOTSTRAP_SERVERS=localhost:9092
KAFKA_SECURITY_PROTOCOL=PLAINTEXT
SECRET_KEY=change-me-in-production
ADMIN_USERNAME=admin
ADMIN_PASSWORD=change-me
RUSTFS_ENDPOINT=http://127.0.0.1:9000
RUSTFS_ACCESS_KEY=minioadmin
RUSTFS_SECRET_KEY=minioadmin
```
### 创建必要的目录
说明:
- `RUSTFS_*` 仅 **gemold / unified** 模式需要
- `inventory-only` 可不使用对象存储
- 当前配置读取实现见 [settings.py](../../src/shared/config/settings.py)
---
## 5. 数据库初始化
项目当前使用 Alembic 管理迁移,应用启动时也会执行初始化流程。
首次部署建议:
1. 确保服务器上的 PostgreSQL / Redis / 对象存储服务已可访问
2. 启动应用前确认 `.env` 中的 `DB_HOST` / `REDIS_HOST` / `RUSTFS_ENDPOINT` 指向真实服务地址
3. 让应用执行初始化/升级逻辑
相关实现参考:
- [init_db.py](../../src/shared/database/init_db.py)
> 当前项目是 **单数据库** 设计,因此 unified / gemold-only / inventory-only 都连接到同一个数据库与同一 migration head。
---
## 6. 启动方式
## 6.1 inventory-only
```bash
mkdir -p uploads html_output logs
chmod 755 uploads html_output logs
source .venv/bin/activate
uvicorn src.entrypoints.inventory:app --host 0.0.0.0 --port 8001
```
## 4. 启动服务
适合:
- 只提供进销存能力
- 不需要模具分析与异步任务
---
## 6.2 gemold-only
### 开发模式启动
```bash
cd moldinsight_project
source venv/bin/activate
python src/main.py
source .venv/bin/activate
uvicorn src.entrypoints.moldinsight:app --host 0.0.0.0 --port 8000
```
### 生产环境启动(使用Gunicorn)
适合:
- 单独部署模具分析能力
- 文件上传 / 分析 / 导出 / 批量分析
### gemold Celery worker
建议同时启动 worker:
```bash
# 安装Gunicorn
pip install gunicorn uvloop httptools
# 启动服务
cd moldinsight_project
source venv/bin/activate
gunicorn src.main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
source .venv/bin/activate
celery -A src.celery_app.celery_app worker --loglevel=info
```
## 5. 系统服务配置(可选)
> gemold 的异步处理链路依赖 Celery + Redis;若只启动 HTTP 服务而不启动 worker,上传分析任务可能无法完整处理。
---
## 6.3 unified
当前仓库仍保留历史统一入口 [main.py](../../src/main.py),但它更适合作为**过渡参考**,不建议作为长期标准入口。
在正式完成组合层重构前,如需统一部署,可优先使用反向代理或部署编排层统一暴露 gemold 与 inventory;后续会演进为显式 `unified_app.py`。
蓝图参考:
- [BACKEND_MODULARIZATION_BLUEPRINT.md](../BACKEND_MODULARIZATION_BLUEPRINT.md)
---
## 7. systemd 部署示例
## 7.1 inventory-only 服务
创建:
### 创建systemd服务文件
```bash
sudo nano /etc/systemd/system/moldinsight.service
sudo nano /etc/systemd/system/gemold-inventory.service
```
添加以下内容:
```ini
[Unit]
Description=MoldInsight Geometry Analysis Service
After=network.target postgresql.service
Description=geMoldInsight Inventory API
After=network.target postgresql.service redis.service
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/moldinsight/moldinsight_project
Environment=PATH=/opt/moldinsight/moldinsight_project/venv/bin
ExecStart=/opt/moldinsight/moldinsight_project/venv/bin/gunicorn src.main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
WorkingDirectory=/opt/geMoldInsight
Environment=PATH=/opt/geMoldInsight/.venv/bin
ExecStart=/opt/geMoldInsight/.venv/bin/uvicorn src.entrypoints.inventory:app --host 0.0.0.0 --port 8001
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
```
### 启用并启动服务
启用:
```bash
sudo systemctl daemon-reload
sudo systemctl enable moldinsight
sudo systemctl start moldinsight
sudo systemctl status moldinsight
sudo systemctl enable gemold-inventory
sudo systemctl start gemold-inventory
```
## 6. Nginx反向代理配置(可选)
---
## 7.2 gemold-only API 服务
创建:
### 安装Nginx
```bash
# Ubuntu/Debian
sudo apt install nginx
# CentOS/RHEL
sudo yum install nginx
sudo nano /etc/systemd/system/gemold-moldinsight.service
```
### 创建Nginx配置文件
```ini
[Unit]
Description=geMoldInsight MoldInsight API
After=network.target postgresql.service redis.service
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/geMoldInsight
Environment=PATH=/opt/geMoldInsight/.venv/bin
ExecStart=/opt/geMoldInsight/.venv/bin/uvicorn src.entrypoints.moldinsight:app --host 0.0.0.0 --port 8000
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
```
---
## 7.3 gemold Celery worker 服务
创建:
```bash
sudo nano /etc/nginx/sites-available/moldinsight
sudo nano /etc/systemd/system/gemold-celery.service
```
添加以下内容:
```ini
[Unit]
Description=geMoldInsight MoldInsight Celery Worker
After=network.target postgresql.service redis.service
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/geMoldInsight
Environment=PATH=/opt/geMoldInsight/.venv/bin
ExecStart=/opt/geMoldInsight/.venv/bin/celery -A src.celery_app.celery_app worker --loglevel=info
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
```
---
## 8. Nginx 反向代理示例
### 8.1 inventory-only
```nginx
server {
listen 80;
server_name your-domain.com;
server_name inventory.example.com;
location / {
proxy_pass http://127.0.0.1:8001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
### 8.2 gemold-only
```nginx
server {
listen 80;
server_name gemold.example.com;
location / {
proxy_pass http://127.0.0.1:8000;
@@ -180,102 +318,86 @@ server {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /static {
alias /opt/moldinsight/moldinsight_project/static;
expires 30d;
}
}
```
### 启用站点并重启Nginx
```bash
sudo ln -s /etc/nginx/sites-available/moldinsight /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
```
### 8.3 unified(示意)
## 7. 防火墙配置
统一对外时,可由网关做模块路由,也可直接暴露统一组合后的应用入口。组合层标准化完成前,更推荐通过部署编排或网关来实现统一对外访问。
---
## 9. 验证部署
### 9.1 健康检查
inventory-only:
```bash
# Ubuntu/Debian (ufw)
sudo ufw allow 80
sudo ufw allow 8000
sudo ufw allow ssh
sudo ufw enable
# CentOS/RHEL (firewalld)
sudo firewall-cmd --permanent --add-port=80/tcp
sudo firewall-cmd --permanent --add-port=8000/tcp
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload
curl http://127.0.0.1:8001/health
```
## 8. 验证部署
gemold-only:
### 检查服务状态
```bash
# 检查应用服务
curl http://localhost:8000/health
# 检查数据库连接
sudo -u postgres psql -d moldinsight -c "SELECT version();"
curl http://127.0.0.1:8000/health
```
### 测试文件上传
访问 `http://your-server-ip:8000` 上传STP文件测试功能。
### 9.2 基础能力验证
## 9. 故障排除
#### inventory-only
- 登录接口可用
- `/api/products` 返回数据
- `/api/inventory` 返回数据
### 常见问题
#### gemold-only
- 登录接口可用
- `/api/upload` 可访问
- 上传后 worker 能正常消费任务
- `/api/status/{task_id}` 能看到进度
1. **数据库连接失败**
- 检查PostgreSQL服务状态:`sudo systemctl status postgresql`
- 验证数据库连接:`psql -h localhost -U molduser -d moldinsight`
---
2. **端口被占用**
- 检查端口使用:`netstat -tulpn | grep 8000`
- 修改端口或停止占用进程
## 10. 常见问题
3. **权限问题**
- 确保目录权限正确:`chmod 755 uploads html_output logs`
- 检查文件所有者:`ls -la`
### 1. 为什么不再推荐 `src.main:app`?
因为当前项目已演进为模块化结构,`src.main:app` 更适合作为过渡兼容入口,而不是长期部署标准。应优先围绕 [entrypoints/](../../src/entrypoints/) 部署。
4. **依赖安装失败**
- 更新pip:`pip install --upgrade pip`
- 使用国内镜像:`pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple`
### 2. inventory-only 为什么不需要对象存储?
因为对象存储主要服务于 gemold 分析产物(HTML、导出文件等)。纯 inventory 部署不需要这部分基础设施。
## 10. 备份和恢复
### 3. gemold-only 为什么建议同时部署 Celery?
因为模具分析任务通常走异步处理链路,仅启动 API 而不启动 worker,会影响上传后的任务处理。
---
## 11. Docker Compose 说明
当前 [docker-compose.yml](../../docker-compose.yml) 仅启动:
- `moldinsight`
- `moldinsight-celery`
- `inventory`
它**不会**再拉起:
- PostgreSQL
- Redis
- MinIO
这些基础设施应由服务器现有服务提供,并通过 `.env` 传入连接信息。
示例:
### 数据库备份
```bash
# 备份数据库
sudo -u postgres pg_dump moldinsight > moldinsight_backup.sql
# 恢复数据库
sudo -u postgres psql -d moldinsight < moldinsight_backup.sql
docker compose --profile full up -d
```
### 文件备份
```bash
# 备份上传的文件和配置
tar -czf moldinsight_backup.tar.gz uploads/ html_output/ .env requirements.txt
```
---
## 快速启动脚本
## 12. 推荐阅读
创建启动脚本 `start.sh`:
```bash
#!/bin/bash
cd /opt/moldinsight/moldinsight_project
source venv/bin/activate
python src/main.py
```
赋予执行权限:
```bash
chmod +x start.sh
./start.sh
```
现在您的MoldInsight项目已经可以在Linux环境下正常运行!
- [README.md](../../README.md)
- [BACKEND_MODULARIZATION_BLUEPRINT.md](../BACKEND_MODULARIZATION_BLUEPRINT.md)
- [DEPLOY_PORT.md](./DEPLOY_PORT.md)
- [PORT_CONFIG.md](./PORT_CONFIG.md)
+145 -78
View File
@@ -1,107 +1,174 @@
# 端口配置说明
# 端口配置说明(模块化架构)
## ⚠️ 重要提示
> 本文档说明当前 geMoldInsight 在**模块化部署**下的端口配置方式。
本项目现在采用**统一端口配置管理**,所有端口配置集中在一个地方:
当前架构中应区分:
**唯一修改端口的地方:** `.env` 文件中的端口配置部分
- **gemold API 端口**
- **inventory API 端口**
- **数据库/Redis/对象存储端口**
- **前端访问地址**
## 配置说明
不再推荐把所有部署场景都抽象成“单应用单端口”。
编辑项目根目录下的 `.env` 文件:
---
```bash
# ================================
# 端口配置 - 唯一修改端口的地方
# ================================
# 应用端口(容器内端口)
PORT=8000
# Docker映射到宿主机的端口(docker-compose使用)
HOST_PORT=10001
# ================================
## 1. 当前主配置位置
对于 Docker Compose 部署,当前主要端口配置来源于:
- [docker-compose.yml](../../docker-compose.yml)
- `.env` / `deploy/.env.example`
注意:该 compose 文件仅负责项目应用容器,不负责 PostgreSQL / Redis / 对象存储容器。
核心环境变量:
```env
MOLDINSIGHT_PORT=8000
INVENTORY_PORT=8001
```
### 端口含义
其余基础设施通常为:
| 变量 | 用途 | 默认值 | 说明 |
|------|------|--------|------|
| `PORT` | 应用监听端口 | 8000 | FastAPI/Uvicorn 服务监听的端口 |
| `HOST_PORT` | 宿主机映射端口 | 10001 | Docker Compose 映射到宿主机的端口 |
### 使用场景
#### 1. 本地直接运行(Python)
```bash
python src/main.py
```env
DB_PORT=5432
REDIS_PORT=6379
```
服务将在 `http://localhost:8000` 启动(使用 `PORT` 配置)
#### 2. Docker Compose 运行
```bash
docker-compose up
对象存储常见端口(由服务器既有服务提供):
```env
RUSTFS_ENDPOINT=http://localhost:9000
```
服务将在 `http://localhost:10001` 访问(使用 `HOST_PORT` 配置)
容器内部使用 `PORT` 配置的端口(8000)
#### 3. 修改端口
---
**场景A:只想修改外部访问端口(Docker)**
```bash
# .env 文件
PORT=8000 # 容器内不变
HOST_PORT=8080 # 宿主机改为8080
## 2. 各端口的含义
| 变量 / 端口 | 用途 |
|---|---|
| `MOLDINSIGHT_PORT` | gemold API 宿主机暴露端口 |
| `INVENTORY_PORT` | inventory API 宿主机暴露端口 |
| `DB_PORT` | PostgreSQL 端口 |
| `REDIS_PORT` | Redis 端口 |
| `9000` | MinIO/RustFS S3 兼容 API |
| `9001` | MinIO 控制台 |
---
## 3. 推荐配置方式
### 3.1 gemold-only
```env
MOLDINSIGHT_PORT=8000
DB_PORT=5432
REDIS_PORT=6379
```
访问地址:`http://localhost:8080`
**场景B:修改应用端口(容器内/本地运行)**
```bash
# .env 文件
PORT=9000 # 应用改为9000
HOST_PORT=10001 # 宿主机映射到10001
### 3.2 inventory-only
```env
INVENTORY_PORT=8001
DB_PORT=5432
REDIS_PORT=6379
```
- 本地运行:`http://localhost:9000`
- Docker运行:`http://localhost:10001` (映射到容器内9000)
**场景C:同时修改两个端口**
```bash
# .env 文件
PORT=9000
HOST_PORT=9000
### 3.3 full / 模块同时部署
```env
MOLDINSIGHT_PORT=8000
INVENTORY_PORT=8001
DB_PORT=5432
REDIS_PORT=6379
```
- 本地运行:`http://localhost:9000`
- Docker运行:`http://localhost:9000`
## 配置文件说明
---
### 配置读取优先级
## 4. 为什么不再强调单一 `PORT` 变量
1. **`config/settings.py`** - 从 `.env` 读取 `PORT` 和 `HOST`
2. **`src/main.py`** - 从 `settings` 获取端口配置
3. **`docker-compose.yml`** - 从 `.env` 读取 `HOST_PORT` 和 `PORT`
历史单体部署通常只有一个后端入口,因此 `PORT=8000` 足够。
### 相关文件
当前项目已经是:
- gemold 独立入口
- inventory 独立入口
- unified 作为组合模式而非默认单体入口
- **`.env`** - ⭐ 唯一需要修改的配置文件
- **`config/settings.py`** - 配置读取逻辑(无需修改)
- **`src/main.py`** - 使用配置启动服务(无需修改)
- **`docker-compose.yml`** - Docker端口映射(自动读取 `.env`)
- **`start.sh` / `start_fixed.sh`** - 启动脚本(自动读取 `.env`)
因此端口配置必须模块化:
## 常见问题
- gemold 一个端口
- inventory 一个端口
- 如果 unified 对外存在,可以由网关统一暴露 80/443
### Q: 为什么 Docker 宿主机端口和应用端口分开配置?
A: 这样可以灵活调整容器端口而不影响外部访问,也避免端口冲突。
这比继续强行把所有模式压成一个 `PORT` 更清晰,也更符合真实部署方式。
### Q: 修改后需要重启吗?
A: 是的,修改 `.env` 后需要重启服务才能生效:
- 本地运行:Ctrl+C 停止后重新 `python src/main.py`
- Docker: `docker-compose down && docker-compose up`
---
### Q: 如何避免端口冲突?
A: 确保 `HOST_PORT` 不与其他服务冲突,可以使用 `netstat -an | grep <端口>` 检查端口占用情况。
## 5. 直接运行与 Compose 的区别
### Q: 可以使用 80 端口吗?
A: 可以,但需要管理员权限:
- Linux/Mac: 使用 sudo
- Docker: 需要容器有足够权限
- 生产环境建议使用反向代理(如 Nginx)
### 直接运行
gemold:
```bash
uvicorn src.entrypoints.moldinsight:app --port 8000
```
inventory:
```bash
uvicorn src.entrypoints.inventory:app --port 8001
```
### Docker Compose
Compose 通过端口映射暴露服务:
- gemold → `${MOLDINSIGHT_PORT}:8000`
- inventory → `${INVENTORY_PORT}:8001`
当前实际定义见:
- [docker-compose.yml](../../docker-compose.yml)
---
## 6. 与前端配置的关系
前端是否使用 unified / split deployment,会影响前端 API 地址配置。
### unified
- 一个 API 基地址
### split
- gemold 与 inventory 各自基地址
因此,修改后端端口后,可能还需要同步:
- 前端 `.env`
- Nginx 反向代理
- 浏览器访问地址
---
## 7. 推荐实践
1. **本地开发**
- gemold:8000
- inventory:8001
2. **服务器部署**
- 外网只暴露 80/443
- Nginx 反代到 8000 / 8001
3. **不要继续把所有部署模式都写成 `src.main:app + PORT=8000`**
- 这已不符合当前架构
---
## 8. 关联文档
- [LINUX_SETUP.md](./LINUX_SETUP.md)
- [DEPLOY_PORT.md](./DEPLOY_PORT.md)
- [BACKEND_MODULARIZATION_BLUEPRINT.md](../BACKEND_MODULARIZATION_BLUEPRINT.md)
- [README.md](../../README.md)
+26 -179
View File
@@ -1,192 +1,39 @@
# 端口配置重构总结
# 端口配置历史说明(已被模块化部署文档取代)
## 修改内容
本文件保留为历史说明。
本次重构将项目的端口配置统一到 `.env` 文件中,确保整个项目只有一个地方需要修改端口。
它所描述的“单体应用单一端口配置”思路,已经不再能完整代表当前 geMoldInsight 的模块化架构。
## 修改的文件
当前项目已演进为:
### 1. ⭐ `.env` - 唯一配置入口
**变更:** 添加了统一的端口配置区域
```bash
# ================================
# 端口配置 - 唯一修改端口的地方
# ================================
# 应用端口(容器内端口)
PORT=8000
# Docker映射到宿主机的端口(docker-compose使用)
HOST_PORT=10001
# ================================
```
- gemold 模块可独立部署
- inventory 模块可独立部署
- unified 作为组合模式存在
- gemold 与 inventory 应分别考虑端口与网关暴露方式
### 2. `src/main.py`
**变更:** 从硬编码的环境变量读取改为从 `config.settings` 读取
```python
# 修改前
host = os.getenv('HOST', '0.0.0.0')
port = int(os.getenv('PORT', '8000'))
因此,端口配置的权威说明已转移到以下文档:
# 修改后
from config.settings import settings
# ...
host=settings.HOST,
port=settings.PORT
```
- [LINUX_SETUP.md](./LINUX_SETUP.md)
- [DEPLOY_PORT.md](./DEPLOY_PORT.md)
- [PORT_CONFIG.md](./PORT_CONFIG.md)
- [BACKEND_MODULARIZATION_BLUEPRINT.md](../BACKEND_MODULARIZATION_BLUEPRINT.md)
### 3. `docker-compose.yml`
**变更:** 端口映射从硬编码改为从环境变量读取
```yaml
# 修改前
ports:
- "10001:8000"
environment:
- PORT=8000
---
# 修改后
ports:
- "${HOST_PORT:-10001}:${CONTAINER_PORT:-8000}"
environment:
- HOST=${HOST:-0.0.0.0}
- PORT=${CONTAINER_PORT:-8000}
```
## 当前结论
### 4. `start.sh` 和 `start_fixed.sh`
**变更:** 自动从 `.env` 读取端口并显示正确的访问地址
```bash
# 添加
PORT=$(grep '^PORT=' .env 2>/dev/null | cut -d'=' -f2 || echo '8000')
echo "🌐 服务将在 http://localhost:${PORT} 启动"
```
1. 不再默认以历史单体 `src.main:app` 作为部署中心。
2. 不再假设整个系统只有一个后端端口。
3. gemold 与 inventory 应按模块分别规划端口。
4. unified 更适合通过组合层或网关统一暴露,而不是继续沿用旧单体部署语义。
### 5. `README.md`
**变更:** 更新访问说明,提示端口配置位置
---
### 6. 新增文件
- `.env.example` - 配置文件模板
- `PORT_CONFIG.md` - 端口配置详细说明
- `DEPLOY_PORT.md` - 部署时端口配置指南
## 建议
## 配置读取流程
如果你正在查找当前有效的端口/部署方式,请不要继续参考旧的单体端口说明,而应直接查看:
```
.env 文件
↓
config/settings.py (读取 PORT 和 HOST)
↓
src/main.py (使用 settings.PORT)
↓
uvicorn 启动服务
```
Docker 部署流程:
```
.env 文件
↓
docker-compose.yml (读取 HOST_PORT 和 PORT)
↓
容器映射和内部启动
```
## 如何修改端口
### 方法 1:修改应用端口
```bash
# 编辑 .env
PORT=9000 # 修改此行
```
- 本地运行:`http://localhost:9000`
- Docker运行:需同时修改 `HOST_PORT=9000`
### 方法 2:修改 Docker 外部访问端口
```bash
# 编辑 .env
HOST_PORT=8080 # 修改此行(PORT 保持不变)
```
- Docker运行:`http://localhost:8080`
- 容器内仍使用 PORT 配置的端口
## 测试验证
### 测试 1:本地运行
```bash
# 修改 .env 中的 PORT
PORT=9999
# 启动服务
python src/main.py
# 验证
curl http://localhost:9999/health
```
### 测试 2:Docker 运行
```bash
# 修改 .env
PORT=8000
HOST_PORT=9999
# 启动容器
docker-compose up -d
# 验证
curl http://localhost:9999/health
```
### 测试 3:启动脚本
```bash
# 修改 .env
PORT=8888
# 运行启动脚本
./start.sh
# 检查输出是否显示正确的端口
```
## 注意事项
1. ✅ 所有端口配置集中在 `.env` 文件
2. ✅ 无需修改代码文件即可更改端口
3. ✅ 支持本地运行和 Docker 部署两种场景
4. ✅ 提供了详细的配置文档
5. ⚠️ 修改端口后需要重启服务
6. ⚠️ Docker 部署时需要同时考虑容器内外端口
7. ⚠️ 确保新端口没有被占用
## 文件清单
### 修改的文件
- `.env` - 添加端口配置区域
- `src/main.py` - 统一使用 settings 配置
- `docker-compose.yml` - 支持环境变量配置端口
- `start.sh` - 自动读取和显示端口
- `start_fixed.sh` - 自动读取和显示端口
- `README.md` - 更新访问说明
### 新增的文件
- `.env.example` - 配置模板
- `PORT_CONFIG.md` - 端口配置详细说明
- `DEPLOY_PORT.md` - 部署配置指南
- `PORT_REFACTOR_SUMMARY.md` - 本文档
## 回滚方案
如果需要回滚,按以下步骤操作:
```bash
git checkout -- src/main.py
git checkout -- docker-compose.yml
git checkout -- start.sh start_fixed.sh
git checkout -- .env
git checkout -- README.md
# 删除新增文件
rm .env.example PORT_CONFIG.md DEPLOY_PORT.md PORT_REFACTOR_SUMMARY.md
```
## 联系支持
如有问题,请查看:
- `PORT_CONFIG.md` - 端口配置详细说明
- `DEPLOY_PORT.md` - 部署配置指南
- `.env.example` - 配置示例
- [README.md](../../README.md)
- [LINUX_SETUP.md](./LINUX_SETUP.md)
- [DEPLOY_PORT.md](./DEPLOY_PORT.md)
- [PORT_CONFIG.md](./PORT_CONFIG.md)