34.5. 单文件发布
以下内容仅限 Furion 3.5.2 +
版本使用。
34.5.1 历史背景
自 .NET Core 3
起,微软就提供了单文件发布的技术支持,但实际上并不是 .NET
所有 CLR
都支持单文件发布,如 Microsoft.Extensions.DependencyModel
包本身不支持单文件发布,原因是内部使用了 Assembley.CodeBase
。
好巧不巧,Furion
中招了,在过去两年中,Furion
依赖该包的 DependencyContext.Default
特性进行程序集扫描,所以单文件发布也就成了 Furion
不愿提起的痛!!!
终于,在 Furion v3.5.2+
版本想出了新的解决方案,自此彻底解决了单文件发布的问题。
34.5.2 必要配置
在 Furion v3.5.2+
版本之后,新增了 ISingleFilePublish
接口。
- 编辑启动层
.csproj
文件,添加下列代码到<PropertyGroup>
节点中
<PublishReadyToRunComposite>true</PublishReadyToRunComposite>
ReadyToRun
如果发布时未打勾 ReadyToRun
选项,则无需配置上述代码。
- 在
Web 启动层
创建类型并实现该接口,如:
using System.Reflection;
namespace YourProject.Web.Entry;
/// <summary>
/// 解决单文件发布问题
/// </summary>
public class SingleFilePublish : ISingleFilePublish
{
/// <summary>
/// 解决单文件不能扫描的程序集
/// </summary>
/// <remarks>和 <see cref="IncludeAssemblyNames"/> 可同时配置</remarks>
/// <returns></returns>
public Assembly[] IncludeAssemblies()
{
// 需要 Furion 框架扫描哪些程序集就写上去即可
return Array.Empty<Assembly>();
}
/// <summary>
/// 解决单文件不能扫描的程序集名称
/// </summary>
/// <remarks>和 <see cref="IncludeAssemblies"/> 可同时配置</remarks>
/// <returns></returns>
public string[] IncludeAssemblyNames()
{
// 需要 Furion 框架扫描哪些程序集就写上去即可
return new[]
{
"YourProject.Application",
"YourProject.Core",
"YourProject.EntityFramework.Core",
"YourProject.Web.Core",
"Furion.Extras.ObjectMapper.Mapster" // 解决 Mapster 单文件失效问题,v3.5.3+版本后无需配置
};
}
}
IncludeAssemblies
和 IncludeAssemblyNames
的区别是前者是开发者直接返回 Assembley
集合,后者是直接返回名称,Furion
会自动加载程序集,可同时配置,也可以配置其中一个。
如果只配置启用一个,则另外一个返回 Array.Empty<Assembley>()
或 Array.Empty<string>()
即可。
如果发布后出现 Mapster
不能映射问题,可将 Furion.Extras.ObjectMapper.Mapster
添加到 IncludeAssemblyNames
集合中即可。v3.5.3+
版本后无需配置。
34.5.3 发布
如无需生成 .pdb
调试包可在生成 中禁用即可。
34.5.4 自定义启动端口
默认单文件发布监听的是 https://localhost:5001
,如果需要修改,可在 program.cs
中配置:
var builder = WebApplication.CreateBuilder(args).Inject();
builder.WebHost.UseUrls("https://*:8089");
var app = builder.Build();
app.Run();
这样就可以通过 https://localhost:8089
访问。
34.5.5 pm2
守护进程部署
34.5.5.1 运行弊端
正常情况下,将应用程序发布成单文件后,需点击 XXXXX.exe
进行启动,这时候程序自动打开终端(控制台),之后根据提示在浏览器上打开对应的地址即可。
但是这种方式有以下问题:
- 必须保证终端/控制台一直运行
- 终端/控制台有时候会出现假死的情况,导致应用程序无法访问
- 无法实时监听应用程序资源使用情况(如 CPU,内存,日志等)
- 无法映射端口启动
- 集群变得复杂