diff --git a/FastGithub.Http/HttpClientFactory.cs b/FastGithub.Http/HttpClientFactory.cs index 61be5a1..76be907 100644 --- a/FastGithub.Http/HttpClientFactory.cs +++ b/FastGithub.Http/HttpClientFactory.cs @@ -20,7 +20,7 @@ namespace FastGithub.Http /// /// 非首次生命周期 /// - private readonly TimeSpan nextLifeTime = TimeSpan.FromMinutes(1d); + private readonly TimeSpan nextLifeTime = TimeSpan.FromSeconds(100d); /// /// LifetimeHttpHandler清理器 @@ -30,7 +30,7 @@ namespace FastGithub.Http /// /// LazyOf(LifetimeHttpHandler)缓存 /// - private readonly ConcurrentDictionary> httpHandlerLazyCache = new(); + private readonly ConcurrentDictionary> httpHandlerLazyCache = new(); /// @@ -45,20 +45,31 @@ namespace FastGithub.Http /// /// 创建httpClient /// + /// /// /// - 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); - Lazy CreateLifetimeHttpHandlerLazy(DomainConfig domainConfig) + Lazy CreateLifetimeHttpHandlerLazy(LifeTimeKey lifeTimeKey) { - return new Lazy(() => this.CreateLifetimeHttpHandler(domainConfig, this.firstLiftTime), true); + return new Lazy(() => this.CreateLifetimeHttpHandler(lifeTimeKey, this.firstLiftTime), true); } } + /// + /// 创建LifetimeHttpHandler + /// + /// + /// + /// + private LifetimeHttpHandler CreateLifetimeHttpHandler(LifeTimeKey lifeTimeKey, TimeSpan lifeTime) + { + return new LifetimeHttpHandler(this.domainResolver, lifeTimeKey, lifeTime, this.OnLifetimeHttpHandlerDeactivate); + } /// /// 当有httpHandler失效时 @@ -66,26 +77,14 @@ namespace FastGithub.Http /// httpHandler 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); - Lazy CreateLifetimeHttpHandlerLazy(DomainConfig domainConfig) + Lazy CreateLifetimeHttpHandlerLazy(LifeTimeKey lifeTimeKey) { - return new Lazy(() => this.CreateLifetimeHttpHandler(domainConfig, this.nextLifeTime), true); + return new Lazy(() => this.CreateLifetimeHttpHandler(lifeTimeKey, this.nextLifeTime), true); } } - - /// - /// 创建LifetimeHttpHandler - /// - /// - /// - /// - private LifetimeHttpHandler CreateLifetimeHttpHandler(DomainConfig domainConfig, TimeSpan lifeTime) - { - var httpClientHandler = new HttpClientHandler(domainConfig, this.domainResolver); - return new LifetimeHttpHandler(httpClientHandler, lifeTime, this.OnLifetimeHttpHandlerDeactivate); - } } } \ No newline at end of file diff --git a/FastGithub.Http/HttpClientHandler.cs b/FastGithub.Http/HttpClientHandler.cs index 2e8fc98..15b9c4a 100644 --- a/FastGithub.Http/HttpClientHandler.cs +++ b/FastGithub.Http/HttpClientHandler.cs @@ -21,14 +21,10 @@ namespace FastGithub.Http /// class HttpClientHandler : DelegatingHandler { + private readonly DomainConfig domainConfig; private readonly IDomainResolver domainResolver; private readonly TimeSpan connectTimeout = TimeSpan.FromSeconds(10d); - /// - /// 获取域名配置 - /// - public DomainConfig DomainConfig { get; } - /// /// HttpClientHandler /// @@ -36,8 +32,8 @@ namespace FastGithub.Http /// public HttpClientHandler(DomainConfig domainConfig, IDomainResolver domainResolver) { + this.domainConfig = domainConfig; this.domainResolver = domainResolver; - this.DomainConfig = domainConfig; this.InnerHandler = this.CreateSocketsHttpHandler(); } @@ -57,16 +53,16 @@ namespace FastGithub.Http // 请求上下文信息 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)); // 设置请求头host,修改协议为http request.Headers.Host = uri.Host; 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); return await base.SendAsync(request, linkedTokenSource.Token); } @@ -157,7 +153,7 @@ namespace FastGithub.Http { if (errors.HasFlag(SslPolicyErrors.RemoteCertificateNameMismatch)) { - if (this.DomainConfig.TlsIgnoreNameMismatch == true) + if (this.domainConfig.TlsIgnoreNameMismatch == true) { return true; } @@ -179,7 +175,7 @@ namespace FastGithub.Http /// private async IAsyncEnumerable 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)) { yield return new IPEndPoint(address, dnsEndPoint.Port); diff --git a/FastGithub.Http/IHttpClientFactory.cs b/FastGithub.Http/IHttpClientFactory.cs index e0e5fc5..77b6ef6 100644 --- a/FastGithub.Http/IHttpClientFactory.cs +++ b/FastGithub.Http/IHttpClientFactory.cs @@ -10,8 +10,9 @@ namespace FastGithub.Http /// /// 创建httpClient /// + /// /// /// - HttpClient CreateHttpClient(DomainConfig domainConfig); + HttpClient CreateHttpClient(string domain, DomainConfig domainConfig); } } diff --git a/FastGithub.Http/LifeTimeKey.cs b/FastGithub.Http/LifeTimeKey.cs new file mode 100644 index 0000000..11ad5f4 --- /dev/null +++ b/FastGithub.Http/LifeTimeKey.cs @@ -0,0 +1,31 @@ +using FastGithub.Configuration; + +namespace FastGithub.Http +{ + /// + /// 生命周期的Key + /// + record LifeTimeKey + { + /// + /// 域名 + /// + public string Domain { get; } + + /// + /// 域名配置 + /// + public DomainConfig DomainConfig { get; } + + /// + /// 生命周期的Key + /// + /// + /// + public LifeTimeKey(string domain, DomainConfig domainConfig) + { + this.Domain = domain; + this.DomainConfig = domainConfig; + } + } +} diff --git a/FastGithub.Http/LifetimeHttpHandler.cs b/FastGithub.Http/LifetimeHttpHandler.cs index 8edf8f4..a3fb0c6 100644 --- a/FastGithub.Http/LifetimeHttpHandler.cs +++ b/FastGithub.Http/LifetimeHttpHandler.cs @@ -1,4 +1,4 @@ -using FastGithub.Configuration; +using FastGithub.DomainResolve; using System; using System.Net.Http; using System.Threading; @@ -12,21 +12,19 @@ namespace FastGithub.Http { private readonly Timer timer; - /// - /// 获取域名配置 - /// - public DomainConfig DomainConfig { get; } + public LifeTimeKey LifeTimeKey { get; } /// /// 具有生命周期的HttpHandler /// - /// HttpHandler - /// 拦截器的生命周期 - /// 失效回调 - public LifetimeHttpHandler(HttpClientHandler handler, TimeSpan lifeTime, Action deactivateAction) - : base(handler) + /// + /// + /// + /// + public LifetimeHttpHandler(IDomainResolver domainResolver, LifeTimeKey lifeTimeKey, TimeSpan lifeTime, Action 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); } diff --git a/FastGithub.HttpServer/HttpReverseProxyMiddleware.cs b/FastGithub.HttpServer/HttpReverseProxyMiddleware.cs index c0762f5..067b3de 100644 --- a/FastGithub.HttpServer/HttpReverseProxyMiddleware.cs +++ b/FastGithub.HttpServer/HttpReverseProxyMiddleware.cs @@ -47,7 +47,7 @@ namespace FastGithub.HttpServer { var scheme = context.Request.Scheme; 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); await HandleErrorAsync(context, error); }