json schema生成工具_深入理解.NET Core的基元(三) 深入理解runtimeconfig.json

5b69fa57d093773c860da1e6e3d9e5b0.png

原文:Deep-dive into .NET Core primitives, part 3: runtimeconfig.json in depth

作者:Nate McMaster[1]

译文:深入理解.NET Core 的基元(三) - 深入 runtimeconfig.json

作者:Lamond Lu

前情回顾

  • 深入理解.NET Core 的基元(一):deps.json, runtimeconfig.json, dll 文件[2]
  • 深入理解.NET Core 的基元(二):共享框架[3]

简介

每个.NET Core 应用都包含了一个名为xxxx.runtimeconfig.json的文件。这个文件可以用来控制多种配置。大多数的开发人员其实并不太关心这个文件,因为它是由 SDK 生成的文件,但是我认为它还是值得我们去学习理解一下的。这个文件常用来控制一些不会在 Visual Studio 中表现出来的配置,例如在使用更高版本的.NET Core 运行你的应用程序,调整线程池和垃圾回收等。

文件的作用

从技术上讲,runtimeconfig.json文件并不是必须的,但是由于一些实践性的因素,所以每个真实世界中的.NET Core 应用都有持有一个runtimeconfig.json文件。这个文件是可以手动编辑的。与deps.json文件不同,runtimeconfig.json是易于理解的。这个文件的主要作用是定义程序所需的共享框架(只针对 FDD - framework-dependency deployment),以及一些其他的运行时选项,我会在后面一一列举。

一个简单的例子

以下是一个最典型的runtimeconfig.json的文件内容。

{
"runtimeOptions": {
"tfm": "netcoreapp2.1",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "2.1.0"
}
}
}

我已经编写了一个完整结构的runtimeconfig.json文件,如果有兴趣你可以查看[5]

runtimeconfig.template.json

在.NET Core 中,有一些配置选项,你是不能在项目文件.csproj中设置的。如果你想对这些配置选项进行设置,这里有两种方案,一种是在项目编译之后,手动编辑runtimeconfig.json文件,另外一种是使用runtimeconfig.template.json文件。当然,如果你希望持久化配置, 我还是推荐你使用模板的方式。

当项目构建(build)的时候,SDK 会从在.csproj文件的基础上,通过读取模板扩充配置。下面我们就通过简单的几个步骤来使用模板。

  1. 创建一个新项目(dotnet new console -n MyApp)

  2. 在当前项目目录中,创建一个名为runtimeconfig.template.json的文件。

  3. 配置文件内容如下

    {
    "rollForwardOnNoCandidateFx": 2
    }
  4. 执行dotnet build

瞧,仅此而已。现在我们可以查看一下bin/Debug/netacoreapp.21/MyApp.runtimeconfig.json,以确保模板正常工作。

Visual Studio 的智能感知

针对 Visual Studio 编辑器,我已经编写了一个 JSON 结构,你可以直接使用。你需要做的,只是将如下代码加入到你当前项目的runtimeconfig.template.json文件中即可。

{
"$schema": "https://gist.githubusercontent.com/natemcmaster/0bdee16450f8ec1823f2c11af880ceeb/raw/runtimeconfig.template.schema.json"
}

运行时配置选项

框架、版本、先前滚动机制

.NET Core 共享框架支持安装并行版本,因此,当一个.NET Core 应用程序启动时候,必须选择一个版本。以下配置选项常用于配置应用应该加载哪些共享框架,以及加载哪个版本的共享框架。

注意:通常来说 SDK 默认生成的配置就已经够用了,但是有时候我们还是需要更改他们的,以解决.NET Core 启动时常见问题。

It was not possible to find any compatible framework version. The specified framework ‘Microsoft.NETCore.App’, version ‘X.Y.Z’ was not found.

共享框架

.NET Core 是通过指定共享框架的名称来指定共享框架的。配置中指定的框架版本,是当前应用使用的最低版本。如果你想不通过更改文件覆盖这个最小值配置,唯一的方式是使用dotnet exec --fx-version命令。

在.NET Core 3.0 以下版本中,一次只能指定一个共享框架。

JSON

{
"runtimeOptions": {
"framework": {
"name": "Microsoft.AspNetCore.App",
"version": "2.2.0"
}
}
}

.csproj

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0" />
ItemGroup>

对于.NET Core 3.0 及以上版本中已经支持多共享框架,所以额外的共享框架不再需要作为包来引用了。

JSON

{
"runtimeOptions": {
"frameworks": [
{
"name": "Microsoft.AspNetCore.App",
"version": "3.0.0"
},
{
"name": "Microsoft.WindowsDesktop.App",
"version": "3.0.0"
}
]
}
}

.csproj

<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<FrameworkReference Include="Microsoft.WindowsDesktop.App" />
ItemGroup>

自动使用更高版本.NET Core 运行程序

这个是.NET Core 3.0 中的一个新配置选项。

默认,.NET Core 会去尝试寻找当前共享框架的,最高修补版本。如果找不到这个版本,它会使用前滚(roll-forward)特性,来查找较新的版本。这个选项受前滚策略的控制。

JSON

{
"runtimeOptions": {
"rollForward": "Major"
}
}

.csproj

当前.csproj项目文件中还没有实现这个配置。

你可以在https://github.com/dotnet/designs/blob/master/accepted/runtime-binding.md[6]中找到这个配置的规范。针对这个配置,官方设计文档中,做了如下描述

RollForward参数有以下几个可选值:

  • LatestPatch - 前滚到最高修补版本,这个配置会禁用前滚特性的最小版本配置。
  • Minor - 如果缺少所需的次要版本,就前滚到最低的次要版本。如果请求的次要版本存在,则使用LatestPatch策略
  • Major - 如果缺少所需的主要版本,则前滚到最低的主要版本,和最低的次要版本。如果请求的主要版本存在,则使用Minor策略
  • LatestMinor - 前滚到最高次要版本,即使当前请求的次要版本存在
  • LatestMajor - 前滚到最高主要版本和最高次要版本,即使当前请求的主要版本存在
  • Disable - 不适用前滚特性。只绑定指定版本。在大多数场景下,这个策略都是不推荐的,因为它会禁用前滚到最新修补版本的能力。这种方式仅推荐来做测试工作。

Minor是当前配置的默认值。如果希望了解更多信息,可以参阅官方文档[7]

在以上配置值中,除了Disable选项之外,其他的选项都是会去选择最高的可用修补版本。

注意:LatestMinorLatestMajor适用于托管和非托管中主机的组件托管(例如托管 COM 组件)

自动使用更高的补丁版本运行项目(.NET Core 3.0 之前的版本)

正如上面所描述的,在.NET Core 3.0 中不推荐使用此策略,而推荐使用更简单的"前滚"选项。

默认情况下,.NET Core 会使用安装在目标机器中最高修补版本的共享框架运行程序。你可以使用applyPatches参数禁用此功能。

JSON

{
"runtimeOptions": {
"applyPatches": false
}
}

.csproj

当前.csproj项目文件中还没有实现这个配置。

自动使用最高主版本或次要版本来运行项目(.NET Core 3.0 之前的版本)

正如上面所描述的,在.NET Core 3.0 中不推荐使用此策略,而推荐使用更简单的"前滚"选项。

默认情况下,.NET Core 会尝试自动查找共享框架的最高补丁版本,该版本的主版本和次要版本和你当前运行的应用所指定的版本相同。但是,如果找不到,它会自动前滚到最新版本。此配置受前滚策略控制。

JSON

{
"runtimeOptions": {
"rollForwardOnNoCandidateFx": 1
}
}

.csproj

当前.csproj项目文件中还没有实现这个配置。

这个参数的值,可以设置为 0,1,2。你可以查看详细的设计文档[8],了解更多详情。

例如,当指定的框架版本是 2.1.0 时,.NET Core 会根据这个参数的值,决定使用如下的兼容框架版本。

rollForwardOnNoCandidateFx兼容的框架版本
0>=2.1.0, < 2.2.0
1 (默认)>=2.1.0, < 3.0.0
2>=2.1.0

目标框架名称

这是一个运行时程序包存储的实现细节。

JSON

{
"runtimeOptions": {
"tfm": "netcoreapp2.1"
}
}

.csproj

<PropertyGroup>
<TargetFramework>netcoreapp2.1TargetFramework>
PropertyGroup>

程序集探测路径

宿主程序可以使用这个参数来指定额外的文件夹,以查找.deps.json文件中列举的程序集文件。你可以查看系列文章的第一篇[9]来查看这个参数是如何工作的。

JSON

{
"runtimeOptions": {
"additionalProbingPaths": [
"C:\\Users\\nmcmaster\\.nuget\\packages\\"
]
}
}

.csproj

<ItemGroup>
<AdditionalProbingPath Include="$(USERPROFILE)\.nuget\packages" />
ItemGroup>

注意:.csproj中的配置项最终只会出现在runtimeconfig.dev.json文件中,该文件仅在开发过程中使用,而不会在生产环境中使用。针对生产环境,你可以使用模板文件来设置runtimeconfig.json

运行时配置

configProperties属性是提供给运行时的键/值对列表。基本上你能想到的配置,在这里都设置,但是最常使用的配置一般是如下几个。

JSON

{
"runtimeOptions": {
"configProperties": {
"key": "value"
}
}
}
常用的运行时配置
配置名称类型描述
System.GC.Server布尔是否启用服务器垃圾回收
System.GC.Concurrent布尔是否启用并发垃圾回收
System.GC.RetainVM布尔是否将应删除的段放入一个备用列表中以备将来使用,而不是将其释放回操作系统。
System.Runtime.TieredCompilation布尔是否启用分层编译
System.Threading.ThreadPool.MinThreads整型覆盖线程池的最小线程数
System.Threading.ThreadPool.MaxThreads整型覆盖线程池的最大线程数
System.Globalization.Invariant布尔是否启用不变模式,禁用全球化行为

以下是一些针对上述配置的文档说明

  • 主机配置开关(Host Configuration Knobs)[10]
  • 全球化不变模式[11]
  • 分层编译[12]

这些配置,你都可以放在你的.csproj文件中。如果你想了解更多相关配置,最好的方案就是去查看Microsoft.NET.Sdk.targets文件。

<PropertyGroup>
<ConcurrentGarbageCollection>trueConcurrentGarbageCollection>
<ServerGarbageCollection>trueServerGarbageCollection>
<RetainVMGarbageCollection>trueRetainVMGarbageCollection>
<ThreadPoolMinThreads>1ThreadPoolMinThreads>
<ThreadPoolMaxThreads>100ThreadPoolMaxThreads>

<TieredCompilation>trueTieredCompilation>
<InvariantGlobalization>trueInvariantGlobalization>
PropertyGroup>

其他运行时配置

除了框架提供的配置,.NET Core 还允许开发人员指定自己的配置。你可以通过System.AppContext.GetData方法来获取这些值。

注意:相较于配置构建器(Configuration Builders), 这个方式并不是特别推荐。

JSON

{
"runtimeOptions": {
"configProperties": {
"ArbitraryNumberSetting": 2,
"ArbitraryStringSetting": "red",
"ArbitraryBoolSetting": true
}
}
}

.csproj

<ItemGroup>
<RuntimeHostConfigurationOption Include="ArbitraryNumberSetting" Value="2" />
<RuntimeHostConfigurationOption Include="ArbitraryStringSetting" Value="red" />
<RuntimeHostConfigurationOption Include="ArbitraryBoolSetting" Value="true" />
ItemGroup>

在 C#中,通过System.AppContext.GetData方法来获取指定参数的值

// "red"
var color = System.AppContext.GetData("ArbitraryStringSetting") as string;

更多信息

你可以通过查看本系列的第一章[13]来了解runtimeconfig.json文件的更多详情,以及如何使用它。同样,我也推荐你通过官方的文档文件[14]来了解一下这些变量配置是如何使用的。

参考资料

[1]

Nate McMaster: https://natemcmaster.com/

[5]

https://gist.github.com/natemcmaster/0bdee16450f8ec1823f2c11af880ceeb: https://gist.github.com/natemcmaster/0bdee16450f8ec1823f2c11af880ceeb

[6]

https://github.com/dotnet/designs/blob/master/accepted/runtime-binding.md: https://github.com/dotnet/designs/blob/master/accepted/runtime-binding.md

[7]

官方文档: https://github.com/dotnet/designs/blob/master/accepted/runtime-binding.md#configuration-precedence

[8]

设计文档: https://github.com/dotnet/core-setup/blob/92072fd9ea03740ea317b631d3894ff3c5d0854d/Documentation/design-docs/roll-forward-on-no-candidate-fx.md

[10]

主机配置开关(Host Configuration Knobs): https://github.com/dotnet/coreclr/blob/v2.2.0/Documentation/project-docs/clr-configuration-knobs.md

[11]

全球化不变模式: https://github.com/dotnet/corefx/blob/v2.2.0/Documentation/architecture/globalization-invariant-mode.md

[12]

分层编译: https://blogs.msdn.microsoft.com/dotnet/2018/08/02/tiered-compilation-preview-in-net-core-2-1/

[14]

文档文件: https://github.com/dotnet

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值