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

nginx+uwsgi 和nginx+gunicorn区别、如何部署,第1张

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

第一种,高并发稳定一点

我在很多的博客中都看过有关 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 中的配置也会有所不同

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

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

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

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

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

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

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

其中 nginxconf 文件为主配置文件,可以用来修改其全局配置; 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 将报错。添加完配置内容并保存为 gconfigpy 文件后,我们就也可以通过 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://wwwcnblogscom/Dicky-Zhang/p/6171954html

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

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

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

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

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

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

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

近日只是为了想尽办法为 Flask 实现 Swagger UI 文档功能,基本上要让 Flask 配合 Flasgger, 所以写了篇 Flask 应用集成 Swagger UI 。然而不断的 Google 过程中偶然间发现了 FastAPI 这么一款集成了 Swagger UI 的更新的 Python Web 框架。起初想要在标题中表达的意思大概是 Flask + Swagger = FastAPI, 后来发现 FastAPI 的闪亮点不仅如此,顺便找了些 Flask 与 FastAPI 对比的文章来,在文后附有链接。

本文不对 Flask 与 FastAPI 的各个方面对进行对比,本人兴趣依然还在 FastAPI 的 Swagger UI 功能,以及与 Flask 的 Blueprint 类似的特性。如果要拿 Flask 与 FastAPI 比较的话,应该用 Flask 2x, 因为它开始支持类似 @appget 的装饰器,并引入了 async 路由函数。

Flask 是在 2010 年发布的,它构建于 WSGI(Python Web Server Gateway Interface) 之上的,产品环境中运行需与 uWSGI, Gunicorn 搭配,或用 mod_wsgi 模块与 Apache 集成。因发布较早,所以目前应该有较多的使用者。Flask 20 需要 Python 36+ 的支持,如果支持 async , 需 Python 37+

FastAPI 发布于 2018 年,构建于 ASGI(Asynchronous Server Gateway Interface) 之上,在 IO 密集型的应用中有更优越的性能。生成环境中配合 ASGI 服务器,如 Uvicorn 或 Hypercorn FastAPI 最为亮丽的特性是集成了 Swagger UI -- 外加一个福利 ReDoc 。FastAPI 需 Python 36+ 版本。

毕竟是在开始学一个新的框架,还是从它的基本用法开始,途中会穿插与 Flask 的对比。

安装:

当前安装的 fastapi 版本为 0701, uvicorn 版本为 0160。开始第一个例子,摘自官方

创建一个 mainpy 文件,内容为

注:以上两个函数前面可以加上 async 关键字

启动服务,用命令

注: uvicorn --help 列出详细帮助,如启动多少个 worker, 绑定网络接口和端口号, 配置 SSL 证书等。

访问服务

另一个服务就是 http://localhost:8000/items/100q=somequery

与 Flask 的对比

回顾一个 Flask 启动服务的方式有

如果程序文件名为 apppy 或 wsgipy 的话,可以省略 FLASK_APP 环境变量,直接执行 flask run 就行。另一种方式就是在代码中加上 main 入口

然后像普通 Python 代码一样执行

对于 FastAPI, 如果总是要用 uvicorn 来启动服务的话,在 IDE 中调用就变得不那么便利。由于 uvicorn 本身就是 Python 实现,当然也就可以把命令过程写到 Python 代码中

注:uvicornrun() 可接受更多的参数,相当于 uvicorn --help 可接受的。

同样把 mainpy 当作普通 Python 程序来启动即可

前面讲过,FastAPI 进入我的视野最首要的一个原因就是它集成了 Swagger UI, 在启动了 FastAPI 服务后,只要访问 http://localhost:8000/docs, 熟悉的 Swagger UI 即刻映入眼帘

同时注意到函数映射为 API 的名称,由于参数是带有类型提示的,所以在 SwaggerUI 中也能看到相应的类型。其他定制 Swagger UI 的工作需要时可细细研究。

FastAPI 除了 SwaggerUI 外,还同时给了我们另一个选择,那就是 redoc, 访问 http://localhost:8000/redoc, 看到下面的界面

我也是头一回从 FastAPI 这里了解到还有一个 Redoc 的 Web API 文档工具,它和 SwaggerUI 类似,都是支持 Open API。

使用 FastAPI 时,在 API 文档中产生请求/响应的 Model 类型也很简单,下面的例子同时包含自定义的输入输出类型

下面是 mainpy 的全新内容

再查看 http://localhost:8000/docs 文档,看到 PUT /items/{item_id} 的界面如下

我们能看到请求与响应中的 Example Value 和 Schema 定义

梳理完 FastAPI 的自动 API 文档功能,进入下一个话题

FastAPI 类似于 Flask 的 Blueprints 功能没有一个特定的名称,只笼统的给出解决方案 Bigger Applications - Multiple Files 我们来看一下它是怎么实现的。这里简化官方的例子,排除了 dependencies 的应用,要用到的目录结构为

每个目录中都可以放一个 __init__py 文件,标识为包,接着是每个文件的内容

app/internal/adminpy

app/routers/itemspy

app/routers/userspy

在每个单独定义路由的文件里用到的是 APIRouter , 它相当是一个迷你的 FastAPI , 也类似于 Flask 的 Blueprint 上面分别演示了两种 APIRouter 的声明方式,声明时带不带 prefix 和 tags。同时在为函数定义路由时也可指定 tags,在后面我们将会注意到 tags 只是为 API 文档分类用的。

app/mainpy

这里实际上使用了三种定义路径前缀与 tags(API 分类) 的方式

现在运行

查看 SwaggerUI http://localhost:8000/docs

到目前为止我重点关注 FastAPI 的就是以上那两个特性:自动 API 文档与大程序多文件(Blueprint) 功能。其他的特性可查阅 FastAPI 的 Features 。比如:

原文 https://yanbinblog/fastapi-new-python-web-framework-vs-flask/

在杜赛的博客中,对Django+Nginx+Gunicorn这三兄弟的描述是这样的:

如果用餐馆来做比喻的话,Nginx 就是迎宾**,客人如果点了酒水,迎宾**自己就帮忙拿了;而 Gunicorn 是传菜员,Django 是厨师,他两一起满足客人对现炒美食的需求。

这个比喻具体是在说什么呢?

首先,我们要分清楚 Web应用 Web服务器 这两个概念。Django开发出来的程序是Web应用,它本身不能起到监听用户请求并响应这种 “收发员” 的功能。监听用户请求并响应是 Web服务器 的职责。

Nginx就是一个 Web服务器 。即使没有web应用运行,只有一大堆 html 静态页面,我们也可以通过配置路由和返回的页面来使用Nginx搞出一个静态网站。

Django开发的Web应用本身是没有和客户端(浏览器)交互的功能的。我们在本地能够运行它是只是因为Django其内置了一个小型Web服务器而已,不过它性能受限,不能用于生产环境。

那么将Nginx和Django组合是不是就大功告吉了呢?没那么简单。Python官方定义了WSGI(Web Server Gateway Interface)作为Web服务器与Python Web应用程序或框架之间的建议标准接口。这样可以提高Web应用程序和服务器之间的可移植性。显然Django需要一个实现WSGI的服务器来和它配合。然而Nginx作为一个普通的http服务器,并没有实现这个接口。

这可以通过两种方式变通:

这里使用的是第二种途径。Gunicorn是一个遵循WSGI的Web服务器。Nginx可以在需要和Django打交道的时候把任务交给Gunicorn处理,而在不需要的时候自己解决就行。在我们的情况下就是 /static 和 /media 这种静态资源由 Nginx 自行快速响应,其他请求通过socket传送给Gunicorn,Gunicorn通过WSGI和Django通信并返回动态响应。这就是为什么说传菜员Gunicorn和厨师Django 他俩一起 满足顾客对现炒美食的需求。

其实Gunicorn本身不需要Nginx的带领也是可以独立运作的,但是它的性能比较差因此不推荐这么做。Gunicorn的 官方文档 也强烈推荐把Gunicorn部署在如Nginx这样的代理服务器的后方,以防止安全问题。

参考好文:

为什么nginx可以直接部署,还要uWSGI,gunicorn等中间件

名字是小明:尝试理解Flask源码 之 搞懂WSGI协议​

DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
网站模板库 » nginx+uwsgi 和nginx+gunicorn区别、如何部署

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情