fix(nodes): locate agents behind a proxy and retry missing countries [CI]
This commit is contained in:
1 parent
1145a53004
commit
0d532caf08
13 files changed
+93
-15
No files matched your search
@@ -115,10 +115,15 @@ public sealed class MoShiroNodeEventSink : INodeEventSink
|
||||
await _events.AddAsync(id, "agent_offline", nodeEvent.AtMs, null, ct);
|
||||
break;
|
||||
case NodeEventKind.Hello when nodeEvent.Hello is { } hello:
|
||||
await ApplyHelloAsync(id, hello, ct);
|
||||
await ApplyHelloAsync(id, hello, nodeEvent.RemoteIp, ct);
|
||||
break;
|
||||
case NodeEventKind.Heartbeat when nodeEvent.Extra is { } extra:
|
||||
await _nodes.SetVersionAsync(id.Value, NodeKinds.Agent, nodeEvent.Node.NodeVersion, ct);
|
||||
if (_nodes.ShouldRetryGeo(id.Value) && await _agents.GetAsync(id, ct) is { } unlocated)
|
||||
{
|
||||
_nodes.ObserveAgentInBackground(id.Value, GeoHostOf(unlocated, nodeEvent.RemoteIp), null);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
AgentRuntimeState state = _runtime.Get(id);
|
||||
@@ -145,6 +150,12 @@ public sealed class MoShiroNodeEventSink : INodeEventSink
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>查国家和运营商用哪个地址:对外地址优先,其次 IPv6 地址,都没有(NAT 后面、或者没有上报公网地址)才用这条连接的来源地址。</summary>
|
||||
private static string? GeoHostOf(AgentRecord? agent, string? remoteIp) =>
|
||||
!string.IsNullOrEmpty(agent?.PublicHost) ? agent.PublicHost
|
||||
: !string.IsNullOrEmpty(agent?.Ipv6Host) ? agent.Ipv6Host
|
||||
: remoteIp;
|
||||
|
||||
/// <summary>Probe 自己连上来了:hello 里带着它的系统、架构和构建信息;上线下线只推给 SSE,不记事件。</summary>
|
||||
private async ValueTask OnProbeEventAsync(NodeId id, NodeEvent nodeEvent, CancellationToken ct)
|
||||
{
|
||||
@@ -213,7 +224,7 @@ public sealed class MoShiroNodeEventSink : INodeEventSink
|
||||
}
|
||||
}
|
||||
|
||||
private async ValueTask ApplyHelloAsync(NodeId id, HelloParams hello, CancellationToken ct)
|
||||
private async ValueTask ApplyHelloAsync(NodeId id, HelloParams hello, string? remoteIp, CancellationToken ct)
|
||||
{
|
||||
var kinds = new List<string>();
|
||||
foreach (string capability in hello.Capabilities)
|
||||
@@ -278,7 +289,7 @@ public sealed class MoShiroNodeEventSink : INodeEventSink
|
||||
|
||||
// 端口、证书指纹或对外地址变了,Probe 需要新的列表
|
||||
AgentRecord? after = await _agents.GetAsync(id, ct);
|
||||
_nodes.ObserveAgentInBackground(id.Value, after?.PublicHost, meta.Platform);
|
||||
_nodes.ObserveAgentInBackground(id.Value, GeoHostOf(after, remoteIp), meta.Platform);
|
||||
await _releases.OfferToNodeAsync(id, ct);
|
||||
await _schedule.SendToNodeAsync(id, ct);
|
||||
if (before is not null && after is not null
|
||||
|
||||
@@ -26,6 +26,7 @@ public sealed class NodeInfoService
|
||||
private readonly TimeProvider _time;
|
||||
private readonly ConcurrentDictionary<string, NodeMeta> _cache = new();
|
||||
private readonly ConcurrentDictionary<string, byte> _inflight = new();
|
||||
private readonly ConcurrentDictionary<string, long> _lastTry = new();
|
||||
private Task? _load;
|
||||
|
||||
public NodeInfoService(INodeMetaStore store, IGeoLookup geo, TimeProvider time)
|
||||
@@ -119,6 +120,7 @@ public sealed class NodeInfoService
|
||||
public async ValueTask ObserveAddressAsync(string nodeId, string kind, string? host, CancellationToken ct)
|
||||
{
|
||||
host = host?.Trim();
|
||||
_lastTry[nodeId] = Now();
|
||||
if (string.IsNullOrEmpty(host) || !IsPublic(host) || !_inflight.TryAdd(nodeId, 0))
|
||||
{
|
||||
return;
|
||||
@@ -162,6 +164,17 @@ public sealed class NodeInfoService
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>国家还没查到、并且离上一次尝试已经过了重试间隔:调用方可以再查一次(心跳里调,不会每次都真去查)。</summary>
|
||||
public bool ShouldRetryGeo(string nodeId)
|
||||
{
|
||||
if (_cache.TryGetValue(nodeId, out NodeMeta? meta) && (meta.Info.Country is not null || meta.Info.IspManual))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return !_lastTry.TryGetValue(nodeId, out long at) || Now() - at >= s_retryAfter.TotalMilliseconds;
|
||||
}
|
||||
|
||||
/// <summary>Agent 报告某个 Probe 连着它:在后台用 Probe 的来源地址查国家和运营商(系统信息是 Probe 自己连上面板时报的)。出错只吞掉。</summary>
|
||||
public void ObserveProbeInBackground(string probeId, string? remote) =>
|
||||
_ = Task.Run(async () =>
|
||||
|
||||
Reference in new issue
Block a user