c# - 当从 Web API 项目调用时,Polly 在 .NET Framework 4.6.1 上无限期地等待线程
问题描述
.NET 版本:.NET Framework 4.6.1
Polly 版本:7.2.2
在 .NET Framework 4.6.1 上,当使用 Web API 项目时,Polly 将无限期地等待正在运行请求的线程,从而导致永远不会有响应返回给调用它的客户端。从控制台应用程序调用相同的方法就可以了。
这是使用 Visual Studio 'ASP.NET Web 应用程序 (.NET Framework)' 中新创建的解决方案进行测试的。我也在 .NET 5 中尝试了相同的代码,但这个问题不存在,它只发生在 .NET Framework 4.6.1 上。
重现问题的代码:
PolicyContainer.cs:
public class PolicyContainer
{
public IAsyncPolicy<HttpResponseMessage> CircutBreakerPolicy { get; set; }
public PolicyContainer()
{
SetCircutBreakerPolicy();
}
private void SetCircutBreakerPolicy()
{
//////////////////////////////////////////////////////////////////////////////////////
// Normally these values would be set by a config file, hardcoded for this example. //
//////////////////////////////////////////////////////////////////////////////////////
// 0.5 means 50% of requests must fail before the circut breaks
double failureThreshold = 0.5;
// 60 means only the most recent 60 seconds are considered for breaking the circut
double samplingDuration = 60;
// 10 means at least this many calls must pass through the circut within the samplingDuration before breaking the circut
int minimumThroughput = 10;
// 60 means the circut will be broken for 60 seconds after the threshold is met
double durationOfBreak = 60;
CircutBreakerPolicy = Policy.HandleResult<HttpResponseMessage>(result => !result.IsSuccessStatusCode)
.AdvancedCircuitBreakerAsync(failureThreshold,
TimeSpan.FromSeconds(samplingDuration),
minimumThroughput,
TimeSpan.FromSeconds(durationOfBreak),
OnBreak,
OnReset,
OnHalfOpen);
}
private void OnBreak(DelegateResult<HttpResponseMessage> response, TimeSpan timespan, Context context)
{
Console.WriteLine("Circut Broken");
}
private void OnReset(Context context)
{
Console.WriteLine("Circut Reset");
}
private void OnHalfOpen()
{
Console.WriteLine("Circut Half-Open");
}
}
PollyTestRequest.cs:
public class PollyTestRequest
{
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// If set to true the Web API will never return a response, though any other type of project works fine. //
///////////////////////////////////////////////////////////////////////////////////////////////////////////
private const bool USE_POLLY = true;
public static async Task<HttpResponseMessage> Send()
{
HttpClient httpClient = new HttpClient();
PolicyContainer policyContainer = new PolicyContainer();
HttpResponseMessage response;
if (USE_POLLY)
{
// Does not work in a Web API application.
// I stepped through the decompiled code this calls and it will arrive at a "public static bool Wait(object obj, int millisecondsTimeout, bool exitContext)" method.
// Inside this method there is a call to "ObjWait(exitContext, millisecondsTimeout, obj)", however the debugger will not decompile this method so the debugging session will stop if you try to step into it.
// The 'millisecondsTimeout' variable passed here will be "-1" and the 'exitContext' will be "null". I believe that this is what is hanging the thread indefinitely.
// Its very strange though, calling this from a Console app, it will work fine, but from a Web API application it will hang indefinitely.
response = await policyContainer.CircutBreakerPolicy.ExecuteAsync(
async token => await httpClient.PostAsync(new Uri("http://example.com"), new StringContent(""), token),
CancellationToken.None
);
}
else
{
// Works perfectly fine in both Web API and Console Apps
response = await httpClient.PostAsync(new Uri("http://example.com"), new StringContent("")).ConfigureAwait(false);
}
return response;
}
}
测试控制器.cs:
[Route("[controller]")]
public class TestController : ApiController
{
[HttpGet]
[Route("testRoute")]
public IHttpActionResult TestGetRoute()
{
var response = PollyTestRequest.Send().Result;
if (response.IsSuccessStatusCode)
{
return Ok();
}
else
{
return new StatusCodeResult(HttpStatusCode.InternalServerError, this);
}
}
}
解决方案
推荐阅读
- php - 使用 Laravel 时访问 .php 文件中的 mysqli
- flutter - 有人在同一个应用程序中使用过颤振谷歌登录和 onesignal 吗?
- ldap - 在 IBM Websphere 中配置了 AD LDAP,但登录应用程序仅适用于完整 DN
- apache-kafka - KSQL 多列连接 - LogicalBinaryExpression 无法转换为 ComparisonExpression
- prestashop - 从 1.7.3 升级到 1.7.6 后,目录产品页面出现错误 500
- java - 使用 IntelliJ IDEA 进行调试时如何将服务帐户凭据添加到 Google App Engine?
- java - 在向数组添加值的情况下,空间复杂度是多少?
- javascript - 是否可以获取从服务器下载的文件的 md5 哈希值?
- php - 里面有 $_SESSION 的 sql。得到这个:解析错误:语法错误,意外''(T_ENCAPSED_AND_WHITESPACE)
- glfw - GLFW | 什么是上下文?