Intro:
我正在构建一个单节点Web搜寻器,以简单地验证URL在.NET Core控制台应用程序中是否为200 OK
。我在使用HttpClient
向其发送请求的不同主机上有一组URL。我对使用Polly和TPL数据流还很陌生。
需求:
MaxDegreeOfParallelism
。429 TooManyRequests
响应。或者,我可能会使用断路器来取消收到同一429
响应的同一主机的并发请求,然后一次处理该特定主机?当前实施:
我当前的实现工作正常,只是我经常看到对同一主机的x
并行请求大约在同一时间返回429
...然后,它们全部暂停以执行重试策略...然后,他们全都在同一时间再次猛击同一台主机,但仍然经常收到429
。即使我在整个队列中平均分配了同一主机的多个实例,我的URL集合也会被一些特定的主机超载,这些主机最终仍会开始生成429
。
[收到429
之后,我想我只想向该主机发送一个并发请求,以尊重远程主机并追求200
。
验证器方法:
public async Task<int> GetValidCount(IEnumerable<Uri> urls, CancellationToken cancellationToken) { var validator = new TransformBlock<Uri, bool>( async u => (await _httpClient.GetAsync(u, HttpCompletionOption.ResponseHeadersRead, cancellationToken)).IsSuccessStatusCode, new ExecutionDataflowBlockOptions {MaxDegreeOfParallelism = MaxDegreeOfParallelism} ); foreach (var url in urls) await validator.SendAsync(url, cancellationToken); validator.Complete(); var validUrlCount = 0; while (await validator.OutputAvailableAsync(cancellationToken)) { if(await validator.ReceiveAsync(cancellationToken)) validUrlCount++; } await validator.Completion; return validUrlCount; }
应用于上面
GetValidCount()
中使用的HttpClient实例的Polly策略。
IAsyncPolicy<HttpResponseMessage> waitAndRetryTooManyRequests = Policy .HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.TooManyRequests) .WaitAndRetryAsync(3, (retryCount, response, context) => response.Result?.Headers.RetryAfter.Delta ?? TimeSpan.FromMilliseconds(120), async (response, timespan, retryCount, context) => { // log stuff });
问题:
我如何修改或替换此解决方案以增加对要求2的满足?
简介:我正在构建一个单节点Web搜寻器,以仅验证.NET Core控制台应用程序中的URL是否正确200。我在向其发送请求的不同主机上有一组URL ...
我将尝试引入某种标志LimitedMode
以检测到此特定客户端以受限模式进入。在下面,我声明了两种策略-一种简单的重试策略,仅用于捕获TooManyRequests并设置标志。第二个策略是现成的BulkHead
策略。
这里是为具有相同密钥的消息创建并发级别受限的TransformBlock
的方法。通过调用提供的TransformBlock
功能可获得每个消息的键。具有相同密钥的消息将彼此顺序处理(而不是并行处理)。该键也作为参数传递给keySelector
函数,因为在某些情况下它可能很有用。