增强dns返回的ip的稳定性

This commit is contained in:
陈国伟 2021-06-16 13:14:02 +08:00
parent 3d20996d4b
commit 42458fd25a
7 changed files with 122 additions and 39 deletions

View File

@ -5,11 +5,26 @@ namespace FastGithub.Scanner
{
sealed class GithubContext : IEquatable<GithubContext>
{
/// <summary>
/// 获取域名
/// </summary>
public string Domain { get; }
/// <summary>
/// 获取ip
/// </summary>
public IPAddress Address { get; }
public TimeSpan? HttpElapsed { get; set; }
/// <summary>
/// 获取或设置是否可用
/// </summary>
public bool Available { get; set; } = false;
/// <summary>
/// 获取或设置扫描总耗时
/// </summary>
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)

View File

@ -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<GithubContext> contextHashSet = new();
private readonly Dictionary<string, IPAddress> 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();
}
}
/// <summary>
/// 查找又稳又快的ip
/// </summary>
/// <param name="domain"></param>
/// <returns></returns>
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;
}
}
}
}

View File

@ -1,9 +0,0 @@
using System.Collections.Generic;
namespace FastGithub.Scanner
{
sealed class GithubContextHashSet : HashSet<GithubContext>
{
public readonly object SyncRoot = new();
}
}

View File

@ -14,7 +14,7 @@ namespace FastGithub.Scanner
{
private readonly GithubMetaService metaService;
private readonly ILogger<GithubScanService> logger;
private readonly GithubContextHashSet results = new();
private readonly GithubContextCollection results = new();
private readonly InvokeDelegate<GithubContext> fullScanDelegate;
private readonly InvokeDelegate<GithubContext> resultScanDelegate;
@ -30,6 +30,7 @@ namespace FastGithub.Scanner
this.fullScanDelegate = pipelineBuilder
.New()
.Use<ConcurrentMiddleware>()
.Use<ScanElapsedMiddleware>()
.Use<PortScanMiddleware>()
.Use<HttpsScanMiddleware>()
.Use<ScanOkLogMiddleware>()
@ -37,6 +38,7 @@ namespace FastGithub.Scanner
this.resultScanDelegate = pipelineBuilder
.New()
.Use<ScanElapsedMiddleware>()
.Use<PortScanMiddleware>()
.Use<HttpsScanMiddleware>()
.Use<ScanOkLogMiddleware>()
@ -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;
}
}
}

View File

@ -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();
}
}

View File

@ -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<GithubContext>
{
public async Task InvokeAsync(GithubContext context, Func<Task> next)
{
var stopwatch = new Stopwatch();
try
{
stopwatch.Start();
await next();
}
finally
{
stopwatch.Stop();
context.Elapsed = stopwatch.Elapsed;
}
}
}
}

View File

@ -17,7 +17,7 @@ namespace FastGithub.Scanner.Middlewares
public Task InvokeAsync(GithubContext context, Func<Task> next)
{
if (context.HttpElapsed != null)
if (context.Available)
{
this.logger.LogInformation(context.ToString());
}