在 Core 5 MVC 应用程序中 ASP.NET ControllerActionInvoker.InvokeActionAsync 方法似乎在同一线程中同时调用两次?

In ASP.NET Core 5 MVC app, ControllerActionInvoker.InvokeActionAsync method seems to be called twice in the same thread simultaneously?

提问人:Morfhine 提问时间:11/14/2023 最后编辑:marc_sMorfhine 更新时间:11/15/2023 访问量:53

问:

我使用 CLR 探查器以原始 APM 的方式记录框架方法。在使用它时,请求流通常流经我动态插入到应用程序中的中间件,然后流向请求处理程序。

在本例中,(ASP.NET Core 5 MVC),这里的请求线程将是相同的,其中函数返回一个对象,并且任务在线程池中的单独线程上继续。但是,在第一个方法返回 Task 对象之前,如何在同一线程中第二次触发呢?仅当负载较高时才会发生这种情况,否则请求流是可预测的。ControllerActionInvokerInvokeActionAsync()TaskInvokeActionAsync()

日志如下:

13-11-2023 21:00:03 [4:(DEBUG)<t:23>] - [TName: ] MiddleWarePipeline.Invoke is called
13-11-2023 21:00:03 [4:(DEBUG)<t:23>] - [TName: ] Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync is called.
13-11-2023 21:00:03 [4:(DEBUG)<t:23>] - [TName: ] Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync is called.
13-11-2023 21:00:03 [4:(DEBUG)<t:23>] - [TName: ] ----- some other -----
13-11-2023 21:00:03 [4:(DEBUG)<t:23>] - [TName: ] ------functions ------
13-11-2023 21:00:03 [4:(DEBUG)<t:23>] - [TName: ] ------are getting-----
13-11-2023 21:00:03 [4:(DEBUG)<t:23>] - [TName: ] ----logged that ------
13-11-2023 21:00:03 [4:(DEBUG)<t:23>] - [TName: ] -------happen inside ----
13-11-2023 21:00:03 [4:(DEBUG)<t:23>] - [TName: ] ----that particular -----
13-11-2023 21:00:03 [4:(DEBUG)<t:23>] - [TName: ] ------action method-----
13-11-2023 21:00:03 [4:(DEBUG)<t:23>] - [TName: ] Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync has returned task obj.
13-11-2023 21:00:03 [4:(DEBUG)<t:23>] - [TName: ] Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync has returned task obj.
13-11-2023 21:00:03 [4:(DEBUG)<t:23>] - [TName: ] MiddleWarePipeline.Invoke has returned  obj.

这是预期的行为吗?这是触发两次的同一请求,还是两个请求?如果是两个,它们如何区分同一线程中的两个请求?InvokeActionAsync()

负载测试 asp.net-core-5.0 clr-profiling-api

评论


答:

0赞 Md Farid Uddin Kiron 11/15/2023 #1

请求线程将与 InvokeActionAsync() 函数返回一个 Task 对象,并且该任务在单独的 线程池中的线程。但是 InvokeActionAsync() 会如何 在第一个方法之前,在同一线程中第二次触发 甚至返回了 Task 对象,这是预期的行为吗?这是 触发 InvokeActionAsync() 两次的相同请求,还是两次 请求?

首先,中间件执行两次并不是缺点。通常,这是执行中间件两次时的预期行为,因为当执行 HTTP 请求时,通常会命中两个端点。因此,中间件执行两次。

如果调试应用程序,则会发现将执行第一个调用 InvokeActionAsync 以加载应用程序本身,基本路径应为域/本地主机或 ./

第二次,您的应用程序具有其资源文件。例如,css、js 或应用程序根文件夹中需要额外执行的任何其他内部文件。

请查看以下网络跟踪日志:

enter image description here

enter image description here

enter image description here

enter image description here

注意:但是,有时,如果您没有通常在程序启动时调用的其他资源,则不会为同一线程中的同一请求多次调用此方法。例如,静态文件。

如果是两个,他们如何区分 同一个线程?

好吧,对于 ASP.NET Core,为了区分同一线程中的多个请求,它使用与每个请求关联的 HttpContext 对象。HttpContext 包含有关当前请求的信息,包括标头、参数和其他相关详细信息。此上下文对于每个传入请求都是唯一的,它用于区分不同的请求,即使它们正在同一个线程上处理。

如果需要更精确地了解在特定方案中调用两次 InvokeActionAsync 的原因,可以分析调用堆栈,在请求处理期间记录其他信息。

此外,在每次调用期间检查 HttpContext 有助于识别两次调用之间的任何差异

注意:如果您想知道如何查看 httpContext 详细信息和后台线程请参阅此官方文档了解更多信息。

评论

0赞 Morfhine 11/15/2023
感谢您的建议。我认为您正在谈论中间件被调用两次,因为浏览器会自动向“/favicon.ico”发出请求以获取您提到的静态/资源文件。但就我而言,中间件被调用一次,ControllerActionInvoker.InvokeActionMethodAsync被调用两次。当 InvokeActionMethodAsync 方法执行时,我还打印出了 HttpContext.TraceIdentifier,似乎该方法在高(并行请求)加载期间在同一线程的同一请求中被调用两次,并且两次执行方法中的 Stacktrace 是相同的。
0赞 Md Farid Uddin Kiron 11/16/2023
是的,我明白了,但是,如前所述,两次打电话并没有太大的缺点。
0赞 Morfhine 11/16/2023
是的,它没有任何缺点,应用程序中的所有内容都运行良好。但我只是想探索这种行为,而我试图了解asp-net核心架构以及它如何处理异步事务。我想知道为什么会这样。刚刚克隆了aspnetcore存储库,如果我发现任何东西,就会发布。无论如何,谢谢。
0赞 Md Farid Uddin Kiron 11/16/2023
哦,我明白了,实际上关于 asp.net 核心异步事务,涉及很多永恒的东西。对于 instace,HTTP 请求通过中间件管道进入应用程序。中间件组件处理请求,可以执行各种任务,如身份验证、授权、日志记录,这些任务允许它们执行非阻塞操作,如 I/O 绑定任务。还有什么我可以帮你的吗?随意分享。