有一套部署的常见约定与实践,可能不是每个开发者都知道,但对做过运营的人来说
都是显而易见的。正如在本章引言中所说,即使你不负责代码部署和运营,但了解其中一
点内容也是很重要的,因为这可以让你在开发过程中做出更好的设计决策。
文件系统层次结构
可能出现在你脑海中最显而易见的约定可能就是关于文件系统层次结构和用户命名。如果
你在本书中寻找这方面的建议,那你要失望了。当然,存在一个文件系统层次结构标准
(Filesystem Hierarchy Standard,FHS),它定义了 Unix 和类似 Unix 的操作系统中的目录结构和
目录内容,但很难找到一个真正的 OS 发行版与 FHS 完全兼容。如果系统设计者和程序员都不
能遵守这些标准,那么很难期望系统管理员能够做到这一点。根据我的经验,我见过应用代码
被部署到几乎所有可能的地方,包括根文件系统级别的非标准自定义目录。做出这些决定的人
对这种做法几乎总是有非常强有力的论据。在这件事上,我能给你的唯一建议如下。
● 明智地选择,避免出现意外。
● 在项目所有可用的基础设施中保持一致。
● 尽量在组织内部(你所在的公司)保持一致。
真正有用的是将你的项目约定文档化。只是要记住,要确保每位感兴趣的团队成员都
可以访问这份文档,并且让所有人都知道这份文档的存在。
隔离
第 1 章中已经讨论过隔离的原因以及推荐的工具。对于部署来说,只需要补充一件重要的事情。你应该始终隔离每个应用版本的项目依赖。在实践中,无论何时部署应用的新
版本,你都应该为这个版本创建一个新的隔离环境(使用 virtualenv 或 venv)。旧的
环境应该在主机上保留一段时间,万一出现问题,你可以轻松回滚到应用的某个历史版本。
为每个版本创建新的环境有助于管理其干净的状态,且有助于符合提供的依赖关系列表。
新环境的意思是在文件系统中创建一个新的目录树,而不是更新已经存在的文件。不幸的是,这
可能使执行一些操作更加困难,例如优雅地重新加载服务,如果就地更新环境的话会更容易实现。
使用进程管理工具
我们通常希望远程服务器上的应用永不停止。如果是 web 应用,它的 HTTP 服务器进
程将会无限期地等待新的连接和请求,只有发生不可恢复的错误时才会退出。
当然不可能在 shell 中手动运行它,并保持永不停止的 SSH 连接。使用 nohup、screen
或 tmux 来半守护进程并不是选项之一。这么做就如同服务设计失败。
你需要的是某种进程管理工具,它可以启动并管理你的应用进程。在选择合适的工具
之前,你需要确保它具有以下功能。
● 如果服务退出的话则重启服务。
● 可靠地跟踪其状态。
● 捕获其 stdout/stder 流用于日志。
● 运行具有特定用户/组权限的进程。
● 配置系统环境变量。
大多数 Unix 和 Linux 发行版都有一些用于进程管理的内置工具/子系统,例如 initd
脚本、upstart 和 runit。不幸的是,在大多数情况下,它们并不适合于运行用户级的
应用代码,并且很难维护。编写可靠的 init.d 脚本尤其是一项挑战,因为它需要编写大
量的 Bash 脚本,做好是很难的。一些 Linux 发行版(例如 Gentoo)对 init.d 脚本采用
了重新设计的方法,因此编写要容易得多。不管怎样,只是为了一个进程管理工具就将你
自己局限于特定的操作系统发行版,这不是一个好主意。
在 Python 社区中,管理应用进程的两个常用工具是 Supervisor(http://supervisord.org)
和 Circus(https://circus.readthedocs.org/en/latest/)。它们在配置和使用方面非常相似。Circus
比 Supervisor 要年轻一些,因为创建它就是为了解决后者的一些缺点。它们都可以用简单
的类似 INI 文件的配置格式进行配置。它们不仅可以运行 Python 进程,还可以被配置来管
理任何应用。很难说哪一个更好,因为它们都提供非常相似的功能。
不管怎样,Supervisor 无法在 Python 3 中运行,所以它不会得到我们的祝福。虽然在
Supervisor 的管理下运行 Python 3 进程并不是一个问题,但我将以此为借口,只介绍 Circus
配置的示例。
假设我们想要在 Circus 的管理下使用 gunicorn 网络服务器来运行 webxample 应用
(本章前面介绍过)。在生产环境中,我们可能会在合适的系统级进程管理工具(initd、
upstart 和 runit)下运行 Circus,尤其是从系统包仓库中安装 Circus 的情况。为了简
单起见,我们将在本地虚拟环境中运行。允许我们在 Circus 中运行应用的最小配置文件(这
里的文件名为 circus.ini)如下所示:
[watcher:webxample]
cmd = /path/to/venv/dir/bin/gunicorn webxample.conf.wsgi:application
numprocesses = 1
下面,可以用这个配置文件作为执行参数来运行 circus 进程:
$ circusd circus.ini
2016-02-15 08:34:34 circus[1776] [INFO] Starting master on pid 1776
2016-02-15 08:34:34 circus[1776] [INFO] Arbiter now waiting for commands
2016-02-15 08:34:34 circus[1776] [INFO] webxample started
[2016-02-15 08:34:34 +0100] [1778] [INFO] Starting gunicorn 19.4.5
[2016-02-15 08:34:34 +0100] [1778] [INFO] Listening at:
http://127.0.0.1:8000 (1778)
[2016-02-15 08:34:34 +0100] [1778] [INFO] Using worker: sync
[2016-02-15 08:34:34 +0100] [1781] [INFO] Booting worker with pid: 1781
现在你可以用 circusctl 命令来运行交互式会话,并利用简单的命令来控制所有被
管理的进程。下面是这样的会话示例:
$ circusctl
circusctl 0.13.0
webxample: active
(circusctl) stop webxample
ok
(circusctl) status
webxample: stopped
(circusctl) start webxample
ok
(circusctl) status
webxample: active
当然,上述两种工具都有更多可用的功能。它们的文档中对所有这些功能进行了解释,
所以在做出选择之前,你应该仔细阅读这些内容。
Python 高手编程系列一千零五十五:常见约定与实践
最新推荐文章于 2024-11-04 22:26:34 发布