推荐两个很是好的教程:
The Django Book(中文版):我本身一开始是参考这个教程学习的,很是有意思的是这个教程中有大量的评论,几乎每段都有,从10年开始一直到如今。虽然这本书比较老,有不少内容都过期了,但在这些评论中有讲解,有勘误和最新的实践,这些评论让整个学习过程变得很是有趣。我本身也留下了很多评论,哈哈。
被解放的姜戈:这是博客园的另外一位博友Vamei(中文读做,挖煤)写的关于Django简介的系列文章,基本概念,简单的实践都有。
建立一个名为mysite的Django项目的命令:
$ django-admin startproject mysite
$ cd mysite
$ python manage.py startapp myApp # 建立一个app,名称为myApp
一个刚建立的Django项目的目录结构
图1:django项目的基本结构
不是要点的要点
- 建立一个专门的用户,例如www-data:在后面部署Django的过程当中,我遇到了自使用Linux以来,最多的权限问题。很大的缘由是由于不一样进程间须要通讯,或相互访问,这就须要这些用户间都有某个文件的读写权限。例如两个进程都要访问同一个socket文件时,这两个进程的用户都要对该socket文件有读写权限。所以将全部这些进程都交给一个专门的用户来操做,能够避免不少权限问题。
- url是web开发的核心要素之一:在客户端,每个url就是一个页面;从开发者来看,全部的开发都是围绕如何正确的路由这些url到正确的html文件来展开的。
- stackoverflow是一个很棒的网站,大部分的问题均可以在上面找到解决方案,若是没有找到答案,就提问吧,很快就能够获得回复。
概述
用户从浏览器访问一个django开发的页面,整个流程是这样的:
the web client <-> the web server <-> the socket <-> WSGI <-> Django
用户从浏览器访问一个url,该请求从用户发送到web server,web server经过socket(或者约定一个端口)与WSGI进行通讯,再由WSGI将请求发给django。web server和WSGI都有不少种选择,常见的组合有Apache + mod_wsgi和nginx + uWSGI。我用的是nginx + uWSGI。下面先介绍几个名词。
web server:
虽然每一个网页服务器程序有不少不一样,但有一些共同的特色:每个网页服务器程序都须要从网络接受HTTP请求,而后提供HTTP回复给请求者。HTTP回复通常包含一个HTML文件,有时也能够包含纯文本文件、图像或其余类型的文件。
通常来讲这些文件都存储在网页服务器的本地文件系统里,而URL和本地文件名都有一个阶级组织结构的,服务器会简单的把URL对照到本地文件系统中。当正确安装和设置好网页服务器软件,服务器管理员会从服务器软件放置文件的地方指定一个本地路径名为根目录。
web server是面对用户请求的第一道门,有些请求由web server本身处理,例如静态文件的访问等;还有一些请求则交给WSGI处理,如对动态页面的访问。
socket: 最近在学习《计算机网络》这门课,socket相关的内容在网络模型中属于传输层,位于网络层和应用层之间。主要用于实现进程间通信。在这里主要是实现nginx和uWSGI两个不一样进程之间的通信。
WSGI:
Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。自从WSGI被开发出来之后,许多其它语言中也出现了相似接口。
能够将WSGI看作是一种协议,听说之因此Python中有不少web框架,就是由于WSGI调用很是方便。uWSGI是WSGI这一协议的实现。在实际使用过程当中,uWSGI代替了python manage.py runserver的做用,固然还有其余做用。
最先的Web服务器只支持静态html。随着网站也愈来愈复杂,出现了动态技术。可是服务器并不能直接运行 php,asp这样的文件,所以须要一个第三方,与第三方作个约定,我把请求参数发送给你,而后我接收你的处理结果给客户端。这个约定就是 common gateway interface,简称cgi。这个协议能够用vb,c,php,python 来实现。
简单地说,cgi是Web App与Http Server之间的桥梁。
除了cgi,还有wsgi(Web Service Gateway Interface)。WSGI所在层的位置低于CGI,与CGI不一样的是WSGI具备很强的伸缩性且能运行于多线程或多进程的环境下,这是由于WSGI只是一份标准并无定义如何去实现。实际上WSGI并不是CGI,由于其位于web应用程序与web服务器之间,而web服务器能够是CGI。
全部均开始于settings文件
若是咱们已经建立了一个hello应用(如何建立,请参考本文开始时提到的两个教程),而且使用下面的语句运行:
python manage.py runserver 0.0.0.0:8000
ROOT_URLCONF = 'mysite.urls'
# urls.py from django.conf.urls import url, include from django.contrib import admin from mysite.views import hello admin.autodiscover() urlpatterns = [ url(r'^hello/$', hello), ]
# viwes.py from django.http import HttpResponse def hello(request): return HttpResponse("Hello World!")
uWSGI与Django之间的通信
uWSGI与Django之间的通信是经过wsgi.py文件实现的,这个文件在建立Django project后就生成了。这里的设置中最主要的一点就是正确的指出settings.py文件的位置。由于Django中的一切都始于这个文件。这些都使用Django的默认配置就能够了。
# wsgi.py
""" WSGI config for mysite project. It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/ """ import os from django.core.wsgi import get_wsgi_application # 这里已经指定了settings文件的位置 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") application = get_wsgi_application()
一些命令:
# 安装uwsgi
$ pip install uwsgi
# 若是 python manage.py runserver 0.0.0.0:8000 能够运行成功,则可使用下面的命令代替django自己的runserver功能(为了可使用8000端口,须要先修改防火墙设置)
$ uwsgi --http :8000 --module mysite.wsgi # 在项目的根目录运行该命令(与运行python manage.py的目录相同),参考"图1"中的目录结构
可是在与nginx联合使用时,端口号由nginx中的配置决定,在uwsgi中就不用配置端口号了(因为nginx与uwsgi之间经过socket通讯,因此直接访问该端口号就能够访问整个django程序)。
下面是一个配置文件的例子,配置完成后能够在6001端口访问django程序,nginx与uwsgi之间经过"/run/uwsgi/metDNA.sock"进行通讯。
server { listen 6001; server_name localhost; # 这里能够根据实际状况填写域名或localhost charset utf-8; client_max_body_size 50M; location / { include uwsgi_params; # include conf.d/corsheaders.conf; uwsgi_pass unix:///run/uwsgi/metDNA.sock; } # Django media location /media { # 设置www.ourlab.cn/media的具体路径,这里是django项目配置文件中的`MEDIA_ROOT`的位置 # your Django project's media files - amend as required alias /mnt/data/metdna-upload; } location /static { # django项目的静态文件夹位置,即`STATIC_ROOT`的位置 # your Django project's static files - amend as required # first project's static files path alias /mnt/data/www/metDNA/metDNA/static/static_root; } }
更多详情,能够参考:https://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html
uwsig的配置:
- 具体配置,能够参考这里;
- 由于在配置文件中设置了touch-reload参数,因此更新django代码后,可使用 touch /path/to/wsgi.py 加载更新,而不用重启整个django项目;
- 使用uwsgi的emperor模式:/usr/bin/uwsgi --emperor /etc/uwsgi/sites,sites文件夹中放的是uwsgi的配置文件mysite.ini(能够放多个django项目相关的配置文件)。该模式始终处于运行状态,若是要中止该django项目,能够重命名sites文件夹下对应的配置文件;
Instances under the control of the emperor should never dies.
If you want to fully stop an instance, simply remove/rename/move the instance config file in a way that the emperor rule will never match.
nginx的配置
因为一开始不熟悉,所以nginx的配置花了很长时间。其中的关键点是:不一样的server之间是没法共用端口号(port)的,所以若是要使用同一个端口号,例如80端口,那么全部的路由都要配置在一个server中。
- 配置文件位置:/etc/nginx/ ;
- 能够将自定义的配置文件放在目录 /etc/nginx/conf.d/,因为在主配置文件 /etc/nginx/nginx.conf 中包含有 include /etc/nginx/conf.d/*.conf; 这条语句,因此该目录下全部的 .conf 文件都会被加载;
- 自定义的配置文件,能够参考这里nginx.conf,主要是指定端口号和server name(网站域名);
值得注意的是,上面配置文件中的sock文件,例如unix:/run/uwsgi/lipidCCS.sock,nginx的用户和uwsgi的用户须要同时对其进行读写操做,所以都须要相应的权限。靠近前端用户的nginx和靠近后端django程序的uwsgi就是经过这个sock文件进行通讯的。
一些命令:
# 重启服务:
$ sudo systemctl restart nginx.service
其余
进程管理:进程管理的工具也有不少,uWSGI中的Emperor mode与进程管理工具具备类似的功能,二者彷佛没法共用。我选择的是Supervisor。
uwsgi程序中的Emperor mode,会与Supervisor相互影响;Emperor mode的做用与Supervisor差很少,但本身感受Supervisor更好用一些
重大修订:
第一次修订于2017年12月20日,补充了uwsgi相关配置的说明,对配置文件添加了注释;
第二次修订于2018年12月27日,勘误以及修复连接(这是每一年这个时间都要写网站的节奏啊!);
参考:
https://zh.wikipedia.org/wiki/%E7%B6%B2%E9%A0%81%E4%BC%BA%E6%9C%8D%E5%99%A8
https://zh.wikipedia.org/wiki/Berkeley%E5%A5%97%E6%8E%A5%E5%AD%97
https://zh.wikipedia.org/wiki/Web%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%BD%91%E5%85%B3%E6%8E%A5%E5%8F%A3
http://djangobook.py3k.cn/2.0/
http://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html
https://www.quora.com/What-are-the-differences-between-nginx-and-gunicorn # 这里讲了为何要使用nginx和gunicorn(做用同uWSGI)
http://data-eater.com/python-worker/
http://www.shellwjl.com/2016/03/07/ali_flask_wsgi_Nginx/