根据统计信息返回最优ip

This commit is contained in:
陈国伟 2021-06-16 16:57:12 +08:00
parent f89952dd18
commit 88d3e08ed3
6 changed files with 96 additions and 57 deletions

View File

@ -18,12 +18,12 @@ namespace FastGithub.Scanner
/// <summary> /// <summary>
/// 获取或设置是否可用 /// 获取或设置是否可用
/// </summary> /// </summary>
public bool Available { get; set; } = false; public bool Available { get; set; }
/// <summary> /// <summary>
/// 获取或设置扫描总耗时 /// 获取统计信息
/// </summary> /// </summary>
public TimeSpan Elapsed { get; set; } = TimeSpan.MaxValue; public GithubContextStatistics Statistics { get; } = new();
public GithubContext(string domain, IPAddress address) public GithubContext(string domain, IPAddress address)
@ -32,11 +32,6 @@ namespace FastGithub.Scanner
this.Address = address; this.Address = address;
} }
public override string ToString()
{
return $"{Address}\t{Domain}\t# {Elapsed}";
}
public override bool Equals(object? obj) public override bool Equals(object? obj)
{ {
return obj is GithubContext other && this.Equals(other); return obj is GithubContext other && this.Equals(other);

View File

@ -8,21 +8,12 @@ namespace FastGithub.Scanner
{ {
private readonly object syncRoot = new(); private readonly object syncRoot = new();
private readonly HashSet<GithubContext> contextHashSet = new(); private readonly HashSet<GithubContext> contextHashSet = new();
private readonly Dictionary<string, IPAddress> domainAdressCache = new();
public void AddOrUpdate(GithubContext context) public bool Add(GithubContext context)
{ {
lock (this.syncRoot) lock (this.syncRoot)
{ {
if (this.contextHashSet.TryGetValue(context, out var value)) return this.contextHashSet.Add(context);
{
value.Elapsed = context.Elapsed;
value.Available = context.Available;
}
else
{
this.contextHashSet.Add(context);
}
} }
} }
@ -39,35 +30,16 @@ namespace FastGithub.Scanner
/// </summary> /// </summary>
/// <param name="domain"></param> /// <param name="domain"></param>
/// <returns></returns> /// <returns></returns>
public IPAddress? FindFastAddress(string domain) public IPAddress? FindBestAddress(string domain)
{ {
lock (this.syncRoot) lock (this.syncRoot)
{ {
// 如果上一次的ip可以使用就返回上一次的ip return this.contextHashSet
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) .Where(item => item.Available && item.Domain == domain)
.OrderBy(item => item.Elapsed) .OrderByDescending(item => item.Statistics.GetSuccessRate())
.ThenBy(item => item.Statistics.GetAvgElapsed())
.Select(item => item.Address) .Select(item => item.Address)
.FirstOrDefault(); .FirstOrDefault();
if (fastAddress != null)
{
this.domainAdressCache[domain] = fastAddress;
}
else
{
this.domainAdressCache.Remove(domain);
}
return fastAddress;
} }
} }
} }

View File

@ -0,0 +1,57 @@
using System;
namespace FastGithub.Scanner
{
sealed class GithubContextStatistics
{
/// <summary>
/// 扫描总次数
/// </summary>
public int TotalScanCount { get; private set; }
/// <summary>
/// 扫描总成功次数
/// </summary>
public int TotalSuccessCount { get; private set; }
/// <summary>
/// 扫描总耗时
/// </summary>
public TimeSpan TotalSuccessElapsed { get; private set; }
public void SetScan()
{
this.TotalScanCount += 1;
}
public void SetScanSuccess(TimeSpan elapsed)
{
this.TotalSuccessCount += 1;
this.TotalSuccessElapsed = this.TotalSuccessElapsed.Add(elapsed);
}
/// <summary>
/// 获取成功率
/// </summary>
/// <returns></returns>
public double GetSuccessRate()
{
return this.TotalScanCount > 0 ?
(double)this.TotalSuccessCount / this.TotalScanCount
: 0d;
}
/// <summary>
/// 获取平均耗时
/// </summary>
/// <returns></returns>
public TimeSpan GetAvgElapsed()
{
return this.TotalScanCount > 0
? this.TotalSuccessElapsed / this.TotalScanCount
: TimeSpan.MaxValue;
}
}
}

View File

@ -30,18 +30,18 @@ namespace FastGithub.Scanner
this.fullScanDelegate = pipelineBuilder this.fullScanDelegate = pipelineBuilder
.New() .New()
.Use<ConcurrentMiddleware>() .Use<ConcurrentMiddleware>()
.Use<ScanElapsedMiddleware>() .Use<ScanOkLogMiddleware>()
.Use<StatisticsMiddleware>()
.Use<PortScanMiddleware>() .Use<PortScanMiddleware>()
.Use<HttpsScanMiddleware>() .Use<HttpsScanMiddleware>()
.Use<ScanOkLogMiddleware>()
.Build(); .Build();
this.resultScanDelegate = pipelineBuilder this.resultScanDelegate = pipelineBuilder
.New() .New()
.Use<ScanElapsedMiddleware>() .Use<ScanOkLogMiddleware>()
.Use<StatisticsMiddleware>()
.Use<PortScanMiddleware>() .Use<PortScanMiddleware>()
.Use<HttpsScanMiddleware>() .Use<HttpsScanMiddleware>()
.Use<ScanOkLogMiddleware>()
.Build(); .Build();
} }
@ -62,7 +62,7 @@ namespace FastGithub.Scanner
await this.fullScanDelegate(context); await this.fullScanDelegate(context);
if (context.Available == true) if (context.Available == true)
{ {
this.results.AddOrUpdate(context); this.results.Add(context);
} }
} }
} }
@ -83,7 +83,7 @@ namespace FastGithub.Scanner
public IPAddress? FindFastAddress(string domain) public IPAddress? FindFastAddress(string domain)
{ {
return domain.Contains("github", StringComparison.OrdinalIgnoreCase) return domain.Contains("github", StringComparison.OrdinalIgnoreCase)
? this.results.FindFastAddress(domain) ? this.results.FindBestAddress(domain)
: default; : default;
} }
} }

View File

@ -1,6 +1,7 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System; using System;
using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace FastGithub.Scanner.Middlewares namespace FastGithub.Scanner.Middlewares
@ -10,19 +11,29 @@ namespace FastGithub.Scanner.Middlewares
{ {
private readonly ILogger<ScanOkLogMiddleware> logger; private readonly ILogger<ScanOkLogMiddleware> logger;
private record ScanOk(string Domain, IPAddress Address, int TotalScanCount, double SuccessRate, TimeSpan AvgElapsed);
public ScanOkLogMiddleware(ILogger<ScanOkLogMiddleware> logger) public ScanOkLogMiddleware(ILogger<ScanOkLogMiddleware> logger)
{ {
this.logger = logger; this.logger = logger;
} }
public Task InvokeAsync(GithubContext context, Func<Task> next) public async Task InvokeAsync(GithubContext context, Func<Task> next)
{ {
await next();
if (context.Available) if (context.Available)
{ {
this.logger.LogInformation(context.ToString()); var mesage = new ScanOk(
} context.Domain,
context.Address,
context.Statistics.TotalScanCount,
context.Statistics.GetSuccessRate(),
context.Statistics.GetAvgElapsed()
);
return next(); this.logger.LogInformation(mesage.ToString());
}
} }
} }
} }

View File

@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace FastGithub.Scanner.Middlewares namespace FastGithub.Scanner.Middlewares
{ {
[Service(ServiceLifetime.Singleton)] [Service(ServiceLifetime.Singleton)]
sealed class ScanElapsedMiddleware : IMiddleware<GithubContext> sealed class StatisticsMiddleware : IMiddleware<GithubContext>
{ {
public async Task InvokeAsync(GithubContext context, Func<Task> next) public async Task InvokeAsync(GithubContext context, Func<Task> next)
{ {
@ -14,12 +14,16 @@ namespace FastGithub.Scanner.Middlewares
try try
{ {
stopwatch.Start(); stopwatch.Start();
context.Statistics.SetScan();
await next(); await next();
} }
finally finally
{ {
stopwatch.Stop(); stopwatch.Stop();
context.Elapsed = stopwatch.Elapsed; if (context.Available == true)
{
context.Statistics.SetScanSuccess(stopwatch.Elapsed);
}
} }
} }
} }