Django 部署基础【使用 Nginx + uWSGI 的方式来部署来 Django】

本文主要讲解在 Linux 平台下,使用 Nginx + uWSGI 的方式来部署来 Django,这是目前比较主流的方式。当然你也可以使用 Gunicorn 代替 uWSGI,不过原理都是类似的,弄懂了其中一种,其它的方式理解起来问题也不会很大。

 

有很多人曾经在邮件中咨询过问我如何部署,部署确实对开发者有着较高的要求,尤其是初学者来说,部署比较难,这很正常,千万不要轻易就放弃了

 

回想我2013年刚开始接触也是一头雾水,整整弄了四五天才完全搞懂,部署好了真是欣喜若狂。我自认为算不上聪明,我都能搞明白,你也一定能行。最关键和宝贵的品质就是坚持不懈和勇于试错。下面就让我们一起开始正式的部署教程吧。

 

基础知识储备

当我们发现用浏览器不能访问的时候,我们需要一步步排查问题。

整个部署的链路是 Nginx -> uWSGI -> Python Web程序,通常还会提到supervisord工具。

uWSGI是一个软件,部署服务的工具,了解整个过程,我们先了解一下WSGI规范,uwsgi协议等内容。

 

WSGI(Web Server Gateway Interface)规范,WSGI规定了Python Web应用和Python Web服务器之间的通讯方式。

目前主流的Python Web框架,比如Django,Flask,Tornado等都是基于这个规范实现的。

 

uwsgi协议是uWSGI工具独有的协议,简洁高效的uwsgi协议是选择uWSGI作为部署工具的重要理由之一,详细的 uwsgi协议 可以参考uWSGI的文档。

uWSGI是 实现了uwsgi协议,WSGI规范和HTTP协议的 一个C语言实现的软件。

 

Nginx是一个Web服务器,是一个反向代理工具,我们通常用它来部署静态文件。主流的Python Web开发框架都遵循WSGI规范。

uWSGI通过WSGI规范和我们编写的服务进程通讯,然后通过自带的高效的 uwsgi 协议和 Nginx进行通讯,最终Nginx通过HTTP协议将服务对外透出。

当一个访问进来的时候,首先到 Nginx,Nginx会把请求(HTTP协议)转换uwsgi协议传递给uWSGI,uWSGI通过WSGI和web server进行通讯取到响应结果,再通过uwsgi协议发给Nginx,最终Nginx以HTTP协议发现响应给用户。

有些同学可能会说,uWSGI不是支持HTTP协议么,也支持静态文件部署,我不用Nginx行不行?

当然可以,这么做没问题,但目前主流的做法是用Nginx,毕竟它久经考验,更稳定,当然也更值得我们信赖。

 

supervisor 是一个进程管理工具。任何人都不能保证程序不异常退出,不别被人误杀,所以一个典型的工程做法就是使用supervisor看守着你的进程,一旦异常退出它会立马进程重新启动起来。

如果服务部署后出现异常,不能访问。我们需要分析每一步有没有问题,这时候就不得不用到Linux中一些命令。

 

进程分析

进程是计算机分配资源的最小单位,我们的程序至少是运行在一个进程中。

1. 查看进程信息

通常我们使用 ps aux | grep python 来查看系统中运行的 python 进程,输出结果如下:

tu@linux / $ ps uax | grep python

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

root      1780  0.0  0.0  58888 10720 ?        Ss   Jan15   8:46 /usr/bin/python /usr/local/bin/supervisord -c /etc/supervisord.conf

tu      4491  0.0 18.0 3489820 2960628 ?     Sl   Jan29   0:19 python a.py

tu     12602  5.3 26.4 4910444 4343708 pts/1 Sl+  12:34   4:07 python b.py

有些同学习惯使用 ps -ef | grep xxx 结果也是类似的,读者可以自行尝试。

 

输出结果中 USER 后面的 PID 代表进程编号。

我们可以通过查看 /proc/PID/ 目录的文件信息来得到这个进程的一些信息(Linux中一切皆文件,进程信息也在文件中),比如它是在哪个目录启动的,启动命令是什么等信息。执行命令后输入内容如下:

tu@linux /proc/4491 $ sudo ls -ahl

...

dr-xr-xr-x   2 tu tu 0 Feb 17 13:32 attr

-rw-r--r--   1 tu tu 0 Feb 17 13:32 autogroup

-r--------   1 tu tu 0 Feb 17 13:32 auxv

-r--r--r--   1 tu tu 0 Feb 17 13:32 cgroup

--w-------   1 tu tu 0 Feb 17 13:32 clear_refs

-r--r--r--   1 tu tu 0 Feb 17 12:49 cmdline  这个文件中有启动进程具体的命令

-rw-r--r--   1 tu tu 0 Feb 17 13:32 comm

-rw-r--r--   1 tu tu 0 Feb 17 13:32 coredump_filter

-r--r--r--   1 tu tu 0 Feb 17 13:32 cpuset

lrwxrwxrwx   1 tu tu 0 Feb 17 13:32 cwd -> /home/tu  启动进程时的工作目录

-r--------   1 tu tu 0 Feb 17 13:32 environ  进程的环境变量列表

lrwxrwxrwx   1 tu tu 0 Feb 17 12:00 exe -> /usr/bin/python2.7 链接到进程的执行命令文件

...省去了部分内容

 

2. 向进程发送信号

我们可以使用 kill PID 杀死一个进程,或者使用 kill -9 PID 强制杀死一个进程。

记得以前在研究生的时候师弟和师妹经常问我,kill -9 里面的 -9 是什么意思,我告诉他们,这是强制杀死进程的意思,让这个进程“九死一生”。当然这是开玩笑,这里的 -9 是信号的一种,kill 命令会向进程发送一个信号,-9代表 SIGKILL 之意,用于强制终止某个进程,当然这是一种无情地,野蛮地方式干掉进程。

我们可以通过 kill -l 命令查看到所有的信号

HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH POLL PWR SYS

 

上面的信号是有顺序的,比如第1个是 HUP,第9个是 KILL,下面两种方式是等价的:

kill -1 PID 和 kill -HUP PID

kill -9 PID 和 kill -KILL PID

信号HUP通常程序用这个信号进行优雅重载配置文件,重新启动并且不影响正在运行的服务。比如

pkill -1 uwsgi 优雅重启uwsgi 进程,对服务器没有影响

kill -1 NGINX_PID 优雅重启nginx进程,对服务器没有影响

除了知道可以这么使用之外,感兴趣的读者还可以自行学习,深入了解下uwsgi和nginx无损reload的机制。

我们常用CTRL+C中断一个命令的执行,其实就是发送了一个信号到该进程

CTRL-C 发送 SIGINT 信号给前台进程组中的所有进程,常用于终止正在运行的程序。

CTRL-Z 发送 SIGTSTP 信号给前台进程组中的所有进程,常用于挂起一个进程。

每个程序可能对部分信号的功能定义不一致,其它信号的含义大家可以自行学习。

 

3. 查看进程打开了哪些文件

sudo lsof -p PID

如果是分析一个你不太了解的进程,这个命令比较有用。

可以使用 lsof -p PID | grep TCP 查看进程中的 TCP 连接信息。

 

4. 查看文件被哪个进程使用

使用这个命令查看一个文件被哪些进程正在使用 sudo lsof /path/to/file,示例如下:

> sudo lsof /home/tu/.virtualenvs/mic/bin/uwsgi

COMMAND   PID USER  FD   TYPE DEVICE SIZE/OFF     NODE NAME

uwsgi    2071 tu txt    REG 253,17  1270899 13240576 /home/tu/.virtualenvs/mic/bin/uwsgi

uwsgi   13286 tu txt    REG 253,17  1270899 13240576 /home/tu/.virtualenvs/mic/bin/uwsgi

uwsgi   13287 tu txt    REG 253,17  1270899 13240576 /home/tu/.virtualenvs/mic/bin/uwsgi

uwsgi   13288 tu txt    REG 253,17  1270899 13240576 /home/tu/.virtualenvs/mic/bin/uwsgi

 

5. 查看进程当前状态

当我们发现一个进程启动了,端口也是正常的,但好像这个进程就是不“干活”。比如我们执行的是数据更新进程,这个进程不更新数据了,但还是在跑着。可能数据源有问题,可能我们写的程序有BUG,也可能是更新时要写入到的数据库出问题了(数据库连接不上了,写数据死锁了)。我们这里主要说下第二种,我们自己的程序如果有BUG,导致工作不正常,我们怎么知道它当前正在干什么呢,这时候就要用到Linux中的调试分析诊断strace,可以使用 sudo strace -p PID这个命令。

通过执行后输出的一些信息,推测分析看是哪些出了问题。

 

这里我们讲了一些进程分析的工具和方法,关于进程分析工具和方法还有许多,大家需要不断练习,熟练运用这些工具去排查遇到的问题。

 

端口分析

比如我们在服务器上运行 Nginx,访问的时候就是连接不上,我们可以使用 ps aux | grep nginx看下nginx进程是不是启动了,也可以看下 80端口有没有被占用。换句话说,如果没有任何程序跑在这个端口上(或者说没有任何程序使用这个端口),证明忘了启动相关程序或者没能启动成功,或者说程序使用的端口被修改了,不是80了,那又怎么可能能访问到呢?

1. 查看全部端口占用情况

Linux中我们可以使用 netstat 工具来进程网络分析,netstat 命令有非常多选项,这里只列出了常用的一部分

-a或--all 显示所有连接中的Socket,默认不显示 LISTEN 相关的。

-c或--continuous 持续列出网络状态,不断自动刷新输出。

-l或--listening 显示监听中的服务器的Socket。

-n或--numeric 直接使用IP地址,而不是展示域名。

-p或--programs 显示正在使用Socket的程序进程PID和名称。

-t或--tcp 显示TCP传输协议的连接。

-u或--udp 显示UDP传输协议的连接。

比如我们可以查看服务器中监控了哪些端口,如果我们的nginx是使用80端口,uwsgi使用的是7001端口,我们就能知道通过下面的命令

> netstat -nltp

Active Internet connections (only servers)

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name

tcp        0      0 0.0.0.0:7001            0.0.0.0:*               LISTEN      2070/uwsgi      

tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      1575/redis-server 1

就能知道80端口的 nginx 是不是启动成功了,7001端口的uwsgi是不是启动成功了。

注意:如果PID和Program Name显示不出来,证明是权限不够,可以使用sudo运行

2. 查看具体端口占用情况

> sudo lsof -i :80 (注意端口80前面有个英文的冒号)

COMMAND    PID     USER   FD   TYPE DEVICE SIZE/OFF NODE NAME

nginx   4123   admin    3u  IPv4  13031      0t0  TCP *:http (LISTEN)

nginx   4124   admin    3u  IPv4  13031      0t0  TCP *:http (LISTEN)

我们可以通过这个方法查询出占用端口的程序,如果遇到端口已经被占用,原来的进程没有正确地终止,可以使用kill命令停掉原来的进程,这样我们就又可以使用这个端口了。

 

除了上面讲的一些命令,在部署过程中会经常用到下面的一些Linux命令,如果不清楚它们是做什么的,可以提前自行学习下这些Linux基础命令:

ls, touch, mkdir, mv, cp, ps, chmod, chown

学习完了这些内容,我们应该就具备了部署Linux服务器的基础知识了,在遇到问题后,应该也会有一些调查思路。

剩余部分大家再去 自强学堂上看 Django部署,应该会容易懂的多。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/456845.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

css的属性是变量是怎么表达,CSS自定义属性(变量)

Github上有个叫electron-api-demos的项目,看代码的时候发现了这么一个css文件(variables.css)::root {--color: hsl(0,0%,22%);--color-subtle: hsl(0,0%,44%);--color-strong: hsl(0,0%,11%);--color-link: hsl(0,0%,22%);--color-border: hsl(0,0%,88%…

Exception in thread main java.lang.UnsupportedClassVersionError的另类解决办法

最近在Linux虚拟机上跑在windows平台上的eclipes打出来的jar包时报出Exception in thread “main” java.lang.UnsupportedClassVersionError的错误: 经过上网查询了解到是因为自己Windows使用的是jdk1.8版本,而Linux使用的是jdk1.7版本,所…

Linux命令【第一篇】

1、创建一个目录/data 记忆方法:英文make directorys缩写后就是mkdir。 命令: mkdir /data 或 cd /;mkdir data #提示:使用分号可以在一行内分割两个命令。 实践过程: 方法一: [rootoldboy66 ~]# mkdir /data #查…

Jenkins + gitlab webhook实现自动化部署

1、先在Jenkins安装插件Gitlab Hook Plugin 和Build Authorization Token Root Plugin;2.插件安装完成后在任务里添加token3、在gitlab上添加钩子4、点击测试钩子或push代码再看Jenkins已经在构建了就说明成功了(也可以在浏览器直接执行这个URL&#xff…

多继承以及MRO顺序【super().的使用】

多继承以及MRO顺序 1. 单独调用父类的方法 # codingutf-8print("******多继承使用类名.__init__ 发生的状态******") class Parent(object):def __init__(self, name):print(parent的init开始被调用)self.name nameprint(parent的init结束被调用)class Son1(Paren…

人工智能专业词汇集

最近看到一篇关于AI专业词汇总结的文章,感觉不错,分享一下。 对应的词汇项目地址为:https://github.com/jiqizhixin/Artificial-Intelligence-Terminology 本词汇库目前拥有的专业词汇共计 500 个,主要为机器学习基础概念和术语…

js 当前日期增加自然月

js 在日期不满足的情况下就会自动加1个月,比如在当前时间为3月31号,传入1,1两个参数,预期结果为2月29日,但是结果输出了3月2日。就是如果不满就会溢出到下个月,后来看了api发现了setMonth有两个方法&#x…

好雨云帮如何对接Git Server

前言 云帮目前支持对接GitLab、Gogs、Github,或者主流代码托管平台的公开项目,后期会考虑接入其他类型的Git服务。 私有云 GitLab是一个用于仓库管理系统的开源项目,私有云服务里使用比较多的自建Git服务。 对接GitLab 通过应用市场进行安装Gitlab 安装G…

Python 生成requirement 使用requirements.txt

python项目中必须包含一个 requirements.txt 文件,用于记录所有依赖包及其精确的版本号。以便新环境部署。requirements.txt可以通过pip命令自动生成和安装生成requirements.txt文件 pip freeze > requirements.txt安装requirements.txt依赖 pip install -r requ…

Source Insight上手教程

目录Project的建立和工作区域同步查看定义查找引用查找调用Source Insight常用快捷键 目录 最近刚参加工作,第一个任务就是查看项目的源码,熟悉代码结构。于是乎就简单学习了Source Insight。在这里就转载别人的文章当做自己的笔记,便于自己…

微信禁用右上角的分享按钮,WeixinJSBridge API以及隐藏分享的子按钮等菜单项

今天在做隐藏微信右上角的分享按钮 百度查到的一串代码&#xff0c;挺好用的 <!--禁用微信分享按钮--><script>function onBridgeReady() {WeixinJSBridge.call(hideOptionMenu);}if (typeof WeixinJSBridge "undefined") {if (document.addEventListen…

python2.7无法使用pip(安装easy_install)

python27和python36 共存时安装pip方法&#xff0c;解决python27文件夹下没有script文件方法 报错&#xff1a; D:\PYTHON2.7>python ez_setup.py Downloading http://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11-py2.7.egg Traceback (most recent call…

Codeforces 754E:Dasha and cyclic table

Codeforces 754E&#xff1a;Dasha and cyclic table 题目链接&#xff1a;http://codeforces.com/problemset/problem/754/E 题目大意&#xff1a;$A$矩阵&#xff08;$size(A)n \times m$&#xff0c;仅含a-z&#xff09;在整个平面做周期延拓&#xff0c;问$B$矩阵&#xff…

位运算中的左移和右移的计算详解

最近在学习javaScrapt&#xff0c;在学到位运算符这部分的时候&#xff0c;突然发现看不懂书上的例子了。经过查找资料后&#xff0c;发现了一遍不错的文章。分享一下&#xff1a; 正数的左移和右移 以3为例 3的二进制为 00000011 右移2位的时候将最右的11去掉左边补00结果…

AC日记——字符串P型编码 openjudge 1.7 31

31:字符串p型编码 总时间限制: 1000ms内存限制: 65536kB描述给定一个完全由数字字符&#xff08;0,1,2,…,9&#xff09;构成的字符串str&#xff0c;请写出str的p型编码串。例如&#xff1a;字符串122344111可被描述为"1个1、2个2、1个3、2个4、3个1"&#xff0c;因…

javascript中的define用法

文章目录1. AMD的由来2. AMD是什么3. AMD实例&#xff1a;如何定义一个模块4. 匿名模块5. 仅有一个参数的define6. Dojo中的AMD7. 结论最近由于工作需求只能快速学习JS&#xff0c;但在看代码的时候发现许多东西都有疑问比如说代码刚开始的define关键字的用法&#xff0c;刚好最…

解决:pip警告!DEPRECATION: The default format will switch to columns in the future.

pip警告&#xff01; DEPRECATION: The default format will switch to columns in the future. You can use --format(legacy|columns) (or define a format(legacy|columns) in your pip.conf under the [list] section) to disable this warning. pip升级到9.0.1后 查看pi…

PLSQL安装配置

&#xff08;1&#xff09;解压&#xff1a;plsql developer Oracle数据库开发工具首先确保有oracle数据库或者有oracle服务器&#xff0c;然后才能使用PLSQL Developer连接数据库。&#xff08;2&#xff09;工具---首选项---连接----输入OCI库&#xff08;设置之后不用再装or…

Mysql 学习笔记2

&#xff08;1&#xff09;MySQL查看表占用空间大小 //先进去MySQL自带管理库&#xff1a;information_schema //自己的数据库&#xff1a;dbwww58com_kuchecarlib //自己的表&#xff1a;t_carmodelparamvalue mysql> use information_schema; Database changed mysql&g…

python程序打包为exe可执行文件

大家都知道&#xff0c;Python是一种脚本语言&#xff0c;也就是解释型的语言&#xff0c;需要解释器来进行解释以后才可以执行&#xff0c;而Python源代码需要在Python虚拟机上面运行&#xff0c;但是我们做好的程序&#xff0c;不可能给用户使用的时候还让他安装一个Python环…