Django学习之路(5)——开始集成uwsgi+nginx+django

2017/02/0122:43:57 2



前言:终于要步入正题了,是不是有点小激动呢,本文我将用两种环境记录下我折腾的过程。

Django是一个高级python WEB开发框架,它倡导高效整洁的开发和简洁的设计理念。

Nginx是一个免费开源、高性能的HTTP和反向代理服务,同时也是一个IMAP/POP3代理服务。

本文并不是一篇详尽描述如何搭建一个生产环境的参考手册,因为具体的生产环境可能会有不同的配置,果子哥只是尽可能的描述一个生产环境应该是一个什么样的配置模式。此外,nginx和uwsgi对于django框架来说是一个不错的选择,但并不是唯一的选择(或者说是“官方”选择)


基本概念


一个WEB服务器——nginx,它是直接面向用户访问的,它能提供诸如静态网页,图片,css等的直接访问,然而并不能直接和django应用对话,包括我们之前所接触过的PHP,它也是把动态请求转发给php-fpm来解析,一定要牢记这一点:nginx是没有解析动态语言的能力的,它需要依赖别的模块来解析。本文将要使用的uwsgi就可以理解为django应用的解析器,所以完成一次django应用的行为如下:


client <-> nginx <-> socket <-> uwsgi <-> django


其中,socket是nginx与uwsgi的通讯模块,它可以通过端口或者unix socket来进行数据交互。


创建一个沙盒


太棒了,我们的沙盒终于要出场了。接下来我要在/home/chin目录下创建一个沙盒,以普通用户chin登录shell终端,执行如下命令:

cd ~
virtualenv PythonEnv
cd PythonEnv
# 临时添加环境变量
source bin/activate
# 你应该会看到如下类似的提示符
# (PythonEnv) chin@chin-PC:~$ 
# 查看下pip和python的路径,你会发现它们都在沙盒路径中了
which pip python
/home/chin/PythonEnv/bin/pip
/home/chin/PythonEnv/bin/python


安装django


这一步也非常简单,该用上我们的pip工具啦,我们在沙盒中创建一个django项目并进入该项目目录:

pip install django==1.8.17
django-admin.py startproject django_project
cd django_project
#查看下django目录
tree -L 2
├── db.sqlite3
├── django_project
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── manage.py
├── test.py

安装并使用uwsgi


有了pip工具,让我们如此得意,继续安装uwsgi

pip install uwsgi

1) 测试一下


创建一个文件test.py,并加下以下内容:

# test.py
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    #return [b"Hello World"] # python3
    return ["Hello World"] # python2

2) 运行uwsgi

uwsgi --http :8080 --wsgi-file test.py

各选项的含义:

  • http :8080 :使用http协议,端口号为8080

  • wsgi-file test.py:加载指定的文件test.py


此时可以在浏览器中访问:http://192.168.1.10:8080,效果如下:

blob.png


该过程的交互如下:

client <-> uwsgi <-> python


测试django项目


到现在为止,我们已经让uwsgi正常运行起来了,只是用test.py来模拟了django的行为,接下来我们将要使用django自带的web服务器来运行:

cd ~/PythonEnv/django_project
python manage.py runserver 0.0.0.0:8080

访问下效果图如下:

blob.png


如果能看到上图,说明我们的django应用也正常部署了,接下来我们测试下用uwsgi能不能运行django应用:

uwsgi --http :8080 --module django_project.wsgi
  • module django_project.wsgi: 加载指定的django项目


如果到这步你还没遇到任何问题的话,恭喜您,我们继续!


说明:此时的交互模式变成:

client <-> uwsgi <-> django


安装nginx

sudo apt-get install nginx
sudo nginx -v
# nginx version: nginx/1.10.0 (Ubuntu)
sudo systemctl start nginx.service

此时,你用浏览器直接访问应该能看到"Welcome to nginx!"的字样,此时说明nginx已经正常运行,交互模式变成:

client <-> web server (nginx)


1) 修改并添加nginx配置文件


注释掉/etc/nginx/nginx.con如下行


#include /etc/nginx/sites-enabled/*;


修改nginx运行用户组为chin:


#user www-data;

user chin; 


添加80.conf文件至/etc/nginx/conf.d中,80.conf文件内容如下:


upstream django_ops{

server 127.0.0.1:9090;

#server unix:///home/chin/PythonEnv/django_project/django_project.sock;

}

server {

listen       80;

server_name  localhost,192.168.1.10;

#root /home/chin/django_project;

location /media {

alias /home/chin/PythonEnv/django_project/media;

}

location /static {

alias /home/chin/PythonEnv/django_project/static;

}

#以上为静态文件分离配置

#非静态文件都转到uwsgi

location / {

include  uwsgi_params;

uwsgi_pass django_ops;

client_max_body_size 35m;

}

}


重启nginx生效:

sudo systemctl restart nginx.service

至此,nginx配置完毕!


生成django静态文件


在django_project/settings.py中最后添加如下行:

STATIC_ROOT = os.path.join(BASE_DIR, "static/")

然后运行命令:

python manage.py collectstatic

此时可以在/home/chin/django_project目录下新建一个文件夹media,放入一张图片media.jpg,接着来访问下:http://192.168.1.10/media/media.jpg

blob.png


开始整合nginx和uwsgi


第一个传说中的程序都是“hello world",接下来我们就让nginx对我们说"hello world"

uwsgi --socket :9090 --wsgi-file test.py

这里的9090是nginx配置的反向代理端口,接下来访问:http://192.168.1.10

blob.png


如果你看到以上图片,说明装逼成功!

此时的交互模式变成:

the web client <-> the web server <-> the socket <-> uWSGI <-> Python

使用unix sockets代替端口


为了更高的性能,我们使用unix sockets来代替端口模式,为什么?

因为端口模式存在tcp的连接、建立、释放过程,如果服务器硬件配置不够的话,可能会引起一些麻烦。

此时,我们修改/etc/nginx/conf.d/80.conf中的如下行:

upstream django_ops{

#server 127.0.0.1:9090;

server unix:///home/chin/PythonEnv/django_project/django_project.sock;

}

重启nginx:

sudo systemctl restart nginx.service

按如下方式启动uwsgi:

uwsgi --socket /home/chin/PythonEnv/django_project/django_project.sock --wsgi-file test.py

接着再次访问首页,如果不能正确显示,比如出现502错误,可以检查下nginx的错误日志:/var/log/nginx/error.log,可能会诸如以下的错误提示:

connect() to unix:///home/chin/PythonEnv/django_project/django_project.sock  failed (13: Permission
denied)

这是因为你可能没有让nginx以chin指定用户去运行,导致没有权限去访问该socket文件,可以尝试用以下方式运行(或者我上边提到的步骤,添加nginx运行组):

uwsgi --socket /home/chin/PythonEnv/django_project/django_project.sock --wsgi-file test.py --chmod-socket=666 #(或者664权限)

接下来我们启动django应用:

uwsgi --socket /home/chin/PythonEnv/django_project/django_project.sock --module django_project.wsgi --chmod-socket=664

此时再次访问:http://192.168.1.10

会出现django的默认首页:It works!的字样。


以ini文件的方式启动uwsgi


为了更方便的修改和管理,我们可以创建一个/home/chin/PythonEnv/django_project/uwsgi.ini文件:

# mysite_uwsgi.ini file
[uwsgi]
# Django-related settings
# the base directory (full path)
chdir           = /home/chin/PythonEnv/django_project
# Django's wsgi file
module          = django_project.wsgi
# the virtualenv (full path)
home            = /home/chin/PythonEnv
# process-related settings
# master
master          = true
# maximum number of worker processes
processes       = 10
# the socket (use the full path to be safe
socket          = /home/chin/PythonEnv/django_project/django_project.sock
#http          = 0.0.0.0:9090
# ... with appropriate permissions - may be needed
chmod-socket    = 666
# clear environment on exit
vacuum          = true
uid = chin
gid = chin
pidfile = /home/chin/PythonEnv/django_project/uwsgi.pid
daemonize = /home/chin/PythonEnv/django_project/django_project.log

此时启动的话也比较简单:

cd /home/chin/PythonEnv/django_project
uwsgi --ini uwsgi.ini

创建uwsgi启动脚本


实际的生产环境中,我们不可能每次都输入那么长的一串命令去重启uwsgi服务,而且我们在开发过程中,更改django应用文件后需要重启uwsgi,此时,一个启动脚本将会更加方便我们的工作,我们可以在/home/chin/PythonEnv/bin目录下创建一个uwsgid文件,内容如下:

#! /bin/sh  
# Description: Startup script for uwsgi webserver on Debian. Place in /etc/init.d and  
# run 'update-rc.d -f uwsgi defaults', or use the appropriate command on your  
# distro. For CentOS/Redhat run: 'chkconfig --add uwsgi'  
### BEGIN INIT INFO  
# Provides:          uwsgi  
# Required-Start:    $all  
# Required-Stop:     $all  
# Default-Start:     2 3 4 5  
# Default-Stop:      0 1 6  
# Short-Description: starts the uwsgi web server  
# Description:       starts uwsgi using start-stop-daemon  
### END INIT INFO  
# Author:   licess  
# website:  http://www.guoziweb.com  
#PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DESC="uwsgi daemon"
NAME=uwsgi
HOME=/home/chin/PythonEnv
PROJECT=django_project
DAEMON=$HOME/bin/uwsgi
CONFIGFILE=$HOME/$PROJECT/$NAME.ini
PIDFILE=$HOME/$PROJECT/$NAME.pid
SCRIPTNAME=/etc/init.d/${NAME}d
set -e  
[ -x "$DAEMON" ] || exit 0
do_start() {
    $DAEMON $CONFIGFILE || echo -n "uwsgi already running"  
}
do_stop() {
    $DAEMON --stop $PIDFILE || echo -n "uwsgi not running"  
    rm -f $PIDFILE
    echo "$DAEMON STOPED."  
}
do_reload() {
    $DAEMON --reload $PIDFILE || echo -n "uwsgi can't reload"  
}
do_status() {
    ps aux|grep $DAEMON
}
case "$1" in
 status)
    echo -en "Status $NAME: \n"  
    do_status
 ;;
 start)
    echo -en "Starting $NAME: \n"  
    do_start
 ;;
 stop)
    echo -en "Stopping $NAME: \n"  
    do_stop
 ;;
  restart)
    echo -en "Restarting $NAME:\n"
    do_stop
    sleep 2
    do_start
  ;;
 reload|graceful)
    echo -en "Reloading $NAME: \n"  
    do_reload
 ;;
 *)
    echo "Usage: $SCRIPTNAME {start|stop|reload}" >&2
    exit 3
 ;;
esac
exit 0

要记得赋予该脚本可执行权限哦:

chmod +x /home/chin/PythonEnv/bin/uwsgid

由于我们是在沙盒环境中,所以重启uwsgi服务的话,只需要输入以下指令即可:

uwsgid restart

好了,到此为止,我们环境准备工作算是全部完成了,后面将开始编写第一个django应用程序了,小伙伴们是不是很期待呢?

如果你还没有相关python基础的话,建议你先去自学下哦,《Head first python》可以推荐下啦!

  • 微信扫码赞助
  • weinxin
  • 支付宝赞助
  • weinxin

发表评论

您必须才能发表评论!

目前评论:2   其中:访客  2   博主  0

    • qin99

      很好的教程,希望作者继续写下去

      • 果子