DotNet 8 Minimal API with AOT (三): Ubuntu Server 生产环境部署

更新日期: 2024-07-20 阅读次数: 1138 字数: 864 分类: Windows

在使用 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

继续阅读 📚

微信关注我哦 👍

大象工具微信公众号

我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式

tags: dotnet