正式起服务打底

This commit is contained in:
Neo
2025-11-19 05:05:37 +08:00
parent 7a822ea7ca
commit 31801ca384
19 changed files with 162 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

48
app/config.py Normal file
View File

@@ -0,0 +1,48 @@
# app/config.py
import os
from functools import lru_cache
class Settings:
"""
后端配置:
- APP_ENV: dev / prod
- DB_*: 数据库连接参数
- 默认库dev 用 LLZQ-testprod 用 LLZQ
"""
def __init__(self) -> None:
self.app_env = os.getenv("APP_ENV", "dev").lower()
self.db_host = os.getenv("DB_HOST", "127.0.0.1")
self.db_port = int(os.getenv("DB_PORT", "5432"))
self.db_user = os.getenv("DB_USER", "local-Python")
self.db_password = os.getenv("DB_PASSWORD", "")
# 默认连接的库,根据 APP_ENV 决定
if self.app_env == "prod":
self.db_name_default = "LLZQ"
else:
self.db_name_default = "LLZQ-test"
self.db_schema = os.getenv("DB_SCHEMA", "XCX")
def resolve_db_name(self, env_header: str | None) -> str:
"""
根据前端传来的 X-LLZQ-Env 决定最终使用哪个 DB
- "prod" => LLZQ
- 其它/为空 => LLZQ-test
"""
if env_header is None:
return self.db_name_default
env_header = env_header.lower()
if env_header == "prod":
return "LLZQ"
else:
return "LLZQ-test"
@lru_cache()
def get_settings() -> Settings:
return Settings()

42
app/db.py Normal file
View File

@@ -0,0 +1,42 @@
# app/db.py
from contextlib import contextmanager
from typing import Iterator
import psycopg2
from psycopg2.extras import RealDictCursor
from .config import get_settings
@contextmanager
def get_connection(db_name: str) -> Iterator[psycopg2.extensions.connection]:
"""
简单连接管理:每次请求开一个连接,用完就关。
当前访问量不高,这种写法足够。
"""
settings = get_settings()
conn = psycopg2.connect(
host=settings.db_host,
port=settings.db_port,
user=settings.db_user,
password=settings.db_password,
dbname=db_name,
)
try:
# 设置 schema = XCX
with conn.cursor() as cur:
cur.execute("SET search_path TO %s;", (settings.db_schema,))
yield conn
finally:
conn.close()
def check_health(db_name: str) -> bool:
"""
DB 健康检查SELECT 1
"""
with get_connection(db_name) as conn:
with conn.cursor(cursor_factory=RealDictCursor) as cur:
cur.execute("SELECT 1 AS v;")
row = cur.fetchone()
return row["v"] == 1

51
app/main.py Normal file
View File

@@ -0,0 +1,51 @@
# app/main.py
from fastapi import FastAPI, Header, Depends
from .config import get_settings
from .db import check_health
app = FastAPI(
title="LLZQ Backend",
version="0.1.0",
)
def resolve_db_name(x_llzq_env: str | None = Header(default=None, alias="X-LLZQ-Env")) -> str:
"""
从请求头 X-LLZQ-Env 中解析要用的 DB 名。
"""
settings = get_settings()
return settings.resolve_db_name(x_llzq_env)
@app.get("/api/ping")
def ping(db_name: str = Depends(resolve_db_name)):
"""
最简单调通接口:
- 返回当前后端环境
- 返回实际连接的 DB 名
- 简单做一个 DB 健康检查
"""
settings = get_settings()
ok = False
error_msg = None
try:
ok = check_health(db_name)
except Exception as e:
error_msg = str(e)
return {
"ok": ok,
"app_env": settings.app_env,
"db": db_name,
"error": error_msg,
}
@app.get("/api/healthz")
def healthz():
"""
给 Nginx / 监控用的探活接口,不查 DB。
"""
return {"status": "ok"}

View File

@@ -0,0 +1 @@
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)

View File

@@ -0,0 +1 @@
INFO: 100.64.0.1:59692 - "GET /api/ping HTTP/1.1" 200 OK

View File

@@ -0,0 +1 @@
INFO: Application startup complete.

View File

@@ -0,0 +1 @@
INFO: 100.64.0.1:59690 - "GET /api/healthz HTTP/1.1" 200 OK

View File

@@ -0,0 +1 @@
INFO: Waiting for application startup.

View File

@@ -0,0 +1 @@
INFO: 100.64.0.1:60268 - "GET /api/ping HTTP/1.1" 200 OK

View File

@@ -0,0 +1 @@
INFO: Started server process [11432]

View File

@@ -0,0 +1 @@
INFO: 100.64.0.1:60266 - "GET /api/healthz HTTP/1.1" 200 OK

View File

@@ -0,0 +1 @@
INFO: 127.0.0.1:56463 - "GET /api/ping HTTP/1.1" 200 OK

View File

@@ -0,0 +1 @@
INFO: 127.0.0.1:56463 - "GET /api/healthz HTTP/1.1" 200 OK

View File

View File

View File

@@ -0,0 +1,11 @@
2025-11-19 04:51:16,714 DEBUG - Starting WinSW in console mode
2025-11-19 04:51:16,728 INFO - Installing service 'LLZQ API (FastAPI 8000) (llzq-api-8000)'...
2025-11-19 04:51:16,755 INFO - Service 'LLZQ API (FastAPI 8000) (llzq-api-8000)' was installed successfully.
2025-11-19 04:51:16,909 DEBUG - Starting WinSW in console mode
2025-11-19 04:51:16,925 INFO - Starting service 'LLZQ API (FastAPI 8000) (llzq-api-8000)'...
2025-11-19 04:51:17,008 DEBUG - Starting WinSW in service mode
2025-11-19 04:51:17,017 INFO - Service 'LLZQ API (FastAPI 8000) (llzq-api-8000)' started successfully.
2025-11-19 04:51:17,024 INFO - Starting D:\LLZQ\LLZQ-server\.venv\Scripts\uvicorn.exe app.main:app --host 0.0.0.0 --port 8000
2025-11-19 04:51:17,041 INFO - Started process 10844
2025-11-19 04:51:17,047 DEBUG - Forwarding logs of the process System.Diagnostics.Process (uvicorn) to WinSW.SizeBasedRollingLogAppender
2025-11-19 04:51:18,533 DEBUG - Starting WinSW in console mode