refactor(proxy-node): 移除非 tunnel 模式兼容,注册和心跳统一为 tunnel 模式

- 注册接口移除 tunnel_mode 参数,固定按 name upsert 并标记为 tunnel 模式
- 心跳接口拒绝非 tunnel 模式节点,返回升级提示
- 移除按 ip+port 查找的旧模式分支
This commit is contained in:
fawney19
2026-02-26 13:54:32 +08:00
parent 7e73e7fab2
commit 8c2928c39d
2 changed files with 19 additions and 30 deletions

View File

@@ -45,9 +45,6 @@ class ProxyNodeRegisterRequest(BaseModel):
hardware_info: dict | None = Field(None, description="硬件信息 JSON") hardware_info: dict | None = Field(None, description="硬件信息 JSON")
estimated_max_concurrency: int | None = Field(None, ge=0, description="估算最大并发连接数") estimated_max_concurrency: int | None = Field(None, ge=0, description="估算最大并发连接数")
# Tunnel 模式
tunnel_mode: bool = Field(False, description="是否使用 tunnel 模式连接")
@field_validator("ip") @field_validator("ip")
@classmethod @classmethod
def validate_ip(cls, v: str) -> str: def validate_ip(cls, v: str) -> str:
@@ -267,7 +264,6 @@ class AdminRegisterProxyNodeAdapter(AdminApiAdapter):
total_requests=req.total_requests, total_requests=req.total_requests,
avg_latency_ms=req.avg_latency_ms, avg_latency_ms=req.avg_latency_ms,
registered_by=context.user.id if context.user else None, registered_by=context.user.id if context.user else None,
tunnel_mode=req.tunnel_mode,
) )
context.add_audit_metadata( context.add_audit_metadata(

View File

@@ -247,33 +247,24 @@ class ProxyNodeService:
total_requests: int | None = None, total_requests: int | None = None,
avg_latency_ms: float | None = None, avg_latency_ms: float | None = None,
registered_by: str | None = None, registered_by: str | None = None,
tunnel_mode: bool = False,
) -> ProxyNode: ) -> ProxyNode:
"""注册或更新 aether-proxy 节点 """注册或更新 aether-proxy 节点tunnel 模式)"""
tunnel 模式按 name upsertport 固定为 0同 IP 可能有多个实例);
旧模式按 ip+port upsert向后兼容
"""
now = datetime.now(timezone.utc) now = datetime.now(timezone.utc)
if tunnel_mode: node = (
node = ( db.query(ProxyNode)
db.query(ProxyNode) .filter(ProxyNode.name == name, ProxyNode.is_manual == False) # noqa: E712
.filter(ProxyNode.name == name, ProxyNode.is_manual == False) # noqa: E712 .first()
.first() )
)
else:
node = db.query(ProxyNode).filter(ProxyNode.ip == ip, ProxyNode.port == port).first()
if node: if node:
node.name = name node.name = name
node.region = region node.region = region
# tunnel 模式:状态完全由 tunnel 连接管理_update_tunnel_status / health_scheduler # 状态完全由 tunnel 连接管理_update_tunnel_status / health_scheduler
# 注册/心跳不干预;非 tunnel 模式照旧 # 注册不干预
if not tunnel_mode:
node.status = ProxyNodeStatus.ONLINE
node.last_heartbeat_at = now node.last_heartbeat_at = now
node.heartbeat_interval = heartbeat_interval node.heartbeat_interval = heartbeat_interval
node.tunnel_mode = tunnel_mode node.tunnel_mode = True
if hardware_info is not None: if hardware_info is not None:
node.hardware_info = hardware_info node.hardware_info = hardware_info
if estimated_max_concurrency is not None: if estimated_max_concurrency is not None:
@@ -291,8 +282,8 @@ class ProxyNodeService:
ip=ip, ip=ip,
port=port, port=port,
region=region, region=region,
# tunnel 模式新节点:等 tunnel 连接后才上线 # 新节点:等 tunnel 连接后才上线
status=ProxyNodeStatus.UNHEALTHY if tunnel_mode else ProxyNodeStatus.ONLINE, status=ProxyNodeStatus.UNHEALTHY,
registered_by=registered_by, registered_by=registered_by,
last_heartbeat_at=now, last_heartbeat_at=now,
heartbeat_interval=heartbeat_interval, heartbeat_interval=heartbeat_interval,
@@ -301,7 +292,7 @@ class ProxyNodeService:
avg_latency_ms=avg_latency_ms, avg_latency_ms=avg_latency_ms,
hardware_info=hardware_info, hardware_info=hardware_info,
estimated_max_concurrency=estimated_max_concurrency, estimated_max_concurrency=estimated_max_concurrency,
tunnel_mode=tunnel_mode, tunnel_mode=True,
created_at=now, created_at=now,
updated_at=now, updated_at=now,
) )
@@ -321,16 +312,18 @@ class ProxyNodeService:
total_requests: int | None = None, total_requests: int | None = None,
avg_latency_ms: float | None = None, avg_latency_ms: float | None = None,
) -> ProxyNode: ) -> ProxyNode:
"""处理节点心跳""" """处理节点心跳(仅 tunnel 模式节点,心跳更新指标但不改变状态)"""
node = db.query(ProxyNode).filter(ProxyNode.id == node_id).first() node = db.query(ProxyNode).filter(ProxyNode.id == node_id).first()
if not node: if not node:
raise NotFoundException(f"ProxyNode {node_id} 不存在", "proxy_node") raise NotFoundException(f"ProxyNode {node_id} 不存在", "proxy_node")
now = datetime.now(timezone.utc)
# tunnel 模式节点:心跳仅更新指标,不改变状态;
# 状态由 tunnel WebSocket 连接建立/断开时决定
if not node.tunnel_mode: if not node.tunnel_mode:
node.status = ProxyNodeStatus.ONLINE raise InvalidRequestException(
"non-tunnel mode is no longer supported, please upgrade aether-proxy to use tunnel mode"
)
now = datetime.now(timezone.utc)
# 状态由 tunnel WebSocket 连接建立/断开时决定,心跳仅更新指标
node.last_heartbeat_at = now node.last_heartbeat_at = now
if heartbeat_interval is not None: if heartbeat_interval is not None:
node.heartbeat_interval = heartbeat_interval node.heartbeat_interval = heartbeat_interval