欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

进击的.NET 在云原生时代的蜕变

程序员文章站 2022-04-14 22:58:25
你一定看过这篇文章 《进击的 Java ,云原生时代的蜕变》, 本篇文章的灵感来自于这篇文章。北京时间9.24 就将正式发布.NET Core 3.0, 所以写下这篇文章让大家全面认识.NET Core。.NET 生态系统是一个不断变化的生态圈,我相信它正在朝着一个伟大的方向发展。正好 最近 Inf... ......

你一定看过这篇文章 《进击的 java ,云原生时代的蜕变》,  本篇文章的灵感来自于这篇文章。北京时间9.24 就将正式发布.net core 3.0, 所以写下这篇文章让大家全面认识.net core。

.net 生态系统是一个不断变化的生态圈,我相信它正在朝着一个伟大的方向发展。正好 最近 infoq 上发布了一篇文章《.net 生态系统概览》,有了开源和跨平台这两个关键优先事项,我们就可以放心了。 下面我们来参考文章《进击的 java ,云原生时代的蜕变》对云原生对应用运行时的不同需求,说明一个.net core 3.0 在云原生时代所完成的蜕变:

  • 体积更小:对于微服务分布式架构而言,更小的体积意味着更少的下载带宽,更快的分发下载速度,.net core 的镜像体积都很小,alpine的镜像更小,带上应用程序通常80m。
  • 启动速度更快:对于传统单体应用,启动速度与运行效率相比不是一个关键的指标。原因是,这些应用重启和发布频率相对较低。然而对于需要快速迭代、水平扩展的微服务应用而言,更快的的启动速度就意味着更高的交付效率,和更加快速的回滚。尤其当你需要发布一个有数百个副本的应用时,缓慢的启动速度就是时间杀手。对于serverless 应用而言,端到端的冷启动速度则更为关键,即使底层容器技术可以实现百毫秒资源就绪,如果应用无法在 500ms 内完成启动,用户就会感知到访问延迟。这里我拿aws lambda来举例,因为各大云厂商都是以aws是模仿的目标,aws lambda中可用的所有语言都是高级的,而不是像assembler,c / c ++或objective c那样。从脚本语言到javascript和python,再到像java和c#到go这样被编译为二进制文件的托管运行时的语言,所有语言都是他们有自己的长处。在基准测试中,最重要的.net core是 冠军,具体参看
  • 占用资源更少:运行时更低的资源占用,意味着更高的部署密度和更低的计算成本。.net core的 clr启动速度非常快,降低启动时资源消耗,可以减少资源争抢,更好保障其他应用 sla。
  • 支持水平扩展:.net core 3.0默认更好的支持docker资源限制,官方团队也在努力让.net core成为真正的容器运行时,使其在低内存环境中具有容器感知功能并高效运行。 具体可以参看文章《从clr gc到coreclr gc看.net core对云原生的支持》,随着内存成本的下降和虚拟化的流行,大内存配比已经成为趋势。所以我们一般是采用水平扩展的方式,同时部署多个应用副本,在一个计算节点中可能运行一个应用的多个副本来提升资源利用率。

.net core 3.0 新增功能 大部分的功能特性已经公开,可以通过网页:,其中有几个特性是非常期待应用到生产的,很多人都在等待着明天的正式发布。

默认可执行文件

.net core 现在默认生成,这个行为是和.net framework保持一致了。 对于使用全局安装的 .net core 版本的应用程序而言,这是一种新行为。 以前,仅会生成可执行文件。

dotnet builddotnet publish 期间,将创建一个与你使用的 sdk 的环境和平台相匹配的可执行文件。 和其他本机可执行文件一样,可以使用这些可执行文件执行相同操作,例如:

  • 可以双击可执行文件。
  • 可以直接从命令提示符启用应用程序,如 windows 上的 myapp.exe,以及 linux 和 macos 上的 ./myapp

单文件可执行文件

dotnet publish 命令支持将应用打包为特定于平台的单文件可执行文件。 该可执行文件是自解压缩文件,包含运行应用所需的所有依赖项(包括本机依赖项)。 首次运行应用时,应用程序将根据应用名称和生成标识符自解压缩到一个目录中。 再次运行应用程序时,启动速度将变快。 除非使用了新版本,否则应用程序无需再次进行自解压缩。

若要发布单文件可执行文件,请使用 dotnet publish 命令在项目或命令行中设置 publishsinglefile

<propertygroup>
   <runtimeidentifier>win10-x64</runtimeidentifier>
   <publishsinglefile>true</publishsinglefile>
</propertygroup>

或者

dotnet publish -r win10-x64 /p:publishsinglefile=true

这个单文件是大家一直期待的go 特性,.net core 3.0正式有了,更详细的信息参看

程序集链接

.net core 3.0 sdk 随附了一种工具,可以通过分析 il 并剪裁未使用的程序集来减小应用的大小。

自包含应用包括运行代码所需的所有内容,而无需在主计算机上安装 .net。 但是,很多时候应用只需要一小部分框架即可运行,并且可以删除其他未使用的库。

.net core 现在包含一个设置,将使用 il 链接器工具扫描应用的 il。 此工具将检测哪些代码是必需的,然后剪裁未使用的库。 此工具可以显著减少某些应用的部署大小。

要启用此工具,请使用项目中的 <publishtrimmed> 设置并发布自包含应用:

<propertygroup>
   <publishtrimmed>true</publishtrimmed>
</propertygroup>

或者

dotnet publish -r <rid> -c release

例如,包含的基本“hello world”新控制台项目模板在发布时命中大小约为 70 mb。 通过使用 <publishtrimmed>,其大小将减少到约 30 mb,这个特性可以用于进一步的减小应用程序的大小。请务必考虑到使用反射或相关动态功能的应用程序或框架(包括 asp.net core 和 wpf)通常会在剪裁时损坏。

分层编译

.net core 3.0 中默认启用了 (tc)。 此功能使运行时能够更适应地使用实时 (jit) 编译器来获得更好的性能,这也是一个可以加速应用启动的选项。

tc 的主要优势是使(重新)实时编译方法能够要么牺牲代码质量以更快地生成代码,要么以较慢的速度生成更高质量的代码。 这有助于提高应用程序在从启动到稳定状态的各个执行阶段的性能。 这与非 tc 方法完全不同,其中每种方法均以单一方式进行编译(与高质量层相同),这种方法偏向于稳定状态而不是启动性能。

若要启用快速 jit(第 0 层实时编译的代码),请在项目文件中使用此设置:

<propertygroup>
   <tieredcompilationquickjit>true</tieredcompilationquickjit>
</propertygroup>

readytorun 映像

可以通过将应用程序集编译为 readytorun (r2r) 格式来改进.net core 应用程序的启动时间。 r2r 是一种预先 (aot) 编译形式,这也是一项加速应用启动时间的选项。

r2r 二进制文件通过减少应用程序加载时实时 (jit) 编译器需要执行的工作量来改进启动性能。 二进制文件包含与 jit 将生成的内容类似的本机代码。 但是,r2r 二进制文件更大,因为它们包含中间语言 (il) 代码(某些情况下仍需要此代码)和相同代码的本机版本。仅当发布面向特定运行时环境 (rid)(如 linux x64 或 windows x64)的自包含应用时 r2r 才可用。

主要版本前滚

.net core 3.0 引入了一项选择加入功能,该功能允许应用前滚到 .net core 最新的主要版本。 此外,还添加了一项新设置来控制如何将前滚应用于应用。 这可以通过以下方式配置:

  • 项目文件属性:rollforward
  • 运行时配置文件属性:rollforward
  • 环境变量:dotnet_roll_forward
  • 命令行参数:--roll-forward

必须指定以下值之一。 如果省略该设置,则默认值为“minor” 。

  • latestpatch
    前滚到最高补丁版本。 这会禁用次要版本前滚。
  • minor
    如果缺少所请求的次要版本,则前滚到最低的较高次要版本。 如果存在所请求的次要版本,则使用 latestpatch 策略。
  • major
    如果缺少所请求的主要版本,则前滚到最低的较高主要版本和最低的次要版本。 如果存在所请求的主要版本,则使用 minor 策略。
  • latestminor
    即使存在所请求的次要版本,仍前滚到最高次要版本。 适用于组件托管方案。
  • latestmajor
    即使存在所请求的主要版本,仍前滚到最高主要版本和最高次要版本。 适用于组件托管方案。
  • disable
    不前滚。 仅绑定到指定的版本。 建议不要将此策略用于一般用途,因为它会禁用前滚到最新补丁的功能。 该值仅建议用于测试。

docker 和 cgroup 内存限制

从预览版 3 开始,在 linux 上使用 docker 运行 .net core 3.0 时,可以更好地处理 cgroup 内存限制。 运行具有内存限制的 docker 容器(例如使用 docker run -m)会更改 .net core 的行为方式。

  • 默认垃圾回收器 (gc) 堆大小:最大为 20 mb 或容器内存限制的 75%。
  • 可以将显式大小设置为绝对数或 cgroup 限制的百分比。
  • 每个 gc 堆的最小保留段大小为 16 mb。 此大小可减少在计算机上创建的堆数量。

垃圾回收堆大小减小

垃圾回收器的默认堆大小已减小,以使 .net core 使用更少的内存。 此更改更符合具有现代处理器缓存大小的第 0 代分配预算。

垃圾回收大型页面支持

大型页面(也称为 linux 上的巨型页面)是一项功能,其中操作系统能够建立大于本机页面大小(通常为 4k)的内存区域,以提高请求这些大型页面的应用程序的性能。

现在可以使用 gclargepages 设置将垃圾回收器配置为一项选择加入功能,以选择在 windows 上分配大型页面。


.net 技术在云原生时代也在不停地进化。.net core 作为.net 生态的非常重要的一员,在对现有 .net 应用保持高度兼容的同时,对启动速度和内存占用做了细致的优化,比较适于微服务架构配合使用, 在以kubernetes 为代表的云原生应用开发平台上发生蜕变。

在云原生时代,我们要能够在横向的应用开发生命周期中,将开发、交付、运维过程进行有效的分割和重组,提升研发协同效率;并且要能在整个纵向软件技术栈中,在编程模型、应用运行时和基础设施等多层面进行系统优化,实现 radical simplification,提升系统效率。