第 2.2 部分 - 安装 Nginx 并将其配置为反向代理服务器

适用于: .NET Core 2.1、.NET Core 3.1、.NET 5

本文介绍如何安装 Nginx 并将其配置为反向代理服务器。

先决条件

若要遵循本部分中的练习,必须创建一个 ASP.NET Core Web 应用程序并将其部署到 /var 文件夹。

本部分的目标

在上一部分中,你使用 .NET CLI 工具创建了一个 ASP.NET Core Web 应用程序,并将该应用程序部署到 /var 文件夹。 应用程序还配置为侦听端口 5000 以获取 HTTP 请求,并删除了 HTTPS 重定向。

此时,客户端应在连接到应用程序时提供端口号(例如)。 http://localhost:5000 但是,这不是所需的行为。

本部分的目标如下:

  • 客户端应该能够导航,而无需提供端口号。 例如,客户端应使用 http://localhost.
  • 如果 Web 应用程序出于某种原因或计算机重启后停止,应自动启动。

在下一部分中,你将使用 Nginx 作为代理服务器,将向端口 80 发出的 HTTP 请求路由到 .NET 应用程序。 你还将将应用程序配置为自动启动。

什么是 Nginx?

Nginx 是一种常用的轻型快速 Web 服务器。 它可以在 Linux 和 Windows 上运行,并且可以配置为反向代理服务器。

什么是守护程序?

Nginx 作为 守护程序运行。 守护程序是后台运行的服务的替代术语。 与在 Windows 上运行的服务一样,守护程序可以配置为在启动期间自动启动。 将 ASP.NET Core 应用程序配置为作为守护程序运行。

使用 APT 安装 Nginx

安装 Nginx 非常简单。 sudo apt install nginx运行命令以在 Ubuntu 虚拟机上安装程序。

sudo 命令的屏幕截图。

安装完成后,运行 whereis nginx 以发现程序安装的位置。 可以通过检查输出来查看 Nginx 配置文件的位置。 以下屏幕截图显示配置文件位于 /etc/nginx 文件夹中。

whereis 命令的屏幕截图。

注意

如果运行 Ubuntu 或 Debian 以外的分发版,可以从官方 Nginx 安装文档中找到等效的包管理器安装命令或说明

使用 systemctl 管理服务

如果未看到 Nginx 正在运行,可以通过运行 sudo systemctl start nginx显式启动它。 尽管本练习将演示 systemctl Nginx 的命令,但这些命令用于将 Web 应用程序配置为作为守护程序自动启动。

安装完成后,Nginx 已配置为自动启动。 Nginx 作为守护程序运行。 可以使用 systemctl 检查守护程序的状态。

systemctl 命令用于管理此类任务的“服务”,例如显示服务的状态或启动和停止它。 某些可用参数是启动、停止、重启、启用、禁用和状态。 若要检查 Nginx 的状态,请运行 systemctl status nginx

systemctl 命令的屏幕截图。

此命令会生成一些有用的信息。 如此屏幕截图所示,Nginx 处于 active (running) 状态,Nginx 实例的进程 ID 为 8539。 另请注意和enabledvendor preset: enabled语句。 Enabled 表示当计算机重新启动时,此守护程序将启动, vendor preset: enabled 并且表示在安装 Nginx 时默认启用 Nginx。 因此,当服务器启动时,Nginx 将自动启动。

测试 Nginx 安装

默认情况下,Nginx 侦听端口 80。 因为它正在运行,因此在浏览 localhost 时,应该能够访问 Nginx 的主页。 用于 curl 通过运行 curl localhost来测试 Nginx。 以下屏幕截图中突出显示的黄色文本显示了 Nginx 默认网页。 因此,Nginx 正在运行:

curl 命令的屏幕截图。

systemctl 命令选项

可以使用命令管理 systemctl 服务或守护程序。 启动、停止或进行更改需要超级用户访问权限。 因此,必须将前缀添加到 sudo 这些命令。

重启守护程序

可能需要不时重启守护程序。 若要重启守护程序,请运行 sudo systemctl restart <daemon_name>。 若要重启 Nginx,请运行 sudo systemctl restart nginx。 请确保在运行此命令之前和之后检查 Nginx 的状态,以监视进程 ID 的更改。

停止守护程序

若要停止守护程序,请运行 sudo systemctl stop <daemon_name>。 若要停止 Nginx,请运行 sudo systemctl stop nginx,然后再次运行 systemctl status nginx 来检查 Nginx 的状态。 这一次,服务显示为非活动(已死),但仍启用。 这意味着,尽管服务未运行,但在重启服务器后,该服务会自动启动。

stop 命令的屏幕截图。

注意

systemctl status 命令还显示守护程序的前几行日志条目。

停止 Nginx 后,再次运行 curl localhost

注意

连接被拒绝,因为端口 80 上没有侦听传入流量。

BuggyAmb localhost 的屏幕截图。

禁用守护程序

禁用守护程序不同于停止守护程序。 禁用的守护程序可以运行,但在重启服务器后它不会自动启动。 若要禁用 Nginx 守护程序,请运行 sudo systemctl disable nginx,然后检查 Nginx 的状态。

禁用命令的屏幕截图。

此屏幕截图显示 Nginx 未运行,并且已禁用。 这意味着 Nginx 在重启后不会自动启动。

启动守护程序

若要启动守护程序,请运行 sudo systemctl start <daemon_name>。 若要启动 Nginx,请运行 sudo systemctl start nginx,然后再次检查服务的状态。

启动命令的屏幕截图。

此屏幕截图显示 Nginx 已启动,但仍处于禁用状态。 尽管服务正在运行,但 Nginx 在重启后不会自动启动,因为它是禁用的服务。

启用守护程序

启用服务意味着它将在重启后自动启动。 若要启用 Nginx,请运行 sudo systemctl enable nginx,然后再次检查 Nginx 的状态。

启用命令的屏幕截图。

此屏幕截图显示 Nginx 正在运行,并在重启服务器后启动。

将 Nginx 配置为反向代理以将请求路由到 ASP.NET Core 应用程序

了解如何启动、停止和重启 Nginx 服务后,接下来将 Nginx 配置为反向代理,将端口 80 上发出的请求路由到侦听端口 5000 的 ASP.NET Core 应用程序。

下面是所需的配置。 突出显示了一些关键部分。

http {
  map $http_connection $connection_upgrade {
    "~*Upgrade" $http_connection;
    default keep-alive;
  }

  server {
    listen        80;
    server_name _;
    location / {
        proxy_pass         http://localhost:5000;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection $connection_upgrade;
        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 将侦听端口 80 的所有请求(指令: listen 80) 。
  • Nginx 会将请求路由到 http://localhost:5000 (指令: proxy_pass http://localhost:5000

注意

server_name _代码中的行。 这用作 catch-all 指令。 若要了解有关server_name的详细信息,请参阅官方文档

配置更改看起来很简单。 我们将使用此代码替换 server 配置文件中的指令部分。 但是配置文件在哪里?

查找正确的 Nginx 配置文件

主 Nginx 配置文件为 /etc/nginx/nginx.conf. 若要检查配置,请使用 cat /etc/nginx/nginx.conf 命令并搜索服务器指令。

cat 命令的屏幕截图。

滚动浏览配置以查找服务器指令。 应该不会找到它。 我们可以将所需的配置更改放在配置文件中的某个位置。 但是,理想情况下,你不希望替换原始配置文件。 这是为了防止引入可能阻止服务器正确启动的配置错误。 该 server 部分不在主配置文件中。 如果不断滚动浏览配置文件,则会发现有一些 include 指令。

include 命令的屏幕截图。

通过将配置拆分为要包含在主配置文件中的区块,Include 指令可以更轻松地管理配置。 主配置文件可以保持简单,某些特定的配置部件可以移动到其他文件。 此屏幕截图中突出显示的行指示以下内容:

  • Nginx 将从位于 /etc/nginx/conf.d 目录中的每个 .conf 文件 加载 配置。
  • Nginx 将从 /etc/nginx/sites-enabled 目录中的每个文件中加载配置。

如果检查这些目录,则不会在 /etc/nginx/conf.d 中找到任何配置文件。 但是,启用了 /etc/nginx/sites 的一个文件

conf 命令的屏幕截图。

默认配置文件类似于托管要查找的配置的主要候选项。 如果使用 检查 /etc/nginx/sites-enabled/default 文件 cat /etc/nginx/sites-enabled/default,则会看到默认服务器指令位于以下代码中。

默认信息的屏幕截图。

因此, 必须编辑 /etc/nginx/sites-enabled/default 文件才能更改配置。

使用 vi 编辑配置文件

你了解了编辑Startup.cs文件时如何编辑文件,以从 ASP.NET 管道中删除 HTTPS 重定向。 现在,你将再次使用 vi 来更改 nginx 配置文件。

提示

始终备份要更改的文件。 如果在编辑后出现问题,则可以使用该副本将文件还原到其以前的状态。 在这种情况下,请运行 cp /etc/nginx/sites-enabled/default ~/nginx-default-backup 以将配置文件复制到主目录。 备份文件名将为 nginx-default-backup。 请注意,备份未在与原始文件相同的目录中进行。 这是因为 Nginx 从该目录中加载所有配置文件,并且你不希望通过加载两个不同的服务器指令来中断配置。

运行 sudo vi /etc/nginx/sites-enabled/default 以编辑配置文件并替换服务器指令,如以下屏幕截图所示。

vi 命令的屏幕截图。

下面是使用 vi 编辑文件的一些提示和技巧:

  • 可以使用箭头键向上和向下滚动。
  • 若要进入编辑模式,请按 InsertI 键。 处于编辑模式时,左下角将显示一 条 --INSERT 消息
  • 在编辑模式下,可以使用键盘一次删除一个字符。
  • 在编辑模式下,复制和粘贴操作可与大多数终端协同工作。 因此,你可以复制本文中的内容并将其粘贴到 vi 中。
  • 若要退出编辑模式,请按 Esc
  • 可以在正常模式下更轻松地删除行。 在正常模式下,转到要删除的行的开头,然后输入 dd。 该 dd 命令删除整行。 还可以键入 5dd 以一次删除五行。 但是,应谨慎使用此选项以避免删除额外的内容。
  • 如何在 Vim/Vi 文章 中删除行是了解如何在 vi 中删除多行的好方法。
  • 若要退出 vi 并保存更改,请输入 :wq!,然后按 Enter。 此处,冒号(:)表示你正在运行命令, w 表示写入更改, q 表示退出,并 ! 意味着重写更改。
  • 若要退出而不保存更改,请输入 :q!,然后按 Enter

更改现已保存,必须重启 Nginx 服务才能使这些更改生效。 在重启服务之前,可以运行 sudo nginx -t 该命令来测试配置文件。 此命令运行时,Nginx 会检查配置文件语法,然后尝试打开配置文件中引用的文件。

t 命令的屏幕截图。

如此处所示,已更改的配置文件似乎正确。

我们必须重启 Nginx,使更改生效:

sudo systemctl restart nginx

重启后,你希望在向 http://localhost 发出请求时看到来自 ASP.NET Core 应用程序的响应,因为 Nginx 应充当对端口 80 发出的请求的反向代理。

重启 Nginx 服务以使更改生效,然后通过运行 curl localhost向 localhost 发出请求。 但是,此命令将失败。 下一步是运行 wget localhost,然后搜索有关问题的源的一些提示。

wget 命令的屏幕截图。

排查 Nginx 代理问题

在前面的屏幕截图中,你将看到以下信息:

Resolving localhost (localhost)... 127.0.0.1  
Connecting to localhost (localhost)|127.0.0.1|:80... connected.  
HTTP request sent, awaiting response... 502 Bad Gateway  
2020-12-27 21:15:53 ERROR 502: Bad Gateway.

第一行和第二行指示你能够解析 localhost 并在套接字上 127.0.0.1:80 连接。 因此,Nginx 应正在运行。 若要验证这一点,可以运行 systemctl status nginx 该命令。

第三行指示问题的来源。 收到 HTTP 502 错误的网关错误消息。 HTTP 502 错误的网关 与代理相关。 这意味着反向代理无法连接到后端应用程序。 在本例中,ASP.NET 核心 Web 应用程序应运行并侦听端口 5000 请求。 我们应该检查 Web 应用程序是否也在运行。

若要开始故障排除,请运行与之前相同的 netstat 命令。 这一次,请使用 grep 筛选应用程序的端口 5000。 然后运行 netstat -tlp | grep 5000

netstat 命令的屏幕截图。

此示例输出指示端口 5000 上没有侦听任何内容。 因此,这是来自 Nginx 的 HTTP 502 响应的原因,因为它找不到侦听端口 5000 的进程。

解决方案是启动 ASP.NET Core 应用程序。 但是,在继续下一步之前,可以查看另一种方法来解决此问题。 并非每个问题都很容易解决,只需查看几行日志内容并找到根本原因即可。 有时,必须深入了解其他系统和应用程序日志。

由于你在 Linux 中设置 ASP.NET Core 应用程序时与 Nginx 密切合作,因此我们建议了解 Nginx 和操作系统提供的用于故障排除的日志类型。

检查 Nginx 日志

如果再次运行 cat /etc/nginx/nginx.conf ,然后查找 logging settings,应注意以下事项。

日志信息的屏幕截图。

这表明 Nginx 有两种类型的日志:访问日志和错误日志。 这些存储在 /var/log/nginx/ 目录中。

访问日志类似于 IIS 日志文件。 快速检查内容会显示它们类似于以下屏幕截图。

访问命令的屏幕截图。

访问日志不会显示除已知道的 HTTP 502 响应状态以外的新信息。 还可以通过运行 cat /var/log/nginx/error.log来检查错误日志。 这些揭示了更多的关于问题的原因。

错误信息的屏幕截图。

指示是明确的:Nginx 可以从客户端获取请求,但它无法连接到服务器,http://127.0.0.1:5000也不能连接到upstream该端口上运行和侦听的 ASP.NET Core 应用程序。

解决方法

若要解决此问题,请手动启动 ASP.NET Core 应用程序。 使用第二个终端会话连接到服务器,然后像以前一样运行 ASP.NET Core 应用程序。

aspnet 信息的屏幕截图。

当 ASP.NET Core 应用程序正在运行时,请切换到其他终端会话,然后运行相同的 curl localhost 命令。 现在,可以访问在 Nginx 后面运行的 ASP.NET Core 应用程序。 以下屏幕截图显示你向 localhost 发出请求,该请求由 Nginx 处理,并路由到后端应用程序,并从 ASP.NET Core 应用程序收到响应。

curllocalhost 命令的屏幕截图。

现在,你已将 Nginx 配置为充当在 Linux 中运行的 ASP.NET Core 应用程序的反向代理。

但是,如果 ASP.NET Core 应用程序在重启后未启动,结果会是什么? 如果 Web 应用程序崩溃且在注意到它未运行之前未启动,会发生什么情况? 每次重启进程终止后,是否应启动 ASP.NET Core 应用程序?

后续步骤

第 2.3 部分 - 将 ASP.NET Core 应用程序配置为自动启动

第三方信息免责声明

本文中提到的第三方产品由 Microsoft 以外的其他公司提供。 Microsoft 不对这些产品的性能或可靠性提供任何明示或暗示性担保。