深入理解.NET Core的基元(三) - 深入理解runtimeconfig.json
原文:Deep-dive into .NET Core primitives, part 3: runtimeconfig.json in depth
作者:Nate McMaster
译文:深入理解.NET Core的基元(三) - 深入runtimeconfig.json
译者: Lamond Lu
前情回顾
- 深入理解.NET Core的基元(一):deps.json, runtimeconfig.json, dll文件
- 深入理解.NET Core的基元(二):共享框架
- 深入理解.NET Core的基元(三):深入理解runtimeconfig.json
简介
每个.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
文件,如果有兴趣你可以查看https://gist.github.com/natemcmaster/0bdee16450f8ec1823f2c11af880ceeb。
runtimeconfig.template.json
在.NET Core中,有一些配置选项,你是不能在项目文件.csproj
中设置的。如果你想对这些配置选项进行设置,这里有两种方案,一种是在项目编译之后,手动编辑runtimeconfig.json
文件,另外一种是使用runtimeconfig.template.json
文件。当然,如果你希望持久化配置, 我还是推荐你使用模板的方式。
当项目构建(build)的时候,SDK会从在.csproj
文件的基础上,通过读取模板扩充配置。下面我们就通过简单的几个步骤来使用模板。
创建一个新项目(
dotnet new console -n MyApp
)在当前项目目录中,创建一个名为
runtimeconfig.template.json
的文件。配置文件内容如下
{
"rollForwardOnNoCandidateFx": 2
}
执行
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中找到这个配置的规范。针对这个配置,官方设计文档中,做了如下描述
RollForward
参数有一下几个可选值:
LatestPatch
- 前滚到最高修补版本,这个配置会禁用前滚特性的最小版本配置。Minor
- 如果缺少所需的次要版本,就前滚到最低的次要版本。如果请求的次要版本存在,则使用LatestPatch
策略Major
- 如果缺少所需的主要版本,则前滚到最低的主要版本,和最低的次要版本。如果请求的主要版本存在,则使用Minor
策略LatestMinor
- 前滚到最高次要版本,即使当前请求的次要版本存在LatestMajor
- 前滚到最高主要版本和最高次要版本,即使当前请求的主要版本存在Disable
- 不适用前滚特性。只绑定指定版本。在大多数场景下,这个策略都是不推荐的,因为它会禁用前滚到最新修补版本的能力。这种方式仅推荐来做测试工作。
Minor
是当前配置的默认值。如果希望了解更多信息,可以参阅官方文档。在以上配置值中,除了
Disable
选项之外,其他的选项都是会去选择最高的可用修补版本。注意:
LatestMinor
和LatestMajor
适用于托管和非托管中主机的组件托管(例如托管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。你可以查看详细的设计文档,了解更多详情。
例如,当指定的框架版本是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.1</TargetFramework>
</PropertyGroup>
程序集探测路径
宿主程序可以使用这个参数来指定额外的文件夹,以查找.deps.json
文件中列举的程序集文件。你可以查看系列文章的第一篇来查看这个参数是如何工作的。
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 | 布尔 | 是否启用不变模式,禁用全球化行为 |
以下是一些针对上述配置的文档说明
这些配置,你都可以放在你的.csproj
文件中。如果你想了解更多相关配置,最好的方案就是去查看Microsoft.NET.Sdk.targets
文件。
<PropertyGroup>
<ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
<ServerGarbageCollection>true</ServerGarbageCollection>
<RetainVMGarbageCollection>true</RetainVMGarbageCollection>
<ThreadPoolMinThreads>1</ThreadPoolMinThreads>
<ThreadPoolMaxThreads>100</ThreadPoolMaxThreads>
<!-- Supported as of .NET Core SDK 3.0 Preview 1 -->
<TieredCompilation>true</TieredCompilation>
<InvariantGlobalization>true</InvariantGlobalization>
</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;
更多信息
你可以通过查看本系列的第一章来了解runtimeconfig.json
文件的更多详情,以及如何使用它。同样,我也推荐你通过官方的文档文件来了解一下这些变量配置是如何使用的。
深入理解.NET Core的基元(三) - 深入理解runtimeconfig.json的更多相关文章
- 深入理解.NET Core的基元(二) - 共享框架
原文:Deep-dive into .NET Core primitives, part 2: the shared framework 作者:Nate McMaster 译文:深入理解.NET Co ...
- 深入理解.NET Core的基元(二)
原文:Deep-dive into .NET Core primitives, part 2: the shared framework作者:Nate McMaster译文:深入理解.NET Core ...
- 深入理解.NET Core的基元: deps.json, runtimeconfig.json, dll文件
原文链接: Deep-dive into .NET Core primitives: deps.json, runtimeconfig.json, and dll's 作者: Nate McMaste ...
- CLR via C#深解笔记三 - 基元类型、引用类型和值类型 | 类型和成员基础 | 常量和字段
编程语言的基元类型 某些数据类型如此常用,以至于许多编译器允许代码以简化的语法来操纵它们. System.Int32 a = new System.Int32(); // a = 0 a = 1 ...
- 深入理解net core中的依赖注入、Singleton、Scoped、Transient(三)
相关文章: 深入理解net core中的依赖注入.Singleton.Scoped.Transient(一) 深入理解net core中的依赖注入.Singleton.Scoped.Transient ...
- CLR via #C读书笔记三:基元类型、引用类型和值类型
1.一些开发人员说应用程序在32位操作系统上运行,int代表32位整数:在64位操作系统上运行,int代表64位整数.这个说法是完全错误的.C#的int始终映射到System.Int32,所以不管在什 ...
- 读经典——《CLR via C#》(Jeffrey Richter著) 笔记_基元类型(三)
[checked 和 unchecked 基元类型操作] 1.第一种使用方式 UInt32 invalid = )); //OK,不会抛异常 Byte b = ; b = ));//抛出Overflo ...
- 【C#进阶系列】28 基元线程同步构造
多个线程同时访问共享数据时,线程同步能防止数据损坏.之所以要强调同时,是因为线程同步问题实际上就是计时问题. 不需要线程同步是最理想的情况,因为线程同步一般很繁琐,涉及到线程同步锁的获取和释放,容易遗 ...
- 谈谈C#基元类型
首先看一下.NET 中的基元类型,如下表: C# Type | .NET Framework Type -------------| ---------------------- bool | Sys ...
随机推荐
- Java设计模式_七大原则
简介 单一职责原则.对类来说,即一个类应该只负责一项职责. 开闭原则.对扩展开放,对修改关闭.在程序需要进行扩展的时候,不能去修改原有代码,使用接口和抽象类实现一个热插拔的效果. 里氏替换原则.任何基 ...
- Java基础01-集合1、泛型
集合.泛型 第一章:集合1 1. 什么是集合 定义:在Java中,集合是一种可以存储多个数据的容器. 代码: ArrayList<String> list = new ArrayList& ...
- mybatis代理机制讲解
问题描述 在使用Mybatis开发中,或者和Spring整合中,在Dao层中的Mapper接口与xml中的sql对应着,在service中直接调用Dao中的方法就可以直接访问sql.如下所示: /** ...
- 转:如何让phpmyadmin输入密码再进入
对于很多不熟悉PHP环境安装的朋友来说,用集成环境可以更快的上手,更方便的搭建PHP的运行环境,但是,WAMP的集成环境仅仅是将底层基础工作做好了,有些个别关键的配置操作并没有集成到环境安装中,所以给 ...
- 程序员这十个java题你都会吗?
前言 不论你是职场新人还是步入职场N年的职场新人大哥大~当然这个N<3~,我能担保你答不对这十个题~不要问我为什么这么自信~,这些个题还是"有水平"的javase的基础题,传 ...
- noip模拟9 达哥随单题
T1.随 看题第一眼,就瞄到最下面 孙金宁教你学数学 ?????原根?目测神题,果断跳过. 最后打了个快速幂,愉快的收到了达哥送来的10分. 实际上这题暴力不难想,看到一个非常小的mod应该就能想到 ...
- Maven配置setting.xml详细说明
<?xml version="1.0" encoding="UTF-8"?> <settings xmlns="http://mav ...
- Tomcat+nginx+Keepalived部署实现集群
Tomcat+nginx+Keepalived部署实现集群 环境说明: 系统:Centos-7 主机:Centos-7 x3 IP地址: 服务器1(192.168.10.102/24) 服务器2(19 ...
- [java] 计算时间复杂度
一.精算: 1.所有的声明,都不计时间: 2.赋值语句占1个时间单位(下称:单位),比如sum=0: 3.return占1个单位,比如,reeturn sum. 我怀疑范围一个链表头,不止占1 ...
- jenkins手把手教你从入门到放弃03-安装Jenkins时web界面出现该jenkins实例似乎已离线
简介 很久没有安装jenkins了,因为之前用的的服务器一直正常使用,令人郁闷的是,之前用jenkins一直没出过这个问题. 令人更郁闷的是,我尝试了好多个历史版本和最新版本,甚至从之前的服务器把je ...