ASP.NET Core之部署应用程序到Linux环境(非Docker模式)
一、前言
在.NET Core中实现跨平台的特性,我们创建一个ASP.NET Core的应用程序,然后通过非Docker方式部署到Linux环境中(Centos),通过一步步实践来体验跨平台的特性,及其在部署过程中要注意的事项,当前实践只是一个Demo实例,在实际生产环境下要考虑各种性能问题,所以要复杂的多。主要包括如下几个,在Linux环境中搭建运行程序的运行时;VS编译工具发布应用程序,上传到Liunx;然后启动应用程序;将应用程序设置系统后台服务运行。
二、Liunx中搭建NET Core运行环境
在Windows环境不管运行.NET Framework或者运行.NET Core都必须安装相关的SDK和运行时,比如在.NET Framework中的.NET 4.5、.NET 4.7、.NET4.8等版本,如果安装的应用程序没有相关的.NET版本会提示错误信息,安装该版本,或者在打包应用程序时一起将SDK、运行时打包到程序中安装。在WIN+R中运行%systemroot%\Microsoft.NET\Framework,可以查看当前Windows环境安装的版本,或者通过下述.bat文件在cmd中运行获取全部版本信息!

@echo off reg query "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP" /s > "%temp%\net_versions.txt" for /f "tokens=1,2,3 delims= " %%a in ('findstr /C:"Version" "%temp%\net_versions.txt"') do ( set "key=%%a" set "value=%%c" echo .NET Framework Version: %%~c ) del "%temp%\net_versions.txt" pause

.NET Core一样通过在cmd中dotnet --info命令获取全部系统已经安装的SDK与运行时的全部版本信息。通过dotnet -version获取当前最终版本号。


上述的安装通过在官网的.NET Core的下载页面https://dotnet.microsoft.com/zh-cn/download/dotnet/8.0,下载不同版本,包括Windows、Liunx、OS环境离线安装包。


主要包括SDK、ASP.NET Core的运行时、.NET桌面运行时、.NET运行时(NET 运行时仅包含运行控制台应用所需的组件),涉及到运行.NET Core中创建Web应用程序、桌面应用程序WPF、控制台应用程序Console。
上述都是安装Windows环境的,接下来安装Linux的运行环境,主要①在下载页下载离线安装包注意(版本号、操作系统、二进制文件区分),②直接在Liunx中在线下载SDK、运行时,③使用Docker容器,创建dockerfile文件包含相关的SDK、运行时信息。通过输入如下命令在线下载安装。
第一步、运行以下命令,将 Microsoft 包签名密钥添加到受信任密钥列表,并添加 Microsoft 包存储库,注意/8版本号。
sudo rpm -Uvh https://packages.microsoft.com/config/centos/8/packages-microsoft-prod.rpm
第二步、选择SDK版本与ASP.NET Core版本执行安装命令,如下命令(其中使用dotnet-runtime-7.0运行时可以替代asp.netcore-runtime-7.0包含该运行时)。
sudo yum install dotnet-sdk-7.0 dotnet-runtime-7.0
或者
sudo yum install dotnet-sdk-7.0 aspnetcore-runtime-7.0




通过dotnet --list-sdks 查看当前系统安装的.NET Core全部版本,及其文件位置,在安装dotnet-sdk-7.0的同时,依赖安装了asp.netcore-runtiime-7.0、dotnet-runtiime-7.0等包。
注意:1、通过命令sudo yum install dotnet-sdk-7.0下载了SDK并且一起依赖安装了asp.netcore-runtiime-7.0、dotnet-runtiime-7.0运行时,在.net core3.1中无法依赖同时安装SDK和运行时,需两个都安装。2、通过在线下载安装.NET Core,如果离线下载.tag包安装时必须确认krb5-libs、libicu、openssl-libs、zlib库是否在系统已经安装了。
三、Liunx中发布ASP.NET Core应用
在VS中创建一个框架为.NET 7.0的ASP.NET Core WebApi应用程序,然后基于简单的测试,直接编译、发布项目,获取\net7.0\publish下的文件内容,上传至Liunx中/home/netcore/WebApplication7。


完成上述的创建项目->编译项目->发布项目,则在Liunx中启动webApi应用,通过运行命令dotnet WebApplication7.dll --urls="http://localhost:5002",注意这个端口被占用,如果不加--urls参数则默认是5000,其运行与在Windows环境一致;不关闭当前的命令窗口,新开一个命令窗口,运行命令curl http://127.0.0.1:5002/weatherforecast,如下图返回接口请求结构,说明WebApi已经部署成功。


四、创建ASP.NET Core系统服务
上述的.NET Core运行在命令窗口中,如果关闭这个窗口会导致程序关闭。可以通过将这个.NET Core应用程序设置成系统服务、后台服务。使用守护进程方式设置程序,可以使用systemd模块或者supervisor为程序创建守护进程,其中systemd在上一个文章中记录了,我们使用supervisor来实现。
第一步、在系统中安装supervisor,当前环境为centos,主要执行下述命令实现安装
1. 使用epel-release仓库来安装Supervisor,先安装epel-release包 sudo yum install -y epel-release 2.安装Supervisor sudo yum install -y supervisor 3.启动Supervisor服务,并设置开机自启 sudo systemctl start supervisord sudo systemctl enable supervisord



上述提示启动失败,通过查看状态找到原因,是要先配置config文件相关参数,然后在启动程序,默认的配置文件位于/etc/supervisord.conf,编辑如下参数项
[unix_http_server] file=/tmp/supervisor.sock ;UNIX socket 文件,supervisorctl 会使用 ;chmod=0700 ;socket文件的mode,默认是0700 ;chown=nobody:nogroup ;socket文件的owner,格式:uid:gid ;[inet_http_server] ;HTTP服务器,提供web管理界面 ;port=127.0.0.1:9001 ;Web管理后台运行的IP和端口,如果开放到公网,需要注意安全性 ;username=user ;登录管理后台的用户名 ;password=123 ;登录管理后台的密码 [supervisord] logfile=/tmp/supervisord.log ;日志文件,默认是 $CWD/supervisord.log logfile_maxbytes=50MB ;日志文件大小,超出会rotate,默认 50MB,如果设成0,表示不限制大小 logfile_backups=10 ;日志文件保留备份数量默认10,设为0表示不备份 loglevel=info ;日志级别,默认info,其它: debug,warn,trace pidfile=/tmp/supervisord.pid ;pid 文件 nodaemon=false ;是否在前台启动,默认是false,即以 daemon 的方式启动 minfds=1024 ;可以打开的文件描述符的最小值,默认 1024 minprocs=200 ;可以打开的进程数的最小值,默认 200 [supervisorctl] serverurl=unix:///tmp/supervisor.sock ;通过UNIX socket连接supervisord,路径与unix_http_server部分的file一致 ;serverurl=http://127.0.0.1:9001 ; 通过HTTP的方式连接supervisord ;包含其它配置文件 [include] files =/etc/supervisord.d/*.ini ;可以指定一个或多个以.ini结束的配置文件
其中files =/etc/supervisord.d/*.ini表示可以加载相关进程,使用.结尾的ini文件,然后重新运行sudo systemctl start supervisord命令,查看是否启动成功,如下所示。

第二步、在/etc/supervisord.d/目录下新建要守护进程的配置文件,使用上述.NET Core应用程序为例,主要参数如下

[program:WebApplication7] command=dotnet WebApplication7.dll --urls="http://localhost:5002" #运行命令 directory=/home/netcore/WebApplication7 #程序路径 environment=ASPNETCORE__ENVIRONMENT=Production user=root stopsignal=INT autostart=true #自动启动 autorestart=true #3秒自动重启 startsecs=3 stderr_logfile=/var/log/ossoffical.err.log stdout_logfile=/var/log/ossoffical.out.log
第三步、重新启动supervisord,加载这个ini文件,然后使用命令sudo systemctl start supervisord查看是否已经加入成功!

通过上述命令应用程序已经启动,并且可以访问获取接口数据,说明成功加入。还可以通过使用supervisord的其他命令操作进程!
第四步、通过在.ini文件中配置的应用程序日志路径,可以查看应用程序的执行日志,如下所示

五、使用nignx代理服务
通过上述的操作,已经在Linux环境下运行ASP.NET Core应用,通过ASP.NET Core的内置服务器Kestrel启动服务,但是对外提供web服务,可以使用ngnix代理服务器的方式转发至这个服务中(ngnix作为web服务提供更好的性能、Kestrel则更多是应用服务),主要的操作如下所示
第一步,在Linux环境中安装nginx应用,可以通过docker或者非docker方式。
第二步、在nginx应用的配置文件中nginx.conf中配置代理参数,如下所示。
# For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/ user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; # Load modular configuration files from the /etc/nginx/conf.d directory. # See http://nginx.org/en/docs/ngx_core_module.html#include # for more information. include /etc/nginx/conf.d/*.conf; server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /usr/share/nginx/html; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { root html; index index.html index.htm; } location /dotnet/ { proxy_pass http://127.0.0.1:5002/weatherforecast; } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } } # Settings for a TLS enabled server. # # server { # listen 443 ssl http2 default_server; # listen [::]:443 ssl http2 default_server; # server_name _; # root /usr/share/nginx/html; # # ssl_certificate "/etc/pki/nginx/server.crt"; # ssl_certificate_key "/etc/pki/nginx/private/server.key"; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 10m; # ssl_ciphers PROFILE=SYSTEM; # ssl_prefer_server_ciphers on; # # # Load configuration files for the default server block. # include /etc/nginx/default.d/*.conf; # # location / { # } # # error_page 404 /404.html; # location = /40x.html { # } # # error_page 500 502 503 504 /50x.html; # location = /50x.html { # } # } }
第三步、然后重启nginx加载修改后的配置文件,在浏览器访问服务器IP/dotnet/获取默认接口数据


六、总结
使用非docker的方式在centos环境下安装.net core的SDK,并且安装asp.net core的运行时,创建ASP.NET Core WebApi应用,部署在系统中。使用supervisord完成了守护进程(.dotnet)的设置,然后通过nignx的代理服务器对外提供这个应用程序的接口服务,至此一个完整的asp.net core应用跨平台部署就完成。这个是简单的Demo,在实际的生产环境要考虑应用的安全性、并发性能、扩展性能、分布式、CI/CD等复杂的内容。
参考:https://learn.microsoft.com/zh-cn/dotnet/core/install/linux-centos#install-preview-versions,https://blog.csdn.net/u014597198/article/details/85158056,https://www.cnblogs.com/leoxuan/p/11108231.html

浙公网安备 33010602011771号