Quantcast
Channel: polygun2000的博客
Viewing all articles
Browse latest Browse all 55

使用gunicorn,supversiovr,nginx部署django应用

$
0
0
一、理解WSGI的工作方式

WSGI有两方:“Server”一方,“Application”一方。

一个常规的请求处理流程如下:
1. "Server"创建socket,监听端口,等待客户端连接。
2."Server"接收到用户的HTTP request请求。
3."Server"解析客户端信息放到环境变量environ中,解析http请求,将请求信息例如method,path等也放到environ中,然后再将一些服务器端信息也放到environ中,这样,服务器信息,客户端信息,本次请求信息全部都保存到了环境变量environ中。
4."Server"调用注册的“Application”,传递给“Application”的参数有两个:
a.第3步中包含所有请求信息的environ字典
b.一个start_response回调函数
5.“Application”处理请求,处理完毕后调用start_response回调函数,将HTTP response headers/status 返回给"Server"。
6.“Application”将响应正文(response body)作为返回值,返回给"Server"。
7."Server"通过socket将response信息返回给客户端。

在django中,创建项目时会自动创建一个wsgi.py,按照WSGI规范的叫法,这个wsgi.py就是一个"WSGI application callable"。在这个wsgi.py里边实现了一个名为"application"的函数,这个函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:environ和start_response,即上边第四步中所说的一个包含所有HTTP请求信息的dict对象和一个发送HTTP响应的函数。
这个函数只有几行,真正执行的代码是django.core模块中的wsgi.py里边的get_wsgi_application()函数。
客户请求进来以后,这个application函数,就会被WSGI Server调用。

在实际使用中,可能还会有"WSGI中间件"这个角色,它同时实现了API的两方,因此可以在WSGI服务和WSGI应用之间起调解作用:从WSGI服务器的角度来说,中间件扮演应用程序,而从应用程序的角度来说,中间件扮演服务器。“中间件”组件可以执行以下功能:

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

二、安装virtualenv,创建django项目

2.1 安装pip,virtualenv
]# yum install python-pip
]# pip install --upgrade pip
]# pip install virtualenv

2.2 创建virtualenv环境
假设我们的django应用都放在/home/webapps/目录下
]# mkdir /home/webapps
]# cd /home/webapps
]# virtualenv venv
]# cd venv
]# source bin/activate

这里要特别提一句,virtualenv其实用在开发环境中的好处更明显,对于生产环境则是可选项。
如果有兴趣可以去看看activate脚本,其作用就是将你的venv/bin放到$PATH最前边。
所以,如果我们的机器是专用来运行django的,且系统默认的python版本合用,其实完全可以不需要virtualenv。

2.3 创建django项目,本例子中的名字叫做mysite
(venv) [root@demo webapps]# pip install django gunicorn gevent
(venv) [root@demo webapps]# django-admin.py startproject mysite .

修改django配置文件,主要修改以下几处,指定主机头,数据库连接,静态文件目录,这些根据自己需要修改即可。
(venv) [root@demo webapps]# vi mysite/settings.py
......
ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', . . .]
......
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'myproject',
        'USER': 'myprojectuser',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '',
    }
}
......
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')  # 将静态文件放到project的目录下,名字为static

(venv) [root@demo webapps]# cd /home/webapps
(venv) [root@demo webapps]# ./manage.py makemigrations
(venv) [root@demo webapps]# ./manage.py migrate

创建管理员用户
(venv) [root@demo webapps]# ./manage.py createsuperuser

将静态文件收集到指定的目录
(venv) [root@demo webapps]# ./manage.py collectstatic

使用django自身的Web Server测试一下是否可用,如果可以访问,CRTL+C终止
(venv) [root@demo webapps]# ./manage.py runserver 0.0.0.0:8000

使用gunicorn测试项目是否可用,如果可以访问,CRTL+C终止
(venv) [root@demo webapps]# cd ~/mysite
(venv) [root@demo webapps]# gunicorn --bind 0.0.0.0:8000 mysite.wsgi:application

如果此时访问/admin会发现所有CSS样式消失了,这是因为我们还没有配置nginx来处理static文件,别紧张。

三、gunicorn的相关说明

django自带的webserver性能不足以用在生产环境,所以一般会使用其他WSGI Server,比如uwsgi和gunicorn。
我们在此不讨论这些server间的优劣,只说明一下gunicorn如何使用。

根据第一部分的说明,WSGI中Server是通过wsgi.py中的application函数与django交互的。

所以gunicorn最简单的运行方式就是: gunicorn mysite.wsgi:application
gunicorn 默认作为一个监听 127.0.0.1:8000 的web server,可以在本机通过http://127.0.0.1:8000 访问。

如果要通过网络访问,则需要绑定不同的地址(也可以同时设置监听端口):gunicorn -b 10.2.20.66:8080 mysite.wsgi:application

在多核服务器上,使用更多的gunicorn进程充分利用资源,下边命令启动8个进程同时处理HTTP请求:
gunicorn -w 8 mysite.wsgi:application

gunicorn 默认使用同步阻塞的网络模型(-k sync),对于大并发的访问可能表现不够好, 它还支持其它更好的模式,比如:gevent或meinheld。
gunicorn -k gevent mysite.wsgi:application

gunicorn支持使用配置文件,配置文件需要是合法的python源文件,但并不需要写成可以import的module。
只需要文件系统中可读取就行,也没有什么语法方面的特使要求,需要变量,定义就是了。

]# vi gunicorn_config.py
import sys
import os
import multiprocessing
path_of_current_file = os.path.abspath(__file__)
path_of_current_dir = os.path.split(path_of_current_file)[0]
_file_name = os.path.basename(__file__)

sys.path.insert(0, path_of_current_dir)
worker_class = 'gevent'
workers = multiprocessing.cpu_count() * 2 + 1
chdir = path_of_current_dir
worker_connections = 1000
timeout = 30
max_requests = 2000
graceful_timeout = 30
loglevel = 'info'
reload = True
debug = False

bind = "%s:%s" % ("0.0.0.0", 8000)
pidfile = '%s/run/%s.pid' % (path_of_current_dir, _file_name)
errorlog = '%s/logs/%s_error.log' % (path_of_current_dir, _file_name)
accesslog = '%s/logs/%s_access.log' % (path_of_current_dir, _file_name)

使用以上配置文件,会在gunicorn_config.py所在目录生成logs,run目录,gunicorn要对这些目录拥有写权限,所以这个配置文件放哪里,自己考虑。

四、使用supervisor运行gunicorn

因为gunicorn在运行中有可能会自己崩溃,我们需要一个机制来自动重启,之前写过一篇关于supervisor和tomcat的文档,所以在此不解释supervisor是什么,能干什么,怎么安装这些问题。只简单说明gunicorn的配置部分。
配置文件名字与项目保持一致,这样方便之后用ansible的模版管理。

]# vi /etc/supervisord.d/nameofyourprogram.ini
[program:nameofyourprogram]
directory = /path/of/your/project/
user = nginx
command = /path/to/venv/bin/gunicorn nameofyourproject.wsgi:application -c /path/of/your/project/gunicorn.conf.py
autostart=true
autorestart=true
redirect_stderr=true

实例如下:
[program:mysite]
directory = /home/webapps/venv
command = /home/webapps/venv/bin/gunicorn mysite.wsgi:application -c gunicorn.conf.py
autostart=true
autorestart=true
redirect_stderr=true

如果你的venv中的python版本不同,你还需要在command那里加入python的绝对路径。

五、使用nginx作为反向代理,并直接serve静态文件

我们在第二步的时候,已经将所有静态文件收集到/home/webapps/static目录中。

在nginx配置如下:

server {
    listen 80;
    server_name www.mysite.com;
    charset utf-8;

    access_log /home/webapps/mysite/access.log;
    error_log /home/webapps/mysite/error.log;

    location /static/ {
        alias /home/webapps/static/;
        access_log off;
    }

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

这样所有静态文件请求就被nginx处理了,动态请求会转到后端的django项目中。
关于静态文件处理,还有django-pipeline,可以做js,css等的合并和压缩,有需要的去看官方文档。

参考文档:
https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-16-04
https://www.digitalocean.com/community/tutorials/how-to-deploy-python-wsgi-apps-using-gunicorn-http-server-behind-nginx
https://gist.github.com/Atem18/4696071
https://blog.teststation.org/centos/python/2016/05/11/installing-python-virtualenv-centos-7/
http://stackoverflow.com/questions/6532486/supervising-virtualenv-django-app-via-supervisor
http://www.rkblog.rk.edu.pl/w/p/continuous-integration-django-projects-jenkins/
http://matthewdaly.co.uk/blog/2014/05/24/django-blog-tutorial-the-next-generation-part-5/
https://sites.google.com/site/kmmbvnr/home/django-jenkins-tutorial
https://media.readthedocs.org/pdf/django-jenkins/latest/django-jenkins.pdf
http://fishi.devtail.io/weblog/2015/02/22/setting-django-ci-jenkins-and-git/
http://www.isaced.com/post-228.html
http://michal.karzynski.pl/blog/2013/06/09/django-nginx-gunicorn-virtualenv-supervisor/
http://honza.ca/2011/05/deploying-django-with-nginx-and-gunicorn
http://www.cnblogs.com/wswang/p/5519101.html
https://docs.djangoproject.com/en/dev/howto/static-files
http://agiliq.com/blog/2013/08/minimal-nginx-and-gunicorn-configuration-for-djang/
http://django-pipeline.readthedocs.io/en/latest/configuration.html
http://rfyiamcool.blog.51cto.com/1030776/1276364?utm_source=tuicool&utm_medium=referral
http://wsgi.tutorial.codepoint.net/application-interface
http://www.nowamagic.net/academy/detail/1330310
http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386832689740b04430a98f614b6da89da2157ea3efe2000
https://gitlab.com/mayan-edms/mayan-edms/blob/972aa029763ad0cdd4cc4d7119a39c8b871fe7d5/contrib/gunicorn/gunicorn.conf.py

 

Viewing all articles
Browse latest Browse all 55

Trending Articles