重构GithubContext
This commit is contained in:
parent
b486f551cf
commit
922d47fdab
@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
@ -10,9 +12,21 @@ namespace FastGithub.Scanner
|
|||||||
sealed class GithubContext : DomainAddress, IEquatable<GithubContext>
|
sealed class GithubContext : DomainAddress, IEquatable<GithubContext>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取或设置是否可用
|
/// 最多保存最的近的10条记录
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Available { get; set; }
|
private const int MAX_LOG_COUNT = 10;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扫描记录
|
||||||
|
/// </summary>
|
||||||
|
private record ScanLog(bool Available, TimeSpan Elapsed);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扫描历史记录
|
||||||
|
/// </summary>
|
||||||
|
private readonly Queue<ScanLog> history = new();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置取消令牌
|
/// 设置取消令牌
|
||||||
@ -20,9 +34,21 @@ namespace FastGithub.Scanner
|
|||||||
public CancellationToken CancellationToken { get; }
|
public CancellationToken CancellationToken { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取扫描历史信息
|
/// 获取可用率
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public GithubContextHistory History { get; } = new();
|
/// <returns></returns>
|
||||||
|
public double AvailableRate => this.GetAvailableRate();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取平均耗时
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public TimeSpan AvgElapsed => this.GetAvgElapsed();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取或设置是否可用
|
||||||
|
/// </summary>
|
||||||
|
public bool Available { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -47,19 +73,74 @@ namespace FastGithub.Scanner
|
|||||||
this.CancellationToken = cancellationToken;
|
this.CancellationToken = cancellationToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取可用率
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private double GetAvailableRate()
|
||||||
|
{
|
||||||
|
if (this.history.Count == 0)
|
||||||
|
{
|
||||||
|
return 0d;
|
||||||
|
}
|
||||||
|
|
||||||
|
var availableCount = this.history.Count(item => item.Available);
|
||||||
|
return (double)availableCount / this.history.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取平均耗时
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private TimeSpan GetAvgElapsed()
|
||||||
|
{
|
||||||
|
var availableCount = 0;
|
||||||
|
var availableElapsed = TimeSpan.Zero;
|
||||||
|
|
||||||
|
foreach (var item in this.history)
|
||||||
|
{
|
||||||
|
if (item.Available == true)
|
||||||
|
{
|
||||||
|
availableCount += 1;
|
||||||
|
availableElapsed = availableElapsed.Add(item.Elapsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return availableCount == 0 ? TimeSpan.MaxValue : availableElapsed / availableCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加扫描记录
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="elapsed">扫描耗时</param>
|
||||||
|
public void AddScanLog(TimeSpan elapsed)
|
||||||
|
{
|
||||||
|
var log = new ScanLog(this.Available, elapsed);
|
||||||
|
this.history.Enqueue(log);
|
||||||
|
while (this.history.Count > MAX_LOG_COUNT)
|
||||||
|
{
|
||||||
|
this.history.Dequeue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否相等
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public bool Equals(GithubContext? other)
|
public bool Equals(GithubContext? other)
|
||||||
{
|
{
|
||||||
return base.Equals(other);
|
return base.Equals(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 转换为为统计信息
|
/// 转换为统计信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public string ToStatisticsString()
|
public string ToStatisticsString()
|
||||||
{
|
{
|
||||||
var rate = Math.Round(this.History.AvailableRate * 100, 2);
|
var availableRate = Math.Round(this.AvailableRate * 100, 2);
|
||||||
return $"{{Address={this.Address}, AvailableRate={rate}%, AvgElapsed={this.History.AvgElapsed.TotalSeconds}s}}";
|
return $"{{{nameof(Address)}={this.Address}, {nameof(AvailableRate)}={availableRate}%, {nameof(AvgElapsed)}={this.AvgElapsed.TotalSeconds}s}}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,77 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace FastGithub.Scanner
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// GithubContext的扫描历史
|
|
||||||
/// </summary>
|
|
||||||
sealed class GithubContextHistory
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 最多保存最的近的10条记录
|
|
||||||
/// </summary>
|
|
||||||
private const int MAX_LOG_COUNT = 10;
|
|
||||||
private record ScanLog(bool Available, TimeSpan Elapsed);
|
|
||||||
|
|
||||||
private readonly Queue<ScanLog> scanLogs = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取可用率
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public double AvailableRate
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (this.scanLogs.Count == 0)
|
|
||||||
{
|
|
||||||
return 0d;
|
|
||||||
}
|
|
||||||
|
|
||||||
var availableCount = this.scanLogs.Count(item => item.Available);
|
|
||||||
return (double)availableCount / this.scanLogs.Count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取平均耗时
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public TimeSpan AvgElapsed
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var availableCount = 0;
|
|
||||||
var availableElapsed = TimeSpan.Zero;
|
|
||||||
|
|
||||||
foreach (var item in this.scanLogs)
|
|
||||||
{
|
|
||||||
if (item.Available == true)
|
|
||||||
{
|
|
||||||
availableCount += 1;
|
|
||||||
availableElapsed = availableElapsed.Add(item.Elapsed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return availableCount == 0 ? TimeSpan.MaxValue : availableElapsed / availableCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 添加记录
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="available">是否可用</param>
|
|
||||||
/// <param name="elapsed">扫描耗时</param>
|
|
||||||
public void Add(bool available, TimeSpan elapsed)
|
|
||||||
{
|
|
||||||
this.scanLogs.Enqueue(new ScanLog(available, elapsed));
|
|
||||||
while (this.scanLogs.Count > MAX_LOG_COUNT)
|
|
||||||
{
|
|
||||||
this.scanLogs.Dequeue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -13,12 +13,12 @@ namespace FastGithub.Scanner
|
|||||||
[Service(ServiceLifetime.Transient)]
|
[Service(ServiceLifetime.Transient)]
|
||||||
sealed class GithubDnsHttpHandler : DelegatingHandler
|
sealed class GithubDnsHttpHandler : DelegatingHandler
|
||||||
{
|
{
|
||||||
private readonly GithubContextCollection scanResults;
|
private readonly GithubScanResults scanResults;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Github的dns解析的httpHandler
|
/// Github的dns解析的httpHandler
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public GithubDnsHttpHandler(GithubContextCollection scanResults)
|
public GithubDnsHttpHandler(GithubScanResults scanResults)
|
||||||
{
|
{
|
||||||
this.scanResults = scanResults;
|
this.scanResults = scanResults;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,10 +9,10 @@ namespace FastGithub.Scanner
|
|||||||
/// GithubContext集合
|
/// GithubContext集合
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Service(ServiceLifetime.Singleton)]
|
[Service(ServiceLifetime.Singleton)]
|
||||||
sealed class GithubContextCollection : IGithubScanResults
|
sealed class GithubScanResults : IGithubScanResults
|
||||||
{
|
{
|
||||||
private readonly object syncRoot = new();
|
private readonly object syncRoot = new();
|
||||||
private readonly List<GithubContext> contextList = new();
|
private readonly List<GithubContext> contexts = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加GithubContext
|
/// 添加GithubContext
|
||||||
@ -23,11 +23,11 @@ namespace FastGithub.Scanner
|
|||||||
{
|
{
|
||||||
lock (this.syncRoot)
|
lock (this.syncRoot)
|
||||||
{
|
{
|
||||||
if (this.contextList.Contains(context))
|
if (this.contexts.Contains(context))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.contextList.Add(context);
|
this.contexts.Add(context);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,23 +40,7 @@ namespace FastGithub.Scanner
|
|||||||
{
|
{
|
||||||
lock (this.syncRoot)
|
lock (this.syncRoot)
|
||||||
{
|
{
|
||||||
return this.contextList.ToArray();
|
return this.contexts.ToArray();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查询ip是否可用
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="domain"></param>
|
|
||||||
/// <param name="address"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public bool IsAvailable(string domain, IPAddress address)
|
|
||||||
{
|
|
||||||
lock (this.syncRoot)
|
|
||||||
{
|
|
||||||
var target = new GithubContext(domain, address);
|
|
||||||
var context = this.contextList.Find(item => item.Equals(target));
|
|
||||||
return context != null && context.Available;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,11 +53,11 @@ namespace FastGithub.Scanner
|
|||||||
{
|
{
|
||||||
lock (this.syncRoot)
|
lock (this.syncRoot)
|
||||||
{
|
{
|
||||||
return this.contextList
|
return this.contexts
|
||||||
.Where(item => item.Domain == domain && item.History.AvailableRate > 0d)
|
.Where(item => item.Domain == domain && item.AvailableRate > 0d)
|
||||||
.OrderByDescending(item => item.History.AvailableRate)
|
.OrderByDescending(item => item.AvailableRate)
|
||||||
.ThenByDescending(item => item.Available)
|
.ThenByDescending(item => item.Available)
|
||||||
.ThenBy(item => item.History.AvgElapsed)
|
.ThenBy(item => item.AvgElapsed)
|
||||||
.Select(item => item.Address)
|
.Select(item => item.Address)
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
}
|
}
|
||||||
@ -15,7 +15,7 @@ namespace FastGithub.Scanner
|
|||||||
sealed class GithubScanService
|
sealed class GithubScanService
|
||||||
{
|
{
|
||||||
private readonly GithubLookupFacotry lookupFactory;
|
private readonly GithubLookupFacotry lookupFactory;
|
||||||
private readonly GithubContextCollection scanResults;
|
private readonly GithubScanResults scanResults;
|
||||||
private readonly ILoggerFactory loggerFactory;
|
private readonly ILoggerFactory loggerFactory;
|
||||||
private readonly ILogger<GithubScanService> logger;
|
private readonly ILogger<GithubScanService> logger;
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ namespace FastGithub.Scanner
|
|||||||
/// <param name="logger"></param>
|
/// <param name="logger"></param>
|
||||||
public GithubScanService(
|
public GithubScanService(
|
||||||
GithubLookupFacotry lookupFactory,
|
GithubLookupFacotry lookupFactory,
|
||||||
GithubContextCollection scanResults,
|
GithubScanResults scanResults,
|
||||||
IServiceProvider appService,
|
IServiceProvider appService,
|
||||||
ILoggerFactory loggerFactory,
|
ILoggerFactory loggerFactory,
|
||||||
ILogger<GithubScanService> logger)
|
ILogger<GithubScanService> logger)
|
||||||
@ -94,8 +94,8 @@ namespace FastGithub.Scanner
|
|||||||
var results = this.scanResults.ToArray();
|
var results = this.scanResults.ToArray();
|
||||||
var contexts = results
|
var contexts = results
|
||||||
.OrderBy(item => item.Domain)
|
.OrderBy(item => item.Domain)
|
||||||
.ThenByDescending(item => item.History.AvailableRate)
|
.ThenByDescending(item => item.AvailableRate)
|
||||||
.ThenBy(item => item.History.AvgElapsed);
|
.ThenBy(item => item.AvgElapsed);
|
||||||
|
|
||||||
foreach (var context in contexts)
|
foreach (var context in contexts)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -7,14 +7,6 @@ namespace FastGithub.Scanner
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IGithubScanResults
|
public interface IGithubScanResults
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 查询ip是否可用
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="domain"></param>
|
|
||||||
/// <param name="address"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
bool IsAvailable(string domain, IPAddress address);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找最优的ip
|
/// 查找最优的ip
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -31,7 +31,7 @@ namespace FastGithub.Scanner.ScanMiddlewares
|
|||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
context.History.Add(context.Available, stopwatch.Elapsed);
|
context.AddScanLog(stopwatch.Elapsed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,7 +44,7 @@ namespace FastGithub
|
|||||||
.AddServiceAndOptions(assembly, configuration)
|
.AddServiceAndOptions(assembly, configuration)
|
||||||
.AddHostedService<GithubFullScanHostedService>()
|
.AddHostedService<GithubFullScanHostedService>()
|
||||||
.AddHostedService<GithubResultScanHostedService>()
|
.AddHostedService<GithubResultScanHostedService>()
|
||||||
.AddSingleton<IGithubScanResults>(appService => appService.GetRequiredService<GithubContextCollection>());
|
.AddSingleton<IGithubScanResults>(appService => appService.GetRequiredService<GithubScanResults>());
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user