首先,Gunicorn是一个高效的Web服务器,地位相当于Java中的Tomcat。简单来说gunicorn封装了HTTP的底层实现,我们通过gunicorn启动服务,用户请求与服务相应都经过gunicorn传输。
下载gunicorn的方法也比较简单,在django工程里一般都是直接写到requirements.txt文件中,当然也可以手动下载,执行pip install gunicorn 即可。
接下来介绍如何使用gunicorn来启动django服务。
其实,这个过程到也简单,就一个命令就可以了。
python3 gunicorn application -c gunicorn_conf.py
一步一步看,python3是指python的解释器,gunicorn是下载下来的python包, application是从wsgi中引出来的django服务信息,上面有说到gunicorn就是一个web服务器,所以gunicorn_conf.py就是它的配置文件了。
看个实际中使用的命令:
sudo /build/mts/mydjango_app/run_gunicorn.sh -c /build/mts/service/mydjango_app/gunicorn_conf.py
这样就可以直接启动django服务了。
其中,run_gunicorn.sh中的内容为:
#!/bin/bash
set -e
envdir=/build/mts/mydjango_app/py38env
export PYTHONDONTWRITEBYTECODE=1
exec $envdir/bin/python3 $envdir/bin/gunicorn mydjango_app.wsgi:application "$@"
在看看gunicorn_conf.py中的内容:
user = 'mts'
group = 'mts'
logconfig = '/build/mts/service/webapps/log_config.ini'
access_log_format = '%(r)s | %(h)s | %(b)s | %(s)s | %(D)s us'
bind = '0.0.0.0:8001'
workers = 16
timeout = 90
max_requests = 500
# pass the ssl values as being forwarded from nginx
secure_scheme_headers = {}
最后,再看看,所谓的wsgi.py是个啥内容:
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings')
application = get_wsgi_application()
所以,不难发现,上面提到的实际使用的关于gunicorn的shell命令,就是我上面写的命令:
python3 gunicorn application -c gunicorn_conf.py
这个命令中,只有application这个参数,才是将gunicorn(web服务),与django工程勾连到一起的参数。
上面提到的关于gunicorn的用法,大体上算是生产环境上的用法,之所以说大体上,就是因为,在gunicorn_conf.py中,bind参数,我选择监听的是本地的地址,这显然是为了测试所做出的选择。生产环境往往bind参数会选择绑定nginx的一个地址。因为gunicorn 可以单独提供服务,但生产环境一般不这样做。首先静态资源(jscssimg)会占用不少的请求资源,而对于 gunicorn 来讲它本身更应该关注实际业务的请求与处理而不应该把资源浪费在静态资源请求上;此外,单独运行 gunicorn 是没有办法起多个进程多个端口来负载均衡的。nginx 的作用就是弥补以上问题,首先作为前端服务器它可以处理一切静态文件请求,此时 gunicorn 作为后端服务器,nginx 将会把动态请求转发给后端服务器,因此我们可以起多个 gunicorn 进程,然后让 nginx 作均衡负载转发请求给多个 gunicorn 进程从而提升服务器处理效率与处理能力。最后,nginx 还可以配置很多安全相关、认证相关等很多处理,可以让你的网站更专注业务的编写,把一些转发规则等其它业务无关的事情交给 nginx 做。
大体上,就是这些了。
看一个gunicorn_conf.py中的内容,注意 bind的变化:
user = 'mts'
group = 'mts'
logconfig = '/build/mts/service/webapps/log_config.ini'
access_log_format = '%(r)s | %(h)s | %(b)s | %(s)s | %(D)s us'
bind = 'unix://var/run/buildapi-sb.sock'
workers = 16
timeout = 90
max_requests = 500
# pass the ssl values as being forwarded from nginx
secure_scheme_headers = {}
再看一个nginx.conf文件内容:
upstream buildapi_sb_server {
server unix://var/run/buildapi-sb.sock fail_timeout=0;
}
server {
listen 80;
server_name build-stage-api.eng.vmware.com ;
client_max_body_size 4G;
proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
access_log /build/mts/logs/nginx/buildapi/access.log main;
error_log /build/mts/logs/nginx/buildapi/error.log;
root /build/mts/buildapi/static/;
location = /favicon.ico {
return 204;
}
location /static/ {
alias /build/mts/buildapi/static/;
}
location /sb {
proxy_pass http://buildapi_sb_server/sb;
}
}
这种也是可以的,它和一般nginx做负载均衡的写法不太一样,这个东西,通常也起不到负载均衡的作用,只是哪哪都能用,很方便,不涉及具体的ip:port。特此记录吧。