我的使用场景: 我有很多Url链接,我会定期请求它们来判断服务是否正常。并且这些URL的状态会显示在客户端
问题: 如果其中一个Url超时,其他Url将一起等待。我该如何处理这种情况?比如Url1超时后不阻塞其他请求(其他url会先返回结果)。
如何通过API返回并行运行的结果(或者持续返回结果)?让客户端显示更加友好。比如先返回正常的URL结果,等待超时后再返回超时结果。
下面的Test1和Test2是我的两次尝试,但都没有达到预期的效果。
string[] urls = new string[]
{
"https://localhost:7268/api/Timeout",
"https://www.google.com:81",
"https://url1",
"https://url2"
};
// Get Data
async Task<HttpResponseMessage> HttpRequest2Async(string url, CancellationToken cancellationToken = default)
{
HttpClient httpClient = new HttpClient();
var responseMessage = await httpClient.GetAsync(url, cancellationToken);
return responseMessage;
}
// Test1 When Url1 times out, other Urls behind will wait.
List<HttpResponseMessage> urlResponses = new();
foreach (string url in urls)
{
var responseMessage = await HttpRequest2Async(url, default);
urlResponses.Add(responseMessage);
}
// Test2 As long as there is a Url timeout, all Urls will wait.
var tasks = new List<Task<HttpResponseMessage>>();
foreach (string url in urls)
{
var task = HttpRequest2Async(url, default);
tasks.Add(task);
}
var res = await Task.WhenAll(tasks);
结果:
如果其中一个Url超时,其他Url将一起等待。
^ 这是不精确的。更准确的说法是:由于代码的组织方式是在处理任何 http 响应之前收集所有 http 响应,因此缓慢的请求会阻止处理(如果任何请求导致超时,则这是最明显的) ,因为在请求超时之前需要花费很长时间)。
我可以看到 4 个选项:
ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = n };
await Parallel.ForEachAsync(urls, parallelOptions, async (uri, cancellationToken) =>
{
var r = await client.GetAsync(uri, cancellationToken);
... process the response here, not after all GetAsyncs are finished
});
这里的重点是 for all {fetch;process}
(与 for all {fetch}; for all {process}
)。Task.WhenAny()
而不是 WhenAll
并在任务完成后开始处理任务。GetAsync
)以下是我后来找到的解决方案。我现在再次回复,希望能帮助到其他人。
.NET有一个实时通信框架SignalR,可以让前后端实时通信,实时显示结果。并且可以使用任务调度框架Quartz.NET来调度监控任务。
这个问题的关键在于不懂的人如何找到合适的解决方案。使用什么语言、框架、技术可能是很多人都会遇到的问题。后来我也是用GPT了解到的,所以遇到这个问题最好的办法可能就是向其他有经验的人请教。