feat: apply inbound/outbound/routing changes live via Xray gRPC API

Add a hot-apply layer that computes a diff between the old and new
generated config and applies only the changed parts through the Xray
gRPC HandlerService and RoutingService, avoiding a full process restart
whenever possible. A restart is still performed when sections that have
no reload API (log, dns, policy, observatory, ...) actually change.

Key additions:
- internal/xray/hot_diff.go: ComputeHotDiff with canonical-JSON
  comparison (sorted keys, null=absent, full number precision) so UI
  reformatting never triggers a spurious restart
- internal/xray/api.go: AddOutbound/DelOutbound, ApplyRoutingConfig,
  GetBalancerInfo, SetBalancerTarget, TestRoute gRPC wrappers
- internal/web/service/xray.go: tryHotApply, ensureAPIServices,
  GetBalancersStatus, OverrideBalancer, TestRoute service methods
- internal/web/controller/xray_setting.go: balancerStatus,
  balancerOverride, routeTest API endpoints
- frontend: BalancersTab live-status/override columns, RouteTester
  component, Restart button removed (Save now hot-applies)
- balancer-helpers.ts: syncObservatories never creates observatory
  sections for random/roundRobin balancers (no reload API → restart)
- i18n: balancerLive/Override/routeTester keys added to all 13 locales
This commit is contained in:
MHSanaei
2026-06-10 23:01:33 +02:00
parent 3092326d9e
commit 6b16d8c37a
32 changed files with 2209 additions and 109 deletions
+15
View File
@@ -1183,6 +1183,21 @@
"Balancers": "负载均衡",
"balancerTagRequired": "标签为必填项",
"balancerSelectorRequired": "至少选择一个出站",
"balancerLive": "当前目标",
"balancerOverride": "强制指定",
"balancerOverridePh": "自动(策略)",
"balancerLiveRefresh": "刷新负载均衡器实时状态",
"balancerNotRunning": "此负载均衡器在运行中的 Xray 未激活 — 请先保存更改或启动 Xray",
"routeTester": "路由测试",
"routeTesterDesc": "向运行中的 Xray 查询某个连接将使用哪个出站。不会发送真实流量 — 结果直接来自实时路由引擎。",
"routeTesterDest": "域名或 IP",
"routeTesterPort": "端口",
"routeTesterInbound": "入站",
"routeTesterProtocol": "嗅探协议",
"routeTesterTest": "测试路由",
"routeTesterMatchedOutbound": "匹配出站",
"routeTesterViaBalancer": "经由负载均衡器",
"routeTesterDefaultOutbound": "无路由规则匹配 — 流量将发往默认(第一个)出站。",
"OutboundsDesc": "设置出站流量传出方式",
"Routings": "路由规则",
"RoutingsDesc": "每条规则的优先级都很重要",