Flask+uWSGI+nginx的最佳实践设置方法
我正在尝试搭建我的第一个网页服务器,使用的是Flask、uWSGI和nginx这几个工具。我已经成功让Flask和uWSGI这两个部分运行起来了。我还从很多博客上获得了一些关于如何搭建的建议。不过,这些建议并不一致,很多文章提供了不同的搭建方法,特别是在文件夹结构、nginx配置和用户/权限方面(我试过一些建议,确实有用,但我不确定哪种方法最好)。所以,是否有一种基本的“最佳实践”来搭建这个组合呢?
3 个回答
你问的其实不是“最佳实践”,而是“约定”。在这个项目里,没有关于路径、权限等方面的约定。每个系统管理员(或者开发者)都有自己的需求和喜好,所以如果你对现在的设置满意……那就算是“任务完成”了。没有什么uWSGI的大神需要取悦你 :) 显然,发行版提供的包会有它们自己的约定,但这些约定在不同的发行版之间是不同的。
这个内容可以分成两部分,一部分是设置系统本身(也就是操作系统和它的各种路径/文件系统),另一部分是安装和配置组件。
我会重点讲第二部分,因为我觉得这才是你问题的关键:
首先,
nginx
应该通过你操作系统自带的包管理工具来安装。这样可以确保所有的权限设置正确,配置文件也放在你(或其他人)能找到的地方。比如在类似 Debian 的系统(像 Ubuntu 及其各种衍生版)上,配置文件会在/etc/nginx/
目录下,网站配置则是通过在/etc/nginx/sites-available/
目录下添加文件来完成的。此外,这样做还意味着当你的操作系统供应商推送更新时,它们会自动通过你的包管理软件安装。其次,
uWSGI
你应该通过源代码安装;因为它的开发周期非常快,uwsgi
的改进会对你的应用产生积极影响。安装过程很简单,不需要特别的权限,只需要正常的超级用户权限就可以了,这样你就能在系统范围内安装应用。最后是你的应用源文件。对此,我强烈建议为每个应用创建单独的用户角色,并隔离所有权限和相关文件(例如,
uwsgi
生成的日志文件),确保它们都归同一个用户所有。这样可以确保其他应用或用户无法读取错误信息或日志文件,并且一个用户可以拥有所有权限来读取和调试与该应用相关的内容,而不需要使用像sudo
这样的工具。
除了以上提到的三点,实际上让这些组件协同工作是一个标准的过程:
在你的应用中创建 wsgi 进程/处理程序。对于 Flask,默认的 Flask 应用已经提供了这个接口。
使用你的 wsgi 引擎运行这个文件。可以是
uwsgi
、gunicorn
或类似的工具。确保你使用的是二进制协议。将你的静态文件映射到一个由你的网络代理(也就是
nginx
)服务的位置,并创建一个上游服务器,指向 wsgi 进程期望连接的位置。这可以是一个端口或一个管道(具体取决于你如何设置这些组件)。可选 使用像
supervisor
这样的进程管理工具来控制 wsgi 进程,以便在系统重启时自动重启,并且更容易管理。
其他的就看个人喜好了(特别是在文件系统布局方面)。对于大型应用,Flask 的创建者提供了 蓝图,但请注意,他们并没有推荐任何特定的文件系统/目录布局。
作为对任何 Python 包的一般建议,我推荐你查看 这个链接。
nginx + uwsgi + flask 组合起来是个强大的技术栈!我还加上了 supervisor,并且这样配置它。
- 把 uwsgi 和 nginx 都放在 supervisor 里运行,这样可以更好地管理它们的进程。你可以设置让 supervisor 在开机时自动启动,这样它就会按正确的顺序运行 uwsgi 和 nginx。如果它们意外停止,supervisor 还会智能地尝试让它们重新启动。下面是一个 supervisor 配置的示例。
- 如果你在同一台机器上运行 nginx 和 uwsgi,建议使用 unix 套接字,而不是 HTTP。
- 如果你的网页服务器监听的是 80 端口,那么 nginx 的主进程必须以 root 用户身份运行。我通常会把我的网页服务器放在其他端口(比如 8080),然后在前面放一个负载均衡器,让它在 80 端口监听,并把请求转发给 nginx。
- 确保你的 uwsgi 服务器可以读取和写入你选择的套接字文件,同时也要有权限访问任何应用代码和数据目录。
不用太担心你的文件夹结构,特别是如果你使用的是像 Ubuntu 这样的 Linux 发行版,它有合理的默认设置。主要的 supervisor 配置文件可以包含来自子目录的文件,比如 /etc/supervisor/conf.d/
,这样可以把你的应用特定配置和 supervisor 的核心配置分开。nginx 也是一样,只不过是 /etc/nginx/sites-enabled
。
下面是一个 uwsgi 和 nginx 的 supervisor 配置示例:
$ cat /etc/supervisor/conf.d/app.conf
[program:app]
command=/usr/local/bin/uwsgi
--enable-threads
--single-interpreter
--vacuum
--chdir /path/to/app
--uid www-data
--log-syslog
--processes 4
--socket /tmp/app.sock
-w mypython:app
--master
directory=/path/to/app
autostart=true
autorestart=true
priority=999
stopsignal=INT
environment=SOMEVAR=somevalue
[program:nginx]
command=/usr/sbin/nginx
autostart=true
autorestart=true
priority=999
nginx.conf 示例:
$ cat /etc/nginx/sites-enabled/myapp.conf
server {
listen 8080;
client_max_body_size 4G;
server_name localhost;
keepalive_timeout 5;
location / {
include uwsgi_params;
uwsgi_pass unix:///tmp/app.sock;
}
}