Browse Source

域名隔离

老九 3 years ago
parent
commit
1163fa4678

+ 22 - 23
FastGithub.Http/HttpClientFactory.cs

@@ -20,7 +20,7 @@ namespace FastGithub.Http
         /// <summary>
         /// <summary>
         /// 非首次生命周期
         /// 非首次生命周期
         /// </summary>
         /// </summary>
-        private readonly TimeSpan nextLifeTime = TimeSpan.FromMinutes(1d);
+        private readonly TimeSpan nextLifeTime = TimeSpan.FromSeconds(100d);
 
 
         /// <summary>
         /// <summary>
         /// LifetimeHttpHandler清理器
         /// LifetimeHttpHandler清理器
@@ -30,7 +30,7 @@ namespace FastGithub.Http
         /// <summary>
         /// <summary>
         /// LazyOf(LifetimeHttpHandler)缓存
         /// LazyOf(LifetimeHttpHandler)缓存
         /// </summary>
         /// </summary>
-        private readonly ConcurrentDictionary<DomainConfig, Lazy<LifetimeHttpHandler>> httpHandlerLazyCache = new();
+        private readonly ConcurrentDictionary<LifeTimeKey, Lazy<LifetimeHttpHandler>> httpHandlerLazyCache = new();
 
 
 
 
         /// <summary>
         /// <summary>
@@ -45,20 +45,31 @@ namespace FastGithub.Http
         /// <summary>
         /// <summary>
         /// 创建httpClient
         /// 创建httpClient
         /// </summary>
         /// </summary>
+        /// <param name="domain"></param>
         /// <param name="domainConfig"></param>
         /// <param name="domainConfig"></param>
         /// <returns></returns>
         /// <returns></returns>
-        public HttpClient CreateHttpClient(DomainConfig domainConfig)
+        public HttpClient CreateHttpClient(string domain, DomainConfig domainConfig)
         {
         {
-            var lifetimeHttpHandlerLazy = this.httpHandlerLazyCache.GetOrAdd(domainConfig, CreateLifetimeHttpHandlerLazy);
-            var lifetimeHttpHandler = lifetimeHttpHandlerLazy.Value;
+            var lifeTimeKey = new LifeTimeKey(domain, domainConfig);
+            var lifetimeHttpHandler = this.httpHandlerLazyCache.GetOrAdd(lifeTimeKey, CreateLifetimeHttpHandlerLazy).Value;
             return new HttpClient(lifetimeHttpHandler, disposeHandler: false);
             return new HttpClient(lifetimeHttpHandler, disposeHandler: false);
 
 
-            Lazy<LifetimeHttpHandler> CreateLifetimeHttpHandlerLazy(DomainConfig domainConfig)
+            Lazy<LifetimeHttpHandler> CreateLifetimeHttpHandlerLazy(LifeTimeKey lifeTimeKey)
             {
             {
-                return new Lazy<LifetimeHttpHandler>(() => this.CreateLifetimeHttpHandler(domainConfig, this.firstLiftTime), true);
+                return new Lazy<LifetimeHttpHandler>(() => this.CreateLifetimeHttpHandler(lifeTimeKey, this.firstLiftTime), true);
             }
             }
         }
         }
 
 
+        /// <summary>
+        /// 创建LifetimeHttpHandler
+        /// </summary>
+        /// <param name="lifeTimeKey"></param>
+        /// <param name="lifeTime"></param>
+        /// <returns></returns>
+        private LifetimeHttpHandler CreateLifetimeHttpHandler(LifeTimeKey lifeTimeKey, TimeSpan lifeTime)
+        {
+            return new LifetimeHttpHandler(this.domainResolver, lifeTimeKey, lifeTime, this.OnLifetimeHttpHandlerDeactivate);
+        }
 
 
         /// <summary>
         /// <summary>
         /// 当有httpHandler失效时
         /// 当有httpHandler失效时
@@ -66,26 +77,14 @@ namespace FastGithub.Http
         /// <param name="lifetimeHttpHandler">httpHandler</param>
         /// <param name="lifetimeHttpHandler">httpHandler</param>
         private void OnLifetimeHttpHandlerDeactivate(LifetimeHttpHandler lifetimeHttpHandler)
         private void OnLifetimeHttpHandlerDeactivate(LifetimeHttpHandler lifetimeHttpHandler)
         {
         {
-            var domainConfig = lifetimeHttpHandler.DomainConfig;
-            this.httpHandlerLazyCache[domainConfig] = CreateLifetimeHttpHandlerLazy(domainConfig);
+            var lifeTimeKey = lifetimeHttpHandler.LifeTimeKey;
+            this.httpHandlerLazyCache[lifeTimeKey] = CreateLifetimeHttpHandlerLazy(lifeTimeKey);
             this.httpHandlerCleaner.Add(lifetimeHttpHandler);
             this.httpHandlerCleaner.Add(lifetimeHttpHandler);
 
 
-            Lazy<LifetimeHttpHandler> CreateLifetimeHttpHandlerLazy(DomainConfig domainConfig)
+            Lazy<LifetimeHttpHandler> CreateLifetimeHttpHandlerLazy(LifeTimeKey lifeTimeKey)
             {
             {
-                return new Lazy<LifetimeHttpHandler>(() => this.CreateLifetimeHttpHandler(domainConfig, this.nextLifeTime), true);
+                return new Lazy<LifetimeHttpHandler>(() => this.CreateLifetimeHttpHandler(lifeTimeKey, this.nextLifeTime), true);
             }
             }
         }
         }
-
-        /// <summary>
-        /// 创建LifetimeHttpHandler
-        /// </summary>
-        /// <param name="domainConfig"></param>
-        /// <param name="lifeTime"></param>
-        /// <returns></returns>
-        private LifetimeHttpHandler CreateLifetimeHttpHandler(DomainConfig domainConfig, TimeSpan lifeTime)
-        {
-            var httpClientHandler = new HttpClientHandler(domainConfig, this.domainResolver);
-            return new LifetimeHttpHandler(httpClientHandler, lifeTime, this.OnLifetimeHttpHandlerDeactivate);
-        }
     }
     }
 }
 }

+ 7 - 11
FastGithub.Http/HttpClientHandler.cs

@@ -21,14 +21,10 @@ namespace FastGithub.Http
     /// </summary> 
     /// </summary> 
     class HttpClientHandler : DelegatingHandler
     class HttpClientHandler : DelegatingHandler
     {
     {
+        private readonly DomainConfig domainConfig;
         private readonly IDomainResolver domainResolver;
         private readonly IDomainResolver domainResolver;
         private readonly TimeSpan connectTimeout = TimeSpan.FromSeconds(10d);
         private readonly TimeSpan connectTimeout = TimeSpan.FromSeconds(10d);
 
 
-        /// <summary>
-        /// 获取域名配置
-        /// </summary>
-        public DomainConfig DomainConfig { get; }
-
         /// <summary>
         /// <summary>
         /// HttpClientHandler
         /// HttpClientHandler
         /// </summary>
         /// </summary>
@@ -36,8 +32,8 @@ namespace FastGithub.Http
         /// <param name="domainResolver"></param> 
         /// <param name="domainResolver"></param> 
         public HttpClientHandler(DomainConfig domainConfig, IDomainResolver domainResolver)
         public HttpClientHandler(DomainConfig domainConfig, IDomainResolver domainResolver)
         {
         {
+            this.domainConfig = domainConfig;
             this.domainResolver = domainResolver;
             this.domainResolver = domainResolver;
-            this.DomainConfig = domainConfig;
             this.InnerHandler = this.CreateSocketsHttpHandler();
             this.InnerHandler = this.CreateSocketsHttpHandler();
         }
         }
 
 
@@ -57,16 +53,16 @@ namespace FastGithub.Http
 
 
             // 请求上下文信息
             // 请求上下文信息
             var isHttps = uri.Scheme == Uri.UriSchemeHttps;
             var isHttps = uri.Scheme == Uri.UriSchemeHttps;
-            var tlsSniValue = this.DomainConfig.GetTlsSniPattern().WithDomain(uri.Host).WithRandom();
+            var tlsSniValue = this.domainConfig.GetTlsSniPattern().WithDomain(uri.Host).WithRandom();
             request.SetRequestContext(new RequestContext(isHttps, tlsSniValue));
             request.SetRequestContext(new RequestContext(isHttps, tlsSniValue));
 
 
             // 设置请求头host,修改协议为http
             // 设置请求头host,修改协议为http
             request.Headers.Host = uri.Host;
             request.Headers.Host = uri.Host;
             request.RequestUri = new UriBuilder(uri) { Scheme = Uri.UriSchemeHttp }.Uri;
             request.RequestUri = new UriBuilder(uri) { Scheme = Uri.UriSchemeHttp }.Uri;
 
 
-            if (this.DomainConfig.Timeout != null)
+            if (this.domainConfig.Timeout != null)
             {
             {
-                using var timeoutTokenSource = new CancellationTokenSource(this.DomainConfig.Timeout.Value);
+                using var timeoutTokenSource = new CancellationTokenSource(this.domainConfig.Timeout.Value);
                 using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutTokenSource.Token);
                 using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutTokenSource.Token);
                 return await base.SendAsync(request, linkedTokenSource.Token);
                 return await base.SendAsync(request, linkedTokenSource.Token);
             }
             }
@@ -157,7 +153,7 @@ namespace FastGithub.Http
             {
             {
                 if (errors.HasFlag(SslPolicyErrors.RemoteCertificateNameMismatch))
                 if (errors.HasFlag(SslPolicyErrors.RemoteCertificateNameMismatch))
                 {
                 {
-                    if (this.DomainConfig.TlsIgnoreNameMismatch == true)
+                    if (this.domainConfig.TlsIgnoreNameMismatch == true)
                     {
                     {
                         return true;
                         return true;
                     }
                     }
@@ -179,7 +175,7 @@ namespace FastGithub.Http
         /// <returns></returns>
         /// <returns></returns>
         private async IAsyncEnumerable<IPEndPoint> GetIPEndPointsAsync(DnsEndPoint dnsEndPoint, [EnumeratorCancellation] CancellationToken cancellationToken)
         private async IAsyncEnumerable<IPEndPoint> GetIPEndPointsAsync(DnsEndPoint dnsEndPoint, [EnumeratorCancellation] CancellationToken cancellationToken)
         {
         {
-            if (IPAddress.TryParse(this.DomainConfig.IPAddress, out var address) ||
+            if (IPAddress.TryParse(this.domainConfig.IPAddress, out var address) ||
                 IPAddress.TryParse(dnsEndPoint.Host, out address))
                 IPAddress.TryParse(dnsEndPoint.Host, out address))
             {
             {
                 yield return new IPEndPoint(address, dnsEndPoint.Port);
                 yield return new IPEndPoint(address, dnsEndPoint.Port);

+ 2 - 1
FastGithub.Http/IHttpClientFactory.cs

@@ -10,8 +10,9 @@ namespace FastGithub.Http
         /// <summary>
         /// <summary>
         /// 创建httpClient
         /// 创建httpClient
         /// </summary>
         /// </summary>
+        /// <param name="domain"></param>
         /// <param name="domainConfig"></param>
         /// <param name="domainConfig"></param>
         /// <returns></returns>
         /// <returns></returns>
-        HttpClient CreateHttpClient(DomainConfig domainConfig);
+        HttpClient CreateHttpClient(string domain, DomainConfig domainConfig);
     }
     }
 }
 }

+ 31 - 0
FastGithub.Http/LifeTimeKey.cs

@@ -0,0 +1,31 @@
+using FastGithub.Configuration;
+
+namespace FastGithub.Http
+{
+    /// <summary>
+    /// 生命周期的Key
+    /// </summary>
+    record LifeTimeKey
+    {
+        /// <summary>
+        /// 域名
+        /// </summary>
+        public string Domain { get; }
+
+        /// <summary>
+        /// 域名配置
+        /// </summary>
+        public DomainConfig DomainConfig { get; }
+
+        /// <summary>
+        /// 生命周期的Key
+        /// </summary>
+        /// <param name="domain"></param>
+        /// <param name="domainConfig"></param>
+        public LifeTimeKey(string domain, DomainConfig domainConfig)
+        {
+            this.Domain = domain;
+            this.DomainConfig = domainConfig;
+        }
+    }
+}

+ 9 - 11
FastGithub.Http/LifetimeHttpHandler.cs

@@ -1,4 +1,4 @@
-using FastGithub.Configuration;
+using FastGithub.DomainResolve;
 using System;
 using System;
 using System.Net.Http;
 using System.Net.Http;
 using System.Threading;
 using System.Threading;
@@ -12,21 +12,19 @@ namespace FastGithub.Http
     {
     {
         private readonly Timer timer;
         private readonly Timer timer;
 
 
-        /// <summary>
-        /// 获取域名配置
-        /// </summary>
-        public DomainConfig DomainConfig { get; }
+        public LifeTimeKey LifeTimeKey { get; }
 
 
         /// <summary>
         /// <summary>
         /// 具有生命周期的HttpHandler
         /// 具有生命周期的HttpHandler
         /// </summary>
         /// </summary>
-        /// <param name="handler">HttpHandler</param>
-        /// <param name="lifeTime">拦截器的生命周期</param>
-        /// <param name="deactivateAction">失效回调</param>
-        public LifetimeHttpHandler(HttpClientHandler handler, TimeSpan lifeTime, Action<LifetimeHttpHandler> deactivateAction)
-            : base(handler)
+        /// <param name="domainResolver"></param>
+        /// <param name="lifeTimeKey"></param>
+        /// <param name="lifeTime"></param>
+        /// <param name="deactivateAction"></param>
+        public LifetimeHttpHandler(IDomainResolver domainResolver, LifeTimeKey lifeTimeKey, TimeSpan lifeTime, Action<LifetimeHttpHandler> deactivateAction)
         {
         {
-            this.DomainConfig = handler.DomainConfig;
+            this.LifeTimeKey = lifeTimeKey;
+            this.InnerHandler = new HttpClientHandler(lifeTimeKey.DomainConfig, domainResolver);
             this.timer = new Timer(this.OnTimerCallback, deactivateAction, lifeTime, Timeout.InfiniteTimeSpan);
             this.timer = new Timer(this.OnTimerCallback, deactivateAction, lifeTime, Timeout.InfiniteTimeSpan);
         }
         }
 
 

+ 1 - 1
FastGithub.HttpServer/HttpReverseProxyMiddleware.cs

@@ -47,7 +47,7 @@ namespace FastGithub.HttpServer
             {
             {
                 var scheme = context.Request.Scheme;
                 var scheme = context.Request.Scheme;
                 var destinationPrefix = GetDestinationPrefix(scheme, host, domainConfig.Destination);
                 var destinationPrefix = GetDestinationPrefix(scheme, host, domainConfig.Destination);
-                var httpClient = this.httpClientFactory.CreateHttpClient(domainConfig);
+                var httpClient = this.httpClientFactory.CreateHttpClient(host.Host, domainConfig);
                 var error = await httpForwarder.SendAsync(context, destinationPrefix, httpClient);
                 var error = await httpForwarder.SendAsync(context, destinationPrefix, httpClient);
                 await HandleErrorAsync(context, error);
                 await HandleErrorAsync(context, error);
             }
             }