C# Asp.net核心中间件,用于在需要很长时间时取消请求
如果我的api花费的时间超过x,我需要一个中间件来取消请求。 我的所有api调用都是异步且可取消的:C# Asp.net核心中间件,用于在需要很长时间时取消请求,c#,asp.net-core,asp.net-core-2.1,C#,Asp.net Core,Asp.net Core 2.1,如果我的api花费的时间超过x,我需要一个中间件来取消请求。 我的所有api调用都是异步且可取消的: public async Task<IActionResult> Get(CancellationToken token) { } ... public async Task InvokeAsync(HttpContext context) { //.... int customDurationMilis = 1000; //1second canc
public async Task<IActionResult> Get(CancellationToken token) { }
...
public async Task InvokeAsync(HttpContext context)
{
//....
int customDurationMilis = 1000; //1second
cancellTimer = new Timer(CancellRequestCallBack, context, customDurationMilis, Timeout.Infinite);
//...
await _next(context);
}
private void CancellRequestCallBack(HttpContext context)
{
//log...
//Aborts the connection underlying this request.
context.Abort();
}
至少有了这一点,我在errorhandlermiddleware中捕捉到了返回状态代码500的异常。但我不知道;邮递员收不到。相反,我得到了
“无法获得任何响应”
另外,我想带有请求的线程仍将运行。如何使用添加弹性和瞬时故障处理
Polly是一个.NET弹性和瞬时故障处理库,允许开发人员以流畅和线程安全的方式表达策略,如重试、断路器、超时、隔离和回退。如何使用添加弹性和瞬时故障处理
Polly是一个.NET弹性和瞬时故障处理库,允许开发人员以流畅和线程安全的方式表达策略,如重试、断路器、超时、隔离和回退。这实际上很难实现,原因有两个:
- 取消是合作的。这意味着您需要等待(传递)的所有内容来尊重令牌
- 异步意味着没有要中止的线程。您可以中止整个TCP连接,但是如果没有人在侦听令牌,也没有人在读取主体,那么它不会对正在运行的服务器代码做任何事情
- 使用
不是一个好的解决方案,因为您可能会同时使用Task.WhenAny
。您“取消”的代码可能会在中间件尝试写入超时响应的同时写入有效响应。即使抛出异常,也很危险,因为有其他正在运行的代码可能会同时触及HttpContext
李>HttpContext
如果您正在考虑取消令牌,那么您可以取消令牌并等待下一个解卷。当它启动时,您可以在写入之前查看响应是否已启动,并返回408(请求超时)。这实际上很难实现,原因有两个:
- 取消是合作的。这意味着您需要等待(传递)的所有内容来尊重令牌
- 异步意味着没有要中止的线程。您可以中止整个TCP连接,但是如果没有人在侦听令牌,也没有人在读取主体,那么它不会对正在运行的服务器代码做任何事情
- 使用
不是一个好的解决方案,因为您可能会同时使用Task.WhenAny
。您“取消”的代码可能会在中间件尝试写入超时响应的同时写入有效响应。即使抛出异常,也很危险,因为有其他正在运行的代码可能会同时触及HttpContext
李>HttpContext
如果您正在考虑取消令牌,那么您可以取消令牌并等待下一个解卷。当它这样做时,您可以在写入之前查看响应是否已启动,并返回408(请求超时)。提出了一个关于令牌的解决方案。 其思想是创建一个新令牌并为其定义一个超时。 但是,还需要使用CreateLinkedTokenSource将原始令牌与新令牌链接起来
public async Task InvokeAsync(HttpContext context)
{
using (var timoutTS = CancellationTokenSource.CreateLinkedTokenSource(context.RequestAborted))
{
timoutTS.CancelAfter(200);
context.RequestAborted = timoutTS.Token;
await _next(context);
}
}
提出了一个关于代币的解决方案。 其思想是创建一个新令牌并为其定义一个超时。 但是,还需要使用CreateLinkedTokenSource将原始令牌与新令牌链接起来
public async Task InvokeAsync(HttpContext context)
{
using (var timoutTS = CancellationTokenSource.CreateLinkedTokenSource(context.RequestAborted))
{
timoutTS.CancelAfter(200);
context.RequestAborted = timoutTS.Token;
await _next(context);
}
}
谢谢John,我们知道如何在自定义中间件组件中实现它。我在最初的问题中添加了一个更新。谢谢John,我们知道如何在自定义中间件组件中进行更新。我在最初的问题中添加了一个更新。谢谢@davidfoll。创建新令牌并使用CancelAfter()为其设置超时并将其链接到原始令牌(下面的新答案)将不起作用?您好,这是针对
netcore 2.1
netcore v3.1的任何更新或合适的解决方案而询问和回答的。创建新令牌并使用CancelAfter()为其设置超时并将其链接到原始令牌(下面的新答案)将不起作用?您好,这是针对netcore 2.1
任何更新或适用于netcore v3.1