.NET Core 在 IIS、Windows 服务、Linux 上的部署方式

随着微软不断的发布更新 .NET Core 新版本,使用该技术的小伙伴们越来越多。主要还是因为两点:跨平台部署 和 开源。
当然只有 ASP.NET Core 网站 和 控制台程序 可以进行跨平台部署。目前 .NET Core 开发的 WinForm 和 WPF 仍然只能运行在 Windows 平台上,希望未来也能够支持跨平台吧。

虽然 .NET Core 开发好的网站和控制台服务可以部署在 Windows 上,但是我还是建议大家以后无论是测试环境部署,还是生产环境部署,尽量使用 Linux 部署,原因如下:

  • .NET Core 部署在 Linux 上是不可逆转的大趋势,未来绝大部分场景都会以微服务的方式部署在 Docker 上,而 Docker 只能运行在 Linux 服务器上。虽然 Windows 也能够安装 Docker ,但是本质上还是在 Windows 上的虚拟机上运行 Linux ,然后在虚拟机的 Linux 上运行 Docker ,性能效率肯定大大折扣。
  • 如果生产环境使用 Linux 部署,那么测试环境最好也是 Linux。因为 Windows 上开发好的 .NET Core 程序即使在 Windows 上运行很好,但是在 Linux 上难免会产生文件路径问题,以及其它一些小问题。因此需要提前发现和修复。

当前微软发布的最新 .NET Core 的版本是 .NET5 ,目前 .NET6 还处于预览版。我们就以 .NET5 开发好的网站为例,分别在 Windows 平台上的 IIS 和 Windows Service 上,以及 CentOS7 上介绍如何进行部署。

一、部署前提条件

我们先 使用 VS2019 基于 .NET5 创建一个默认网站样例:

1 创建新项目,选择 ASP.NET Core Web 应用(模型-视图-控制器)

image

2 然后一直点击下一步,可以考虑取消勾选 HTTPS,然后一直下一步,创建出如下图所示的代码结构:

image

3 为了能够自定义网站启动时的端口,我们需要修改两个地方,appsettings.json 和 Program.cs

appsettings.json 配置文件修改后的代码如下:

{
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        }
    },
    "AllowedHosts": "*",
    //这个是我新增加的配置节:网站启动时的端口
    "ListenPort": "http://*:9090"
}

Program.cs 文件修改后的代码如下:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    //这个是我新增加的代码,作用是在网站启动前加载 appsettings.json 配置文件
    public static IConfiguration Config = 
        (new ConfigurationBuilder()).SetBasePath(Environment.CurrentDirectory)
        .AddJsonFile("appsettings.json", false, true).Build();

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>
        {
            //我在这里增加了代码 UseUrls(要监听的网站地址端口)
            //格式类似为:UseUrls(Http://*:9090)
	    webBuilder.UseUrls(Config["ListenPort"]).UseStartup<Startup>();
        });
}

4 选择使用控制台的方式启动(默认使用的是 IIS Express 方式启动,端口是 5000)。

image

image

控制台窗口启动后,可以看到网站启动的端口,如果是配置的端口,则表明上面新增加的代码编写的没有问题。
(备注:从 appsetting.json 中的 ListenPort 配置节中读取的启动端口的配置值为:"http://*:9090")
如上图所示,此时使用浏览器访问 localhost:9090 或者 127.0.0.1:9090 就可以看到网页。

5 采用框架依赖、可移植的方式发布网站程序

image

发布后的文件如下图所示:

image
到此为止,部署前的准备工作已经完毕。

二、在 IIS 上部署

这里我们使用服务器操作系统 Windows Server 2019 进行演示,并且服务器已经安装好了 IIS
(因为篇幅有限,服务器上 IIS 的安装不是本篇博客的重点,这里就不介绍了)

我们首先将发布后的文件,复制到服务器上,假设复制到 C 盘的 CoreDemoWeb 文件夹。
(文件夹中 web.config 是必须的,exe 文件不是必须文件,可以删除掉)

1 安装 dotnet-hosting-xxx-win.exe

在 IIS 上部署 .NET Core 网站,只需要安装着一个软件即可,不需要安装其它额外的软件。

该软件的下载地址为:https://dotnet.microsoft.com/download/dotnet

进入网页后,点击具体的 .NET Core 版本,这里我选择 .NET 5.0,点击后进入详细页面:

image

上面有这样一句话:
On Windows, we recommend installing the Hosting bundle, which includes the .NET Runtime and IIS support 。
这句话的意思表明:
只需要下载安装 Hosting Bundle 这一个软件就可以了,它已经包含了 .NET Core 运行时 和 对 IIS 的支持。

下载并安装好软件后,打开 IIS 管理窗口,在右侧点击 “模块

image

然后会发现模块列表中,多出一项:AspNetCoreModuleV2 ,看到这个表明已经安装成功。

image

2 在 IIS 上部署 .NET 5 网站

打开 IIS 管理器,新建网站,在弹出框中填写相应的内容

image

应用程序池,不需要特意将应用程序池选择无托管,因此创建了应用程序池后,不需要进行任何操作。

这里随便绑定的一个域名 www.testweb.com ,目的是为了使用 80 端口。
(我们在上面创建的网站示例中,可以在配置文件中指定具体的启动端口,
但是如果部署在 IIS 上的话,那么就使用 IIS 新建网站时指定的端口。)

最后点击 确定 按钮,网站就创建好了。

3 浏览网站验证部署效果

我的服务器 ip 地址是:192.168.174.128

我的本机 ip 地址是:192.168.174.1

我们修改一下 hosts 文件,将 www.testweb.com 这个域名指向服务器 ip 192.168.174.128 即可。
(如果你想在服务器上使用浏览器访问刚刚部署好的网站,就在服务器的 hosts 文件添加域名指向记录,
当然如果想在本机使用浏览器访问网站,就在本机的 hosts 文件中添加域名指向记录即可)

如果你的操作系统安装在 C 盘,那么 hosts 文件就在 C:\Windows\System32\drivers\etc 文件夹内。

我用记事本打开本机的 hosts 文件,添加如下域名指向记录

image

然后打开浏览器访问 www.testweb.com,网页显示如下,大功告成,(#^.^#)

image

三、在 Windows Service 上部署

我们再复制一份发布后的文件到服务器上,假设复制到 C 盘的 CoreDemoService 文件夹。
(文件夹中 web.config 和 exe 文件都不是必须文件,可以删除掉)

1 安装 .NET5 的 SDK 或 ASP.NET Core Runtime

软件下载地址同上:https://dotnet.microsoft.com/download/dotnet

进入网页后,点击具体的 .NET Core 版本,这里我选择 .NET 5.0,点击后进入详细页面:

SDK 下载界面如下:(因为我的服务器操作系统是 64 位,所以我下载 64 位的 SDK)

image

ASP.NET Core Runtime 下载界面如下:(因为我的服务器操作系统是 64 位,所以我下载 64 位的 SDK)

image

这两个软件,安装其中一个即可,我个人建议安装 SDK,因为 SDK 包含的组件内容非常全面,省去了后续的很多麻烦事情。

2 下载和使用 nssm.exe

nssm 软件是一个非常小巧实用 Windows Service 管理工具,功能也很强大,
这里只使用最核心的功能,如果你对其它功能感兴趣的话,可以详细研究一下。
截止到目前 nssm 的最新版本是 2.24,下载地址为:http://www.nssm.cc/download

下载完成后,解压缩会发现有分为 32 位和 64 位,
我的服务器是 64 位,因此我将 64 位的 nssm.exe 复制到服务器上即将要部署的文件夹 C:\CoreDemoService 文件夹下。
image

然后打开控制台,将 nssm.exe 拖动控制台窗口,后面跟上 install 参数,运行命令:

C:\CoreDemoService\nssm.exe install

弹出如下窗口,然后录入相关的信息:

image

Application Path:
这个路径是固定的,在 SDK 或相关 Runtime 安装后,就会有 dotnet.exe 这个文件,选择这个文件的绝对路径即可。

Startup directory:
这个是服务所在的文件夹,因为我要安装服务的所有文件都复制到了 C:\CoreDemoService 中,因此我填写这个文件夹。

Arguments:
运行时的参数,这个选择你程序发布时的 dll 文件即可,一般该文件的名称与 exe 的名称相同。

Service name:
服务的名字,这个名字会显示在 Windows 服务中,你自己可以随便命名。

以上参数填写好后,点击 Install service 即可。安装成功后,到打开 服务 管理器,启动服务即可。

image

3 浏览 Windows Service 部署的网站验证部署效果

查看配置文件 appsettings.json ,我们配置的启动端口为 9090。
(你也可以修改为其它端口,修改完成后,需要重新启动服务即可)

我的服务器 ip 地址是:192.168.174.128

在我本机,打开浏览器,直接访问 http://192.168.174.128:9090 即可,如下所示:

image

我之前本机的 hosts 文件中,添加了 www.testweb.com 指向服务器 ip 192.168.174.128,
因此我也可以通过域名加端口的方式访问:

image

如果想要使用 80 端口访问网站的话,只需要在服务器上安装并配置 nginx 进行转发即可,留在下面进行 Linux 部署时进行演示。

4 在进程中查看和识别服务

我们肯定会遇到这样的场景:你使用 .NET Core 开发好的网站或者服务,部署成 Windows Service 后,使用 任务管理器 只能看到 .NET Host ,鼠标右键菜单选择属性查看具体信息,只能看到其路径是 C:\Program Files\dotnet ,尤其是当服务器部署了好多 .NET Core 的 Windows Service 时,你就很难快速辨别每个 .NET Host 对应的是哪个服务。当你发现某些 .NET Core 的服务 CPU 占用很高或者内存占用很大,由于无法快速识别具体的服务,就很耽误事情。

image

为了解决以上问题,我推荐一个工具软件 Process Explorer ,下载地址为:

https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer

下载完成后解压缩,我的服务器是 64 位的操作系统,因此我复制 procexp64.exe 到服务器上运行:

image

Process Explorer 跟任务管理器一样,运行后也能查看每个进程的 CPU、内存、进程号等信息。

你可以选择具体的每个 nssm.exe 下面的 dotnet.exe,通过右键菜单 properties ,弹出属性框。
从里面的 Command line 和 Current directory 就可以快速辨别出是哪个服务,非常方便。

5 卸载 nssm 部署的 .NET Core 服务

如果想卸载服务:

1 先在服务管理器中,停止服务,这一步很重要。
如果不停止服务就卸载的话,虽然提示卸载成功,但是服务管理列表中还存在该服务,无法启动,无法操作。
对于强迫症患者来说,是一种精神折磨。

2 找到被卸载服务所在的文件夹,打开控制台窗口,
将文件夹下的 nssm.exe 拖动到控制台窗口,后面跟上 remove 参数,运行命令:

C:\CoreDemoService\nssm.exe remove

在弹出的窗口中,输入服务的名字,点击 Remove service 即可删除服务。

image

四、在 Linux 上部署

这里我们使用服务器操作系统 CentOS7 来进行演示,
使用 Xshell 进行命令行输入,使用 xftp 进行本机和服务器之间文件的传输和操作。
(强烈建议使用 xftp 进行 Linux 上文件的传输和编辑操作,比通过命令行操作要方便很多)

我安装的 CentOS7 服务器的 ip 地址为:192.168.8.143

1 首先使用 xftp 将发布的网站复制一份到 Linux 服务器上

使用 xftp 以 SFTP 的方式登录 CentOS7 系统。(注意这里选择的是 SFTP)

image

在 xftp 软件界面中,左边是你自己电脑本机的目录和文件操作界面,右边是远程服务器的目录和文件操作界面。

使用 xftp 通过右键菜单 “新建文件夹” 在 CentOS7 服务器的根目录下创建一个文件夹 webapp,
将之前发布的网站文件复制到该文件夹下。(文件夹中 web.config 和 exe 文件都不是必须文件,可以删除掉)

image

2 下载安装 .NET SDK 或 ASP.NET Core 运行时

在 CentOS7 上安装 .NET5 SDK 的官方文档地址为:

https://docs.microsoft.com/zh-cn/dotnet/core/install/linux-centos

我在安装 CentOS7 时,没有创建其它账号,我只能使用 root 账号登录,因此运行任何命令不需要在命令前加上 sodu,
如果你以普通用户的身份登录的话,则运行下面的安装命令,则需要在前面加上 sudo,具体安装步骤如下:

1 安装 .NET 之前,请运行以下命令,将 Microsoft 包签名密钥添加到受信任密钥列表,并添加 Microsoft 包存储库。

rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm

2 安装 .NET SDK 或 ASP.NET Core 运行时(两者只需要安装其中任何一个即可

# 安装 sdk
yum install dotnet-sdk-5.0

# 安装运行时
yum install aspnetcore-runtime-5.0

3 安装完成后,运行 dotnet --version 命令,如果能够查看到版本号,则表明安装成功


3 部署 .NET Core 网站

在 Linux 上部署 .NET Core 网站的官方文档地址为:

https://docs.microsoft.com/zh-cn/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-5.0

具体部署步骤为:
1 使用 xftp 找到 /etc/systemd/system 这个文件夹,通过鼠标右键 "新建文件" 创建一个服务的安装配置文件,假设名称为 CoreWebDemo.service

2 鼠标选择 CoreWebDemo.service 这个文件,鼠标右键菜单 “用记事本编辑”。
(如果你电脑上安装了 NotePad++ 或其它比较好用的文本编辑软件的话,使用鼠标右键菜单 “打开”,在弹出的框中寻找和选择相应的文本编辑软件即可)

3 在文件中录入以下内容即可,可以从官网上复制,然后进行修改并保存。

[Unit]
# 这个是服务的描述信息,可以随便录入
Description=我开发的 .NET5 网站 Demo

[Service]
# 这个网站或服务所在的文件夹,之前我们复制到了 /webapp 这个目录
WorkingDirectory=/webapp
# 这个运行网站或服务的命令,建议都使用绝对路径
# 其中前面的 /usr/bin/dotnet 是运行网站或服务所需要的命令
# 后面的 /webapp/CoreWebDemo.dll 是命令行参数,这个是程序的 dll 文件
ExecStart=/usr/bin/dotnet /webapp/CoreWebDemo.dll
# 服务崩溃时,是否重启服务
Restart=always
# 如果服务奔溃,10 秒后重启服务
RestartSec=10
KillSignal=SIGINT
# 系统日志的标识,可以随便录入,建议跟网站或服务的名字相同,这样比较好识别
SyslogIdentifier=CoreWebDemo
# 以服务器上的哪个账号运行服务,这里使用root账号
User=root
# 设置环境变量,这里设置运行为生产环境
Environment=ASPNETCORE_ENVIRONMENT=Production
# 服务运行时是否打印临时信息
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

[Install]
# 服务运行在 linux 上的哪个 level,这里选择多用户命令行,也就是第 3 级别
WantedBy=multi-user.target

4 安装和运行服务

服务的名字就是文件的名字
上面创建的文件名是 CoreWebDemo.service ,因此服务的名字就是 CoreWebDemo.service,
在使用 xshell 运行命令安装和运行服务时,后缀名 .service 可以进行省略,运行以下命令即可:
特别注意,在 Linux 下文件名是区分大小写的,因此服务名也区分大小写

# 将服务设置为开机自动运行
systemctl enable CoreWebDemo
# 启动服务
systemctl start CoreWebDemo
# 查看服务运行状态
systemctl status CoreWebDemo

# 下面列出 停止服务 和 重启服务 操作命令
systemctl stop CoreWebDemo
systemctl restart CoreWebDemo

image

4 使用浏览器访问验证

我们在网站部署成功后,有可能并不能访问,还需要将网站的端口开通防火墙(不建议关闭防火墙)。

查看配置文件 appsettings.json ,我们配置的启动端口为 9090。
(你也可以修改为其它端口,修改完成后,需要重新启动服务即可)

因此使用以下命令将 9090 端口开通防火墙,然后 重新加载防火墙,以便防火墙配置生效

# 在防火墙中开通 9090 端口
firewall-cmd --zone=public --add-port=9090/tcp --permanent
# 重启加载防火墙配置
firewall-cmd --reload

# 下面列出防火墙的其它操作命令

# 删除防火墙之前开放的某个端口
firewall-cmd --zone=public --remove-port=9090/tcp --permanent
# 查看具体某个端口的开放状态
firewall-cmd --query-port=80/tcp
# 查看已经开放了哪些端口
firewall-cmd --list-port
# 启动防火墙
systemctl start firewalld
# 关闭防火墙
systemctl stop firewalld.service
# 开机自动运行防火墙
systemctl enable firewalld.service
# 禁用firewall(开机不会自动运行防火墙)
systemctl disable firewalld.service
# 查看防火墙状态
systemctl status firewalld

我的 CentOS 服务器的 ip 地址是 192.168.8.143 ,网站启动的端口是 9090,
我的电脑跟服务器在同一个 ip 网段,因此只需要访问 http://192.168.8.143:9090 即可访问网站,如下图所示:

image

5 使用 nginx 转发请求,通过 80 端口访问网站

安装 nginx 软件,官网文档地址是:http://nginx.org/en/linux_packages.html#RHEL-CentOS

安装步骤如下:

1 运行命令 yum install yum-utils 安装必备的工具包

2 使用 xftp 在 /etc/yum.repos.d 目录下,创建 nginx.repo 文件,并从官网上复制以下内容,编辑并保存:

[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

3 然后使用 xshell 运行命令 yum install nginx 安装最新版的 nginx 即可

4 安装完成后,运行命令 nginx -v 查看 nginx 的版本,如果能够查看到,则表示 nginx 安装成功。

然后运行以下命令,确保 nginx 开机自动运行,以及重启 nginx 服务

# 设置开机自动运行 nginx 服务
systemctl enable nginx

# 重启启动 nginx 服务,只需要重启一次即可,后续不需要再重启了
# 安装好后,一般最好重启一次 nginx 服务
# 否则后面修改了 nginx 的配置文件后,执行 nginx -s reload 重启加载 nginx 配置时,可能会命令执行失败
systemctl restart nginx

5 使用 xftp 访问 /etc/nginx 目录,可以看到 nginx.conf 这个主配置文件。打开主配置文件,在文件最后可以看到这样一行:
include /etc/nginx/conf.d/*.conf;

说明 nginx.conf 会自动加载 /etc/nginx/conf.d 目录下面所有后缀为 .conf 的配置文件。(在生产环境中,nginx.conf 这个主配置文件修改好后,后续就基本不会再动,绝大部分情况下都会去在 /etc/nginx/conf.d 目录下,添加或修改具体的网站的配置文件)

我进入 /etc/nginx/conf.d 目录下,创建一个配置文件 CoreWebDemo.conf 文件,从微软官网上复制以下内容并修改保存:

server {
    listen        80;
    # 要绑定的域名
    server_name   www.testweb.com;
    
    # nginx 默认情况下,一次最大只允许上传 1M 的文件
    # 你可以通过这个配置项进行修改,本示例修改为 10M
    client_max_body_size  10m;
    client_body_buffer_size 1m;
    
    location / {
    	# 将请求转发到网站服务的端口
        proxy_pass         http://127.0.0.1:9090;
        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;
        # 转发客户浏览器的 ip 地址
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }
}

6 使用 xshell 运行以下命令,使 nginx 重新加载配置:
# 重新加载 nginx 配置
nginx -s reload

# 如果上面的命令报错,可以运行以下命令重启 nginx
systemctl restart nginx
# 重启 nginx 后,以后再运行 nginx -s reload 就没问题了。
# 生产环境中,建议新增或修改了配置节后,使用 nginx -s reload

7 将防火墙开通 80 端口,并重新加载防火墙的配置,以便防火墙规则生效:
# 防火墙开通 80 端口
firewall-cmd --zone=public --add-port=80/tcp --permanent
# 重新加载防火墙配置
firewall-cmd --reload

8 在测试访问网站的电脑上的 hosts 文件中,添加或修改域名指向

由于我们在 nginx 中给网站绑定的域名是 www.testweb.com,我的 Linux 服务器的 ip 地址为 192.168.8.143。
因此我在自己电脑 windows 系统的 hosts 文件中,添加域名指向记录:
(如果之前已经添加过,则修改一下 www.testweb.com 指向的 ip 地址)

# hosts 文件存放在 C:\Windows\System32\drivers\etc 这个目录下
192.168.8.143  www.testweb.com

9 检查 Linux 服务器的 SeLinux 是否正在启用,如果启用的话,修改配置文件,彻底关闭它(这一步很重要)

SeLinux 是 Linux 系统的安全策略,在国内的服务器一般很少使用。相对于 Linux 使用的便利性而言,SeLinux 确实会在使用过程中带来很多麻烦,因此安装好 CentOS 系统后,首先要做的事情就是关闭它。
如果你不关闭它的话,在使用 CentOS 系统安装软件使用的过程中,经常会遇到一些莫名其妙的问题。有的时候查看日志也未必能够发现是 SeLinux 搞得鬼。

比如我们上面的 nginx 、防火墙、hosts 文件的域名指向 都已经配置好了,但是在自己的电脑上进行访问测试,报 502 Bad GateWay 错误,无法访问,查看 nginx 日志可能会发现是 SeLinux 启用导致的。

SeLinux 的配置文件在 /etc/selinux 目录下,配置文件的名称是 config,打开它进行编辑,将 SELINUX 后面的值修改为 disabled

image

然后使用 xshell 运行命令 init 6 重新启动 Linux 服务器。(SeLinux 配置修改,必须重启才能生效)

10 以上操作都完成后,接下来见证奇迹的时候到了

在我自己的电脑上,打开浏览器,访问 www.testweb.com 如下图所示,成功访问网站,(#^.^#)

image

此时你可以将防火墙的 9090 端口关闭,这样就只能通过 80 端口的域名访问网站了。

firewall-cmd --zone=public --remove-port=9090/tcp --permanent



posted @ 2021-09-04 20:59  乔京飞  阅读(11451)  评论(0编辑  收藏  举报