推薦兩個很是好的教程:
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/