在使用 HTMX 调用 .NET 8 Minimal API 实现的接口后,这个小的练手项目就算是开发完了。现在需要部署到生产服务器上。
编译
> dotnet publish
可执行文件的大小
> ls bin/Release/net8.0/linux-x64/publish/ -lah
total 32M
4.0K ./
4.0K ../
11M app*
21M app.dbg*
127 appsettings.Development.json*
151 appsettings.json*
4.0K wwwroot/
app 就是生成的独立的可执行的二进制文件。只有 11M 大小。 跟 golang gin 有得一拼了。
静态文件无法嵌入
唯一的问题是,wwwroot 下的静态文件,没法打包进最终的二进制文件中。
我网上搜索了几个方案,都行不通。讨论的人也非常少。
这点明显不如 golang 和 rust 的发布方便,可以灵活地配置是否将静态文件打包进去。
不过,目前也能接受。毕竟目前的 DotNet 8 Minimal API with AOT 只是个半成品,我也没打算在大项目中使用。 目前只在简单的小工具中使用。
开发环境端口设置
配置文件:
Properties/launchSettings.json
例如,我想改成 9029 端口,只需要修改下面的配置
"applicationUrl": "http://localhost:9029",
生产环境端口设置
配置文件:
appsettings.json
比较有趣的是,执行 dotnet publish 之后,生成的 bin/Release/net8.0/linux-x64/publish 目录中, 包含了两个配置文件:
- appsettings.Development.json*
- appsettings.json*
这两个文件就是从项目根目录复制过来的。
还是挺贴心的,方便内部测试和生产环境使用不同的配置文件。
所以,要修改生产环境的端口,只需要修改配置文件 appsettings.json,增加 Kestrel 的配置:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://localhost:9029"
}
}
}
}
然后,执行 publish 目录中的可执行文件,就能看到端口号已经生效。
> ./app
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:9029
当然,还有好几种配置方法(例如,命令行参数,系统环境变量,代码里设置等),可以参考:
https://stackoverflow.com/questions/70332897/how-to-change-default-port-no-of-my-net-core-6-api
Kestrel 是什么
Kestrel is a cross-platform web server for ASP.NET Core. Kestrel is the recommended server for ASP.NET Core, and it's configured by default in ASP.NET Core project templates.
Kestrel 是 ASP.NET Core 内置的 Web Server。
但,Kestrel 是何时被引入的呢?
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
WebApplication.CreateBuilder 内部调用了 UseKestrel。
而,我这里使用的 Minimal API with AOT,则使用的是:
var builder = WebApplication.CreateSlimBuilder(args);
CreateSlimBuilder 也调用了 UseKestrel,但是默认去掉了 HTTPS 和 HTTP3 支持。 这是也是为什么,在 appsettings.json 中配置 HTTPS URL 时,在执行 dotnet publish 会报错的原因。
Unhandled Exception: System.InvalidOperationException: Call UseKestrelHttpsConfiguration() on IWebHostBuilder to enable loading HTTPS settings from configuration.
详细参考:
https://andrewlock.net/exploring-the-dotnet-8-preview-comparing-createbuilder-to-the-new-createslimbuilder-method/
Nginx 配置
server {
listen 80 default_server;
location / {
proxy_pass http://127.0.0.1:9029;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
如何要实现 Nginx 配置文件中请求路径 /prefix/api_a,但是转发给本地的 .Net 服务,去掉 /prefix 前缀:
location /prefix/ {
proxy_pass http://localhost:9029/;
...
}
查看进程占用的内存
使用 top 命令,然后按下大写 M,按照使用内存排序。
VIRT RES SHR S %CPU %MEM COMMAND
4872968 1.0g 20056 S 0.0 13.0 java
2940928 805824 13696 S 1.7 9.9 mysqld
259.5g 24064 12032 S 0.0 0.3 NetServerTool
会看到这个 .NET AOT 程序,占用内存 24M。 但是比较诡异的是虚拟内存占了 260G ... 按照 github 上的讨论,这没有什么问题。。。只是方便 GC 使用。(即便是 AOT 模式,也是有 GC 的)
https://github.com/dotnet/runtime/issues/9199
继续阅读 📚
- DotNet 8 Minimal API with AOT (一): 新建项目
- DotNet 8 Minimal API with AOT (二): 编写接口
- DotNet 8 Minimal API with AOT (三): Ubuntu Server 生产环境部署
微信关注我哦 👍
我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式