refactor(dnfs): 删除默认配置逻辑,confs 改为强依赖
- 配置加载从三层(默认值→confs→环境变量)改为两层(confs 强依赖→环境变量覆盖) - confs 连接失败直接 sys.exit(1),不再静默使用内置默认值 - _dnfs_config 初始值改为空字符串白名单模板,移除内置默认值 - 新增配置完整性校验:confs 返回后检查所有必需 section/key 非空 - 区分错误类型:连接拒绝/RpcError/通用异常分别打印明确错误信息到 stderr - confs 连接地址改为引导配置(环境变量优先,默认 127.0.0.1:8010),移除 dnfs.ini 中 [confs] 段 - 启动顺序调整为 confs → db → dnfs → ai_review/...(dnfs 同时依赖 confs 和 db) - 更新 dnfs/README.md 与 confs/README.md 文档
This commit is contained in:
1 parent
2cbb93b3b7
commit
84adec4722
4 files changed
+81
-47
No files matched your search
+6
-3
@@ -236,7 +236,7 @@ except RpcError as e:
|
||||
| 服务 | 配置文件 | 接入方式 |
|
||||
|------|---------|---------|
|
||||
| [static](../static/) | [static.ini](configs/static.ini) | 三层 fail-safe:内置默认值 → confs(优先)→ 本地 `config.ini` 回退 |
|
||||
| [dnfs](../dnfs/) | [dnfs.ini](configs/dnfs.ini) | 三层 fail-safe:内置默认值 → confs(优先)→ 环境变量覆盖 |
|
||||
| [dnfs](../dnfs/) | [dnfs.ini](configs/dnfs.ini) | confs 强依赖(confs 不可用时 dnfs 直接退出)→ 环境变量覆盖(最高优先级,Docker 兼容) |
|
||||
| [db](../db/) | [db.ini](configs/db.ini) | confs 强依赖(confs 不可用时 db 直接退出)→ 环境变量覆盖(最高优先级,Docker 兼容) |
|
||||
|
||||
static 的接入实现见 [static/fsys.py](../static/fsys.py):
|
||||
@@ -246,9 +246,12 @@ static 的接入实现见 [static/fsys.py](../static/fsys.py):
|
||||
- 配置来源会记录到日志(`logs.info/warning`),便于排查实际用了哪一层
|
||||
|
||||
dnfs 的接入实现见 [dnfs/dnfs.py](../dnfs/dnfs.py):
|
||||
- 三层加载顺序:内置默认值 → confs(dnfs.ini)→ 环境变量覆盖(优先级最高)
|
||||
- 两层加载顺序:confs(dnfs.ini,强依赖)→ 环境变量覆盖(优先级最高)
|
||||
- confs 连接失败或 dnfs.ini 缺失必需配置项时,dnfs 直接 `sys.exit(1)` 终止,不使用默认值
|
||||
- 配置项涵盖:`[server]` host/port、`[database]` host/port/timeout、`[ai_review]` url/timeout
|
||||
- confs 连接地址为引导配置:环境变量 `CONFS_HOST`/`CONFS_PORT` 优先,默认 `127.0.0.1:8010`
|
||||
- 支持的环境变量:`LISTEN_ADDR`/`LISTEN_PORT`/`DB_HOST`/`DB_PORT`/`REVIEW_URL`/`CONFS_HOST`/`CONFS_PORT`
|
||||
- Docker 环境通过环境变量传入服务名(db/ai_review),覆盖 confs 中的 127.0.0.1 默认值
|
||||
- 启动顺序:confs → db → dnfs → ai_review/...(dnfs 同时依赖 confs 和 db)
|
||||
|
||||
db 的接入实现见 [db/dbv2.py](../db/dbv2.py):
|
||||
- 两层加载顺序:confs(db.ini,强依赖)→ 环境变量覆盖(优先级最高)
|
||||
|
||||
@@ -10,7 +10,3 @@ timeout = 10
|
||||
[ai_review]
|
||||
url = http://127.0.0.1:8007/review
|
||||
timeout = 10
|
||||
|
||||
[confs]
|
||||
host = 127.0.0.1
|
||||
port = 8010
|
||||
+28
-17
@@ -215,27 +215,32 @@ curl -X POST http://localhost:8006/update_note \
|
||||
|
||||
## 配置
|
||||
|
||||
dnfs 已接入 confs 统一配置服务,采用**三层 fail-safe** 加载模式(与 static 服务一致):
|
||||
dnfs 已接入 confs 统一配置服务,confs 是 dnfs 启动的**强依赖**:
|
||||
|
||||
**加载顺序**:内置默认值 → confs 统一配置服务(dnfs.ini,优先)→ 环境变量覆盖(最高优先级)
|
||||
1. **confs 统一配置服务** — 必须成功从 confs 拉取 `dnfs.ini`,否则 dnfs 启动失败直接退出(exit code 1)
|
||||
2. **环境变量覆盖**(最高优先级)— Docker/部署环境通过环境变量覆盖 confs 中的值
|
||||
|
||||
### 配置文件
|
||||
|
||||
集中托管在 [confs/configs/dnfs.ini](../confs/configs/dnfs.ini),由 confs 服务分发:
|
||||
|
||||
| Section | Key | 默认值 | 说明 |
|
||||
|---------|-----|--------|------|
|
||||
| `[server]` | `host` | `127.0.0.1` | 监听地址 |
|
||||
| `[server]` | `port` | `8006` | 监听端口 |
|
||||
| `[database]` | `host` | `127.0.0.1` | db 服务地址 |
|
||||
| `[database]` | `port` | `8005` | db 服务端口 |
|
||||
| `[database]` | `timeout` | `10` | RPC 调用超时(秒) |
|
||||
| `[ai_review]` | `url` | `http://127.0.0.1:8007/review` | AI 审核接口地址 |
|
||||
| `[ai_review]` | `timeout` | `10` | AI 审核请求超时(秒) |
|
||||
| `[confs]` | `host` | `127.0.0.1` | confs 服务地址 |
|
||||
| `[confs]` | `port` | `8010` | confs 服务端口 |
|
||||
| Section | Key | 说明 |
|
||||
|---------|-----|------|
|
||||
| `[server]` | `host` | 监听地址 |
|
||||
| `[server]` | `port` | 监听端口 |
|
||||
| `[database]` | `host` | db 服务地址 |
|
||||
| `[database]` | `port` | db 服务端口 |
|
||||
| `[database]` | `timeout` | RPC 调用超时(秒) |
|
||||
| `[ai_review]` | `url` | AI 审核接口地址 |
|
||||
| `[ai_review]` | `timeout` | AI 审核请求超时(秒) |
|
||||
|
||||
### 环境变量(Docker 环境必需,优先级最高)
|
||||
### 引导配置(confs 连接地址)
|
||||
|
||||
confs 自身的连接地址不通过 confs 获取(避免循环依赖),通过以下方式确定(优先级从高到低):
|
||||
- 环境变量 `CONFS_HOST` / `CONFS_PORT`
|
||||
- 默认值 `127.0.0.1:8010`
|
||||
|
||||
### 环境变量(最高优先级,覆盖 confs 配置值)
|
||||
|
||||
环境变量覆盖配置文件值,容器化部署时通过 docker-compose.yml 传入服务名:
|
||||
|
||||
@@ -246,10 +251,16 @@ dnfs 已接入 confs 统一配置服务,采用**三层 fail-safe** 加载模
|
||||
| `DB_HOST` | `db` | db 服务主机名(docker-compose 服务名) |
|
||||
| `DB_PORT` | `8005` | db 服务端口 |
|
||||
| `REVIEW_URL` | `http://ai_review:8007/review` | ai_review 服务地址 |
|
||||
| `CONFS_HOST` | - | 可选,confs 容器化后使用 |
|
||||
| `CONFS_PORT` | - | 可选,confs 容器化后使用 |
|
||||
| `CONFS_HOST` | `confs` | confs 服务主机名(引导配置) |
|
||||
| `CONFS_PORT` | `8010` | confs 服务端口(引导配置) |
|
||||
|
||||
配置来源会记录到日志(`logs.info/warning`),便于排查实际用了哪一层。本地裸机运行时 confs 不可用会自动回退到内置默认值 + 环境变量。
|
||||
### 启动顺序要求
|
||||
|
||||
**confs 必须先于 dnfs 启动**(启动顺序:confs → db → dnfs → ai_review/...)。若 confs 不可用:
|
||||
- dnfs 打印致命错误到 stderr(包含 confs 地址和具体错误原因),以 exit code 1 终止
|
||||
- 不会静默使用默认值启动
|
||||
- 配置完整性校验:若 dnfs.ini 中缺少必需的 section/key 且无对应环境变量覆盖,同样报错退出
|
||||
- 启动成功时控制台打印:`配置来源: confs (dnfs.ini @ host:port)`
|
||||
|
||||
## 前端
|
||||
|
||||
|
||||
+47
-23
@@ -33,15 +33,21 @@ from log_client import logs
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
||||
from pymsg import RpcClient, RpcError # noqa: E402
|
||||
|
||||
# ==================== 配置加载(三层 fail-safe) ====================
|
||||
# 加载顺序:内置默认值 → confs 统一配置服务(dnfs.ini) → 环境变量覆盖
|
||||
# 环境变量优先级最高(Docker 环境使用服务名 db/ai_review 而非 127.0.0.1)
|
||||
# ==================== 配置加载(两层:confs 强依赖 → 环境变量覆盖) ====================
|
||||
# confs 是 dnfs 启动的强依赖:必须成功从 confs 拉取 dnfs.ini,否则直接退出。
|
||||
# 环境变量优先级最高(Docker 环境使用服务名 db/ai_review 而非 127.0.0.1)。
|
||||
# confs 自身的连接地址通过引导配置确定:环境变量 CONFS_HOST/CONFS_PORT 优先,
|
||||
# 缺省使用 127.0.0.1:8010(与其他服务一致的约定)。
|
||||
|
||||
# 引导配置:confs 连接地址(不依赖 confs 本身)
|
||||
_confs_host = os.environ.get('CONFS_HOST', '127.0.0.1')
|
||||
_confs_port = int(os.environ.get('CONFS_PORT', '8010'))
|
||||
|
||||
# 白名单结构:_merge_ini 仅覆盖此处列出的 section/key,防止意外字段
|
||||
_dnfs_config = {
|
||||
'server': {'host': '127.0.0.1', 'port': '8006'},
|
||||
'database': {'host': '127.0.0.1', 'port': '8005', 'timeout': '10'},
|
||||
'ai_review': {'url': 'http://127.0.0.1:8007/review', 'timeout': '10'},
|
||||
'confs': {'host': '127.0.0.1', 'port': '8010'},
|
||||
'server': {'host': '', 'port': ''},
|
||||
'database': {'host': '', 'port': '', 'timeout': ''},
|
||||
'ai_review': {'url': '', 'timeout': ''},
|
||||
}
|
||||
|
||||
|
||||
@@ -57,23 +63,29 @@ def _merge_ini(text):
|
||||
|
||||
|
||||
def _fetch_from_confs():
|
||||
"""从 confs 统一配置服务拉取 dnfs.ini 全文,失败返回 None(fail-safe)。"""
|
||||
"""从 confs 统一配置服务拉取 dnfs.ini 全文,失败直接终止进程。"""
|
||||
try:
|
||||
host = os.environ.get('CONFS_HOST', _dnfs_config['confs']['host'])
|
||||
port = int(os.environ.get('CONFS_PORT', _dnfs_config['confs']['port']))
|
||||
data = RpcClient(host, port, 'dnfs', timeout=3).call(
|
||||
data = RpcClient(_confs_host, _confs_port, 'dnfs', timeout=5).call(
|
||||
'get', {'name': 'dnfs.ini'})
|
||||
return data.get('content')
|
||||
except Exception:
|
||||
return None
|
||||
except (ConnectionRefusedError, ConnectionError, OSError) as e:
|
||||
print(f'[dnfs] 致命错误: 无法连接 confs 服务 ({_confs_host}:{_confs_port}): {e}',
|
||||
file=sys.stderr)
|
||||
print(f'[dnfs] 请确认 confs 服务已启动并监听 {_confs_host}:{_confs_port}',
|
||||
file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except RpcError as e:
|
||||
print(f'[dnfs] 致命错误: 从 confs 获取 dnfs.ini 失败: {e}',
|
||||
file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f'[dnfs] 致命错误: confs 配置拉取异常: {e}',
|
||||
file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
_confs_text = _fetch_from_confs()
|
||||
if _confs_text is not None:
|
||||
_merge_ini(_confs_text)
|
||||
logs.info("dnfs", "配置来源: confs 统一配置服务 (dnfs.ini)")
|
||||
else:
|
||||
logs.warning("dnfs", "confs 不可用,使用内置默认值 + 环境变量")
|
||||
_merge_ini(_confs_text)
|
||||
|
||||
# 环境变量覆盖(优先级最高,Docker 环境需要)
|
||||
if os.environ.get('LISTEN_ADDR'):
|
||||
@@ -86,20 +98,32 @@ if os.environ.get('DB_PORT'):
|
||||
_dnfs_config['database']['port'] = os.environ['DB_PORT']
|
||||
if os.environ.get('REVIEW_URL'):
|
||||
_dnfs_config['ai_review']['url'] = os.environ['REVIEW_URL']
|
||||
if os.environ.get('CONFS_HOST'):
|
||||
_dnfs_config['confs']['host'] = os.environ['CONFS_HOST']
|
||||
if os.environ.get('CONFS_PORT'):
|
||||
_dnfs_config['confs']['port'] = os.environ['CONFS_PORT']
|
||||
|
||||
# 配置完整性校验
|
||||
_required = {
|
||||
'server': ['host', 'port'],
|
||||
'database': ['host', 'port', 'timeout'],
|
||||
'ai_review': ['url', 'timeout'],
|
||||
}
|
||||
for section, keys in _required.items():
|
||||
for key in keys:
|
||||
if not _dnfs_config[section][key]:
|
||||
print(f'[dnfs] 致命错误: 配置项 [{section}] {key} 缺失(dnfs.ini 中未配置且无环境变量覆盖)',
|
||||
file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# 提取配置常量
|
||||
_DB_TIMEOUT = int(_dnfs_config['database']['timeout'])
|
||||
_DBV2_ADDR = _dnfs_config['database']['host']
|
||||
_DBV2_PORT = int(_dnfs_config['database']['port'])
|
||||
_DB_TIMEOUT = int(_dnfs_config['database']['timeout'])
|
||||
_REVIEW_SERVER_URL = _dnfs_config['ai_review']['url']
|
||||
_REVIEW_TIMEOUT = int(_dnfs_config['ai_review']['timeout'])
|
||||
_ADDR = _dnfs_config['server']['host']
|
||||
_PORT = int(_dnfs_config['server']['port'])
|
||||
|
||||
_config_source = f'confs (dnfs.ini @ {_confs_host}:{_confs_port})'
|
||||
print(f'[dnfs] 配置来源: {_config_source}')
|
||||
|
||||
# 管理员判定已上移至 gateway:登录时命中 [Admin] users 白名单即在 Token payload
|
||||
# 写入 is_admin=true,本服务通过 info.get('is_admin') 读取,不再本地维护名单。
|
||||
# 旧 Token 无此字段,按非管理员处理(安全方向)。
|
||||
|
||||
Reference in new issue
Block a user