一次依赖注入不慎引发的一连串事故 (5)

PS: Kestrel (https://github.com/aspnet/KestrelHttpServer) is a lightweight cross-platform web server that supports .NET Core and runs on multiple platforms such as Linux, macOS, and Windows. Kestrel is fully written in .Net core. It is based on libuv which is a multi-platform asynchronous eventing library.

PS 人话: .NET Core 内置的 HTTP Server,和 Spring Boot 中的 tomcat 组件类似

很正常,说明请求正常到了我们的服务里面了。

再看一下剩下的调用链信息。

dotnet-call-tree-di

简要的调用信息日志在这里:

System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start(!!0&) Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.KestrelConnection+<ExecuteAsync>d__32.MoveNext() Microsoft.AspNetCore.Server.Kestrel.Core.Internal.HttpConnectionMiddleware`1[System.__Canon].OnConnectionAsync(class Microsoft.AspNetCore.Connections.ConnectionContext) Microsoft.AspNetCore.Server.Kestrel.Core.Internal.HttpConnection.ProcessRequestsAsync(class Microsoft.AspNetCore.Hosting.Server.IHttpApplication`1<!!0>) System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start(!!0&) System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start(!!0&) Microsoft.AspNetCore.Server.Kestrel.Core.Internal.HttpConnection+<ProcessRequestsAsync>d__12`1[System.__Canon].MoveNext() Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequestsAsync(class Microsoft.AspNetCore.Hosting.Server.IHttpApplication`1<!!0>) System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start(!!0&) System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start(!!0&) Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol+<ProcessRequestsAsync>d__216`1[System.__Canon].MoveNext() Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests(class Microsoft.AspNetCore.Hosting.Server.IHttpApplication`1<!!0>) System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start(!!0&) System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start(!!0&) Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol+<ProcessRequests>d__217`1[System.__Canon].MoveNext() Microsoft.AspNetCore.Hosting.HostingApplication.ProcessRequestAsync(class Context) Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware.Invoke(class Microsoft.AspNetCore.Http.HttpContext) UserCenter.ErrorHandlingMiddleware.Invoke(class Microsoft.AspNetCore.Http.HttpContext) System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start(!!0&) System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start(!!0&) ...... ...... ...... e.StaticFiles.StaticFileMiddleware.Invoke(class Microsoft.AspNetCore.Http.HttpContext) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass4_1.<UseMiddleware>b__2(class Microsoft.AspNetCore.Http.HttpContext) dynamicClass.lambda_method(pMT: 00007FB6D3BBE570,class System.Object,pMT: 00007FB6D4739560,pMT: 00007FB6D0BF4F98) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.GetService(class System.IServiceProvider,class System.Type,class System.Type) Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(class System.Type) System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start(!!0&) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext,System.__Canon].VisitCallSite(class Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite,!0) System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start(!!0&) System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start(!!0&)

看到这里,其实又有了一些很给力的信息被暴露出来了。

PerformWaitCallback

直接字面理解,线程正在执行等待回调

调用链信息

耐心点,把所有的电调用链都展开。

我们能看到程序已经依次经过了下面几个流程:

->ProcessRequestsAsync(系统)

->ErrorHandlingMiddleware(已经加载了自定义的错误中间件)

-> HostFilteringMiddleware(加载了 Filter 中间件)

-> Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor(调用链中的最后一个操作)

对应最上面的日志来说,

请求进来,经过了中间件和 Filter 都是没问题的,

最后在 DependencyInjection(依赖注入) 中没有了踪迹。

到这里,

再次验证我们昨天的思路:

这是一个 “资源阻塞问题”产生的问题

虽然做 ptrace 是想能直接抓到“凶手”的,

最后发现并没有能跟踪到具体的实现,

那可咋办呢?

控制变量实践

已知:

并发 300 访问 /v1/user/test/account-balance 接口程序会假死

移除 Filter 中间件不能解决问题

并发 300 访问 /v1/health 健康检查接口程序正常

ptrace 信息告诉我们有“东西”在阻塞 DI 容器创建某些实例

开始控制变量 + 人肉二分查找。

挪接口代码

/v1/user/test/account-balance 的逻辑是由 AccountService 实现的,

AccountService 大概依赖四五个其他的 Service 和 DBContext,

最主要的逻辑是加载用户几个账号,然后计算一下 balance。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpzwpj.html