8.1 发布方式与部署目标


文档摘要

8.1 发布方式与部署目标 发布是把应用翻译成"目标机可运行的产物集":框架依赖发布产出轻量包但要求目标机装运行时,自包含发布把运行时打进产物换取零依赖。部署目标决定产物落在哪——IIS 或 Nginx 后面当反向代理、容器镜像里随编排调度、或直接交给平台托管。选型跟着运维能力与交付约束走。 最后一章第一节处理一个开发机上感觉不到的问题: 与"服务器上运行"之间隔着一次翻译。观察哨本节先拆开发布产物的包裹看里面是什么,再做两种发布方式的对照实验,最后给部署目标一张选型表。 拆开发布产物 产物里没有源代码,也没有"服务器程序"——应用集加配置由目标机上的运行时装载执行。理解这一点,"目标机要装什么"的问题就有了答案的雏形:要么目标机有运行时(框架依赖),要么产物自己带(自包含)。

8.1 发布方式与部署目标

发布是把应用翻译成"目标机可运行的产物集":框架依赖发布产出轻量包但要求目标机装运行时,自包含发布把运行时打进产物换取零依赖。部署目标决定产物落在哪——IIS 或 Nginx 后面当反向代理、容器镜像里随编排调度、或直接交给平台托管。选型跟着运维能力与交付约束走。

最后一章第一节处理一个开发机上感觉不到的问题:dotnet run 与"服务器上运行"之间隔着一次翻译。观察哨本节先拆开发布产物的包裹看里面是什么,再做两种发布方式的对照实验,最后给部署目标一张选型表。

拆开发布产物

# 发布:产出落在 publish 目录(Debug 默认配置) dotnet publish -c Release # 输出关键行: # 已成功创建包 # 已将以下文件复制到输出目录(节选) # 看看包裹里有什么 dir bin\Release\net8.0\publish\ # 应用程序集(ObsStation.dll)——编译后的代码 # 依赖清单与运行时配置(deps.json 与 runtimeconfig.json)——告诉运行时怎么装配 # 配置文件(appsettings 全家)——2.3 节的配置来源 # 静态资源目录——页面与样式脚本 # 依赖包清单里登记的 NuGet 依赖

产物里没有源代码,也没有"服务器程序"——应用集加配置由目标机上的运行时装载执行。理解这一点,"目标机要装什么"的问题就有了答案的雏形:要么目标机有运行时(框架依赖),要么产物自己带(自包含)。

两种发布方式的对照实验

# 方式一:框架依赖发布(默认) dotnet publish -c Release -o fdd # 产物大小(空模板实测):约 200 KB 量级 # 前提:目标机必须装有匹配版本的 .NET 运行时 # 方式二:自包含发布,指定目标平台 dotnet publish -c Release -r linux-x64 --self-contained -o scd # 产物大小:约 90 MB 量级——把运行时整个带上了 # 前提:无。目标机不需要装任何 .NET # 运行方式也变了: # 框架依赖:dotnet ObsStation.dll ← 用目标机的运行时 # 自包含: ./ObsStation ← 产物自带可执行入口
维度 框架依赖 自包含
产物体积 小(百 KB 级) 大(百 MB 级)
目标机要求 装匹配运行时 零要求
补丁升级 运行时补丁全局生效,一次安装多家受益 每个产物独立升运行时,需重新发布
版本锁定 跟随目标机 锁死在发布时刻
典型场景 服务器池统一管理运行时 容器、嵌入式、客户环境不可控

图 8.1-1 两种发布产物的构成对照

图 8.1-1 两种发布产物的构成对照

单文件发布与裁剪是两个进阶开关:单文件把散落文件合并成一个可执行(交付清爽,启动时仍解压到内存或磁盘);裁剪移除"未引用"的运行时程序集(体积再减,但反射密集的应用有裁剪掉在用代码的风险——开启前必须回归测试)。两个开关解决的是分发体验问题,与运行行为无关,优先级低于主选型。

部署目标:产物落在哪

反向代理形态:Kestrel 直接对外在现代部署里已经少见,主流是前面站一层 Nginx 或 IIS。代理负责 TLS 终结、静态资源分流、多实例负载均衡;应用只管收转发来的请求。有一个必配细节:代理转发后应用看到的"客户端地址与协议"都是代理的,需要转发头协议把原始信息传回来(代理设置转发头,应用侧启用对应中间件处理),否则日志里的 IP 全是代理地址、生成的链接协议错乱——观察哨处理过"日志全是内网地址、封禁功能失效"的事故,根因就是这一处配置。

容器形态:自包含与容器天然一对——镜像里除了产物不需要任何 .NET 安装。容器化的 ASP.NET Core 有个约定俗成的组合拳:基础镜像带运行时(框架依赖风格的分层复用)、配置全走环境变量(2.3 节的双下划线约定在这里发光,一份镜像靠环境变量跑遍三套环境)、健康检查端点交给编排器探活(8.2 节展开)。

平台托管形态:应用服务平台按"代码或产物"维度收货,构建、发布、证书、扩缩容全托管。适合小团队起步,代价是平台绑定与定制上限。

选型不走信仰走约束:运维团队能力(有没有容器平台)、交付环境(客户机房还是云上)、合规要求(补丁责任归谁)。我的默认建议:新项目容器化起步(本地与生产环境一致性收益最大),传统机房交付用反向代理形态,平台托管留给原型与内部工具。

问题:Release 与 Debug 配置差在哪,为什么要用 Release 发布?

Release 编译打开优化、去掉调试符号,吞吐与体积都占优;Debug 面向调试器,性能不可代表生产。发布永远用 Release,这是底线而非偏好。另有一档发布优化常被忽略:发布与编译是两个开关,配置选 Release 的同时,发布参数里还能选"发布时就绪运行"——产物带预编译机器码,首个请求不再付出即时编译成本,冷启动敏感的场景值得打开。

问题:一个产物能同时在两台服务器上跑吗?

能,而且这正是发布方式与 8.2 节环境机制的组合价值:产物完全相同,两台机器用不同的环境变量集(环境名、连接串、端口)各自启动。运维上把"产物"与"配置"分开管理——产物从构建流水线来,配置从部署清单来,回滚时只换产物不动配置,发布事故的恢复时间以秒计。

⚠️ 常见坑:开发机验证的是框架依赖产物,交付给客户的却是自包含产物且没在目标平台跑过一次——运行时标识写错平台(比如把 linux-x64 写成 win-x64),到客户现场才暴露。发布矩阵里每个目标平台都要有 CI 或手工的冒烟验证。

💡 关键直觉:发布是"翻译"不是"拷贝"——把"能在我的开发机跑"翻译成"能在目标环境跑"。翻译要核对两份词典:运行时(装没装、版本对不对)与环境(配置、地址、头信息)。两份词典都对上,产物才真正落地。

本节要点回顾

  • 产物构成:应用集、依赖清单、运行时配置、配置文件、静态资源,没有源码也没有服务器程序;
  • 两种发布:框架依赖小而依赖目标机,自包含大而自由,容器场景常组合两者优点;
  • 反向代理必配转发头:否则应用看到的地址与协议全是代理的,日志与安全功能齐失真;
  • 容器三约定:分层基础镜像、配置走环境变量、健康检查交编排器;
  • 选型走约束:运维能力、交付环境、合规要求,默认新项目容器化起步。

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U