〖Python〗-- Nginx + Uwsgi +Django 實現生產環境部署

【Nginx + Uwsgi +Django 實現生產環境部署】

1、如何在生產上部署Django?

Django的部署能夠有不少方式,採用nginx+uwsgi的方式是其中比較常見的一種方式。javascript

2、uwsgi介紹

uWSGI是一個Web服務器,它實現了WSGI協議、uwsgi、http等協議。Nginx中HttpUwsgiModule的做用是與uWSGI服務器進行交換。php

要注意 WSGI / uwsgi / uWSGI 這三個概念的區分。css

  1. WSGI是一種Web服務器網關接口。它是一個Web服務器(如nginx,uWSGI等服務器)與web應用(如用Flask框架寫的程序)通訊的一種規範。
  2. uwsgi是一種線路協議而不是通訊協議,在此經常使用於在uWSGI服務器與其餘網絡服務器的數據通訊。
  3. 而uWSGI是實現了uwsgi和WSGI兩種協議的Web服務器。
  4. uwsgi協議是一個uWSGI服務器自有的協議,它用於定義傳輸信息的類型(type of information),每個uwsgi packet前4byte爲傳輸信息類型描述,它與WSGI相比是兩樣東西。

uwsgi性能很是高html

uWSGI的主要特色以下java

  1. 超快的性能
  2. 低內存佔用(實測爲apache2的mod_wsgi的一半左右)
  3. 多app管理(終於不用左思右想下個app用哪一個端口比較好了-.-)
  4. 詳盡的日誌功能(能夠用來分析app性能和瓶頸)
  5. 高度可定製(內存大小限制,服務必定次數後重啓等)

If you are searching for a simple wsgi-only server, uWSGI is not for you, but if you are building a real (production-ready) app that need to be rock-solid, fast and easy to distribute/optimize for various load-average, you will pathetically and morbidly fall in love (we hope) with uWSGI.node

3、Django + Uwsgi + Nginx 生產部署

一、準備環境python

a、須要linux服務器一臺mysql

[root@web01 ~]# cat /etc/redhat-release 
CentOS release 6.6 (Final)
[root@web01 ~]# uname -r
2.6.32-504.el6.x86_64

b、在服務器上面安裝好Python和Djangolinux

一、安裝setuptoolsnginx

 
[root@django tools]# yum install pcre pcre-devel openssl openssl-devel zlib bzip2-devel -y

[root@django tools]# ll 
-rw-r--r-- 1 root root 641502 3月   2 18:50 setuptools-19.6.tar.gz

[root@django tools]# tar xf setuptools-19.6

[root@django tools]# cd setuptools-19.6

[root@django tools]#python setup.py install

[root@django tools]#cd ..

##################################################################

#nginx模塊

pcre pcre-devel  #perl語言兼容正則表達式,用來作Nginx的HTTP Rewrite 模塊

bzip2-devel   ·#提供壓縮功能

openssl openssl-devel  #https加密模塊

###################################################################

zlib #在編譯python3的時候,加載setuptools的時候會報錯,因此這裏提早處理啦!
 

二、安裝pip

 
[root@django tools]# ll 
-rw-r--r-- 1 root root 1197370 3月   2 13:30 pip-9.0.1.tar.gz

[root@django tools]# tar xf pip-9.0.1.tar.gz 

[root@django tools]# cd pip-9.0.1

[root@django pip-9.0.1]# python setup.py install

[root@django pip-9.0.1]# cd ..

#配置環境變量:

[root@django bin]# vi /etc/profile
export PATH="/usr/local/python3/bin:$PATH"

  [root@django bin]# tail -1 /etc/profile
  export PATH="/usr/local/python3/bin:$PATH"
  [root@django bin]# source /etc/profile
  #查看幫助
  [root@django bin]# pip3  或 pip
 

三、安裝sqlite3

 
方法一:
yum install sqlite-devel

或

方法二:

軟件下載官網:http://www.sqlite.org

[root@django tools]# ll
-rw-r--r-- 1 root root 2515143 3月   2 13:33 sqlite-autoconf-3170000.tar.gz

[root@django tools]# tar xf sqlite-autoconf-3170000.tar.gz

[root@django tools]# cd sqlite-autoconf-3170000

[root@django tools]# ./configure

[root@django tools]#make && make install
 

四、安裝Python3

 
方法一:

升級爲python3.5版本步驟
root@template ~]# cd /home/oldboy/tools/

#下載python-3.5.2
[root@template tools]# wget https://www.python.org/ftp/python/3.5.2/Python-3.5.2.tgz

[root@template tools]# ll
總用量 20104
-rw-r--r--  1 root root 20566643 6月  26 05:47 Python-3.5.2.tgz

#解壓到下載目錄
[root@template tools]# tar zxvf Python-3.5.2.tgz 

#進入解壓後的文件夾
[root@template tools]# cd Python-3.5.2

#在編譯前先在/usr/local建一個文件夾python3(做爲python的安裝路徑,以避免覆蓋老的版本)
[root@template Python-3.5.2]# mkdir /usr/local/python3

#開始編譯安裝
[root@template Python-3.5.2]#  ./configure --prefix=/usr/local/python3

[root@template Python-3.5.2]# make && make install

此時沒有覆蓋老版本,再將原來/usr/bin/python連接改成別的名字
[root@template Python-3.5.2]# mv /usr/bin/python /usr/bin/python_old

#再創建新版本python的軟連接
[root@template Python-3.5.2]# ln -s /usr/local/python3/bin/python3 /usr/bin/python

#就會顯示出python的新版本信息
[root@template Python-3.5.2]# python
Python 3.5.2 (default, Aug  2 2016, 11:35:06) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-11)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()     #<----退出python

PS:若是不創建新安裝路徑python3,而是直接默認安裝,則安裝後的新python應該會覆蓋linux下自帶的老版本。固然若是還想保留原來的版本,那麼這種方法最好不過了。

注意事項:
這種方法雖然能安裝成功,但會致使yum不能正常使用。

解決方法:
[root@template tools]# cp /usr/bin/yum /usr/bin/yum.backup_2016-08-02

修改第一行參數
vi /usr/bin/yum   
把  #!/usr/bin/python    修改成:/usr/bin/python_old  
或
把  #!/usr/bin/python    修改成:/usr/bin/python2.6

#查看版本
[root@template Python-3.5.2]# python --version
Python 3.5.2

#查看安裝路徑(能夠省略這步)
[root@web01 ~]# python
Python 3.5.2 (default, May 27 2017, 18:39:42) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-11)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print(sys.path)
['', '/usr/local/python3/lib/python35.zip', '/usr/local/python3/lib/python3.5', '/usr/local/python3/lib/python3.5/plat-linux', '/usr/local/python3/lib/python3.5/lib-dynload', '/usr/local/python3/lib/python3.5/site-packages']
>>> exit()
 

5.安裝Django

 
方式一:用pip3安裝

pip3 install django

升級方法:

pip3 install django --upgrade
 
啓動django項目命令(備註:其它settings鏈接數據庫方法跟window同樣的)
#& 表示後臺啓動
python manage.py runserver 0.0.0.0:80 &   

六、安裝PyMysql (選裝,具體看你的項目鏈接方式)

 
pip3 install PyMySQL

#檢查模塊是否安裝成功
[root@web01 ~]# python
Python 3.5.2 (default, May 27 2017, 18:39:42) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-11)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pymysql 
>>> 
>>> exit()
 

c、uwsgi

# 安裝 uwsgi
[root@localhost teacher]# pip3 install uwsgi

測試uwsgi

 
[root@web01 nulige]# cd /home/nulige

[root@web01 nulige]# mkdir -p uwsgi_test

[root@web01 nulige]# cd uwsgi_test/

#測試文件

[root@web01 uwsgi_test]# vi test.py 

def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"] # python3
    #return ["Hello World"] # python2
 

啓動uwsgi

 
[root@web01 uwsgi_test]# uwsgi --http :8000 --wsgi-file test.py
*** Starting uWSGI 2.0.15 (64bit) on [Sat May 27 19:12:58 2017] ***
compiled with version: 4.4.7 20120313 (Red Hat 4.4.7-11) on 27 May 2017 18:48:50
os: Linux-2.6.32-504.el6.x86_64 #1 SMP Wed Oct 15 04:27:16 UTC 2014
nodename: web01
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 1
current working directory: /home/nulige/uwsgi_test
detected binary path: /usr/local/python3/bin/uwsgi
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
*** WARNING: you are running uWSGI without its master process manager ***
your processes number limit is 14719
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uWSGI http bound on :8000 fd 4
spawned uWSGI http 1 (pid: 17972)
uwsgi socket 0 bound to TCP address 127.0.0.1:38831 (port auto-assigned) fd 3
Python version: 3.5.2 (default, May 27 2017, 18:39:42)  [GCC 4.4.7 20120313 (Red Hat 4.4.7-11)]
*** Python threads support is disabled. You can enable it with --enable-threads ***
Python main interpreter initialized at 0x1ed4a90
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 72768 bytes (71 KB) for 1 cores
*** Operational MODE: single process ***
WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x1ed4a90 pid: 17970 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI worker 1 (and the only) (pid: 17970, cores: 1)
 

查看啓動端口

[root@web01 ~]# ps -ef|grep uwsgi
root      17970   1000  0 19:12 pts/0    00:00:00 uwsgi --http :8000 --wsgi-file test.py
root      17972  17970  0 19:12 pts/0    00:00:00 uwsgi --http :8000 --wsgi-file test.py
root      17996  17973  0 19:14 pts/1    00:00:00 grep uwsgi

在瀏覽器中,經過ip+端口號進行訪問

根據項目進行配置

# 啓動 uwsgi
    **進入項目目錄**
    **使用uwsgi啓動前確保無代碼問題致使經過runserver能夠正常啓動起來**
    uwsgi --http 192.168.31.123:8080 --file teacher/wsgi.py --static-map=/static=static #測試啓動

    # 解釋
        --http 這個就和runserver同樣指定IP 端口
        --file 這個文件就裏有一個反射,若是你在調用他的時候沒有指定Web Server就使用默認的
        -- static   作一個映射,指定靜態文件

 

二、生產環境配置

Nginx + uWSGI + Djangos配置方法:

 
# uwsig使用配置文件啓動
    [uwsgi]
    # 項目目錄
    chdir=/opt/project_teacher/teacher/
    # 指定項目的application
    module=teacher.wsgi:application
    # 指定sock的文件路徑
    socket=/opt/project_teacher/script/uwsgi.sock
    # 進程個數
    workers=5
    pidfile=/opt/project_teacher/script/uwsgi.pid
    # 指定IP端口
    http=192.168.31.123:8080
    # 指定靜態文件
    static-map=/static=/opt/test_project/teacher/static
    # 啓動uwsgi的用戶名和用戶組
    uid=root
    gid=root
    # 啓用主進程
    master=true
    # 自動移除unix Socket和pid文件當服務中止的時候
    vacuum=true
    # 序列化接受的內容,若是可能的話
    thunder-lock=true
    # 啓用線程
    enable-threads=true
    # 設置自中斷時間
    harakiri=30
    # 設置緩衝
    post-buffering=4096
    # 設置日誌目錄
    daemonize=/opt/project_teacher/script/uwsgi.log
 

# uwsig經常使用命令

 
    # 經過配置文件啓動
        uwsgi --ini uwsgi.ini
        # 會生成兩個文件
            PID文件 他是標識這個程序所處的狀態
            SOCK文件  他是用來和其餘程序通訊的
    # 中止uwsgi
        uwsgi --stop uwsgi.pid

    # 重載配置
        uwsgi --reload uwsgi.ini
 

d、nginx

#先換成國內yum源

 
#以CentOS6.x 系統爲例

一、備份
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup

二、更換成國內源
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo

三、以後運行yum makecache生成緩存
 

# 安裝nginx

yum -y install nginx

# Nginx添加配置文件

 
#先進入到配置文件:
vi /etc/nginx/conf.d/

#編輯配置文件
server {   # 這個server標識我要配置了
        listen 80;  # 我要監聽那個端口
        server_name 10.129.205.183 ;  # 你訪問的路徑前面的url名稱
        access_log  /var/log/nginx/access.log  main;  # Nginx日誌配置
        charset  utf-8; # Nginx編碼
        gzip on;  # 啓用壓縮,這個的做用就是給用戶一個網頁,好比3M壓縮後1M這樣傳輸速度就會提升不少
        gzip_types text/plain application/x-javascript text/css text/javascript application/x-httpd-php application/json text/json image/jpeg image/gif image/png application/octet-stream;  # 支持壓縮的類型

        error_page  404           /404.html;  # 錯誤頁面
        error_page   500 502 503 504  /50x.html;  # 錯誤頁面

        # 指定項目路徑uwsgi
        location / {        # 這個location就和我們Django的url(r'^admin/', admin.site.urls),
            include uwsgi_params;  # 導入一個Nginx模塊他是用來和uWSGI進行通信的
            uwsgi_connect_timeout 30;  # 設置鏈接uWSGI超時時間
            uwsgi_pass unix:/opt/project_teacher/script/uwsgi.sock;  # 指定uwsgi的sock文件全部動態請求就會直接丟給他
        }

        # 指定靜態文件路徑
        location /static/ {
            alias  /opt/project_teacher/teacher/static/;
            index  index.html index.htm;
        }

        }
 

# 啓動Nginx經過Nginx訪問

 
/etc/init.d/nginx start
/etc/init.d/nginx stop

# 這裏有個命令configtest,Nginx配置是重啓生效的,若是你修改完了,不知道對不對又擔憂影響其餘人可使用它測試
/etc/init.d/nginx configtest

# 若是是生產環境的話Nginx正在運行,就不要直接stop start 或者 restart  直接reload就好了
# 對線上影響最低(生產環境用的方法)
/etc/init.d/nginx reload 
 

e、Django Admin靜態文件配置

有一個小bug: 

# 解決Django靜態配置文件丟失

 
問題緣由:
    是由於admin所需的js,css等靜態文件都在django的安裝目錄內,可是咱們並無配置指向Django的配置文件。

解決辦法:
    咱們能夠經過配置 STATIC_ROOT = os.path.join(BASE_DIR, "static_all")來指定靜態文件的默認家目錄是那裏,而後把項目裏全部的靜態文件都收集起來放到這個目錄下面。

收集命令:
    python3 manage.py collectstatic --noinput

修改Nginx 指定靜態路徑
    alias  /opt/test_project/teacher/static_all/;
複製代碼

#參數優化

     首先參考下官網的 things to know : http://uwsgi-docs.readthedocs.org/en/latest/ThingsToKnow.html

     我這邊最終啓動的命令以下: 

     uwsgi --socket 127.0.0.1:9090 -p 16 -l 8192 -M -R 100000  -z30 -L --wsgi-file  app.py --max-apps 65535 --stats 127.0.0.1:1717 --post-buffering 100M --cpu affinity --buffer-size 65535 --daemonize /tmp/uwsgi --pidfile /tmp/uwsgi.pid  --memory-report --threads 16

4、簡易部署案例

一、準備環境

a.關閉iptables和selinux

b.配置settings.py

1
ALLOWED_HOSTS = [ '服務器' ,]

c.Django默認遵循wsgi協議:wsgiref

1
2
# 安裝uwsgi
pip3 install uwsgi 

二、簡單測試:

 
app.py
    def application(env, start_response):
        start_response('200 OK', [('Content-Type','text/html')])
        return [b"Hello World"]
        
uwsgi --http :9001 --wsgi-file app.py

uwsgi --http :9002 --wsgi-file foobar.py --master --processes 4 --threads 2
 

# 不處理靜態文件

uwsgi --http :9002 --chdir /data/s4/deploy --wsgi-file deploy/wsgi.py --master --processes 4 --threads 2 

# 處理靜態文件

 
STATICFILES_DIRS = (
    os.path.join(BASE_DIR,'static'),
)
STATIC_ROOT = os.path.join(BASE_DIR,'uuuuuu')

python manage.py collectstatic

完事,註釋靜態配置

uwsgi --http :9003 --chdir /data/s4/deploy --wsgi-file deploy/wsgi.py --static-map /static=/data/s4/deploy/uuuuuu
 

# 寫一個配置文件

 
wsgi_http.ini
    [uwsgi]
    http = 0.0.0.0:9004
    chdir = /data/s4/deploy
    wsgi-file = deploy/wsgi.py
    # processes = 4
    # threads = 2
    static-map = /static=/data/s4/deploy/uuuuuu
uwsgi wsgi_http.ini
 

# nginx反向代理使用

 
wsgi_sock.ini
    [uwsgi]
    socket = 127.0.0.1:8001
    chdir = /data/s4/deploy
    wsgi-file = deploy/wsgi.py
    # processes = 4
    # threads = 2
    static-map = /static=/data/s4/deploy/uuuuuu
uwsgi wsgi_sock.ini
 

三、Nginx

# 安裝並啓動

1
2
3
4
yum install nginx
 
/etc/init.d/nginx start/stop/restart
systemctl start/stop/restart/reload nginx

# 配置文件:/etc/nginx/nginx.conf

 
# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user root;
worker_processes 4;

error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;

events {
    worker_connections  1024;
}


http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    #types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;
    
    upstream django {
        # server unix:///path/to/your/mysite/mysite.sock; # for a file socket
        server 127.0.0.1:8001; # for a web port socket (we'll use this first)
    }
    server {
        listen      80;

        #server_name ; 
        charset     utf-8;

        
        # max upload size
        client_max_body_size 75M;   # adjust to taste

        location /static {
            alias  /data/s4/deploy/uuuuuu; # your Django project's static files - amend as required
        }

        # Finally, send all non-media requests to the Django server.
        location / {
            uwsgi_pass  django;
            include     uwsgi_params; # the uwsgi_params file you installed
        }
    }
}
相關文章
相關標籤/搜索