django+uWSGI+nginx的工做原理流程與部署過程

django+uWSGI+nginx的工做原理流程與部署過程

1、前言

知識的分享,不該該只是展現出來,還應該解釋這樣作是爲何...html

獻給和我同樣懵懂中不斷汲取知識,進步的人們。前端

授人與魚,不如授人以漁!python


2、必要的前提知識

2.1 準備知識

  1. Djangomysql

    .基於python的一個web框架,同類框架有Flask、Tornado...
  2. uWSGIlinux

    .實現了WSGI協議的一個web服務器

    web服務器和web框架nginx

    .在理解uWSGI和WSGI以前,先要弄清楚web開發的兩大塊,web服務器和web框架。
    .web服務器即用來接受客戶端請求,創建鏈接,轉發響應的程序。至於轉發的內容是什麼,交由web框架來處理,即處理這些業務邏輯。如查詢數據庫、生成實時信息等。
    .Nginx就是一個web服務器,Django或flask就是web框架。

    uWSGI和WSGIgit

    .那麼如何實現uWSGI和WSGI的配合呢?如何作到任意一個web服務器,都能搭配任意一個框架呢?
    這就產生了WSGI協議。只要web服務器和web框架知足WSGI協議,它們就能相互搭配。
    因此WSGI只是一個協議,一個約定。而不是python的模塊、框架等具體的功能。
    .而uWSGI則是實現WSGI協議的一個web服務器。即用來接受請求,轉發響應的程序。
    實際上,一個uWSGI的web服務器,再加上Django這樣的框架,就已經能夠實現網站功能了,那麼爲什麼還須要Nginx呢?

    須要Nginx的緣由github

    一個普通的我的網站,訪問量不大的時候,用uWSGI和Django部署是沒問題的,可是一旦訪問量過大,客戶的請求鏈接就要進行長時間的等待。
    這個時候就出現了分佈式服務器,也就是說我用多臺服務器,這些服務器都能處理請求,可是誰來分配客戶的的請求鏈接和web服務器呢?Nginx就是這樣一個管家的存在,由他分配,這其實就是Nginx的反向代理,即代理服務器。
  3. Nginx簡單介紹web

    .Nginx是俄羅斯人編寫的十分輕量級的HTTP服務器,Nginx以事件驅動的方式編寫,因此有很是好的性能,同時也是一個很是高效的反向代理、負載平衡。其擁有匹配Lighttpd的性能,同時尚未Lighttpd的內存泄漏問題。
    .nginx作爲HTTP服務器,有如下幾項基本特性:
     處理靜態文件,索引文件以及自動索引;打開文件描述符緩衝.
     無緩存的反向代理加速,簡單的負載均衡和容錯.
     FastCGI,簡單的負載均衡和容錯.
     模塊化的結構。包括gzipping, byte ranges, chunked responses,以及 SSI-filter等filter。若是由FastCGI或其它代理服務器處理單頁中存在的多個SSI,則這項處理能夠並行運行,而不須要相互等待。
     支持SSL 和 TLSSNI.
    .Nginx專爲性能優化而開發,性能是其最重要的考量,實現上很是注重效率 。它支持內核Poll模型,能經受高負載的考驗,有報告代表能支持高達 50,000個併發鏈接數。
    .Nginx具備很高的穩定性。其它HTTP服務器,當遇到訪問的峯值,或者有人惡意發起慢速鏈接時,也極可能會致使服務器物理內存耗盡頻繁交換,失去響應,只能重啓服務器。例如當前apache一旦上到200個以上進程,web響應速度就明顯很是緩慢了。而Nginx採起了分階段資源分配技術,使得它的CPU與內存佔用率很是低。nginx官方表示保持10,000個沒有活動的鏈接,它只佔2.5M內存,因此相似DOS這樣的攻擊對nginx來講基本上是毫無用處的。就穩定性而言,nginx比lighthttpd更勝一籌。
    .Nginx支持熱部署。它的啓動特別容易, 而且幾乎能夠作到7*24不間斷運行,即便運行數個月也不須要從新啓動。你還可以在不間斷服務的狀況下,對軟件版本進行進行升級。
    .Nginx採用master-slave模型,可以充分利用SMP的優點,且可以減小工做進程在磁盤I/O的阻塞延遲。當採用select()/poll()調用時,還能夠限制每一個進程的鏈接數。
    .Nginx代碼質量很是高,代碼很規範,手法成熟, 模塊擴展也很容易。特別值得一提的是強大的Upstream與Filter鏈。Upstream爲諸如reverse proxy,與其餘服務器通訊模塊的編寫奠基了很好的基礎。而Filter鏈最酷的部分就是各個filter沒必要等待前一個filter執行完畢。它能夠把前一個filter的輸出作爲當前filter的輸入,這有點像Unix的管線。這意味着,一個模塊能夠開始壓縮從後端服務器發送過來的請求,且能夠在模塊接收完後端服務器的整個請求以前把壓縮流轉向客戶端。
  4. wsgi.pyredis

    django項目攜帶的一個wsgi接口文件
    若是項目名叫br_api的話,此文件就位於[br_api/br_api/wsgi.py]
  5. 相關資料

    .wsgi:一種實現python解析的通用接口標準/協議,俗稱web服務網關接口
     須要搞清楚一點:wsgi不是服務器、Python模塊、框架、API或者任何軟件,它只是一種規範,描述web服務器與web程序通訊的規範。
    .uwsgi:同wsgi同樣,也是一種通訊協議
     uwsgi協議是一個uWSGI服務器自有的協議,它用於定義傳輸信息的類型,它與wsgi相比是兩樣東西。
    .uWSGI:一種python web server或者能夠這麼稱它:Server/Gatway
    uWSGI是實現了uWSGI和wsgi兩種協議的Web服務器,負責相應python的web請求。
     uWSGI實現了wsgi協議、uwsgi協議、http協議

2.2項目流程分析

流程

1.首先客戶端向服務器發送請求,請求資源,
2.nginx做爲直接對外的服務接口,接收到客戶端發送過來的http請求,會解包、分析,
    若是是靜態文件請求就根據配置的靜態文件目錄,返回請求的資源,
    若是是動態請求,nginx就經過配置文件,將請求傳遞給uWSGI,uWSGI將接收到包進行處理,並轉發給wsgi,3.wsgi根據返回值進行打包,轉發給uSWGI,
    uWSGI接收後轉發給nginx,nginx最終將返回值返回給客戶端(如瀏覽器)
*.這裏須要瞭解一點:不一樣的組件之間的信息傳遞涉及到數據格式和協議的轉換

分析

1.首先,守在最外面的nginx並非必須的,uwsgi徹底能夠完成整個與瀏覽器(前端)交互的流程;
2.在nginx上加上安全性或其餘限制,能夠達到保護程序的做用;
3.uWSGI本事是內網接口,開啓多個work和processes可能都不夠用,而nginx能夠代理墮胎uWSGI完成uWSGI的   負載均衡;
4.django在某些狀況下對靜態文件的處理能力不是很好,二用nginx來處理會更加高效。

3、安裝與配置

3.1 基礎環境安裝

首先,項目是部署在服務器上,環境是centeos,linux系統環境

使用xshell遠程鏈接服務器搭建項目環境

3.1.1 更新系統軟件包
yum update -y
3.1.2 安裝軟件管理包和可能會使用到的依賴
yum -y groupinstall "Development tools"

yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel psmisc libffi-devel
3.1.3 安裝Python3.6.7
1)前往用戶根目錄cd ~
2)下載 或 上傳 Python3.6.7
wget https://www.python.org/ftp/python/3.6.7/Python-3.6.7.tar.xz
3)解壓安裝包
tar -xf Python-3.6.7.tar.xz
4)進入目標文件
cd Python-3.6.7
5)配置安裝路徑
./configure --prefix=/usr/local/python3
6)編譯並安裝
make && sudo make install
7)創建軟鏈接:終端命令 python3,pip3
ln -s /usr/local/python3/bin/python3 /usr/bin/python3
ln -s /usr/local/python3/bin/pip3.6 /usr/bin/pip3
8)刪除安裝包與文件(可選)
cd ..
rm -rf Python-3.6.7
rm -rf Python-3.6.7.tar.xz
3.1.4 配置pip源加速(阿里和騰訊雲服務器自帶源加速,可不執行此步)
1)建立pip配置路徑mkdir ~/.pip
2)進入目錄編輯配置文件:填入下方內容
cd ~/.pip && vim pip.conf

[global]
index-url = http://pypi.douban.com/simple
[install]
use-mirrors =true
mirrors =http://pypi.douban.com/simple/
trusted-host =pypi.douban.com
3.1.5 安裝虛擬環境

默認工做路徑 ~/.virtualenvs

1)安裝依賴
pip3 install virtualenv
pip3 install virtualenvwrapper

2)創建虛擬環境軟鏈接
ln -s /usr/local/python3/bin/virtualenv /usr/bin/virtualenv

3)配置虛擬環境服務默認啓動:
vim ~/.bash_profile
添加下方內容:
VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
source /usr/local/python3/bin/virtualenvwrapper.sh
4)退出保存
esc >>> :wq
5)讓配置文件生效
source ~/.bash_profile

使用虛擬環境部署項目
1.先建立一個虛擬環境:
mkvirtualenv 虛擬環境名稱
2.建立完畢會自動進入該虛擬環境,第二次進入方法
workon 虛擬環境名稱
3.查看已經存在的虛擬環境
workon
4.推出當前虛擬環境
deactivate
3.1.6 安裝Mysql 5.7
1)前往用戶根目錄cd ~
2)下載mysql57
wget http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm
3)安裝mysql57
yum -y install mysql57-community-release-el7-10.noarch.rpm
yum -y install mysql-community-server
4)啓動mysql57並查看啓動狀態
啓動 systemctl start mysqld.service
狀態 systemctl status mysqld.service
5)Mysql5.7在第一次啓動會設置一個默認初始密碼,須要查看root用戶、登陸並修改,而後退出,從新登陸
查看 grep "password" /var/log/mysqld.log
登陸 mysql -uroot -p
修改 ALTER USER 'root'@'localhost' IDENTIFIED BY 'new password';
退出 exit
6)建立項目數據庫和獨立用戶(注意本地Django項目settings文件須要配置對應數據庫名稱和密碼)
建立數據庫 
create database '數據庫名' default charset=utf8;
建立用戶並授予權限(注意密碼必須包含字符、數字和特殊字符)
grant 權限(create, update) on 庫.表 to '帳號'@'host' identified by '密碼'
grant all privileges on xxx.* to 'xxx'@'%' identified by 'xxx';
grant all privileges on xxx.* to 'xxx'@'localhost' identified by 'xxx';
刷新生效
flush privileges;
非root戶查看數據庫只能看到受權的數據庫列表,而root能夠看到所有
查看用戶相關信息
select user,host,authentication_string from mysql.user;
3.1.7 安裝Redis
1)前往用戶根目錄
cd ~
2)下載redis-5.0.5
wget http://download.redis.io/releases/redis-5.0.5.tar.gz
3)解壓安裝包
tar -xf redis-5.0.5.tar.gz
4)進入目標文件
cd redis-5.0.5
5)編譯環境
make
6)複製環境到指定路徑完成安裝
cp -r ~/redis-5.0.5 /usr/local/redis
7)配置redis能夠後臺啓動:修改下方內容
vim /usr/local/redis/redis.conf
daemonize yes
8)完成配置修改
esc0
:wq
9)創建軟鏈接
ln -s /usr/local/redis/src/redis-server /usr/bin/redis-server
ln -s /usr/local/redis/src/redis-cli /usr/bin/redis-cli
10)後臺運行redis
redis-server &
ctrl + c
11)測試redis環境
redis-cli
config set requirepass '12345'
ctrl + c
12)關閉redis服務
pkill -f redis -9

3.2 安裝配置nginx和uWSGI,部署django項目

3.2.1 nginx安裝
1)前往用戶根目錄
cd ~
2)下載nginx1.13.7
wget http://nginx.org/download/nginx-1.13.7.tar.gz
3)解壓安裝包
tar -xf nginx-1.13.7.tar.gz
4)進入目標文件
cd nginx-1.13.7
5)配置安裝路徑:/usr/local/nginx
./configure --prefix=/usr/local/nginx
6)編譯並安裝
make && sudo make install
7)創建軟鏈接:終端命令 nginx
ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx
8)刪除安裝包與文件:(非必須)
rm -rf nginx-1.13.7
rm -rf nginx-1.13.7.tar.xz
9)測試Nginx環境,服務器運行nginx,本地訪問服務器ip
nginx
服務器綁定的域名 或 ip:80

nginx操做命令

1)啓動
nginx
2)關閉nginx
nginx -s stop
3)重啓nginx
nginx -s reload
4)查看端口,強行關閉
ps -aux|grep nginx
kill <進程編號>
查看端口占用
netstat -tunlp|grep 8000
3.2.2 uwsgi安裝
1).安裝(若是是虛擬環境記得在虛擬環境下再安裝一遍)
pip3 install uwsgi
2).創建軟鏈接
ln -s /usr/local/python3/bin/uwsgi /usr/bin/uwsgi
3).測試一下:
在本地新建test.py文件,寫入內容
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"]
而後保存複製到服務器root目錄
cd ~
sudo uwsgi --http 0.0.0.0:8000 --wsgi-file test.py
本地瀏覽器輸入http://118.25.94.126:8000/ (前面是個人公網ip)
tips:
若是端口被佔用,使用
lsof -i :8000
列出佔用端口的程序pid號,殺掉進程再執行一遍就能夠了
sudo kill -9 pid
3.2.3 配置nginx和uwsgi

配置以前須要環境知足要求

.python pip已安裝
.django項目文件已經上傳服務器,固然django已經安裝完畢
.django項目所依賴的第三方模塊都已經安裝完畢(安裝方法同與本地同樣,經過pip install ***安裝)
    django項目測試在項目目錄下:python manage.py runserver 0.0.0.0:8000

3.2.3_1 nginx配置

創建工程單獨的nginx配置文件

查看nginx的默認配置文件目錄(nginx.conf)的路徑

nginx -t

顯示結果參考:

nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

因此nginx默認配置文件路徑爲:

/usr/local/nginx/conf/nginx.conf

建立nginx配置文件

.確保nginx.conf的同目錄下有[uwsgi_params]文件
    使用命令cd /usr/local/nginx/conf/進行查看
.沒有的話根據連接(https://github.com/nginx/nginx/blob/master/conf/uwsgi_params)獲取,後面要用到。
.在本身的工程目錄下(/home/project/br_api/),創建如                                       br_api.conf(/home/project/br_api/br_api.conf)的配置文件;
複製nginx.conf裏面所有的內容,所有寫入br_api.conf中。
而後按照下面寫的,把所有寫入br_api.conf配置文件中的server段部分所有替換掉。
⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇
server {
        listen 80;
        server_name 127.0.0.1;
        charset     utf-8;
        access_log      /home/project/br_api/nginx_access.log;
        error_log       /home/project/br_api/nginx_error.log;
        client_max_body_size 75M;


        location /static {
            alias /home/project/br_api/static;
        }
        location /media {
            alias /home/project/br_api/media;
        }
        location / {
            root        /home/project/br_api;
            include     /usr/local/nginx/conf/uwsgi_params;
            uwsgi_pass  127.0.0.1:8001;
        }
    }
替換內容說明:
.listen 80 表明服務器開放80端口,也就是說外界能夠經過服務器ip:80端口訪問到nginx服務器,這裏80端口默承認以不寫
.access_log與error_log 定義nginx訪問日誌和錯誤日誌的存放路徑,這裏我把他們所有放到項目br_api項目根目錄下
.location /目錄名 {} 表明項目路徑的引導
.location /static {} 項目的靜態文件定位配置
    django靜態文件的絕對路徑是根據本身的實際狀況來肯定的,通常在本身的django項目根目錄的/static目錄下,或本身python manage.py collectstatic後的路徑下。
    像個人是在/home/project/br_api/static下。 
.location / 指訪問項目根目錄時,nginx要作的事。其中須要指定 uwsgi_params文件的絕對路徑,上面已經提到了;若是還有media文件之類的靜態目錄,仿照static的寫法,本身補充。
.uwsgi_pass 指uWSGI綁定的監聽地址,這裏使用了9090端口,這裏須要和下面的uwsgi配置文件中的socket一致

3.2.3_2 uwsgi配置

項目根目錄建立uwsgi.ini文件,寫入如下內容

[uwsgi]
socket = 127.0.0.1:8001
chdir=/home/project/br_api
module=br_api.wsgi:application
master = true         
processes=2
threads=2
max-requests=2000
chmod-socket=664
vacuum=true
daemonize = /home/project/br_api/uwsgi.log

3.2.3_3 配置路徑總覽

項目配置 配置路徑
項目路徑 /home/project/br_api
項目靜態文件路徑 /home/project/br_api/static
項目media文件路徑 /home/project/br_api/media
wsgi.py的路徑 /home/project/br_api/br_api/wsgi.py
uwsgi.ini的路徑 /home/project/br_api/uwsgi.ini
uwsgi日誌路徑 /home/project/br_api/uwsgi.log
br_api.conf的路徑 /home/project/br_api/br_api.conf
uwsgi_params的路徑 /usr/local/nginx/conf/uwsgi_params
nginx訪問日誌路徑 /home/project/br_api/nginx_access.log
nginx錯誤日誌路徑 /home/project/br_api/nginx_error.log

能夠發現,我幾乎把全部有關項目的配置文件和日誌文件都放在該項目目錄下了,方便後期維護與查錯。

4、啓動

啓動 uWSGI

sudo uwsgi --ini /home/project/br_api/uwsgi.ini

啓動 nginx

.在這以前,咱們要先去nginx配置文件的根目錄拷貝mime.types(/usr/local/nginx/conf/mime.types)到工程目錄(/home/project/br_api/mime.types),和br_api.conf放在一塊兒。 不然啓動時會報錯
.固然,若是不想拷貝mime.types文件,也能夠將配置文件中「include mime.types;」一項,改爲絕對路徑「include /usr/local/nginx/conf/mime.types;」 
若是nginx已經開啓,先關閉nginx(service nginx stop或nginx -s stop),再執行如下命令:
若是nginx已經開啓,先關閉nginx(service nginx stop或nginx -s stop),再執行如下命令:
nginx -c /home/project/br_api/br_api.conf
這裏的-c 表示加載配置文件啓動
nginx -s reload

補充

若是出現502錯誤,查看uwsgi.log文件發現缺乏模塊,若是是這個錯誤,能夠在br_api/br_api/wsgi.py中添加環境變量參數:

import os, sys
sys.path.append('/home/project/br_api')
# 添加的2個環境變量,將第三方模塊包所在目錄添加進去
sys.path.append('/root/.virtualenvs/br_api/lib/python3.6/site-packages')


from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'br_api.dev')
application = get_wsgi_application()
相關文章
相關標籤/搜索