nginx+uwsgi和nginx+gunicorn区别、如何部署

author author     2023-02-15     179

关键词:

参考技术A

大家是采用的何种部署方式?

第一种,高并发稳定一点

我在很多的博客中都看过有关 Flask 应用的部署,也有很多博主在开博后都记录了部署的教程,因为其中的坑可以说不少。一开始我在网上看到相比较与 Ubuntu , CentOS 因为更新少作为服务器的操作系统会更加稳定。所以在第一次购买云服务器时,我选择了 CentOS ,后来由于 CentOS 不同发行版的 Nginx 缘故,我又换成了 Ubuntu 的镜像

首先呢,我们先来了解下关于Web服务器与Web应用还有WSGI之间的联系

WSGI (Web Server Gateway Interface),翻译为 Python web 服务器网关接口,即 Python 的 Web 应用程序(如 Flask )和 Web 服务器(如 Nginx )之间的一种通信协议。也就是说,如果让你的 Web 应用在任何服务器上运行,就必须遵循这个协议。

那么实现 WSGI 协议的web服务器有哪些呢?就比如 uWSGI 与 gunicorn 。两者都可以作为Web服务器。可能你在许多地方看到的都是采用 Nginx + uWSGI (或 gunicorn )的部署方式。实际上,直接通过 uWSGI 或 gunicorn 直接部署也是可以让外网访问的,那你可能会说,那要 Nginx 何用?别急,那么接来下介绍另一个Web服务器—— Nginx

Nginx 作为一个高性能Web服务器,具有负载均衡、拦截静态请求、高并发...等等许多功能,你可能要问了,这些功能和使用 Nginx + WSGI 容器的部署方式有什么关系?

首先是负载均衡,如果你了解过 OSI模型 的话,其实负载均衡器就是该模型中4~7层交换机中的一种,它的作用是能够仅通过一个前端唯一的URL访问分发到后台的多个服务器,这对于并发量非常大的企业级Web站点非常有效。在实际应用中我们通常会让 Nginx 监听(绑定) 80 端口,通过多域名或者多个location分发到不同的后端应用。

其次是拦截静态请求,简单来说, Nginx 会拦截到静态请求(静态文件,如图片),并交给自己处理。而动态请求内容将会通过 WSGI 容器交给 Web 应用处理;

Nginx 还有其他很多的功能,这里便不一一介绍。那么前面说了,直接通过 uWSGI 或 gunicorn 也可以让外网访问到的,但是鉴于 Nginx 具有高性能、高并发、静态文件缓存、及以上两点、甚至还可以做到限流与访问控制,所以选择 Nginx 是很有必要的;

这里可以说明,如果你选择的架构是:Nginx + WSGI容器 + web应用,WSGI容器相当于一个中间件;如果选择的架构是uWSGI + web应用,WSGI容器则为一个web服务器

普遍的部署方式都是通过让 Nginx 绑定 80 端口,并接受客户端的请求将动态内容的请求反向代理给运行在本地端口的 uWSGI 或者 Gunicorn ,所以既可以通过 Nginx + uWSGI 也可以通过 Nginx + Gunicorn 来部署 Flask 应用,这篇教程中都将一一介绍这两种方法

当然采用不同的 WSGI 容器, Nginx 中的配置也会有所不同

我们现在虚拟环境下安装好 uWSGI :

安装完成之后我们在项目的目录下(即你实际创建的Flask项目目录,在本文所指的项目目录都假设为/www/demo)创建以 .ini 为扩展名的配置文件。在设置与 Nginx 交互的时候有两种方式:
第一种是通过配置网络地址,第二种是通过本地的 .socket 文件进行通信。需要注意的是,不同的交互方式下, Nginx 中的配置也会有所不同

如果采用的是第一种网络地址的方式,则将之前创建 uwsgi.ini 配置文件添加如下的配置内容:

这里的 wsgi-file 参数所指的 run.py 其实是启动文件,你也可以使用 manage.py 。不过我通常习惯创建一个这样的文件,可以直接运行该文件来启动项目:

保存好配置文件后,就可以通过如下的命令来启动应用了:

如果你采用的是第二种本地 socket 文件的方式,则添加如下的配置内容:

可以看到,其实与网络地址的配置方式只有 socket 参数的配置不同,在这里填写好路径名和文件名并启动 uWSGI 后,将会自动在改目录下生成 nginx_uwsgi.socket 文件,这个文件就是用来与 Nginx 交互的。

首先我们来通过 apt 安装 Nginx :

安装完成之后,我们 cd 到 /etc/nginx/ 的目录下(可能由于不同系统导致不同的Nginx发行版缘故,目录有所差别,在此只针对 Ubuntu 中的发行版的Nginx),可以看到 Nginx 的所有配置文件。

其中 nginx.conf 文件为主配置文件,可以用来修改其全局配置; sites-available 存放你的配置文件,但是在这里添加配置是不会应用到 Nginx 的配置当中,需要软连接到同目录下的 sites-enabled 当中。但是在我实际操作的过程中中,当我在 sites-available 修改好配置文件后,会自动更新到 sites-enabled 。如果没有的话,则需要像上述的操作那样,将修改好的配置文件 软链接 到 sites-enabled 当中

在上边说到,配置 uWSGI 有两种与 Nginx 交互的方式,那么选择不同的方式的话在 Nginx 的配置也会有所不同:

第一种:网络配置方式

这里的 proxy_set_header 设置的三个参数的作用都是能够直接获得到客户端的 IP ,如果你感兴趣可以参考: Nginx中proxy_set_header 理解

用 include uwsgi_params 导入 uWSGI 所引用的参数,通过 uwsgi_pass 反向代理给在 localhost:8001 运行的 uWSGI :

在每次完Nginx配置文件内容后,需要通过如下的命令来重启Nginx:

第二种:socket文件方式

与上边的配置内容大体相同,只是在配置 uwsgi_pass 不是反向代理给网络地址,而是通过 socket 文件进行交互,我们只需要指定之前设置的路径和文件名即可:

首先先在虚拟环境下安装 Gunicorn :

安装完成后,我们来创建以 .py 结尾的配置文件,这里我参考了Jiyuankai的 GitHub 关于 Gunicorn 的配置文件内容:

需要注意的是要在配置文件的同层目录下创建 log 文件,否则运行 gunicorn 将报错。添加完配置内容并保存为 gconfig.py 文件后,我们就也可以通过 gunicorn 来运行 Flask 应用了:

和 uWSGI 的任意一种配置方法类似,只是在 location 中的配置有所不同:

通过Gunicorn的Nginx配置中,我们只需要通过 proxy_pass 参数反向代理给运行在 http://localhost:5000/ 上的Gunicorn

如果你采取如上的任意一种部署方式,在Nginx与uWSGI或Gunicorn同时运行,并且配置无误的状态下,那么你现在应该是可以通过你的公网 ip 或者域名访问到你的网站了。

但是还有一个问题,到目前为止,uWSGI和gunicorn都是直接通过命令行运行,并不能够在后台运行,也是当我们关闭了xShell(或者你使用的是Putty及其他SSH连接的软件),将无法再访问到你的应用。所以我们需要让uWSGI或gunicorn在后台运行,也就是所谓的daemon(守护进程)。

如果你熟悉Linux命令,你应该知道在Linux中后台运行可以通过 nohup 命令,例如我们要让gunicorn在后台运行,我们只需要运行 nohup 命令:

运行后你可以通过 ps -e | grep gunicorn 指令来查看到当前gunicorn的运行状态:

如果你选择的是uWSGI,同样也可以通过 nohup 命令来实现守护进程:

这样你就可以关闭连接服务器的终端,还能通过你的浏览器访问到你的 Flask 应用了!

但是 nohup 运行的后台程序并不能够可靠的在后台运行,我们最好让我们的后台程序能够监控进程状态,还能在意外结束时自动重启,这就可以使用一个使用Python开发的进程管理程序supervisor。
参考: https://www.cnblogs.com/Dicky-Zhang/p/6171954.html

首先我们通过 apt 来安装supervisor:

安装完成后,我们在 /etc/supervisor/conf.d/ 目录下创建我们控制进程的配置文件,并以.conf结尾,这样将会自动应用到主配置文件当中,创建后添加如下的配置内容:

在上面的配置文件中, [program:demo] 设置了进程名,这与之后操作进程的状态名称有关,为 demo ; command 为进程运行的命令,必须使用绝对路径,并且使用虚拟环境下的 gunicorn 命令; user 指定了运行进程的用户,这里设置为 root

保存配置文件之后,我们需要通过命令来更新配置文件:

命令行将显示: demo: added process group ,然后我们来启动这个 demo 进程:

当然你也直接在命令行输入 supervisorctl 进入supevisor的客户端,查看到当前的进程状态:

通过 stop 命令便可以方便的停止该进程:

Nginx 和 uWSGI 的内部服务器错误

】Nginx和uWSGI的内部服务器错误【英文标题】:InternalServerErrorwithNginxanduWSGI【发布时间】:2015-09-2217:51:38【问题描述】:我正在尝试在Linode.com上使用Nginx托管一个应用程序,但我在uWSGI配置上遇到了早期问题。我使用了"GettingStarted... 查看详情

Django+Nginx+uWSGI = 504 网关超时

】Django+Nginx+uWSGI=504网关超时【英文标题】:Django+Nginx+uWSGI=504GatewayTime-out【发布时间】:2011-10-0401:33:00【问题描述】:我正在运行Ubuntu10.04、Django1.3、Nginx0.8.54和uWSGI0.9.7。Nginx和uWSGI都可以正常加载。但是,当您访问我的网站时,... 查看详情

在 Nginx 和 UWSGI 中使用 GeoIP 模块

】在Nginx和UWSGI中使用GeoIP模块【英文标题】:UsingtheGeoIPmodulewithNginxandUWSGI【发布时间】:2012-11-2211:48:24【问题描述】:我正在尝试集成这个模块,但它有点超出我的能力:http://wiki.nginx.org/HttpGeoipModule在我的nginx配置中,我有这个... 查看详情

带有 Nginx 和 uWSGI 的 Django CDN

】带有Nginx和uWSGI的DjangoCDN【英文标题】:DjangoCDNwithNginxanduWSGI【发布时间】:2017-04-1822:58:58【问题描述】:我在使用Django1.10、uWSGI和Nginx提供静态文件时遇到困难。我有一个index.html文件,其中包含CDN。Django文档here说“将静态文... 查看详情

连接 Nginx 和 Django

】连接Nginx和Django【英文标题】:ConnectingNginxandDjango【发布时间】:2018-10-0815:52:52【问题描述】:这是我第一次在Nginx工作。我知道为了轻松连接Django和Nginx,我需要uWSGI。设置uWSGI:我认为我的uWSGI设置完全没问题,我用它在HTTP... 查看详情

NGINX 与 uwsgi 和 django 连接被拒绝

】NGINX与uwsgi和django连接被拒绝【英文标题】:NGINXwithuwsgianddjangoconnectionrefused【发布时间】:2015-04-3001:34:01【问题描述】:欢迎***ers。我一直在努力用django应用程序用uwsgi设置nginx......某处必须有一个小错误,但我找不到它。这是... 查看详情

nginx和uwsgi服务器中的uwsgi模块的区别

】nginx和uwsgi服务器中的uwsgi模块的区别【英文标题】:differencebetweenuwsgimoduleinnginxanduwsgiserver【发布时间】:2014-01-0417:12:29【问题描述】:我是linux开发的新手。我对阅读的文档有点困惑。我的最终目标是托管一个简单的python支持... 查看详情

我应该为 Flask、uWSGI 和 nginx 提供单独的容器吗?

】我应该为Flask、uWSGI和nginx提供单独的容器吗?【英文标题】:ShouldIhaveseparatecontainersforFlask,uWSGI,andnginx?【发布时间】:2017-11-1521:47:12【问题描述】:我打算使用Kubernetes和Ingress进行负载平衡。我正在尝试学习如何设置Flask、uWSGI... 查看详情

Nginx 连接重置,uWsgi 的响应丢失

】Nginx连接重置,uWsgi的响应丢失【英文标题】:Nginxconnectionreset,responsefromuWsgilost【发布时间】:2011-04-2714:18:52【问题描述】:我有一个通过Nginx和uWsgi托管的django应用程序。在某个非常简单的请求中,我得到了GET和POST的不同行为... 查看详情

Nginx中uwsgi_pass和proxy_pass的区别?

】Nginx中uwsgi_pass和proxy_pass的区别?【英文标题】:Differencebetweenuwsgi_passandproxy_passinNginx?【发布时间】:2016-04-0609:18:51【问题描述】:我在Nginx后面运行uWSGI,并且一直在使用proxy_pass让Nginx访问uWSGI。切换到uwsgi_pass有什么好处。如... 查看详情

如何避免使用 Django、nginx 和 uWSGI 将环境变量放到多个地方?

】如何避免使用Django、nginx和uWSGI将环境变量放到多个地方?【英文标题】:HowtoavoidputtingenvironmentvariablesintomultipleplaceswithDjango,nginxanduWSGI?【发布时间】:2014-07-0311:18:24【问题描述】:我正在尝试配置nginx+uWSGI来为我的Django应用程... 查看详情

在 Docker 上使用 Nginx、uWSGI 和 Postgres 配置 Django

】在Docker上使用Nginx、uWSGI和Postgres配置Django【英文标题】:ConfiguringDjangowithNginx,uWSGIandPostgresonDocker【发布时间】:2016-04-1123:44:30【问题描述】:我正在尝试使用Nginx、uWSGI和Postgres在Docker上设置Django应用程序。我找到了这篇关于为... 查看详情

nginx,wsgi,uwsgi区别

web开发必须要有web服务器nginx是web服务器wsgi是web的服务协议web开发必须要遵守uwsgi是python开发web和融合框架的web服务器为什么还要存在nginx uwsgi对访问量又要求,过高的访问量会崩掉所以需要nginx服务器做负载均衡。  查看详情

nginx uwsgi 和 cgi python 脚本

】nginxuwsgi和cgipython脚本【英文标题】:nginxuwsgiandcgipythonscript【发布时间】:2012-04-2019:22:47【问题描述】:我遇到了问题。我有一个python脚本。您可以将其称为CGI脚本。它在Apache2下工作正常,但在我关闭系统之前只剩下一个它永... 查看详情

Nginx+uWSGI+Django 在大请求正文和过期会话时返回 502

】Nginx+uWSGI+Django在大请求正文和过期会话时返回502【英文标题】:Nginx+uWSGI+Djangoarereturning502whenbigrequestbodyandexpiredsession【发布时间】:2017-05-1105:04:13【问题描述】:我有一个Django视图,它处理随机大小的POST请求(介于20char到30kcha... 查看详情

使用 uwsgi 和 nginx 运行 Flask 应用程序

】使用uwsgi和nginx运行Flask应用程序【英文标题】:RunningFlaskappwithuwsgiandnginx【发布时间】:2016-01-1917:07:51【问题描述】:我正在关注配置nginxuwsgi以服务于烧瓶应用程序的数字海洋教程。DigitalOceanTuttoriallink我已经为启动我的应用... 查看详情

Django 频道和 uWSGI

...时间】:2019-02-1503:33:17【问题描述】:我目前使用docker、nginx、uWSGI、redis、Django和Angular开发的Djangorestapi。我正在添加几个websocket端点,我想保留现有架构并继续通过uWSGI和nginx服务http请求。并使用Django通道(使用nginx)进行网络... 查看详情

nginx与uwsgi详解(代码片段)

什么是nginxnginx是一个开源的,支持高性能,高并发的代理服务软件nginx不但是一个优秀的web服务软件,还可以作为反想代理和负载均衡,以及缓存服务或使用为什么使用nginx支持高并发,能支持几万个并发链接资源消耗少,三万并发编程... 查看详情