uwsgi+nginx項目部署

部署Django項目

Django+uWSGI+nginx 部署

  • django 一個pyhton的開源web框架。
  • uWSGI 一個基於自有的uwsgi協議、WSGI協議和http服務協議的web網關
  • nginx 經常使用的代理服務器php

    WSGI:一種實現python解析的通用接口標準/協議,是一種通用的接口標準或者接口協議,實現了python web程序與服務器之間交互的通用性。 
    利用它,web.py或bottle或者django等等的python web開發框架,就能夠輕鬆地部署在不一樣的web server上了;

    uwsgi:同WSGI同樣是一種通訊協議 
    uwsgi協議是一個uWSGI服務器自有的協議,它用於定義傳輸信息的類型,它與WSGI相比是兩樣東西。html

    uWSGI :一種python web server或稱爲Server/Gateway 
    uWSGI相似tornadoweb或者flup,是一種python web server,uWSGI是實現了uwsgi和WSGI兩種協議的Web服務器,負責響應python 的web請求。 
    由於apache、nginx等,它們本身都沒有解析動態語言如php的功能,而是分派給其餘模塊來作,好比apache就能夠說內置了php模塊,讓人感受好像apache就支持php同樣。 
    uWSGI實現了wsgi協議、uwsgi協議、http等協議。 Nginx中HttpUwsgiModule的做用是與uWSGI服務器進行交換。前端

項目流程

首先客戶端請求服務資源,
nginx做爲直接對外的服務接口,接收到客戶端發送過來的http請求,會解包、分析,
若是是靜態文件請求就根據nginx配置的靜態文件目錄,返回請求的資源,
若是是動態的請求,nginx就經過配置文件,將請求傳遞給uWSGI;uWSGI 將接收到的包進行處理,並轉發給wsgi,
wsgi根據請求調用django工程的某個文件或函數,處理完後django將返回值交給wsgi,
wsgi將返回值進行打包,轉發給uWSGI,
uWSGI接收後轉發給nginx,nginx最終將返回值返回給客戶端(如瀏覽器)。
*注:不一樣的組件之間傳遞信息涉及到數據格式和協議的轉換

做用: python

  1. 第一級的nginx並非必須的,uwsgi徹底能夠完成整個的和瀏覽器交互的流程; 
  2. 在nginx上加上安全性或其餘的限制,能夠達到保護程序的做用; 
  3. uWSGI自己是內網接口,開啓多個work和processes可能也不夠用,而nginx能夠代理多臺uWSGI完成uWSGI的負載均衡; 
  4. django在debug=False下對靜態文件的處理能力不是很好,而用nginx來處理更加高效。

安裝與配置

  1. 建立項目運行的虛擬環境nginx

    virtualenv env --python=python3.6
    pip install -r requirements.txt  #安裝django運行環境
  2. 運行開發服務器測試web

    cd project # 進入項目 project 目錄
                    python manage.py runserver
    運行開發服務器測試,確保開發服務器下能正常打開網站。
  3. 安裝uWSGIshell

    # 在普通用戶下安裝
                    sudo apt install libpython3.6-dev
                    # 虛擬環境中
                    pip install uwsgi
  4. 測試uWSGI: 新建文件test.py,寫入如下內容數據庫

    def application(env, start_response):
                        start_response('200 OK', [('Content-Type','text/html')])
                        return "Hello World"
  5. 運行apache

    # 0.0.0.0能夠省略 
                    sudo uwsgi --http 0.0.0.0:8000 --wsgi-file test.py --processes 4 --threads 3
    若是提示端口已經被佔用,這時能夠把相關的進程 kill 掉。
    probably another instance of uWSGI is running on the same address (:8002).
                bind(): Address already in use [core/socket.c line 764]
    按照端口進行查詢進程
    lsof -i :8002
    能夠查出:
    COMMAND  PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
                uwsgi   2208   tu    4u  IPv4 0x53492abadb5c9659      0t0  TCP *:teradataordbms (LISTEN)
                uwsgi   2209   tu    4u  IPv4 0x53492abadb5c9659      0t0  TCP *:teradataordbms (LISTEN)
    這時根據 PID 能夠用下面的命令 kill 掉相關程序:
sudo kill -9 2208 2209
  1. 運行django項目django

    # --chdir 項目目錄 --home 虛擬環境目錄 project.wsgi 指的是 project/wsgi.py 文件
          uwsgi --http :8000 --chdir=/path/to/project  --home=/path/to/env --module project.wsgi
  2. 配置文件運行

    上面這樣使用一行命令太長了,咱們使用 ini 配置文件來搞定,好比項目在 /home/ray/project 這個位置,在其中新建一個 uwsgi.ini 全路徑爲 /home/ray/project/uwsgi.ini
    [uwsgi]
                    #socket 爲上線使用,http爲直接做爲服務器使用。
                    socket = 127.0.0.1:8080 #ip和端口號能夠改
                    http = 127.0.0.1:8000
                    #項目目錄
                    chdir=/home/ray/project
                    module=project.wsgi
                    #虛擬環境目錄
                    #home = home/ray/MxOnline/mxonlineEnv
                    master = true         
                    processes=4
                    threads=2
                    # 下面的參數不必定要加
                    # pidfile=uwsgi.pid   uwsgi.pid 和uwsgi.log會在啓動uwsgi時自動生成在項目目錄下。
                    # daemonize=uswgi.log
                    # max-requests=2000    
                    # chmod-socket=664
                    # vacuum=true
    # uwsgi啓動
    uwsgi --ini uwsgi.ini
    #uwsgi 中止
    uwsgi --stop uwsgi.pid
  3. 安裝nginx,在普通用戶下安裝。

    # 安裝
                    sudo apt install nginx 
                    #重載
                    sudo /etc/init.d/nginx reload
                    sudo nginx -s reload
                    # 啓動
                    sudo /etc/init.d/nginx start
                    # 中止
                    sudo /etc/init.d/nginx stop
                    # 重啓
                    sudo /etc/init.d/nginx restart
                    #查看nginx是否啓動
                    ps -ef | grep nginx
                root     24956     1  0 19:41 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
                nobody   24957 24956  0 19:41 ?        00:00:00 nginx: worker process
                root     24959 10533  0 19:41 pts/0    00:00:00 grep --color=auto nginx
  4. 配置 nginx

    ##### sites-enable 和 sites-available
    These directories are used to define configurations for your websites. Files are generally created in the "sites-available" directory, and thensymbolically linked to the "sites-enabled" directory when they are ready to go live.

    ​ 都是在nginx.conf做修改,由於nginx.conf include指令已經包括了sites-enabled的內容,在site-enabled做修改就至關於在nginx.conf做修改,可維護性高。

    include /etc/nginx/conf.d/*.conf;

    include /etc/nginx/sites-enabled/*;

    ites-available是存放當前的server配置, 在這裏修改。

    sites-enabled是激活並使用的server配置(從sites_available的文件建立快捷方式到sites-enabled)

    新建一個網站 test

# 不用sudo沒有權限修改
sudo vim /etc/nginx/sites-available/test.conf
#配置負載均衡
     # upstream ray {
     #    server 127.0.0.1:8000; # for a web port socket
     #}

     server {
         listen 80;
         server_name www.helloray.cn;#域名或者ip地址
         charset utf-8;
         # Django 的static和 media等靜態資源交給Nginx處理
         location /static {
             # 路徑必須和STATIC_ROOT同樣
             alias /var/www/myApp/static/;
         }
          location /media  {
              #項目下的media路徑
             alias /var/www/myApp/media/; 
         } 
         location /{
             # 必須和uwsgi.ini中socket同樣,配置了upstream能夠將uwsgi_pass配置爲:http:// +             upstream名稱,即「http://ray」.
             uwsgi_pass 127.0.0.1:8080; 
             #uwsgi_pass http://ray; 
             include uwsgi_params;
         }
     }

激活網站:創建軟連接

sudo ln -s /etc/nginx/sites-available/test.conf  /etc/nginx/sites-enabled/test.conf

nginx建立靜態文件目錄,並更改權限

sudo mkdir -vp /var/www/myApp/static/
 sudo chmod 777 /var/www/myApp/static/

在項目下setting.py 文件中

STATIC_URL = 'static'
 STATIC_ROOT = '/var/www/myApp/static/'
 STATICFILES_DIRS = [
   os.path.join(BASE_DIR,'static'),
 ]
 MEDIA_URL = '/media/'
 MEDIA_ROOT = os.path.join(BASE_DIR,'media')

在項目目錄下遷移靜態文件

python manage.py collectstatic

Django中settings.py中的五個設置參數的一些故事:

一、MEDIA_ROOT與MEDIA_URL

事實上MEDIA_ROOT和MEDIA_URL表明的是用戶上傳後的文件通常保存的地方。個人理解是,可變文件的文件夾。

與這兩個參數有聯繫的,是在Django的FileField和ImageField這樣的Model類中,有upload_to參數可選。當upload_to設置相關的地址後,如:upload_to="username";文件上傳後將自動保存到 os.path.join(MEDIA_ROOT, upload_to)。

而MEDIA_URL,,則表明用戶經過URL來訪問這個本地地址的URL。如本機http://127.0.0.1/, MEDIA_URL設置爲"/site_media/",那麼經過 http://127.0.0.1/site_media/***  就能夠訪問相關的上傳圖片或者其餘資源。

二、STATIC_ROOT與STATIC_URL

STATIC_ROOT和STATIC_URL則是網站中,用於網站顯示的靜態圖片、CSS、JS等文件的保存地址。個人理解是,運行中不會再變文件的文件夾(即不會刪除或者新增)

2.1 STATIC_URL

 同MEDIA_URL相似;STATIC_URL爲"/static/"時候,經過http://127.0.0.1/static/***就能夠訪問相關的靜態文件了。

2.2 STATIC_ROOT

STATIC_ROOT是一個比較特殊的文件夾。這是區別Django的開發模式和部署模式下最大的地方了。

一般咱們在開發模式下,能夠在咱們所在的project下創建相應的app, 而後每一個app下都創建相應的static文件夾。在開發模式下(Debug=True),Django將爲咱們自動查找這些靜態文件(每一個app)並在網頁上顯示出來。然而,在部署模式下,Django認爲這些工做交由web服務器來運行會更有效率。

所以,在部署時,咱們須要運行一下python manage.py collectstatic 這個命令。這個命令將會把每一個app裏的static目錄下的文件copy到STATIC_ROOT這個文件夾下,這時候若是在部署模式下(Debug=False),網頁中相關的,如: http://127.0.0.1/static/*** 的訪問,將不會訪問Django下各個App中的static,而是STATIC_ROOT中所指定的文件夾。

三、Debug=False後,爲什麼沒法訪問圖片和js等文件了?

其實這個問題,是在於web服務器沒有對STATIC_ROOT以及MEDIA_ROOT這兩個文件夾進行映射所致使的。

以apache爲例,假定:

STATIC_ROOT="/home/user/static/" 

STATIC_URL="/static/"

 MEDIA_ROOT="/home/user/media/"

MEDIA_URL="/media/"

那麼能夠在apache的配置文件中,增長如下:


<Location "/static/">
Order deny,allow
Allow from all
Satisfy Any
</Location>
Alias /static/     "/home/user/static"
<Location "/media/">
Order deny,allow
Allow from all
Satisfy Any
</Location>
Alias /media/      "/home/user/media/"


四、STATICFILES_DIRS:和TEMPLATE_DIRS的含義差很少,就是除了各個app的static目錄之外還須要管理的靜態文件,添加到這裏的文件會在collectstatic時 copy到STATIC_ROOT中

負載均衡的設置

網站的訪問量愈來愈大,服務器的服務模式也得進行相應的升級,好比分離出數據庫服務器、分離出圖片做爲單獨服務,這些是簡單的數據的負載均衡,將壓力分散到不一樣的機器上。有時候來自web前端的壓力,也能讓人十分頭痛。怎樣將同一個域名的訪問分散到兩臺或更多的機器上呢?這其實就是另外一種負載均衡了,nginx自身就能夠作到,只須要作個簡單的配置就行。

  nginx不單能夠做爲強大的web服務器,也能夠做爲一個反向代理服務器,並且nginx還能夠按照調度規則實現動態、靜態頁面的分離,能夠按照輪詢、ip哈希、URL哈希、權重等多種方式對後端服務器作負載均衡,同時還支持後端服務器的健康檢查。

nginx 的 upstream目前支持 4 種方式的分配 

輪詢:將請求依次輪詢發給每一個服務器,若是後端服務器down掉,能自動剔除。

最少連接:將請求發送給持有最少活動連接的服務器。

ip哈希:經過ip的哈希函數結果決定請求發送給哪一個服務器。這樣每一個訪客固定訪問一個後端服務器,能夠解決session的問題。

權重:服務器的權重越高,處理請求的機率越大。用於後端服務器性能不均的狀況。

輪詢負載均衡

在nginx.conf配置文件中添加以下配置,此配置有三臺服務器提供支付服務。

  1. 缺省配置就是輪詢策略;
  2. nginx負載均衡支持http和https協議,只須要修改 proxy_pass後面的協議便可;

    1. nginx支持FastCGI, uwsgi, SCGI,memcached的負載均衡,只需將 proxy_pass改成uwsgi_pass, fastcgi_pass, scgi_pass,memcached_pass便可。
  3. 此策略適合服務器配置至關,無狀態且短平快的服務使用。
http {
    upstream CashServers {
        server CashServers1.com;
        server CashServers2.com;
        server CashServers3.com;
    }

    server {
        listen 80;

        location / {
            proxy_pass http://CashServers;
        }
    }
}

最少連接負載均衡

  1. 最少連接負載均衡經過least_conn指令定義;
  2. 此負載均衡策略適合請求處理時間長短不一形成服務器過載的狀況;
http {
    upstream CashServers {
      least_conn;
        server CashServers1.com;
        server CashServers2.com;
        server CashServers3.com;
    }

    server {
        listen 80;

        location / {
            proxy_pass http://CashServers;
        }
    }
}

ip哈希負載均衡

  1. ip哈希負載均衡使用ip_hash指令定義;
  2. nginx使用請求客戶端的ip地址進行哈希計算,確保使用同一個服務器響應請求;
  3. 此策略適合有狀態服務,好比session;
http {
    upstream CashServers {
      ip_hash;
        server CashServers1.com;
        server CashServers2.com;
        server CashServers3.com;
    }

    server {
        listen 80;

        location / {
            proxy_pass http://CashServers;
        }
    }
}

 權重負載均衡

  1. 權重負載均衡須要使用weight指令定義;
  2. 權重越高分配到須要處理的請求越多;
  3. 此策略能夠與最少連接負載和ip哈希策略結合使用;
  4. 此策略比較適合服務器的硬件配置差異比較大的狀況;
http {
    upstream CashServers {      
        server CashServers1.com weight=3;
        server CashServers2.com weight=2;
        server CashServers3.com weight=1;
    }

    server {
        listen 80;
        location / {
            proxy_pass http://CashServers;
        }
    }
}

附錄:參數說明

>----------------附錄:uwsgi參數說明----------------
   >
   >- http : 協議類型和端口號
   >- processes : 開啓的進程數量
   >- workers : 開啓的進程數量,等同於processes(官網的說法是spawn the specified number ofworkers / processes)
   >- chdir : 指定運行目錄(chdir to specified directory before apps loading)
   >- wsgi-file : 載入wsgi-file(load .wsgi file)
   >- stats : 在指定的地址上,開啓狀態服務(enable the stats server on the specified address)
   >- threads : 運行線程。因爲GIL的存在,我以爲這個真心沒啥用。(run each worker in prethreaded mode with the specified number of threads)
   >- master : 容許主進程存在(enable master process)
   >- daemonize : 使進程在後臺運行,並將日誌打到指定的日誌文件或者udp服務器(daemonize uWSGI)。實際上最常
   >  用的,仍是把運行記錄輸出到一個本地文件上。
   >- daemonize : 使進程在後臺運行,並將日誌打到指定的日誌文件或者udp服務器(daemonize uWSGI)。實際上最常
   >  用的,仍是把運行記錄輸出到一個本地文件上。
   >- vacuum : 當服務器退出的時候自動清理環境,刪除unix socket文件和pid文件(try to remove all of the generated file/sockets)

相關文章
相關標籤/搜索