通过主机追踪深入探索.NET启动过程
理解通过追踪的启动过程
本文主要展示现代.NET中可用的主机追踪功能。这不是像OpenTelemetry或APM解决方案那样的"追踪",而是老式的追踪,即日志记录。😄
主机追踪为您提供有关.NET应用程序"启动"过程早期步骤的详细诊断信息。如果您试图理解为什么应用程序使用了"错误"的.NET版本,这会很有用。您不会经常需要它,但当事情不按预期工作时,它可能非常宝贵!
启用主机追踪
启用主机追踪需要设置单个环境变量:COREHOST_TRACE=1。默认情况下,这会将追踪写入stderr,但您可以通过将COREHOST_TRACEFILE设置为以下两个值之一来将输出重定向到文件:
COREHOST_TRACEFILE=<file_path>将日志附加到文件。如果文件不存在则创建,但其所在目录必须存在。相对路径相对于工作目录。 COREHOST_TRACEFILE=<dir_path>(仅限.NET 10+),如果目录<dir_path>存在,则将文件<exe_name>..log附加到该目录。
您还可以通过设置COREHOST_TRACE_VERBOSITY=<level>来控制日志的详细程度,其中
使用现代.NET加载应用程序
当考虑现代.NET应用程序时,我通常想到三个主要部分:
- .NET运行时,即CoreCLR,运行JIT编译器、垃圾收集器以及构成.NET应用程序的所有内容
- .NET基类库(BCL),作为.NET一部分提供的所有库
- 您的.NET应用程序,即您编写的代码,可能引用其他.NET库以及构成BCL的库
然而,还有一整个"加载"过程必须发生才能运行.NET运行时!
dotnet多路复用器
dotnet多路复用器是您作为.NET开发人员所做的大部分工作的入口点。无论您使用dotnet build和dotnet publish进行开发,还是实际使用dotnet MyApp.dll运行应用程序,dotnet多路复用器都是您的入口点。
多路复用器只负责一件事:加载hostfxr库并调用它。也就是说,它仍然进行一些初步验证。
hostfxr库
hostfxr库有几个职责:
- 解析提供的参数以决定要执行什么;这是像
dotnet build和dotnet publish这样的.NET SDK命令,还是像dotnet MyApp.dll这样的应用程序执行 - 如果是SDK命令,找到要使用的正确SDK
- 决定要加载哪个版本的.NET运行时
- 为所选运行时加载hostpolicy库
解析参数和决定行为
第一步在概念上是多路复用器的一部分,因为它涉及决定调用者的意图。他们试图执行SDK命令,还是试图执行应用程序?
查找SDK
一旦hostfxr确定执行了SDK命令,下一步就是通过读取路径中的任何global.json文件来确定要加载哪个.NET SDK。
选择要加载的.NET运行时
此时hostfxr知道要加载哪个.NET应用程序,但不知道要加载哪个.NET运行时。它通过检查应用程序的runtimeconfig.json来确定这一点。
加载hostpolicy
一旦.NET运行时被解析,hostfxr需要为特定选择的运行时版本加载hostpolicy库。
hostpolicy库
hostpolicy的主要职责是:
- 基于应用程序和框架deps.json构建可信平台程序集列表
- 设置上下文开关以运行应用程序
- 启动.NET运行时以运行您的应用程序
构建可信平台程序集列表
hostpolicy读取所选运行时的deps.json文件,并加载它列出的所有库。
创建上下文开关
这显示了在运行时加载时将传递给运行时的上下文属性。如您所见,它主要是一组从环境加载的配置值,包含用于初始化运行时的各种文件路径的详细信息。
最后,hostpolicy加载coreclr.dll .NET运行时并启动它!
总结
在本文中,我展示了如何通过设置COREHOST_TRACE=1并将COREHOST_TRACEFILE设置为文件路径来启用主机追踪。然后我运行了一个非常简单的应用程序并探索了它产生的主机追踪日志。
我们看到dotnet多路复用器是应用程序的入口点,它定位并加载hostfxr。hostfxr然后负责找到要加载的正确.NET运行时并加载hostpolicy.dll。最后hostpolicy.dll启动.NET运行时并运行您的应用程序。