nginx+uwsgi+django
一django部分需要修改:
归纳:
- 自定义设置404.html和500.html文件
- 关闭开发模式:DEBUG = False 和TEMPLATE_DEBUG = False
- 设置ALLOWED_HOSTS =[]
平时我们写的代码都是用django的开发模式,该模式输出的错误信息(error详情页)和修改配置文件之后自动重启配置生效的特点。
在生产模式中,为了安全,以及程序稳定性,需要关闭开发模式。
一:关闭debug模式:
在开发模式中,默认是开启debug模式,在setting.py中可以看出:
1 # SECURITY WARNING: don't run with debug turned on in production! 2 DEBUG = True
在setting配置文件已经告知这个模式不在生产中使用。
该模式:
- 所有的数据库查询将被保存在内存中, 以 django.db.connection.queries 的形式. 你可以想象,这个吃内存!
- 任何404错误都将呈现django的特殊的404页面,而不是普通的404页面。 这个页面包含潜在的敏感信息,但是不会暴露在公共互联网。比如含有url信息:

- 你的应用中任何未捕获的异常,从基本的python语法错误到数据库错误以及模板语法错误都会返回漂亮的Django错误页面。 这个页面包含了比404错误页面更多的敏感信息,所以这个页面绝对不要公开暴露。
注意:
debug设置成True和False的时候,setting.py文件中ALLOWED_HOSTS 默认值是[]empty list设置:
ALLOWED_HOSTS可以设置成完整的可以被解析的FQDN主机名,比如:www.example.com 句点前可以写shell的通配符比如:*.example.com会匹配以example.com结尾的主机名。
其中匹配的不区分大小和端口号。当然如果ALLOWED_HOSTS 的值写成['*']会匹配所有的主机。
1、DEBUG=True
- ALLOWED_HOSTS设置成空的列表即:ALLOWED_HOSTS =[]和DEBUG=True的时候,那么将会阻止一些host访问:['localhost', '127.0.0.1', '[::1]']。ALLOWED_HOSTS value default is empty list。
- DEBUG=False的时候,需要设置ALLOWED_HOSTS 的值,来保证那些主机可以访问的web项目。
- 在django1.10.3 、1.911、 1.8.16当DEBUG=True,会ALLOWED_HOSTS进行检查,其他的老版本中不会检查ALLOWED_HOSTS。
二、关闭模板的debug模式:
类似的在模板的debug形式,也会显示一些敏感信息,也需要关闭这个模式。
该设置的值在:OPTIONS中设置debug,默认值是False
1 TEMPLATES = [ 2 { 3 'BACKEND': 'django.template.backends.django.DjangoTemplates', 4 'DIRS': [], 5 'APP_DIRS': True, 6 'OPTIONS': { 7 # ... some options here ... 8 }, 9 }, 10 ]
综上所述需要关闭在setting.py的里的DEBUG=False或者去掉该选项,默认值是False。之后需要设置ALLOWED_HOSTS的值,否则django启动报错。(CommandError: You must set settings.ALLOWED_HOSTS if DEBUG is False.)
设置成False之后,django将不会提供错误页面以及静态资源(css、js、html等)的访问。
所以接下来我们需要做:写错误页面和静态资源访问设置(由nginx提供)
设置404错误页面:
在模板的根目录下设置一个404页面,楼主的模板的根目录为template:

404页面内容:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta http-equiv="content-type" content="text/html; charset=utf-8"> 5 <title>Page not found at /</title> 6 <meta name="robots" content="NONE,NOARCHIVE"> 7 <style type="text/css"> 8 html * { padding:0; margin:0; } 9 body * { padding:10px 20px; } 10 body * * { padding:0; } 11 body { font:small sans-serif; background:#eee; } 12 body>div { border-bottom:1px solid #ddd; } 13 h1 { font-weight:normal; margin-bottom:.4em; } 14 h1 span { font-size:60%; color:#666; font-weight:normal; } 15 table { border:none; border-collapse: collapse; width:100%; } 16 td, th { vertical-align:top; padding:2px 3px; } 17 th { width:12em; text-align:right; color:#666; padding-right:.5em; } 18 #info { background:#f6f6f6; } 19 #info ol { margin: 0.5em 4em; } 20 #info ol li { font-family: monospace; } 21 #summary { background: #ffc; } 22 #explanation { background:#eee; border-bottom: 0px none; } 23 </style> 24 </head> 25 <body> 26 <div id="summary"> 27 <h1>Page not found <span>(404)</span></h1> 28 <table class="meta"> 29 <tr> 30 <th>Request Method:</th> 31 <td>GET</td> 32 </tr> 33 <tr> 34 <th>Request URL:</th> 35 <td>http://127.0.0.1:8000/</td> 36 </tr> 37 38 </table> 39 </div> 40 </body> 41 </html>
我们访问一个不存在url:

同样我们可以定义的500错误页面在模板的根目录下:
1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" 2 "http://www.w3.org/TR/html4/strict.dtd"> 3 <html lang="en"> 4 <head> 5 <title>Page unavailable</title> 6 </head> 7 <body> 8 9 10 <h1>Page unavailable</h1> 11 12 <p>Sorry, but the requested page is unavailable due to a 13 server hiccup.</p> 14 15 <p>Our engineers have been notified, so check back later.</p> 16 </body> 17 </html>
针对不同的产品线和环境设置你们想要的模式:
比如说在生成环境中 你不要自己手动修改DEBUG=False,和TEMPLATE_DEBUG=False,在测试环境中设置True的时候,你可以在你自己的setting.py的文件中进行如下代码的判断:
1 # settings.py 2 3 import socket 4 5 if socket.gethostname() == 'my-laptop': 6 DEBUG = TEMPLATE_DEBUG = True 7 else: 8 DEBUG = TEMPLATE_DEBUG = False
根据主机名的不同。设置不同的参数。方便灵活每次切换环境。
当然了,我们在测试环境和生产环境中的数据库是不一样的,所以我们有可能setting的设置是不一样的。那怎么办呢?
我们可以进行如下设计:
1、你可以根据上面的例子,对系统的主机名进行判断加载不同的配置。
测试:
1 2 3 DEBUG = True 4 TEMPLATE_DEBUG = DEBUG 5 6 DATABASE_ENGINE = 'postgresql_psycopg2' 7 DATABASE_NAME = 'devdb' 8 DATABASE_USER = '' 9 DATABASE_PASSWORD = '' 10 DATABASE_PORT = ''
生产:
1 2 3 from settings import * 4 5 DEBUG = TEMPLATE_DEBUG = False 6 DATABASE_NAME = 'production' 7 DATABASE_USER = 'app' 8 DATABASE_PASSWORD = 'letmein'
主配置文件为:setting.py文件。内容如下:
1 # settings.py 2 3 import socket 4 5 if socket.gethostname() == 'my-laptop': 6 DEBUG = TEMPLATE_DEBUG = True 7 DATABASE_ENGINE = 'postgresql_psycopg2' 8 DATABASE_NAME = 'devdb' 9 DATABASE_USER = '' 10 DATABASE_PASSWORD = '' 11 DATABASE_PORT = '' 12 else: 13 DEBUG = TEMPLATE_DEBUG = False 14 DEBUG = TEMPLATE_DEBUG = False 15 DATABASE_NAME = 'production' 16 DATABASE_USER = 'app' 17 DATABASE_PASSWORD = 'letmein'
这样根据不同的环境设置我们想要的开发模式。
注意:
- 如果修改了setting.py文件的文件名字,django并不关心你想修改成什么文件名字,只要你告诉django使用的配置文件是哪个就可以.
- 在manange.py文件中进行修改,其中有如下配置需要更改:
1 if __name__ == "__main__": 2 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "url.settings")
我的项目叫做url,所以在url.setting 改成url.yousettingname即可!
二:配置uwsgi
官方地址:http://uwsgi-docs.readthedocs.io/en/latest/WSGIquickstart.html
首先安装uwsgi:我们采用的pip安装
1 pip install uwsgi
测试我们安装的uwsgi,测试的脚本:
1 # test.py 2 def application(env, start_response): 3 start_response('200 OK', [('Content-Type','text/html')]) 4 #return ["Hello World"] # python2 5 return [b"Hello World"] # python3
shell命令行测试命令:
1 uwsgi --http :8001 --plugin python --wsgi-file test.py
浏览器输入:http://192.168.217.167:8001/
效果:

表示uwsgi 测试成功!
注意:
一般nginx端的配置如下:
1 location / { 2 include uwsgi_params; 3 uwsgi_pass 127.0.0.1:3031; 4 }
如上配置说明,每个请求都通过端口为3031的为uwsgi协议的服务器,所以uwsgi的服务启动以--socket形式启动而不是http。
uwsgi --socket 127.0.0.1:3031 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191
如果前端的代理、webserver、路由是HTTP协议的话,你需要告诉你UWSGI的服务是以http协议进行进行接收nginx的请求,uwsgi服务以如下方式启动:
uwsgi --http-socket 127.0.0.1:3031 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191
出现的状况:
- 启动的方式需要注意:是以uwsgi --http :8001 --plugin python --wsgi-file test.py 以http方式。如果使用前端nginx的时候,不要以http方式启动,需要以uwsgi --socket:8001 --plugin python --wsgi-file test.py
- socket方式启动。这种方式直接访问,是访问不了,需要通过nginx,以uninx socket的方式访问,nginx配置为:uwsgi_pass localhost:8001;方式访问,不能以http方式启动监听否则报502错误!
测试django:
linux环境安装app:
安装project:
1 django-admin.py startproject testdj
安装应用:
1 python3.5 manage.py startapp testuwsgi
配置url:
1 urlpatterns = [ 2 url(r'^admin/', admin.site.urls), 3 url(r'^test/', view.ws), 4 ]
视图配置:
1 from django.shortcuts import render,HttpResponse 2 3 # Create your views here. 4 def ws(request): 5 return HttpResponse('ok')
关闭django开发模式和配置:ALLOWED_HOSTS = ['*’]注意是字符串。
启动项目:
1 python3.5 manage.py runserver 0.0.0.0:8888## 注意是0.0.0.0 监听所有地址
访问:http://192.168.217.167:8888/test/
效果:

然后uwsgi和django结合,需要到django的项目根目录里。执行shell命令:
1 uwsgi --http :8001 --plugin python --module testdj.wsgi
然后访问:http://192.168.217.167:8001/test/
效果:

uwsgi出现日志:

说明配置没问题。注意这时项目的静态文件是不会被加载的,需要用nginx做静态文件代理
如果这个时候,你不行配置nginx的话,使用uwsgi的话,需要做如下配置:
uwsgi支持文件启动,我们可以在django项目的根目录建立uswgi.ini文件,代理django项目,文件内容如下:
1 [uwsgi] 2 socket = 0.0.0.0:9090 3 chdir = /export/testdj#django的项目的路径。 4 wsgi-file = testdj/wsgi.py#wsgi文件。 5 processes = 4#主进程为4 6 threads = 2#每个进程的线程为2。 7 stats = 127.0.0.1:9191#uwsgi的监控信息监听地址。
shell命令行启动:
1 # uwsgi --ini uwsgi.ini
更详细的参数请参照:https://uwsgi.readthedocs.io/en/latest/Configuration.html
深入讲解uwsgi:
一、并发参数
如上启动只启动一个uwsgi进程来处理nginx请求,当我们的请求并发高的时候,这个时候需要增加uwsgi的进程数来帮忙处理nginx的请求,参数如下:
--processes 进程数 --threads 每个进程的线程数。
1 uwsgi --http :9090 --wsgi-file foobar.py --master --processes 4 --threads 2
将会产生4个进程,每个进程有2个线程,还有一个主进程,作用是当进程死之后,派生子进程以及http路由的作用!!!!

二、监控uwsgi信息
uwsgi还为提供一个json串的监控信息,方便我们进行对uwsgi的监控,但是需要额外启动另外一个监听进行相关的操作:--stats 127.0.0.1:9191
1 uwsgi --http :9090 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191
以这种方式进行启动的时候,本地会启动9191的监听,方便我们进行对uwsgi进行相关监控,对于监听视情况而定 是本机监控还是扩服务器而进行不同的地址监听(--stats 0.0.0.0:9191)
用浏览器访问或者Telnet都可以获取目前的监控信息。
方便我们以后进行相关监控的提供api!
如
三:wsgi.py不存在:
如果文件django中wsgi.py文件不存在的话,你使用django的版本低于1.4,如果是这种情况的话。需要做一些参数添加和修改:
1 uwsgi --socket 127.0.0.1:3031 --chdir /home/foobar/myproject/ --pythonpath .. --env DJANGO_SETTINGS_MODULE=myproject.settings --module "django.core.handlers.wsgi:WSGIHandler()" --processes 4 --threads 2 --stats 127.0.0.1:9191
uwsgi的启动文件变动如下:
1 [uwsgi] 2 socket = 127.0.0.1:3031 3 chdir = /export/testdj 4 pythonpath = .. 5 env = DJANGO_SETTINGS_MODULE=myproject.settings 6 module = django.core.handlers.wsgi:WSGIHandler() 7 processes = 4 8 threads = 2 9 stats = 127.0.0.1:9191
三:配置nginx
nginx这里我们采用yum安装,当然也可以进行编译安装,视情况而定:
1 # yum install -y nginx 2 # /etc/init.d/nginx start 3 Starting nginx: [ OK ]
yum安装之后,默认读取的xml文件路径:
1 /etc/nginx/conf.d/default.conf
可以在nginx.conf可以指定:

nginx的配置文件:
1 # cat /etc/nginx/conf.d/default.conf 2 # the upstream component nginx needs to connect to 3 upstream django { 4 # server unix:///run/uwsgi/stats.sock; # for a file socket 5 server 127.0.0.1:9090; # for a web port socket (we'll use this first) 6 } 7 8 # configuration of the server 9 server { 10 # the port your site will be served on 11 listen 80; 12 # the domain name it will serve for 13 server_name 192.168.217.169; # substitute your machine's IP address or FQDN 14 charset utf-8; 15 16 # max upload size 17 client_max_body_size 75M; # adjust to taste 18 19 # Django media 20 location /media { 21 alias /path/to/your/mysite/media; # your Django project's media files - amend as required 22 } 23 24 location /static { 25 alias /export/testdj/static; # your Django project's static files - amend as required 26 } 27 28 # Finally, send all non-media requests to the Django server. 29 location / { 30 uwsgi_pass django; 31 include /etc/nginx/uwsgi_params; # the uwsgi_params file you installed 32 } 33 }
访问:http://192.168.217.169/test/

uwsgi官方地址:http://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html
完美!!! 搞定!

浙公网安备 33010602011771号