域名隔离
This commit is contained in:
parent
3f01444f2d
commit
1163fa4678
@ -20,7 +20,7 @@ namespace FastGithub.Http
|
||||
/// <summary>
|
||||
/// 非首次生命周期
|
||||
/// </summary>
|
||||
private readonly TimeSpan nextLifeTime = TimeSpan.FromMinutes(1d);
|
||||
private readonly TimeSpan nextLifeTime = TimeSpan.FromSeconds(100d);
|
||||
|
||||
/// <summary>
|
||||
/// LifetimeHttpHandler清理器
|
||||
@ -30,7 +30,7 @@ namespace FastGithub.Http
|
||||
/// <summary>
|
||||
/// LazyOf(LifetimeHttpHandler)缓存
|
||||
/// </summary>
|
||||
private readonly ConcurrentDictionary<DomainConfig, Lazy<LifetimeHttpHandler>> httpHandlerLazyCache = new();
|
||||
private readonly ConcurrentDictionary<LifeTimeKey, Lazy<LifetimeHttpHandler>> httpHandlerLazyCache = new();
|
||||
|
||||
|
||||
/// <summary>
|
||||
@ -45,20 +45,31 @@ namespace FastGithub.Http
|
||||
/// <summary>
|
||||
/// 创建httpClient
|
||||
/// </summary>
|
||||
/// <param name="domain"></param>
|
||||
/// <param name="domainConfig"></param>
|
||||
/// <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);
|
||||
|
||||
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>
|
||||
/// 当有httpHandler失效时
|
||||
@ -66,26 +77,14 @@ namespace FastGithub.Http
|
||||
/// <param name="lifetimeHttpHandler">httpHandler</param>
|
||||
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<LifetimeHttpHandler> CreateLifetimeHttpHandlerLazy(DomainConfig domainConfig)
|
||||
Lazy<LifetimeHttpHandler> CreateLifetimeHttpHandlerLazy(LifeTimeKey lifeTimeKey)
|
||||
{
|
||||
return new Lazy<LifetimeHttpHandler>(() => this.CreateLifetimeHttpHandler(domainConfig, 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);
|
||||
return new Lazy<LifetimeHttpHandler>(() => this.CreateLifetimeHttpHandler(lifeTimeKey, this.nextLifeTime), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -21,14 +21,10 @@ namespace FastGithub.Http
|
||||
/// </summary>
|
||||
class HttpClientHandler : DelegatingHandler
|
||||
{
|
||||
private readonly DomainConfig domainConfig;
|
||||
private readonly IDomainResolver domainResolver;
|
||||
private readonly TimeSpan connectTimeout = TimeSpan.FromSeconds(10d);
|
||||
|
||||
/// <summary>
|
||||
/// 获取域名配置
|
||||
/// </summary>
|
||||
public DomainConfig DomainConfig { get; }
|
||||
|
||||
/// <summary>
|
||||
/// HttpClientHandler
|
||||
/// </summary>
|
||||
@ -36,8 +32,8 @@ namespace FastGithub.Http
|
||||
/// <param name="domainResolver"></param>
|
||||
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
|
||||
/// <returns></returns>
|
||||
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))
|
||||
{
|
||||
yield return new IPEndPoint(address, dnsEndPoint.Port);
|
||||
|
||||
@ -10,8 +10,9 @@ namespace FastGithub.Http
|
||||
/// <summary>
|
||||
/// 创建httpClient
|
||||
/// </summary>
|
||||
/// <param name="domain"></param>
|
||||
/// <param name="domainConfig"></param>
|
||||
/// <returns></returns>
|
||||
HttpClient CreateHttpClient(DomainConfig domainConfig);
|
||||
HttpClient CreateHttpClient(string domain, DomainConfig domainConfig);
|
||||
}
|
||||
}
|
||||
|
||||
31
FastGithub.Http/LifeTimeKey.cs
Normal file
31
FastGithub.Http/LifeTimeKey.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// 获取域名配置
|
||||
/// </summary>
|
||||
public DomainConfig DomainConfig { get; }
|
||||
public LifeTimeKey LifeTimeKey { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 具有生命周期的HttpHandler
|
||||
/// </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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user