feat: 综合平台services多服务支持+SW网络优先缓存修复+适配层/定时任务完善

This commit is contained in:
gouki
2026-08-05 11:57:17 +00:00
parent 7f1268f508
commit 1b7d4823c3
47 changed files with 2895 additions and 1189 deletions
+43 -4
View File
@@ -1,17 +1,53 @@
"""Agent 上报接收路由(数据写入 metrics.db)"""
from datetime import datetime
import threading
import time
from fastapi import APIRouter, Depends
from fastapi import APIRouter, Depends, HTTPException, status
from sqlmodel import Session, select
from app.core.config import settings
from app.core.security import require_agent_key
from app.database import get_metrics_session
from app.core.timeutils import utcnow
from app.database import assets_engine, get_metrics_session
from app.models.asset import Asset
from app.models.monitor import EventLog, MetricPoint, SecurityCheck, ServerInfo
from app.schemas.agent import AgentReport
router = APIRouter(prefix="/api/agent", tags=["agent"])
# 内存级频率限制:{asset_id: 上次上报的 monotonic 时间戳}
# 同步路由运行在线程池,多线程并发读写需加锁保证“读-判断-写”原子性
_last_report_ts: dict = {}
_rate_limit_lock = threading.Lock()
def _check_rate_limit(asset_id: int) -> None:
"""限制同一资产的上报频率,防止配置错误的 Agent 高频写入填满数据库"""
interval = settings.AGENT_REPORT_MIN_INTERVAL
if interval <= 0:
return
now = time.monotonic()
with _rate_limit_lock:
last = _last_report_ts.get(asset_id)
if last is not None and (now - last) < interval:
raise HTTPException(
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
detail=f"上报过于频繁,同一资产最小间隔 {interval}",
)
_last_report_ts[asset_id] = now
def _validate_asset_id(asset_id: int) -> None:
"""校验上报的 asset_id 在资产库中真实存在,防止脏数据写入"""
with Session(assets_engine) as session:
asset = session.get(Asset, asset_id)
if not asset:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"asset_id={asset_id} 不存在,请先在资产列表中登记该服务器",
)
@router.post(
"/report",
@@ -19,6 +55,9 @@ router = APIRouter(prefix="/api/agent", tags=["agent"])
dependencies=[Depends(require_agent_key)],
)
def report(data: AgentReport, session: Session = Depends(get_metrics_session)) -> dict:
_validate_asset_id(data.asset_id)
_check_rate_limit(data.asset_id)
# 资源监控时序
if data.metrics:
session.add(MetricPoint(asset_id=data.asset_id, **data.metrics.model_dump()))
@@ -26,7 +65,7 @@ def report(data: AgentReport, session: Session = Depends(get_metrics_session)) -
# 服务器信息快照(每资产一条,覆盖更新)
if data.server_info:
info = data.server_info.model_dump()
info["last_seen"] = datetime.utcnow()
info["last_seen"] = utcnow()
existing = session.exec(
select(ServerInfo).where(ServerInfo.asset_id == data.asset_id)
).first()