【实战学习(五)】开源项目学习之uWSGI的部署以及配合nginx



涉及开源项目(dailyfresh-B2C)的部署架构如下:
部署框架



1)uWSGI是什么?

uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http等协议。这样我们可以不再关注网络通信的底层实现,将精力更多放在处理HTTP请求数据,返回HTML。

主要特点

  • 超快的性能
  • 低内存占用(实测为apache2的mod_wsgi的一半左右)
  • 多app管理
  • 详尽的日志功能(可以用来分析app性能和瓶颈)
  • 高度可定制(内存大小限制,服务一定次数后重启等)

所以在uwsgi协议的基础上,配合nginx来做python(类如django的框架)的web项目部署就很常见了。

1.1 WSGI

WSGI(Web Server Gateway Interface)即Web服务器网关接口,是一个规范协议,定义了Web服务器如何与Python应用程序进行交互,使得使用Python写的Web应用程序可以和Web服务器对接起来。只要遵照协议,WSGI应用(Application)都可以在任何服务器(Server)上运行, 反之亦然。WSGI标准在 PEP 333 中定义并被许多框架实现,其中包括现广泛使用的django框架。

很多框架都自带了 WSGI server ,比如 Flask,webpy,Django、CherryPy等等。当然性能都不好,自带的 web server 更多的是测试用途,发布时则使用生产环境的 WSGI server或者是联合 nginx 做 uwsgi 。


在WSGI中定义了两个角色,Web服务器端称为server或者gateway,应用程序端称为application或者framework(因为WSGI的应用程序端的规范一般都是由具体的框架来实现的)。

server端会先收到用户的请求,然后会根据规范的要求调用application端,调用的结果会被封装成HTTP响应后再发送给客户端。如下图所示:
在这里插入图片描述

要使用WSGI,需要分别实现server角色和application角色:

1.1.1 Application端

Application端的实现一般是由Python的各种框架来实现的,比如Django, web.py等,一般开发者不需要关心WSGI的实现,框架会会提供接口让开发者获取HTTP请求的内容以及发送HTTP响应。

1.1.2 Server端

一般常用的Web服务器,如Apache和nginx,都不会内置WSGI的支持,而是通过扩展来完成。

比如Apache服务器,会通过扩展模块mod_wsgi来支持WSGI。Apache和mod_wsgi之间通过程序内部接口传递信息,mod_wsgi会实现WSGI的server端、进程管理以及对application的调用。

Nginx上一般是用proxy的方式,用nginx的协议将请求封装好,发送给应用服务器,比如uWSGI,应用服务器会实现WSGI的服务端、进程管理以及对application的调用。】

1.1.3 WSGI中间件

所谓的 WSGI中间件同时实现了API的两方,因此可以在WSGI服务和WSGI应用之间起调解作用:从WSGI服务器的角度来说,中间件扮演应用程序,而从应用程序的角度来说,中间件扮演服务器。

“中间件”组件可以执行以下功能:

  • 重写环境变量后,根据目标URL,将请求消息路由到不同的应用对象。
  • 允许在一个进程中同时运行多个应用程序或应用框架。
  • 负载均衡和远程处理,通过在网络上转发请求和响应消息。
  • 进行内容后处理,例如应用XSLT样式表。

1.2 uwgi

uwsgi协议是一个uWSGI服务器自有的协议,它用于定义传输信息的类型(type of information),每一个uwsgi packet前4byte为传输信息类型描述,它与WSGI相比是两样东西。

uwsgi是一种线路协议而不是通信协议,在此常用于在uWSGI服务器与其他网络服务器的数据通信。

1.3 uWSGI、WSGI、uwsgi之间的关系

实现过程图解
用户从网页浏览器中发出请求,nginx 服务器收到请求后,会通过它的 uwsgi 模块将用户的请求转发给 uWSGI 服务器,uWSGI 服务器通过django处理完毕后将结果返回给 nginx,浏览器将最终的结果展现给用户。

  • WSGI就像是一座桥梁,一边连着web服务器,另一边连着用户的应用。
  • uWSGI 所扮演的的角色是后端 http 服务器,nginx 扮演的角色是前端 http 服务器,django项目是客户所真正要访问到的提供数据方。

*为什么有了uWSGI为什么还需要nginx?

因为nginx具备优秀的静态内容处理能力,然后将动态内容转发给uWSGI服务器,这样可以达到很好的客户端响应。

利用uWIGS可以使web应用得到更强的并发能力。
虽然uWIGS也可以返回静态文件(css,js,img…),但是很笨拙,一般静态文件都交由Nginx进行传输,所以配置中一般不配置static-map。如果直接由uWIGS接受HTTP请求则需要设置http:xxxx,如果只需要与反向代理服务器进行交互则只需要接受socket。


uWIGS与Nginx交互相当于两个进程间交互,一般使用的是.sock文件或者指定端口接受socket。指定端口时再使用浏览器访问相应端口,uWIGS会提示skip,跳过该HTTP请求。
————————————————
版权声明:本文为CSDN博主「shu_8708」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/shu_8708/article/details/79068581

Nginx中HttpUwsgiModule的作用是与uWSGI服务器进行交换。

2)连接uwsgi和Django

*避坑之Windows10安装uWSGI非常极其艰难,最好勿浪费时间,直接转战Linux吧:

原本是想说在windows上玩六了再去Linux浪,没想到栽到uWSGI上了:

- 用pip安装uwsgi出现报错:AttributeError: module 'os' has no attribute 'uname'

然后在网上查看了很多方法和资料,最后看到https://www.cnblogs.com/luo630/p/9031756.html 时决定放弃,还是默默转战Linux了。于是这几天一直在Linux重新之前在windows上的操作,具体操作已经补充到前面的《实战学习》的(二)至(四)了!

回到正题:

2.1 uWGI部署

基于nginx和uwsgi部署django,从客户端发起请求到服务器响应请求,会经过一下几个环节:

在这里插入图片描述

2.1.1 在虚拟环境下安装uwsgi:

(dailyfresh) he@he-ThinkPad-X200:~$ pip install uwsgi
Collecting uwsgi
  Downloading uWSGI-2.0.19.1.tar.gz (803 kB)
     |████████████████████████████████| 803 kB 314 kB/s 
Building wheels for collected packages: uwsgi
  Building wheel for uwsgi (setup.py) ... done
  Created wheel for uwsgi: filename=uWSGI-2.0.19.1-cp37-cp37m-linux_x86_64.whl size=6034865 sha256=4aaef524c267d129df2d6d42d801c469f02284fba3bc99556017b2fc1ec76314
  Stored in directory: /home/he/.cache/pip/wheels/0c/f9/df/fb7fb12204a8f5c67682f31e10485863c24123a2a626e71203
Successfully built uwsgi
Installing collected packages: uwsgi
Successfully installed uwsgi-2.0.19.1
(dailyfresh) he@he-ThinkPad-X200:~$ uwsgi --version
2.0.19.1

2.1.2 测试uWSGI的运行

即测试 web client <–> uWSGI <–> Python 是否通:

  • 先(vim test-uwsgi.py)编写一个简单的python脚本:
def application(env,start_response):
    start_response('200 OK',[('Content-Type','text/html')])
    return [b"Hello!"]
  • 运行后 ,访问web服务器8083端口(localhost:8083),可以正常显示脚本中返回的文本。

  • ctrl+c可中止程序

(dailyfresh) he@he-ThinkPad-X200:~$ uwsgi --http :8083 --wsgi-file test-uwsgi.py  # 运行uwsgi服务,在8083端口上开放web访问
*** Starting uWSGI 2.0.19.1 (64bit) on [Mon Apr 26 21:21:11 2021] ***
compiled with version: 9.3.0 on 26 April 2021 13:14:59
os: Linux-5.8.0-48-generic #54~20.04.1-Ubuntu SMP Sat Mar 20 13:40:25 UTC 2021
nodename: he-ThinkPad-X200
machine: x86_64
clock source: unix
detected number of CPU cores: 2
current working directory: /home/he
detected binary path: /home/he/.virtualenvs/dailyfresh/bin/uwsgi
!!! no internal routing support, rebuild with pcre support !!!
*** WARNING: you are running uWSGI without its master process manager ***
your processes number limit is 15095
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uWSGI http bound on :8083 fd 4
spawned uWSGI http 1 (pid: 198655)
uwsgi socket 0 bound to TCP address 127.0.0.1:39853 (port auto-assigned) fd 3
Python version: 3.7.9 (default, Apr 24 2021, 20:06:16)  [GCC 9.3.0]
*** Python threads support is disabled. You can enable it with --enable-threads ***
Python main interpreter initialized at 0x558f827d49f0
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 72920 bytes (71 KB) for 1 cores
*** Operational MODE: single process ***
WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x558f827d49f0 pid: 198654 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI worker 1 (and the only) (pid: 198654, cores: 1)
[pid: 198654|app: 0|req: 1/1] 127.0.0.1 () {36 vars in 572 bytes} [Mon Apr 26 21:21:29 2021] GET / => generated 8 bytes in 0 msecs (HTTP/1.1 200) 1 headers in 44 bytes (1 switches on core 0)
[pid: 198654|app: 0|req: 2/2] 127.0.0.1 () {36 vars in 537 bytes} [Mon Apr 26 21:21:29 2021] GET /favicon.ico => generated 8 bytes in 0 msecs (HTTP/1.1 200) 1 headers in 44 bytes (1 switches on core 0)

2.1.3 使用uWSGI运行Django项目

即测试 web client <–> uWSGI <–> Django 是否通:

  • 在虚拟环境下,进入到django根目录下后用以下命令:
 uwsgi --http :8000 --module 项目的名字.wsgi
 
 # 等价于直接用:
 # python manage.py runserver 0.0.0.0:8000
 # 无ip和port时默认只能本地访问网站,如果需要其他人也可以访问,需要指定0.0.0.0这个ip和8000这个端口

实际运行结果,同样 ctrl+c 中止程序:

(dailyfresh) he@he-ThinkPad-X200:~/github-learning/dailyfresh-B2C/dailyfresh$ ls
apps  celery_tasks  dailyfresh  db  manage.py  requirements.txt  start.md  static  templates  utils  uwsgi.ini
(dailyfresh) he@he-ThinkPad-X200:~/github-learning/dailyfresh-B2C/dailyfresh$ uwsgi --http :8000 --module dailyfresh.wsgi
*** Starting uWSGI 2.0.19.1 (64bit) on [Mon Apr 26 21:51:29 2021] ***
compiled with version: 9.3.0 on 26 April 2021 13:14:59
os: Linux-5.8.0-48-generic #54~20.04.1-Ubuntu SMP Sat Mar 20 13:40:25 UTC 2021
nodename: he-ThinkPad-X200
machine: x86_64
clock source: unix
detected number of CPU cores: 2
current working directory: /home/he/github-learning/dailyfresh-B2C/dailyfresh
detected binary path: /home/he/.virtualenvs/dailyfresh/bin/uwsgi
!!! no internal routing support, rebuild with pcre support !!!
*** WARNING: you are running uWSGI without its master process manager ***
your processes number limit is 15095
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uWSGI http bound on :8000 fd 4
spawned uWSGI http 1 (pid: 198841)
uwsgi socket 0 bound to TCP address 127.0.0.1:37437 (port auto-assigned) fd 3
Python version: 3.7.9 (default, Apr 24 2021, 20:06:16)  [GCC 9.3.0]
*** Python threads support is disabled. You can enable it with --enable-threads ***
Python main interpreter initialized at 0x55fa3ca34a20
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 72920 bytes (71 KB) for 1 cores
*** Operational MODE: single process ***
WSGI app 0 (mountpoint='') ready in 1 seconds on interpreter 0x55fa3ca34a20 pid: 198840 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI worker 1 (and the only) (pid: 198840, cores: 1)
Not Found: /
[pid: 198840|app: 0|req: 1/1] 127.0.0.1 () {36 vars in 573 bytes} [Mon Apr 26 21:51:45 2021] GET / => generated 3027 bytes in 2282 msecs (HTTP/1.1 404) 3 headers in 102 bytes (1 switches on core 0)
Not Found: /favicon.ico
[pid: 198840|app: 0|req: 2/2] 127.0.0.1 () {36 vars in 538 bytes} [Mon Apr 26 21:51:47 2021] GET /favicon.ico => generated 3078 bytes in 6 msecs (HTTP/1.1 404) 3 headers in 102 bytes (1 switches on core 0)

2.1.4 uWSGI热加载Django项目

  • 热加载:
    也就是在程序代码发生改变后, 自动重启程序。
uwsgi --http :8000 --module 项目的名字.wsgi --py-autoreload=1

# 多了参数:--py-autoreload=1
# 监控python模块以触发重载(仅在开发中使用)
# 此时修改django代码,uWSGI会自动加载django程序,页面生效

2.2 nginx部署

2.2.1 nginx配置uwsgi和django

  • nginx从文件系统中拉起media和static文件作为服务,同时响应django的request。
  • 每次都运行命令来拉起django项目实在不方便,可以将这些配置写在.ini文件中,能大大简化工作,即下面2.2.2的方式。

目前不作重点介绍,有兴趣地可移步:https://blog.csdn.net/u012145252/article/details/82147440

2.2.2 使用uwsgi配置文件运行Django项目

  • uwsgi支持ini,xml等多种配置方式,本项目选用的是ini方式,在项目根目录下有一个uwsgi.ini:
(dailyfresh) he@he-ThinkPad-X200:~/github-learning/dailyfresh-B2C/dailyfresh$ ls
apps  celery_tasks  dailyfresh  db  manage.py  requirements.txt  start.md  static  templates  utils  uwsgi.ini

# uwsgi.ini原始的内容如下:
[uwsgi]
# 使用nginx连接时使用,Django程序所在服务器地址;*补充:设置使用的socket端口或socket地址
socket=127.0.0.1:8080
# 直接做web服务器使用,Django程序所在服务器地址
# http=127.0.0.1:8080
# 项目目录;*项目的绝对路径,定位到项目的第一层
chdir=/pythondemo/dailyfresh
# 项目中wsgi.py文件的目录,相对于项目目录;*指明项目的wsgi文件路径
wsgi-file=dailyfresh/wsgi.py
# 进程数;开启多少个进程数,workers项也等同processes
processes=4
# 线程数;threads项则是设置运行线程,测试倒不用设置上线程
threads=2
# uwsgi服务器的角色
master=True
# 存放进程编号的文件
pidfile=uwsgi.pid
# 日志文件,因为uwsgi可以脱离终端在后台运行,日志看不见。我们以前的runserver是依赖终端的
daemonize=uwsgi.log
# 指定依赖的虚拟环境
virtualenv=/dailyfresh/venv
  • 在退出uwsgi环境后,清空环境变量(其实就是将自动生成的luffy.sock和相关pid文件给干掉),可补充:

    vacuum = true
    
  • uwsgi指定配置文件启动django项目,建议使用nginx用户执行:

(dailyfresh) he@he-ThinkPad-X200:~/github-learning/dailyfresh-B2C/dailyfresh$ uwsgi --ini uwsgi.ini  # 启动Django项目
[uWSGI] getting INI configuration from uwsgi.ini
(dailyfresh) he@he-ThinkPad-X200:~/github-learning/dailyfresh-B2C/dailyfresh$ ps -ef | grep nginx
he        199228  196895  0 22:38 pts/1    00:00:00 grep --color=auto nginx
(dailyfresh) he@he-ThinkPad-X200:~/github-learning/dailyfresh-B2C/dailyfresh$ ls
apps  celery_tasks  dailyfresh  db  manage.py  requirements.txt  start.md  static  templates  utils  uwsgi.ini  uwsgi.log  uwsgi.pid
(dailyfresh) he@he-ThinkPad-X200:~/github-learning/dailyfresh-B2C/dailyfresh$ uwsgi --stop uwsgi.pid  # 停止
(dailyfresh) he@he-ThinkPad-X200:~/github-learning/dailyfresh-B2C/dailyfresh$ ls
apps  celery_tasks  dailyfresh  db  manage.py  requirements.txt  start.md  static  templates  utils  uwsgi.ini  uwsgi.log  uwsgi.pid
(dailyfresh) he@he-ThinkPad-X200:~/github-learning/dailyfresh-B2C/dailyfresh$ vi uwsgi.log 

  • uWSGI 通过 xxx.ini 启动后会在相同目录下生成一个 xxx.pid 的文件,里面只有一行内容是 uWSGI 的主进程的进程号。
  • 重启命令:uwsgi --reload xxx.pid
  • 停止命令:uwsgi --stop xxx.pid
  • 启动命令:uwsgi --ini xxx.ini



【部分内容参考自】

  • WSGI,uwsgi, uWSGI详解:https://blog.csdn.net/gymaisyl/article/details/85038932
  • uWSGI详解:https://blog.csdn.net/midion9/article/details/51354774
  • 浅谈uWSGI和Nginx:https://blog.csdn.net/shu_8708/article/details/79068581
  • Nginx+uWSGI+Django部署web服务器:https://blog.csdn.net/u012145252/article/details/82147440
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
uwsginginx是常用的Python Web应用程序部署工具,可以用于部署Flask项目。下面是部署Flask项目的步骤: 1. 安装uwsginginxLinux系统中,可以使用以下命令安装uwsginginx: ``` sudo apt-get install uwsgi nginx ``` 2. 创建Flask应用程序 在Flask应用程序的根目录下,创建一个名为`app.py`的文件,并在其中编写Flask应用程序的代码。 3. 创建uwsgi配置文件 在Flask应用程序的根目录下,创建一个名为`uwsgi.ini`的文件,并在其中编写uwsgi的配置信息。例如: ``` [uwsgi] module = app callable = app master = true processes = 4 socket = /tmp/uwsgi.sock chmod-socket = 660 vacuum = true die-on-term = true ``` 其中,`module`和`callable`分别指定Flask应用程序的模块名和可调用对象名。`socket`指定uwsginginx之间的通信方式,`processes`指定uwsgi启动的进程数。 4. 创建nginx配置文件 在Linux系统中,可以在`/etc/nginx/sites-available/`目录下创建一个名为`flask`的文件,并在其中编写nginx的配置信息。例如: ``` server { listen 80; server_name example.com; location / { include uwsgi_params; uwsgi_pass unix:///tmp/uwsgi.sock; } } ``` 其中,`listen`指定监听的端口号,`server_name`指定服务器的域名。`location`指定请求的URL路径,`uwsgi_pass`指定uwsgi的通信方式。 5. 启动uwsginginx 在Flask应用程序的根目录下,使用以下命令启动uwsgi: ``` uwsgi --ini uwsgi.ini ``` 在Linux系统中,使用以下命令启动nginx: ``` sudo service nginx start ``` 6. 访问Flask应用程序 在浏览器中输入服务器的IP地址或域名,即可访问Flask应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值