使用nginx和uwsgi在Linux上部署falcon

nginx是一个功能强大的Web服务器和反向代理,uwsgi是一个快速且高度可配置的wsgi应用服务器。nginx和uwsgi一起创建了一个一二冲头的速度和功能,将满足大多数应用。此外,此堆栈为水平可伸缩和高可用性(HA)生产环境提供了构建块,下面的配置只是一个起点。

本指南仅提供部署到Linux环境的说明。但是,通过一些努力,您应该能够将此配置适应其他操作系统,如OpenBSD。

以其他用户身份运行应用程序

最好是以不同的操作系统用户身份执行应用程序,而不是以拥有应用程序源代码的用户身份执行。应用程序用户应该 NOT 对您的源具有写入权限。这降低了有人通过您可能定义的上载端点将恶意Python文件写入您的源目录的可能性;当您的应用程序重新启动时,恶意文件将被加载,并继续导致任意数量的Bad Things™发生。

$ useradd myproject --create-home
$ useradd myproject-runner --no-create-home

切换到项目用户(myproject)并使用主目录作为应用程序环境是很有帮助的。

如果您在远程服务器上工作,请切换到MyProject用户并下拉应用程序的源代码。

$ git clone git@github.com/myorg/myproject.git /home/myproject/src

备注

您可以使用tarball、zip文件、scp或任何其他方法将源文件放到服务器上。

接下来,创建一个可用于安装依赖项的虚拟环境。

$ python3 -m venv /home/myproject/venv

然后安装依赖项。

$ /home/myproject/venv/bin/pip install -r /home/myproject/src/requirements.txt
$ /home/myproject/venv/bin/pip install -e /home/myproject/src
$ /home/myproject/venv/bin/pip install uwsgi

备注

创建虚拟环境的确切命令可能会因所使用的Python版本和操作系统的不同而有所不同。最后,应用程序需要在/home/myproject/venv中安装virtualenv,并安装项目依赖项。使用 pip 虚拟环境中的二进制文件 source venv/bin/activate 或者使用完整路径。

准备您的服务申请

出于本教程的目的,我们假设您已经实现了一种配置应用程序的方法,例如使用 create_app() 函数或模块级脚本。此函数或脚本的作用是提供 falcon.App ,它实现了标准的WSGI Callable接口。

你需要暴露 falcon.App 以某种方式举例,以便Uwsgi可以找到它。对于本教程,我们建议创建 wsgi.py 文件。修改以下示例文件的逻辑以正确配置应用程序。确保公开一个名为 application 分配给您的 falcon.App 实例。

/home/myproject/src/wsgi.py
import os
import myproject

# Replace with your app's method of configuration
config = myproject.get_config(os.environ['MYPROJECT_CONFIG'])

# uWSGI will look for this variable
application = myproject.create_app(config)

请注意,在上面的示例中,wsgi可调用文件只是简单地分配给一个变量, application 而不是被传递到一个自托管的wsgi服务器,例如 wsgiref.simple_server.make_server .在您的 wsgi.py 文件将呈现意外结果。

在UWSGI后面部署Falcon

与您的 wsgi.py 文件就位,是时候配置UWSGI了。首先创建一个简单的 uwsgi.ini 文件。通常,您不应该将此文件提交到源代码管理;它应该由部署工具链根据目标环境(CPU数量等)从模板生成。

执行此配置时,将创建一个由您的 wsgi.py 文件和监听 127.0.0.1:8080 .

/home/myproject/src/uwsgi.ini
[uwsgi]
master = 1
vacuum = true
socket = 127.0.0.1:8080
enable-threads = true
thunder-lock = true
threads = 2
processes = 2
virtualenv = /home/myproject/venv
wsgi-file = /home/myproject/src/wsgi.py
chdir = /home/myproject/src
uid = myproject-runner
gid = myproject-runner

备注

线程与进程

在决定如何管理实际运行Python代码的进程时,需要考虑许多问题。您通常是CPU绑定还是IO绑定?您的应用程序线程安全吗?你有多少个CPU?你用的是什么系统?是否需要进程内缓存?

这里介绍的配置同时支持线程和进程。但是,您必须进行一些实验和研究,以了解您的应用程序的独特需求,然后相应地定制您的uwsgi配置。一般来说,uwsgi足够灵活,可以支持大多数类型的应用程序。

备注

TCP与Unix套接字

nginx和uwsgi可以通过普通TCP(使用IP地址)或Unix套接字(使用套接字文件)进行通信。TCP套接字更容易设置,通常用于简单的部署。如果您想更好地控制哪些进程、用户或组可以访问uwsgi应用程序,或者您正在寻找一点速度提升,请考虑使用unix套接字。uwsgi可以自动删除权限 chmod-socket 和切换用户 chown-socket .

这个 uidgid 如上所示,设置对于确保部署的安全至关重要。这些值控制服务器将用于执行应用程序的操作系统级用户和组。指定的OS用户和组不应具有对源目录的写入权限。在这种情况下,我们使用 myproject-runner 以前为此目的创建的用户。

现在您可以这样启动Uwsgi:

$ /home/myproject/venv/bin/uwsgi -c uwsgi.ini

如果一切顺利,您应该看到如下情况:

*** Operational MODE: preforking+threaded ***
...
*** uWSGI is running in multiple interpreter mode ***
...
spawned uWSGI master process (pid: 91828)
spawned uWSGI worker 1 (pid: 91866, cores: 2)
spawned uWSGI worker 2 (pid: 91867, cores: 2)

备注

注意uwsgi日志始终是一个好主意,因为它们将包含异常和来自应用程序的其他信息,这些信息有助于揭示意外行为。

连接nginx和uwsgi

虽然Uwsgi可以直接为HTTP请求提供服务,但使用反向代理(如nginx)可以帮助卸载TLS协商、静态文件服务等。

nginx本机支持 the uwsgi protocol ,以便有效地将请求代理到uwsgi。按照nginx的说法,我们将创建一个“上游”并将其(通过TCP套接字)引导到我们现在运行的uwsgi应用程序。

在继续之前,根据 the instructions for your platform .

然后,创建一个nginx conf文件,如下所示:

/etc/nginx/Sites-Available/myproject.conf
server {
  listen 80;
  server_name myproject.com;

  access_log /var/log/nginx/myproject-access.log;
  error_log  /var/log/nginx/myproject-error.log  warn;

  location / {
    uwsgi_pass 127.0.0.1:8080
    include uwsgi_params;
  }
}

最后,启动(或重启)nginx:

$ sudo service start nginx

现在应该有一个有效的应用程序了。如果应用程序没有启动,请检查Uwsgi和nginx日志中的错误。

进一步考虑

我们没有解释如何为nginx配置tls(https),将其作为一个练习留给读者。但是,我们确实建议使用let's encrypt,它提供免费的短期证书和自动续订。访问 Let’s Encrypt site 了解如何将他们的服务直接与nginx集成。

除了设置nginx和uwsgi来运行应用程序外,您当然还需要部署数据库服务器或应用程序所需的任何其他服务。由于在这一领域有多种选择和考虑,我们选择不在本指南中包括辅助服务。但是,Falcon社区总是乐于帮助解决部署问题,因此 please don't hesitate to ask .