使用nginx和uwsgi在Linux上部署falcon

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

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

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

最好以不同于拥有应用程序源代码的操作系统用户的身份执行应用程序。应用程序用户应该 NOT 对源具有写访问权限。这减少了有人可能通过您可能定义的上载端点将恶意python文件写入源目录的可能性;当应用程序重新启动时,会加载恶意文件并继续导致发生任何数量的错误:sup:(tm)。

$ 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_api() 函数或模块级脚本。此函数或脚本的作用是提供 falcon.App 实现了标准的wsgi可调用接口。

你需要暴露 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_api(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 .