附录 E:部署故障排除
当应用程序运行时,部署它会让人非常满意,尤其是如果您以前从未这样做过的话。 然而,部署过程中可能会出现许多障碍,不幸的是,其中一些问题可能难以识别和解决。 本附录将帮助您了解现代的部署方法,并为您提供在部署过程出现问题时排除故障的具体方法。
如果本附录中的补充信息不足以帮助您成功完成部署过程,请参阅 https://ehmatthes.github.io/pcc_3e 上的在线资源;那里的更新几乎肯定会帮助您成功完成部署。
了解部署
当你试图排除某个特定部署尝试的故障时,清楚了解典型部署的工作原理会很有帮助。部署是指将在本地系统上运行的项目复制到远程服务器上,使其能够响应互联网上任何用户的请求的过程。远程环境与典型的本地系统有许多重要的不同之处:它可能与你正在使用的操作系统(OS)不同,而且很可能是一台物理服务器上的许多虚拟服务器之一。
部署项目或将其推送到远程服务器时,需要采取以下步骤:
-
在数据中心的物理机上创建虚拟服务器。
-
在本地系统和远程服务器之间建立连接。
-
将项目代码复制到远程服务器。确定项目的所有依赖项,并将其安装到远程服务器上。
-
建立数据库并运行任何现有迁移。
-
将静态文件(CSS、JavaScript 文件和媒体文件)复制到可以有效提供服务的地方。
-
启动服务器处理传入请求。
-
一旦项目准备好处理请求,就开始将接收到的请求路由到项目。
考虑到部署过程中的所有因素,部署经常失败也就不足为奇了。幸运的是,一旦你了解了应该发生什么,你就更有可能找出出错的原因。如果能找出问题所在,就有可能找到修复方法,使下一次部署尝试取得成功。
你可以在一种操作系统上进行本地开发,然后推送到运行不同操作系统的服务器上。知道你要推送到哪种系统非常重要,因为这可以为你的一些故障排除工作提供参考。在撰写本文时,Platform.sh 上的基本远程服务器运行的是 Debian Linux;大多数远程服务器都是基于 Linux 的系统。
基本故障排除
有些故障排除步骤是每个操作系统特有的,但我们稍后会讲到。首先,让我们考虑一下每个人在排除部署故障时都应该尝试的步骤。
在尝试推送过程中生成的输出是最好的资源。这些输出结果可能看起来很吓人;如果你是部署应用程序的新手,它可能看起来技术性很强,而且通常会有很多输出结果。好在你不需要理解输出中的所有内容。在浏览日志输出时,你应该有两个目标:找出任何有效的部署步骤,以及任何无效的步骤。如果能做到这一点,你也许就能找出项目或部署流程中需要改变的地方,从而使下一次推进取得成功。
按照屏幕上的建议进行操作
有时,你要推送的平台会生成一条信息,对如何解决问题提出明确建议。例如,如果在初始化 Git 仓库之前创建 Platform.sh 项目,然后尝试推送该项目,就会看到以下信息:
$ platform push
❶ Enter a number to choose a project:
[0] ll_project (votohz445ljyg)
> 0
❷ [RootNotFoundException]
Project root not found. This can only be run from inside a project directory.
❸ To set the project for this Git repository, run:
platform project:set-remote [id]
我们正在尝试推送一个项目,但本地项目尚未与远程项目关联。因此,Platform.sh CLI 会询问我们要将哪个远程项目推送到 ❶。我们输入 0,选择列出的唯一一个项目。但接下来,我们看到了 RootNotFoundException ❷。出现这种情况是因为 Platform.sh 在检查本地项目时会查找 .git 目录,以确定如何将本地项目与远程项目连接起来。在这种情况下,由于创建远程项目时没有 .git 目录,所以连接从未建立。CLI 提出了一个解决方案❸;它告诉我们可以使用 project:set-remote 命令指定与本地项目关联的远程项目。
让我们试试这个建议:
$ platform project:set-remote votohz445ljyg
Setting the remote project for this repository to: ll_project(votohz445ljyg)
The remote project for this repository is
now set to: ll_project (votohz445ljyg)
在前面的输出中,CLI 显示了这个远程项目的 ID,即 votohz4451jyg。因此,我们使用这个 ID 运行建议的命令,CLI 就能在本地项目和远程项目之间建立连接。
现在,让我们再次尝试推送项目:
$ platform push
Are you sure you want to push to the main (production) branch? [Y/n] y
Pushing HEAD to the existing environment main
--snip--
这是一次成功的推送;按照屏幕上的建议操作奏效了。
在运行不完全了解的命令时应小心谨慎。不过,如果你有充分的理由相信某个命令不会造成什么伤害,而且如果你信任建议的来源,那么尝试一下你正在使用的工具所提供的建议也许是合理的。
请记住,有些人会告诉你运行会清除系统或使系统遭受远程攻击的命令。听从你信任的公司或组织提供的工具的建议,与听从网上随便什么人的建议是不同的。在处理远程连接时,请务必谨慎行事。 |
读取日志输出
如前所述,运行 platform push 等命令时看到的日志输出既能提供信息,又能吓人一跳。请阅读下面的日志输出片段,它来自一次使用 platform push 的不同尝试,看看你能否发现问题所在:
--snip--
Collecting soupsieve==2.3.2.post1
Using cached soupsieve-2.3.2.post1-py3-none-any.whl (37 kB)
Collecting sqlparse==0.4.2
Using cached sqlparse-0.4.2-py3-none-any.whl (42 kB)
Installing collected packages: platformshconfig, sqlparse,...
Successfully installed Django-4.1 asgiref-3.5.2 beautifulsoup
4-4.11.1...
W: ERROR: Could not find a version that satisfies the require
ment gunicorrn
W: ERROR: No matching distribution found for gunicorrn
130 static files copied to '/app/static'.
Executing pre-flight checks...
--snip--
当部署尝试失败时,一个好的策略是查看日志输出,看看是否能发现类似警告或错误的内容。警告是相当常见的;它们通常是关于项目依赖关系中即将发生的变化的信息,以帮助开发人员在问题导致实际失败之前加以解决。
成功的推送可能会有警告,但不应该有任何错误。在本例中,Platform.sh 无法找到安装需求 gunicorrn 的方法。这是 requirements_remote.txt 文件中的一个错字,该文件本应包含 gunicorn(带一个 r)。要从日志输出中找出根本问题并不总是那么容易,尤其是当问题导致一系列连环错误和警告时。就像在本地系统上阅读回溯日志一样,最好仔细查看列出的前几个错误和最后几个错误。中间的大多数错误往往是内部软件包抱怨出了问题,并将错误信息传递给其他内部软件包。我们能修复的实际错误通常是列出的第一个或最后一个错误。
有时,你能发现错误,有时,你却不知道输出结果意味着什么。这当然值得一试,利用日志输出成功诊断出错误会让人感到非常满足。当你花更多时间查看日志输出时,你就能更好地识别对你最有意义的信息。
特定于操作系统的故障排除
你可以在任何你喜欢的操作系统上进行开发,并推送到任何你喜欢的主机上。推送项目的工具已经发展到可以根据需要修改项目,使其在远程系统上正常运行。不过,也会出现一些操作系统特有的问题。
在 Platform.sh 部署过程中,最可能出现的困难之一就是安装 CLI。下面是安装命令
$ curl -fsS https://platform.sh/cli/installer | php
该命令以 curl 开始,它是一种可以让你在终端中通过 URL 请求远程资源的工具。在这里,它被用来从 Platform.sh 服务器下载 CLI 安装程序。命令中的-fsS部分是一组修改curl运行方式的标志。f标志让curl抑制大部分错误信息,这样CLI安装程序就可以处理这些信息,而不是全部报告给你。s标志让curl静默运行,让CLI安装程序决定在终端显示哪些信息。S 标志让 curl 在整个命令失败时显示错误信息。命令末尾的 | php 让系统使用 PHP 解释器运行下载的安装文件,因为 Platform.sh CLI 是用 PHP 编写的。
这意味着系统需要使用 curl 和 PHP 才能安装 Platform.sh CLI。要使用 CLI,还需要 Git 和能运行 Bash 命令的终端。Bash 是一种可在大多数服务器环境中使用的语言。大多数现代系统都有足够的空间来安装类似的多种工具。
下面的章节将帮助你解决操作系统的这些需求。如果尚未安装 Git,请参阅附录 D 第 484 页的 Git 安装说明,然后转到此处适用于你的操作系统的章节。
https://explainshell.com 是了解类似此处所示终端命令的绝佳工具。输入要理解的命令,网站就会显示命令所有部分的文档。用安装 Platform.sh CLI 的命令试试吧。 |
从 Windows 部署
近年来,Windows 再次受到程序员的青睐。Windows 集成了其他操作系统的许多不同元素,为用户提供了许多进行本地开发工作和与远程系统交互的选择。
从 Windows 进行部署的最大困难之一是,Windows 核心操作系统与基于 Linux 的远程服务器所使用的操作系统不同。基础 Windows 系统与基础 Linux 系统拥有不同的工具和语言集,因此要从 Windows 进行部署工作,就需要选择如何将基于 Linux 的工具集集成到本地环境中。
Windows Linux 子系统
一种常用的方法是使用 Windows Subsystem for Linux (WSL),这是一种允许 Linux 直接在 Windows 上运行的环境。如果设置了 WSL,在 Windows 上使用 Platform.sh CLI 就会变得和在 Linux 上一样简单。CLI 不会知道自己是在 Windows 上运行,它只会看到你正在使用它的 Linux 环境。
设置 WSL 有两个步骤:首先安装 WSL,然后选择一个 Linux 发行版安装到 WSL 环境中。设置 WSL 环境的内容比这里描述的要多;如果你对这种方法感兴趣,但还没有设置好,请参阅 https://docs.microsoft.com/en-us/windows/wsl/about 上的文档。设置好 WSL 后,就可以按照本附录 Linux 部分的说明继续部署工作了。
Git Bash
另一种构建本地环境的方法是使用 Git Bash,它是一个与 Bash 兼容但可在 Windows 上运行的终端环境。当你使用 ht tps://git-scm.com 上的安装程序时,Git Bash 会与 Git 一起安装。这种方法可行,但不如 WSL 那样精简。在这种方法中,有些步骤需要使用 Windows 终端,有些则需要使用 Git Bash 终端。
首先需要安装 PHP。您可以使用 XAMPP 进行安装,它是一个将 PHP 与其他一些以开发者为中心的工具捆绑在一起的软件包。访问 https://apachefriends.org,点击按钮下载 XAMPP for Windows。打开并运行安装程序;如果看到有关用户帐户控制 (UAC) 限制的警告,请单击 "确定"。接受安装程序的所有默认设置。
安装程序运行完成后,需要将 PHP 添加到系统路径中;这将告诉 Windows 在运行 PHP 时要查找的位置。在 "开始 "菜单中输入路径,然后单击 "编辑系统环境变量";单击标有 "环境变量 "的按钮。你会看到路径变量高亮显示;单击该窗格下的编辑。单击 "新建",在当前路径列表中添加新路径。假设你在运行 XAMPP 安装程序时保留了默认设置,请在出现的框中添加 C:\xampp\php,然后单击确定。完成后,关闭所有仍打开的系统对话框。
满足这些要求后,就可以安装 Platform.sh CLI 了。您需要使用具有管理员权限的 Windows 终端;在 "开始 "菜单中输入命令,在 "命令提示符 "应用程序下单击 "以管理员身份运行"。在出现的终端中输入以下命令:
> curl -fsS https://platform.sh/cli/installer | php
这将安装 Platform.sh CLI,如前所述。
最后,你将在 Git Bash 中工作。要打开 Git Bash 终端,请在 "开始 "菜单中搜索 git bash。点击出现的 Git Bash 应用程序,就会打开一个终端窗口。你可以在这个终端中使用基于 Linux 的传统命令,如 ls,也可以使用基于 Windows 的命令,如 dir。为确保安装成功,请执行 platform list 命令。你会看到 Platform.sh CLI 中所有命令的列表。从现在起,在 Git Bash 终端窗口中使用 Platform.sh CLI 执行所有部署工作。
从 macOS 部署
macOS 操作系统并非基于 Linux,但两者的开发原理相似。实际上,这意味着你在 macOS 上使用的许多命令和工作流程也能在远程服务器环境中运行。你可能需要安装一些以开发者为中心的资源,以便在本地 macOS 环境中使用所有这些工具。如果在工作过程中出现安装命令行开发工具的提示,请单击 "安装 "以批准安装。
安装 Platform.sh CLI 时最可能遇到的困难是确保已安装 PHP。如果出现找不到 php 命令的提示,则需要安装 PHP。安装 PHP 的最简单方法之一是使用 Homebrew 软件包管理器,它可以安装程序员依赖的各种软件包。如果尚未安装 Homebrew,请访问 https://brew.sh 并按照说明安装。
安装好 Homebrew 后,使用以下命令安装 PHP:
$ brew install php
运行需要一些时间,但一旦运行完成,就可以成功安装 Platform.sh CLI。
从 Linux 部署
由于大多数服务器环境都基于 Linux,因此安装和使用 Platform.sh CLI 不会有太大困难。如果你尝试在刚刚安装了 Ubuntu 的系统上安装 CLI,它会准确地告诉你需要哪些软件包:
$ curl -fsS https://platform.sh/cli/installer | php
Command 'curl' not found, but can be installed with:
sudo apt install curl
Command 'php' not found, but can be installed with:
sudo apt install php-cli
实际输出结果将包含更多有关其他几个可用软件包的信息,以及一些版本信息。下面的命令将安装 curl 和 PHP:
$ sudo apt install curl php-cli
运行此命令后,Platform.sh CLI 安装命令应能成功运行。由于您的本地环境与大多数基于 Linux 的托管环境非常相似,因此您所学到的有关在终端中工作的大部分知识也将用于在远程环境中工作。
其他部署方法
如果 Platform.sh 不适合你,或者你想尝试不同的方法,有许多托管平台可供选择。有些平台的工作方式与第 20 章中描述的过程类似,而有些平台在执行本附录开头所述步骤时采用的方法则大相径庭:
Platform.sh允许你使用浏览器执行我们使用CLI执行的步骤。如果你更喜欢基于浏览器的界面,而不是基于终端的工作流程,那么你可能更喜欢这种方法。
还有一些托管服务提供商同时提供基于 CLI 和浏览器的方法。其中一些提供商在浏览器中提供终端,因此你无需在系统上安装任何东西。
有些提供商允许你将项目推送到 GitHub 等远程代码托管网站,然后将 GitHub 仓库连接到托管网站。然后主机就会从 GitHub 抓取你的代码,而不需要你将代码从本地系统直接推送到主机。Platform.sh 也支持这种工作流程。
有些提供商会提供一系列服务供你选择,以便组合出适合你项目的基础设施。这通常需要你对部署流程有更深入的了解,以及远程服务器需要什么才能为项目提供服务。这些主机包括亚马逊网络服务(AWS)和微软的 Azure 平台。在这类平台上跟踪成本可能要困难得多,因为每项服务都可以独立计费。
许多人将项目托管在虚拟专用服务器(VPS)上。在这种方法中,你租用的虚拟服务器就像一台远程计算机,登录服务器,安装运行项目所需的软件,复制代码,设置正确的连接,然后让服务器开始接受请求。
新的托管平台和托管方式会定期出现;找到一个对你有吸引力的托管平台,并花时间学习该提供商的部署流程。保持你的项目足够长的时间,这样你就能知道什么能与你的提供商的方法很好地配合,什么不能。没有一个托管平台是完美无缺的;你需要不断判断你目前使用的提供商对你的使用情况是否足够好。
关于部署平台和整体部署方法的选择,我想最后提醒大家一句。有些人会热情地引导你使用过于复杂的部署方法和服务,这些方法和服务的目的是使你的项目高度可靠,能够同时为数百万用户提供服务。许多程序员花费大量时间、金钱和精力构建复杂的部署策略,却发现几乎没有人使用他们的项目。大多数 Django 项目都可以设置在小型托管计划上,并调整为每分钟服务数千个请求。如果您的项目流量低于这个水平,那么在投资世界上最大网站的基础架构之前,请花时间配置您的部署,使其在最小的平台上运行良好。
部署工作有时极具挑战性,但当您的上线项目运行良好时,也同样令人满意。享受挑战,并在需要时寻求帮助。