主要变更: config - 引入 python-dotenv,从 .env 加载 SECRET_KEY / MAIL_* / SQLALCHEMY_DATABASE_URI - 拆分 BaseConfig / DevConfig / ProConfig,PEAR_ENV 控制切换 - ProConfig 在 init_app() 校验 SECRET_KEY,禁止使用默认值 ops - 新增 /healthz 端点:DB 探活 + 环境名 + 时间戳,失败返回 503 - 新增 start.bat (Windows) / Makefile (跨平台) 一键启动 / 初始化 - 新增 .env.example 模板;.gitignore 排除 .env / logs / vscode 等 - 新增 docs/DEPLOY.md(部署指南)和 docs/SECURITY.md(安全清单) - app.py 不再硬编码 debug=False,交给配置类决定 本提交不包含上一次会话的其它工作树修改(模板/导航相关),后续单独 PR。
72 lines
1.9 KiB
Python
72 lines
1.9 KiB
Python
"""
|
|
健康检查端点(无需登录)
|
|
|
|
- GET /healthz
|
|
用于探活/负载均衡/容器 readinessProbe。
|
|
返回:
|
|
{
|
|
"status": "ok" | "degraded",
|
|
"db_ok": true | false,
|
|
"env": "dev" | "production",
|
|
"system": "Pear Admin",
|
|
"timestamp": "2026-09-05T17:00:00+08:00"
|
|
}
|
|
|
|
HTTP 状态码:
|
|
200 - 全部正常
|
|
503 - DB 不可达(用于触发 k8s readinessProbe 失败)
|
|
"""
|
|
from datetime import datetime, timedelta, timezone
|
|
import os
|
|
|
|
from flask import Blueprint, current_app, jsonify
|
|
from sqlalchemy import text
|
|
|
|
from applications.extensions import db
|
|
|
|
bp = Blueprint("health", __name__)
|
|
|
|
|
|
def _beijing_now() -> str:
|
|
"""返回 +08:00 时区 ISO8601 时间字符串。"""
|
|
tz = timezone(timedelta(hours=8))
|
|
return datetime.now(tz).isoformat()
|
|
|
|
|
|
@bp.get("/healthz")
|
|
def healthz():
|
|
# 优先按 PEAR_ENV/FLASK_ENV 取环境名;兜底按 DEBUG 反推
|
|
env = (
|
|
os.environ.get("PEAR_ENV")
|
|
or os.environ.get("FLASK_ENV")
|
|
or current_app.config.get("PEAR_ENV")
|
|
or ("dev" if current_app.config.get("DEBUG") else "production")
|
|
)
|
|
system_name = current_app.config.get("SYSTEM_NAME", "Pear Admin")
|
|
|
|
# DB 探活:跑一个最轻量的 SELECT 1
|
|
db_ok = True
|
|
db_error = None
|
|
try:
|
|
db.session.execute(text("SELECT 1"))
|
|
except Exception as e: # noqa: BLE001 - 这里就是要把异常吃掉,转换成 False
|
|
db_ok = False
|
|
db_error = str(e)
|
|
finally:
|
|
try:
|
|
db.session.rollback()
|
|
except Exception:
|
|
pass
|
|
|
|
payload = {
|
|
"status": "ok" if db_ok else "degraded",
|
|
"db_ok": db_ok,
|
|
"env": env,
|
|
"system": system_name,
|
|
"timestamp": _beijing_now(),
|
|
}
|
|
if db_error:
|
|
payload["db_error"] = db_error
|
|
|
|
return jsonify(payload), (200 if db_ok else 503)
|