完善IP测速缓存
This commit is contained in:
		
							parent
							
								
									ea3206d20e
								
							
						
					
					
						commit
						2bc292483b
					
				@ -109,13 +109,7 @@ namespace FastGithub.DomainResolve
 | 
				
			|||||||
                    hashSet.Add(address);
 | 
					                    hashSet.Add(address);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var statusArray = await this.statusService.GetParallelAsync(hashSet, dnsEndPoint.Port, cancellationToken);
 | 
					                var newAddresses = await this.statusService.GetAvailableAddressesAsync(hashSet, dnsEndPoint.Port, cancellationToken);
 | 
				
			||||||
                var newAddresses = statusArray
 | 
					 | 
				
			||||||
                    .Where(item => item.Elapsed < TimeSpan.MaxValue)
 | 
					 | 
				
			||||||
                    .OrderBy(item => item.Elapsed)
 | 
					 | 
				
			||||||
                    .Select(item => item.Address)
 | 
					 | 
				
			||||||
                    .ToArray();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (oldAddresses.SequenceEqual(newAddresses) == false)
 | 
					                if (oldAddresses.SequenceEqual(newAddresses) == false)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    this.dnsEndPointAddress[dnsEndPoint] = newAddresses;
 | 
					                    this.dnsEndPointAddress[dnsEndPoint] = newAddresses;
 | 
				
			||||||
 | 
				
			|||||||
@ -5,6 +5,7 @@ using System.Collections.Generic;
 | 
				
			|||||||
using System.Diagnostics;
 | 
					using System.Diagnostics;
 | 
				
			||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
using System.Net;
 | 
					using System.Net;
 | 
				
			||||||
 | 
					using System.Net.NetworkInformation;
 | 
				
			||||||
using System.Net.Sockets;
 | 
					using System.Net.Sockets;
 | 
				
			||||||
using System.Threading;
 | 
					using System.Threading;
 | 
				
			||||||
using System.Threading.Tasks;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
@ -13,30 +14,40 @@ namespace FastGithub.DomainResolve
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// IP状态服务
 | 
					    /// IP状态服务
 | 
				
			||||||
    /// 连接成功的IP缓存5分钟
 | 
					    /// 状态缓存5分钟
 | 
				
			||||||
    /// 连接失败的IP缓存2分钟
 | 
					    /// 连接超时5秒
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    sealed class IPAddressStatusService
 | 
					    sealed class IPAddressStatusService
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly TimeSpan activeTTL = TimeSpan.FromMinutes(5d);
 | 
					        private readonly TimeSpan brokeExpiration = TimeSpan.FromMinutes(1d);
 | 
				
			||||||
        private readonly TimeSpan negativeTTL = TimeSpan.FromMinutes(2d);
 | 
					        private readonly TimeSpan normalExpiration = TimeSpan.FromMinutes(5d);
 | 
				
			||||||
        private readonly TimeSpan connectTimeout = TimeSpan.FromSeconds(5d);
 | 
					        private readonly TimeSpan connectTimeout = TimeSpan.FromSeconds(5d);
 | 
				
			||||||
        private readonly IMemoryCache statusCache = new MemoryCache(Options.Create(new MemoryCacheOptions()));
 | 
					        private readonly IMemoryCache statusCache = new MemoryCache(Options.Create(new MemoryCacheOptions()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// 并行获取多个IP的状态
 | 
					        /// 并行获取可连接的IP
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <param name="addresses"></param>
 | 
					        /// <param name="addresses"></param>
 | 
				
			||||||
        /// <param name="port"></param>
 | 
					        /// <param name="port"></param>
 | 
				
			||||||
        /// <param name="cancellationToken"></param>
 | 
					        /// <param name="cancellationToken"></param>
 | 
				
			||||||
        /// <returns></returns>
 | 
					        /// <returns></returns>
 | 
				
			||||||
        public Task<IPAddressStatus[]> GetParallelAsync(IEnumerable<IPAddress> addresses, int port, CancellationToken cancellationToken)
 | 
					        public async Task<IPAddress[]> GetAvailableAddressesAsync(IEnumerable<IPAddress> addresses, int port, CancellationToken cancellationToken)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var statusTasks = addresses.Select(item => this.GetAsync(item, port, cancellationToken));
 | 
					            if (addresses.Any() == false)
 | 
				
			||||||
            return Task.WhenAll(statusTasks);
 | 
					            {
 | 
				
			||||||
 | 
					                return Array.Empty<IPAddress>();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var statusTasks = addresses.Select(item => this.GetStatusAsync(item, port, cancellationToken));
 | 
				
			||||||
 | 
					            var statusArray = await Task.WhenAll(statusTasks);
 | 
				
			||||||
 | 
					            return statusArray
 | 
				
			||||||
 | 
					                .Where(item => item.Elapsed < TimeSpan.MaxValue)
 | 
				
			||||||
 | 
					                .OrderBy(item => item.Elapsed)
 | 
				
			||||||
 | 
					                .Select(item => item.Address)
 | 
				
			||||||
 | 
					                .ToArray();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// 获取IP状态
 | 
					        /// 获取IP状态
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
@ -44,7 +55,7 @@ namespace FastGithub.DomainResolve
 | 
				
			|||||||
        /// <param name="port"></param>
 | 
					        /// <param name="port"></param>
 | 
				
			||||||
        /// <param name="cancellationToken"></param>
 | 
					        /// <param name="cancellationToken"></param>
 | 
				
			||||||
        /// <returns></returns>
 | 
					        /// <returns></returns>
 | 
				
			||||||
        public async Task<IPAddressStatus> GetAsync(IPAddress address, int port, CancellationToken cancellationToken)
 | 
					        private async Task<IPAddressStatus> GetStatusAsync(IPAddress address, int port, CancellationToken cancellationToken)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var endPoint = new IPEndPoint(address, port);
 | 
					            var endPoint = new IPEndPoint(address, port);
 | 
				
			||||||
            if (this.statusCache.TryGetValue<IPAddressStatus>(endPoint, out var status))
 | 
					            if (this.statusCache.TryGetValue<IPAddressStatus>(endPoint, out var status))
 | 
				
			||||||
@ -52,19 +63,6 @@ namespace FastGithub.DomainResolve
 | 
				
			|||||||
                return status;
 | 
					                return status;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            status = await this.GetAddressStatusAsync(endPoint, cancellationToken);
 | 
					 | 
				
			||||||
            var ttl = status.Elapsed < TimeSpan.MaxValue ? this.activeTTL : this.negativeTTL;
 | 
					 | 
				
			||||||
            return this.statusCache.Set(endPoint, status, ttl);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// <summary>
 | 
					 | 
				
			||||||
        /// 获取IP状态
 | 
					 | 
				
			||||||
        /// </summary>
 | 
					 | 
				
			||||||
        /// <param name="endPoint"></param>
 | 
					 | 
				
			||||||
        /// <param name="cancellationToken"></param>
 | 
					 | 
				
			||||||
        /// <returns></returns>
 | 
					 | 
				
			||||||
        private async Task<IPAddressStatus> GetAddressStatusAsync(IPEndPoint endPoint, CancellationToken cancellationToken)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            var stopWatch = Stopwatch.StartNew();
 | 
					            var stopWatch = Stopwatch.StartNew();
 | 
				
			||||||
            try
 | 
					            try
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -72,12 +70,17 @@ namespace FastGithub.DomainResolve
 | 
				
			|||||||
                using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutTokenSource.Token);
 | 
					                using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutTokenSource.Token);
 | 
				
			||||||
                using var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
 | 
					                using var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
 | 
				
			||||||
                await socket.ConnectAsync(endPoint, linkedTokenSource.Token);
 | 
					                await socket.ConnectAsync(endPoint, linkedTokenSource.Token);
 | 
				
			||||||
                return new IPAddressStatus(endPoint.Address, stopWatch.Elapsed);
 | 
					
 | 
				
			||||||
 | 
					                status = new IPAddressStatus(endPoint.Address, stopWatch.Elapsed);
 | 
				
			||||||
 | 
					                return this.statusCache.Set(endPoint, status, this.normalExpiration);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            catch (Exception)
 | 
					            catch (Exception)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                cancellationToken.ThrowIfCancellationRequested();
 | 
					                cancellationToken.ThrowIfCancellationRequested();
 | 
				
			||||||
                return new IPAddressStatus(endPoint.Address, TimeSpan.MaxValue);
 | 
					
 | 
				
			||||||
 | 
					                status = new IPAddressStatus(endPoint.Address, TimeSpan.MaxValue);
 | 
				
			||||||
 | 
					                var expiration = NetworkInterface.GetIsNetworkAvailable() ? this.normalExpiration : this.brokeExpiration;
 | 
				
			||||||
 | 
					                return this.statusCache.Set(endPoint, status, expiration);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            finally
 | 
					            finally
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user