init: 项目初始提交 - NeoZQYY Monorepo 完整代码
This commit is contained in:
11
apps/etl/pipelines/feiqiu/docs/operations/README.md
Normal file
11
apps/etl/pipelines/feiqiu/docs/operations/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# 运维文档
|
||||
|
||||
本目录包含飞球 ETL 系统的运维相关指南。
|
||||
|
||||
## 文档索引
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [environment_setup.md](environment_setup.md) | 环境搭建指南:Python、PostgreSQL、依赖安装与配置 |
|
||||
| [scheduling.md](scheduling.md) | 调度配置说明:CLI 参数、管道模式、时间窗口与处理模式 |
|
||||
| [troubleshooting.md](troubleshooting.md) | 故障排查手册:常见错误与解决方案 |
|
||||
134
apps/etl/pipelines/feiqiu/docs/operations/environment_setup.md
Normal file
134
apps/etl/pipelines/feiqiu/docs/operations/environment_setup.md
Normal file
@@ -0,0 +1,134 @@
|
||||
# 环境搭建指南
|
||||
|
||||
## 1. 前置条件
|
||||
|
||||
| 组件 | 版本要求 | 说明 |
|
||||
|------|----------|------|
|
||||
| Python | 3.10+ | 推荐 3.12 或 3.13 |
|
||||
| PostgreSQL | 远程实例 | 需要可访问的 PostgreSQL 服务 |
|
||||
| pip | 最新版 | Python 包管理器 |
|
||||
|
||||
## 2. 安装步骤
|
||||
|
||||
### 2.1 克隆仓库并创建虚拟环境
|
||||
|
||||
```bash
|
||||
git clone <repo-url> etl-billiards
|
||||
cd etl-billiards
|
||||
|
||||
# 创建并激活虚拟环境
|
||||
python -m venv .venv
|
||||
# Linux/macOS
|
||||
source .venv/bin/activate
|
||||
# Windows
|
||||
.venv\Scripts\activate
|
||||
```
|
||||
|
||||
### 2.2 安装依赖
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
核心依赖说明:
|
||||
|
||||
| 包名 | 用途 |
|
||||
|------|------|
|
||||
| `psycopg2-binary` | PostgreSQL 驱动 |
|
||||
| `requests` | 上游 API HTTP 客户端 |
|
||||
| `python-dateutil` / `tzdata` | 日期解析与时区处理 |
|
||||
| `python-dotenv` | `.env` 文件加载 |
|
||||
| `openpyxl` | Excel 导入导出(DWS 数据) |
|
||||
| `PySide6` | Qt 桌面 GUI 框架 |
|
||||
| `flask` | 可选 Web API |
|
||||
|
||||
如需运行测试,还需安装:
|
||||
|
||||
```bash
|
||||
pip install pytest hypothesis
|
||||
```
|
||||
|
||||
### 2.3 配置环境变量
|
||||
|
||||
在项目根目录创建 `.env` 文件(禁止提交到版本控制):
|
||||
|
||||
```dotenv
|
||||
# 数据库连接
|
||||
PG_DSN=postgresql://用户名:密码@主机:端口/数据库名
|
||||
# 或分别指定
|
||||
PG_HOST=localhost
|
||||
PG_PORT=5432
|
||||
PG_NAME=billiards
|
||||
PG_USER=your_user
|
||||
PG_PASSWORD=your_password
|
||||
|
||||
# 门店与 API
|
||||
STORE_ID=1
|
||||
API_TOKEN=your_bearer_token
|
||||
|
||||
# 可选
|
||||
APP_TIMEZONE=Asia/Shanghai
|
||||
```
|
||||
|
||||
> **安全提示**:`.env` 文件包含敏感信息,已在 `.gitignore` 中排除。
|
||||
|
||||
## 3. 配置体系
|
||||
|
||||
系统采用三层配置叠加,优先级从低到高:
|
||||
|
||||
```
|
||||
config/defaults.py → .env / 环境变量 → CLI 参数
|
||||
```
|
||||
|
||||
- 默认值定义在 `config/defaults.py`
|
||||
- 环境变量通过 `python-dotenv` 加载,由 `config/env_parser.py` 解析
|
||||
- CLI 参数拥有最高优先级,可覆盖前两层
|
||||
- 通过 `AppConfig.get("dotted.path")` 访问配置值,例如 `config.get("db.dsn")`
|
||||
|
||||
## 4. 数据库初始化
|
||||
|
||||
系统使用四个 Schema:
|
||||
|
||||
| Schema | 用途 |
|
||||
|--------|------|
|
||||
| `billiards_ods` | ODS 原始数据层 |
|
||||
| `billiards_dwd` | DWD 明细数据层 |
|
||||
| `billiards_dws` | DWS 汇总数据层 |
|
||||
| `etl_admin` | 调度与运行记录 |
|
||||
|
||||
初始化步骤:
|
||||
|
||||
```bash
|
||||
# 1. 执行 DDL 创建表结构
|
||||
psql "$PG_DSN" -f database/schema_ods.sql
|
||||
psql "$PG_DSN" -f database/schema_dwd.sql
|
||||
psql "$PG_DSN" -f database/schema_dws.sql
|
||||
psql "$PG_DSN" -f database/schema_etl_admin.sql
|
||||
|
||||
# 2. 执行种子数据(如有)
|
||||
psql "$PG_DSN" -f database/seed_*.sql
|
||||
|
||||
# 3. 执行迁移脚本(按日期前缀顺序)
|
||||
ls database/migrations/*.sql | sort | xargs -I {} psql "$PG_DSN" -f {}
|
||||
```
|
||||
|
||||
## 5. 验证安装
|
||||
|
||||
```bash
|
||||
# 试运行(不写库),确认连接和配置正常
|
||||
python -m cli.main --dry-run --tasks ODS_MEMBER --store-id 1
|
||||
|
||||
# 运行单元测试
|
||||
pytest tests/unit
|
||||
|
||||
# 运行集成测试(需要数据库)
|
||||
TEST_DB_DSN="postgresql://..." pytest tests/integration
|
||||
```
|
||||
|
||||
## 6. 运行入口
|
||||
|
||||
| 入口 | 命令 | 说明 |
|
||||
|------|------|------|
|
||||
| CLI | `python -m cli.main` | 主入口,支持全部参数 |
|
||||
| GUI | `python -m gui.main` | PySide6 桌面界面 |
|
||||
| 批处理 | `run_etl.bat` / `run_gui.bat` | Windows 快捷脚本 |
|
||||
152
apps/etl/pipelines/feiqiu/docs/operations/scheduling.md
Normal file
152
apps/etl/pipelines/feiqiu/docs/operations/scheduling.md
Normal file
@@ -0,0 +1,152 @@
|
||||
# 调度配置说明
|
||||
|
||||
## 1. 运行模式概览
|
||||
|
||||
系统支持两种运行模式:
|
||||
|
||||
| 模式 | 说明 | 适用场景 |
|
||||
|------|------|----------|
|
||||
| **任务模式** | 通过 `--tasks` 指定具体任务代码 | 单任务调试、手动补数 |
|
||||
| **管道模式** | 通过 `--pipeline` 指定管道类型 | 日常增量、全流程运行 |
|
||||
|
||||
## 2. CLI 参数详解
|
||||
|
||||
### 2.1 基本参数
|
||||
|
||||
```bash
|
||||
python -m cli.main [参数]
|
||||
```
|
||||
|
||||
| 参数 | 说明 | 示例 |
|
||||
|------|------|------|
|
||||
| `--store-id` | 门店 ID(整数) | `--store-id 1` |
|
||||
| `--tasks` | 任务列表,逗号分隔(任务模式) | `--tasks ODS_MEMBER,ODS_ORDER` |
|
||||
| `--dry-run` | 试运行,不提交数据库事务 | `--dry-run` |
|
||||
| `--pg-dsn` | PostgreSQL 连接字符串 | `--pg-dsn "postgresql://..."` |
|
||||
| `--api-token` | API Bearer Token | `--api-token "xxx"` |
|
||||
|
||||
### 2.2 管道参数
|
||||
|
||||
| 参数 | 说明 | 可选值 |
|
||||
|------|------|--------|
|
||||
| `--pipeline` | 管道类型 | 见下方管道定义表 |
|
||||
| `--processing-mode` | 处理模式(默认 `increment_only`) | `increment_only` / `verify_only` / `increment_verify` |
|
||||
| `--fetch-before-verify` | 校验前先从 API 获取数据 | 仅在 `verify_only` 模式下有效 |
|
||||
| `--verify-tables` | 仅校验指定表(逗号分隔) | `--verify-tables "dim_member,fact_order"` |
|
||||
|
||||
### 2.3 时间窗口参数
|
||||
|
||||
| 参数 | 说明 | 默认值 |
|
||||
|------|------|--------|
|
||||
| `--window-start` | 固定窗口开始时间 | 当前时间 - 24h |
|
||||
| `--window-end` | 固定窗口结束时间 | 当前时间 |
|
||||
| `--window-split` | 窗口切分粒度 | `none`(可选 `day` / `week` / `month`) |
|
||||
| `--lookback-hours` | 回溯小时数 | `24` |
|
||||
| `--overlap-seconds` | 冗余秒数(窗口重叠) | `3600` |
|
||||
| `--force-window-override` | 强制使用指定窗口,不走游标兜底 | 关闭 |
|
||||
|
||||
### 2.4 数据源参数
|
||||
|
||||
| 参数 | 说明 | 可选值 |
|
||||
|------|------|--------|
|
||||
| `--data-source` | 数据源模式 | `online`(仅 API 抓取)/ `offline`(仅本地入库)/ `hybrid`(抓取+入库) |
|
||||
| `--fetch-root` | 抓取 JSON 输出根目录 | 默认 `export/JSON` |
|
||||
| `--ingest-source` | 本地清洗入库源目录 | — |
|
||||
|
||||
> `--pipeline-flow` 已弃用,请使用 `--data-source` 替代。映射关系:`FULL` → `hybrid`,`FETCH_ONLY` → `online`,`INGEST_ONLY` → `offline`。
|
||||
|
||||
## 3. 管道定义
|
||||
|
||||
每个管道包含一组按顺序执行的 ETL 层:
|
||||
|
||||
| 管道名称 | 包含层 | 典型用途 |
|
||||
|----------|--------|----------|
|
||||
| `api_ods` | ODS | 仅从 API 抓取原始数据 |
|
||||
| `api_ods_dwd` | ODS → DWD | 抓取并清洗至明细层 |
|
||||
| `api_full` | ODS → DWD → DWS → INDEX | 全流程(抓取→清洗→汇总→指数) |
|
||||
| `ods_dwd` | DWD | 从 ODS 清洗至 DWD(不抓取) |
|
||||
| `dwd_dws` | DWS | 从 DWD 汇总至 DWS |
|
||||
| `dwd_dws_index` | DWS → INDEX | 汇总并计算指数 |
|
||||
| `dwd_index` | INDEX | 仅计算指数 |
|
||||
|
||||
## 4. 处理模式
|
||||
|
||||
| 模式 | 说明 |
|
||||
|------|------|
|
||||
| `increment_only` | 仅执行增量 ETL(默认) |
|
||||
| `verify_only` | 跳过增量,仅执行校验并修复 |
|
||||
| `increment_verify` | 先增量 ETL,再校验并修复 |
|
||||
|
||||
校验模式下可配合 `--fetch-before-verify` 先从 API 获取最新数据再校验。
|
||||
|
||||
## 5. 常用命令示例
|
||||
|
||||
```bash
|
||||
# 日常增量:全流程管道
|
||||
python -m cli.main --pipeline api_full --store-id 1
|
||||
|
||||
# 仅抓取 ODS 数据
|
||||
python -m cli.main --pipeline api_ods --store-id 1
|
||||
|
||||
# 指定任务模式
|
||||
python -m cli.main --tasks ODS_MEMBER,ODS_ORDER --store-id 1
|
||||
|
||||
# 校验并修复(先获取 API 数据)
|
||||
python -m cli.main --pipeline api_full --processing-mode verify_only --fetch-before-verify
|
||||
|
||||
# 增量 + 校验
|
||||
python -m cli.main --pipeline api_full --processing-mode increment_verify
|
||||
|
||||
# 指定时间窗口
|
||||
python -m cli.main --pipeline api_ods --window-start "2026-02-01" --window-end "2026-02-02"
|
||||
|
||||
# 按天切分窗口
|
||||
python -m cli.main --pipeline api_full --window-split day --window-split-days 10
|
||||
|
||||
# 试运行
|
||||
python -m cli.main --dry-run --tasks DWD_LOAD_FROM_ODS
|
||||
```
|
||||
|
||||
## 6. 定时任务配置
|
||||
|
||||
### 6.1 使用系统定时任务
|
||||
|
||||
Linux(crontab)示例:
|
||||
|
||||
```cron
|
||||
# 每天凌晨 4:00 执行全流程增量
|
||||
0 4 * * * cd /path/to/etl-billiards && .venv/bin/python -m cli.main --pipeline api_full --store-id 1 >> /var/log/etl.log 2>&1
|
||||
```
|
||||
|
||||
Windows(任务计划程序)示例:
|
||||
|
||||
```
|
||||
程序:C:\path\to\etl-billiards\.venv\Scripts\python.exe
|
||||
参数:-m cli.main --pipeline api_full --store-id 1
|
||||
起始于:C:\path\to\etl-billiards
|
||||
```
|
||||
|
||||
### 6.2 闲时窗口
|
||||
|
||||
系统支持闲时窗口配置,在闲时使用更大的时间窗口以减少 API 调用频率:
|
||||
|
||||
| 配置项 | 默认值 | 说明 |
|
||||
|--------|--------|------|
|
||||
| `run.idle_window.start` | `04:00` | 闲时开始 |
|
||||
| `run.idle_window.end` | `16:00` | 闲时结束 |
|
||||
| `run.window_minutes.default_busy` | `30` | 忙时窗口(分钟) |
|
||||
| `run.window_minutes.default_idle` | `180` | 闲时窗口(分钟) |
|
||||
|
||||
CLI 参数覆盖:`--idle-start "04:00" --idle-end "16:00"`
|
||||
|
||||
## 7. 游标与增量机制
|
||||
|
||||
系统通过 `CursorManager` 管理每个任务的增量水位(游标):
|
||||
|
||||
- 每个任务 + 门店组合维护独立的游标记录
|
||||
- 游标存储在 `etl_admin` Schema 中
|
||||
- 每次成功执行后,游标自动推进到当前窗口结束时间
|
||||
- `--force-window-override` 可强制使用指定窗口,绕过游标
|
||||
- `--allow-empty-advance` 允许空结果时仍推进游标
|
||||
|
||||
`RunTracker` 记录每次运行的状态、计数和耗时,用于运行历史追溯。
|
||||
140
apps/etl/pipelines/feiqiu/docs/operations/troubleshooting.md
Normal file
140
apps/etl/pipelines/feiqiu/docs/operations/troubleshooting.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# 故障排查手册
|
||||
|
||||
## 1. 数据库连接问题
|
||||
|
||||
### 1.1 连接超时
|
||||
|
||||
**现象**:`psycopg2.OperationalError: connection timed out` 或启动后长时间无响应。
|
||||
|
||||
**排查步骤**:
|
||||
1. 确认 `PG_DSN` 或 `PG_HOST`/`PG_PORT` 配置正确
|
||||
2. 确认 PostgreSQL 服务可达:`pg_isready -h <host> -p <port>`
|
||||
3. 检查防火墙/安全组是否放行端口
|
||||
4. 系统限制连接超时为 1–20 秒(`db.connect_timeout_sec`,默认 20 秒)
|
||||
|
||||
### 1.2 认证失败
|
||||
|
||||
**现象**:`FATAL: password authentication failed for user "xxx"`
|
||||
|
||||
**排查步骤**:
|
||||
1. 确认 `.env` 中的 `PG_USER` 和 `PG_PASSWORD` 正确
|
||||
2. 确认 PostgreSQL 的 `pg_hba.conf` 允许远程连接
|
||||
3. 如使用 DSN 格式,确认密码中的特殊字符已 URL 编码
|
||||
|
||||
### 1.3 Schema 不存在
|
||||
|
||||
**现象**:`relation "billiards_ods.xxx" does not exist`
|
||||
|
||||
**解决方案**:执行 DDL 初始化脚本,参见 [环境搭建指南](environment_setup.md#4-数据库初始化)。
|
||||
|
||||
## 2. API 相关问题
|
||||
|
||||
### 2.1 API Token 无效
|
||||
|
||||
**现象**:HTTP 401 或 403 错误。
|
||||
|
||||
**排查步骤**:
|
||||
1. 确认 `.env` 中的 `API_TOKEN` 有效且未过期
|
||||
2. 可通过 CLI 参数 `--api-token` 临时覆盖测试
|
||||
3. 检查 Token 是否包含多余空格或换行符
|
||||
|
||||
### 2.2 API 超时
|
||||
|
||||
**现象**:`requests.exceptions.Timeout` 或 `ReadTimeout`
|
||||
|
||||
**排查步骤**:
|
||||
1. 默认超时为 20 秒(`api.timeout_sec`),可通过 `--api-timeout` 调大
|
||||
2. 系统自动重试最多 3 次(退避间隔 1/2/4 秒)
|
||||
3. 检查网络连通性和上游服务状态
|
||||
|
||||
### 2.3 API 分页数据不完整
|
||||
|
||||
**现象**:抓取的记录数明显少于预期。
|
||||
|
||||
**排查步骤**:
|
||||
1. 检查时间窗口是否覆盖目标范围(`--window-start` / `--window-end`)
|
||||
2. 确认分页大小设置合理(`api.page_size`,默认 200)
|
||||
3. 使用 `--dry-run` 查看实际请求的时间窗口
|
||||
|
||||
## 3. ETL 任务问题
|
||||
|
||||
### 3.1 任务代码不存在
|
||||
|
||||
**现象**:`ValueError: 未注册的任务代码: XXX`
|
||||
|
||||
**解决方案**:确认任务代码拼写正确(大写蛇形命名),可用的任务代码在 `orchestration/task_registry.py` 中注册。
|
||||
|
||||
### 3.2 DWD 装载失败
|
||||
|
||||
**现象**:`DWD_LOAD_FROM_ODS` 任务报错或数据不一致。
|
||||
|
||||
**排查步骤**:
|
||||
1. 确认 ODS 层数据已成功入库
|
||||
2. 检查是否有 Schema 变更未执行迁移脚本
|
||||
3. 查看日志中的具体错误信息(字段类型不匹配、约束冲突等)
|
||||
|
||||
### 3.3 DWS 汇总数据异常
|
||||
|
||||
**现象**:汇总指标与明细数据不一致。
|
||||
|
||||
**排查步骤**:
|
||||
1. 使用 `--processing-mode verify_only` 执行校验
|
||||
2. 配合 `--verify-tables` 指定具体表进行单表验证
|
||||
3. 检查 DWD 层数据是否完整(时间窗口是否覆盖)
|
||||
|
||||
### 3.4 锁冲突
|
||||
|
||||
**现象**:`ERROR: deadlock detected` 或 `lock timeout`
|
||||
|
||||
**排查步骤**:
|
||||
1. 避免多个 ETL 进程同时运行
|
||||
2. 调整锁超时:`db.session.lock_timeout_ms`(默认 5000ms)
|
||||
3. 事实表 upsert 可调整批量大小:`dwd.fact_upsert_batch_size`(默认 1000)
|
||||
|
||||
## 4. 配置问题
|
||||
|
||||
### 4.1 缺少必需配置
|
||||
|
||||
**现象**:`SystemExit: 缺少必需配置: app.store_id`
|
||||
|
||||
**解决方案**:在 `.env` 中设置 `STORE_ID`,或通过 CLI 参数 `--store-id` 指定。
|
||||
|
||||
### 4.2 配置优先级不符合预期
|
||||
|
||||
**排查步骤**:配置加载顺序为 `config/defaults.py` → `.env` → CLI 参数,后者覆盖前者。使用 `--dry-run` 可在不写库的情况下验证最终配置。
|
||||
|
||||
### 4.3 弃用配置警告
|
||||
|
||||
**现象**:`DeprecationWarning: 配置键 pipeline.flow=XXX 已弃用`
|
||||
|
||||
**解决方案**:将 `.env` 中的 `PIPELINE_FLOW` 替换为 `DATA_SOURCE`。映射关系:`FULL` → `hybrid`,`FETCH_ONLY` → `online`,`INGEST_ONLY` → `offline`。
|
||||
|
||||
## 5. 运行环境问题
|
||||
|
||||
### 5.1 Python 版本不兼容
|
||||
|
||||
**现象**:`SyntaxError` 或类型注解相关错误。
|
||||
|
||||
**解决方案**:确认 Python 版本 ≥ 3.10。代码使用了 `X | Y` 联合类型语法(3.10+)。
|
||||
|
||||
### 5.2 依赖缺失
|
||||
|
||||
**现象**:`ModuleNotFoundError: No module named 'xxx'`
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### 5.3 编码问题
|
||||
|
||||
**现象**:`UnicodeDecodeError` 或中文乱码。
|
||||
|
||||
**解决方案**:确保终端和文件编码为 UTF-8。Windows 下可设置 `chcp 65001`。
|
||||
|
||||
## 6. 日志与调试
|
||||
|
||||
- 日志通过 `utils/logging_utils.py` 统一管理
|
||||
- 日志输出目录:`export/LOG`(可通过 `--log-root` 覆盖)
|
||||
- 使用 `--dry-run` 进行试运行,不提交数据库事务
|
||||
- 安全配置 `security.redact_in_logs` 默认开启,敏感字段(token、password)在日志中自动脱敏
|
||||
Reference in New Issue
Block a user