在dotnet核心http应用程序中,我们有一个调用来执行工作,对支持服务进行几次http调用,然后返回。一切都在等待。这意味着该呼叫正在等待支持服务执行其工作,然后再将该呼叫返回给客户端。这导致呼叫超时。
提出的解决方案是将异步等待一直降低到最低,然后我们基本上可以将http调用(仍然是异步任务方法)包装在可抑制警告/编译器错误的编译指示中。
这让我感到紧张,因为您不能保证在调用线程返回并清理与该线程关联的异步计算机之前发出了HTTP请求的最终(或任何)请求。
我想念什么吗?这是那些奇怪但可用的情况之一吗?还是剥离线程来处理那些http调用更合适?
答案 0 :(得分:2)
您在谈论fire-and-forget,所以担心是对的。一劳永逸的问题。这是因为“忘记”的意思是“忘记”,并且几乎总是错误的决定让您的应用程序忘记某些事情。
如果有一个异常调用这些内部HTTP请求之一,则该异常将被忽略,除非您有特殊的逻辑来处理这种情况。并且请记住,不再有外部请求,因此不可能返回错误(无处可返回)。因此,您可能会无意间吞下错误。这会让您感到紧张。
此外,您还有一个问题,就是不通知ASP.NET您正在进行正在进行的后台工作。通过早点返回,您是在告诉ASP.NET发送响应,并且一切都很好,即使实际上工作还没有完成,您也不知道何时完成或什至不会成功。这里的要点是,代码上游(包括ASP.NET,IIS / Kestrel,代理,负载均衡器)没有任何想法,认为您的代码仍在工作-毕竟,您的代码只是告诉了所有这些内容,即完成处理该请求。 ASP.NET会响应关闭请求吗?当然! IIS可以定期回收其应用程序池吗?当然!滚动升级时,您的代理服务器能否使该节点停止旋转?当然!负载均衡器什么都不做,会给它带来更多工作吗?当然!据这些系统中的任何一个知道,您的应用程序实际上并没有处理该请求,并且可能会导致问题,例如您的“即发即弃”工作突然消失-同样,没有例外,日志或其他任何东西。这会让您感到紧张。
我会说最好的方法是修复下游呼叫(如果可能)。另外,还要研究异步并发,例如,先启动多个调用,然后再启动await Task.WhenAll
。如果这些方法还不够用,那么我建议使用适当的分布式体系结构:将API写入持久队列,并由处理该队列的单独应用程序完成后台工作。