diff --git a/FastGithub.Scanner/GithubContext.cs b/FastGithub.Scanner/GithubContext.cs index 3f233b7..dffefca 100644 --- a/FastGithub.Scanner/GithubContext.cs +++ b/FastGithub.Scanner/GithubContext.cs @@ -5,11 +5,26 @@ namespace FastGithub.Scanner { sealed class GithubContext : IEquatable { + /// + /// 获取域名 + /// public string Domain { get; } + /// + /// 获取ip + /// public IPAddress Address { get; } - public TimeSpan? HttpElapsed { get; set; } + /// + /// 获取或设置是否可用 + /// + public bool Available { get; set; } = false; + + /// + /// 获取或设置扫描总耗时 + /// + public TimeSpan Elapsed { get; set; } = TimeSpan.MaxValue; + public GithubContext(string domain, IPAddress address) { @@ -19,7 +34,7 @@ namespace FastGithub.Scanner public override string ToString() { - return $"{Address}\t{Domain}\t# {HttpElapsed}"; + return $"{Address}\t{Domain}\t# {Elapsed}"; } public override bool Equals(object? obj) diff --git a/FastGithub.Scanner/GithubContextCollection.cs b/FastGithub.Scanner/GithubContextCollection.cs new file mode 100644 index 0000000..5c01444 --- /dev/null +++ b/FastGithub.Scanner/GithubContextCollection.cs @@ -0,0 +1,66 @@ +using System.Collections.Generic; +using System.Linq; +using System.Net; + +namespace FastGithub.Scanner +{ + sealed class GithubContextCollection + { + private readonly object syncRoot = new(); + private readonly HashSet contextHashSet = new(); + private readonly Dictionary domainAdressCache = new(); + + public bool Add(GithubContext context) + { + lock (this.syncRoot) + { + return this.contextHashSet.Add(context); + } + } + + public GithubContext[] ToArray() + { + lock (this.syncRoot) + { + return this.contextHashSet.ToArray(); + } + } + + /// + /// 查找又稳又快的ip + /// + /// + /// + public IPAddress? FindFastAddress(string domain) + { + lock (this.syncRoot) + { + // 如果上一次的ip可以使用,就返回上一次的ip + if (this.domainAdressCache.TryGetValue(domain, out var address)) + { + var key = new GithubContext(domain, address); + if (this.contextHashSet.TryGetValue(key, out var context) && context.Available) + { + return address; + } + } + + var fastAddress = this.contextHashSet + .Where(item => item.Available && item.Domain == domain) + .OrderBy(item => item.Elapsed) + .Select(item => item.Address) + .FirstOrDefault(); + + if (fastAddress != null) + { + this.domainAdressCache[domain] = fastAddress; + } + else + { + this.domainAdressCache.Remove(domain); + } + return fastAddress; + } + } + } +} diff --git a/FastGithub.Scanner/GithubContextHashSet.cs b/FastGithub.Scanner/GithubContextHashSet.cs deleted file mode 100644 index b96f419..0000000 --- a/FastGithub.Scanner/GithubContextHashSet.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; - -namespace FastGithub.Scanner -{ - sealed class GithubContextHashSet : HashSet - { - public readonly object SyncRoot = new(); - } -} diff --git a/FastGithub.Scanner/GithubScanService.cs b/FastGithub.Scanner/GithubScanService.cs index e44c74b..a1d3d7d 100644 --- a/FastGithub.Scanner/GithubScanService.cs +++ b/FastGithub.Scanner/GithubScanService.cs @@ -14,7 +14,7 @@ namespace FastGithub.Scanner { private readonly GithubMetaService metaService; private readonly ILogger logger; - private readonly GithubContextHashSet results = new(); + private readonly GithubContextCollection results = new(); private readonly InvokeDelegate fullScanDelegate; private readonly InvokeDelegate resultScanDelegate; @@ -30,6 +30,7 @@ namespace FastGithub.Scanner this.fullScanDelegate = pipelineBuilder .New() .Use() + .Use() .Use() .Use() .Use() @@ -37,6 +38,7 @@ namespace FastGithub.Scanner this.resultScanDelegate = pipelineBuilder .New() + .Use() .Use() .Use() .Use() @@ -58,12 +60,9 @@ namespace FastGithub.Scanner async Task ScanAsync(GithubContext context) { await this.fullScanDelegate(context); - if (context.HttpElapsed != null) + if (context.Available == true) { - lock (this.results.SyncRoot) - { - this.results.Add(context); - } + this.results.Add(context); } } } @@ -71,15 +70,10 @@ namespace FastGithub.Scanner public async Task ScanResultAsync() { this.logger.LogInformation("结果扫描开始"); - GithubContext[] contexts; - lock (this.results.SyncRoot) - { - contexts = this.results.ToArray(); - } + var contexts = this.results.ToArray(); foreach (var context in contexts) { - context.HttpElapsed = null; await this.resultScanDelegate(context); } @@ -88,19 +82,9 @@ namespace FastGithub.Scanner public IPAddress? FindFastAddress(string domain) { - if (domain.Contains("github", StringComparison.OrdinalIgnoreCase)) - { - lock (this.results.SyncRoot) - { - return this.results - .Where(item => item.Domain == domain && item.HttpElapsed != null) - .OrderBy(item => item.HttpElapsed) - .Select(item => item.Address) - .FirstOrDefault(); - } - } - - return default; + return domain.Contains("github", StringComparison.OrdinalIgnoreCase) + ? this.results.FindFastAddress(domain) + : default; } } } diff --git a/FastGithub.Scanner/Middlewares/HttpsScanMiddleware.cs b/FastGithub.Scanner/Middlewares/HttpsScanMiddleware.cs index 09119b6..6ceb89a 100644 --- a/FastGithub.Scanner/Middlewares/HttpsScanMiddleware.cs +++ b/FastGithub.Scanner/Middlewares/HttpsScanMiddleware.cs @@ -27,6 +27,8 @@ namespace FastGithub.Scanner.Middlewares { try { + context.Available = false; + var request = new HttpRequestMessage { Method = HttpMethod.Get, @@ -40,13 +42,12 @@ namespace FastGithub.Scanner.Middlewares UseProxy = false, }); - var startTime = DateTime.Now; using var cancellationTokenSource = new CancellationTokenSource(this.options.CurrentValue.HttpsScanTimeout); var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationTokenSource.Token); var server = response.EnsureSuccessStatusCode().Headers.Server; if (server.Any(s => string.Equals("GitHub.com", s.Product?.Name, StringComparison.OrdinalIgnoreCase))) { - context.HttpElapsed = DateTime.Now.Subtract(startTime); + context.Available = true; await next(); } } diff --git a/FastGithub.Scanner/Middlewares/ScanElapsedMiddleware.cs b/FastGithub.Scanner/Middlewares/ScanElapsedMiddleware.cs new file mode 100644 index 0000000..382c37b --- /dev/null +++ b/FastGithub.Scanner/Middlewares/ScanElapsedMiddleware.cs @@ -0,0 +1,26 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Diagnostics; +using System.Threading.Tasks; + +namespace FastGithub.Scanner.Middlewares +{ + [Service(ServiceLifetime.Singleton)] + sealed class ScanElapsedMiddleware : IMiddleware + { + public async Task InvokeAsync(GithubContext context, Func next) + { + var stopwatch = new Stopwatch(); + try + { + stopwatch.Start(); + await next(); + } + finally + { + stopwatch.Stop(); + context.Elapsed = stopwatch.Elapsed; + } + } + } +} diff --git a/FastGithub.Scanner/Middlewares/ScanOkLogMiddleware.cs b/FastGithub.Scanner/Middlewares/ScanOkLogMiddleware.cs index 3730642..18dfd16 100644 --- a/FastGithub.Scanner/Middlewares/ScanOkLogMiddleware.cs +++ b/FastGithub.Scanner/Middlewares/ScanOkLogMiddleware.cs @@ -17,7 +17,7 @@ namespace FastGithub.Scanner.Middlewares public Task InvokeAsync(GithubContext context, Func next) { - if (context.HttpElapsed != null) + if (context.Available) { this.logger.LogInformation(context.ToString()); }