Nginx+uwsgi+Django 的web應用環境部署-完整記錄

散盡浮華發表於2018-12-12

 

Python作為當前最火爆最熱門,也是最主要的Web開發語言之一,在其二十多年的歷史中出現了數十種Web框架,比如Django、Tornado、Flask、Twisted、Bottle和Web.py等,它們有的歷史悠久,有的發展迅速,還有的已經停止維護。Django是一個開放原始碼的Web應用框架,由Python寫成, 它作為Python重量級選手中最有代表性的一個Web框架, 許多成功的網站和APP都基於Django。

線上的web環境準備用Nginx+Django部署, 下面分別實現了Nginx+Django的http方式Nginx+uwsgi+Django的sock方式 (並通過supervisor以守護程式方式管理uwsgi),在大併發情況下, 使用第二種方式效能會更好.  簡單記錄下操作過程:

一. Nginx+Django (http方式)

作業系統為Centos7.5 (本機ip為172.16.60.211)
[root@web-node ~]# cat /etc/redhat-release
CentOS Linux release 7.5.1804 (Core)
  
關閉防火牆和selinux
[root@web-node ~]# systemctl disable firewalld
[root@web-node ~]# systemctl stop firewalld
  
[root@web-node ~]# setenforce 0
[root@web-node ~]# vim /etc/sysconfig/selinux
SELINUX=disabled
  
1)  安裝Python3.6.1
系統預設的是python2.7, 需要升級到Python3.6.1 ( 該Django專案跑在Python3.6.1版本下)
[root@web-node ~]# python -V
Python 2.7.5
  
下載並安裝Python3.6.1
[root@web-node ~]# yum install -y gcc gcc-c++
[root@web-node ~]# yum -y install epel-release
[root@web-node ~]# yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel
[root@web-node ~]# cd /usr/local/src/
[root@web-node src]# wget wget https://www.python.org/ftp/python/3.6.1/Python-3.6.1.tar.xz
[root@web-node src]# tar xf Python-3.6.1.tar.xz
[root@web-node src]# cd Python-3.6.1
[root@web-node Python-3.6.1]# ./configure --prefix=/usr/local/python3
[root@web-node Python-3.6.1]# make && make install
  
確認安裝的Python下有pip3
[root@web-node Python-3.6.1]# ll /usr/local/python3/bin/python3
lrwxrwxrwx 1 root root 9 Dec 12 15:57 /usr/local/python3/bin/python3 -> python3.6
  
[root@web-node Python-3.6.1]# ll /usr/local/python3/bin/pip3
-rwxr-xr-x 1 root root 222 Dec 12 15:57 /usr/local/python3/bin/pip3
  
替換python
[root@web-node Python-3.6.1]# cd /usr/bin
[root@web-node bin]# mv python python.bak
[root@web-node bin]# ln -s /usr/local/python3/bin/python3.6 /usr/bin/python
[root@web-node bin]# python -V                                           
Python 3.6.1
  
設定系統環境變數
[root@web-node bin]# vim /etc/profile
PATH=$PATH:/usr/local/python3/bin
  
[root@web-node bin]# source /etc/profile
  
解決遺留問題
所有python相關的應用,如果使用/usr/bin/python開頭的指令碼,替換為/usr/bin/python2.7
[root@web-node ~]# vim /usr/bin/yum
#!/usr/bin/python2.7
  
[root@web-node ~]# vim /usr/libexec/urlgrabber-ext-down
#! /usr/bin/python2.7
  
2) 安裝nginx
[root@web-node ~]# useradd www
[root@web-node ~]# cd /usr/local/src/
[root@web-node src]# wget http://10.0.8.50/software/nginx-1.12.2.tar.gz
[root@web-node src]# tar -zvxf nginx-1.12.2.tar.gz
[root@web-node src]# cd nginx-1.12.2
[root@web-node nginx-1.12.2]# ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-http_flv_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream
[root@web-node nginx-1.12.2]# make && make install
  
配置nginx
[root@web-node nginx-1.12.2]# cd /usr/local/nginx/conf/
[root@web-node conf]# cp nginx.conf nginx.conf.bak
[root@web-node conf]# > nginx.conf
[root@web-node conf]# vim nginx.conf
user  www;
worker_processes  4;
       
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
       
#pid        logs/nginx.pid;
       
       
events {
    worker_connections  65535;
}
       
       
http {
    include       mime.types;
    default_type  application/octet-stream;
    charset utf-8;
             
    ######
    ## set access log format
    ######
    log_format  main  '$http_x_forwarded_for $remote_addr $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_cookie" $host $request_time';
       
    #######
    ## http setting
    #######
    sendfile       on;
    tcp_nopush     on;
    tcp_nodelay    on;
    keepalive_timeout  65;
    proxy_cache_path /var/www/cache levels=1:2 keys_zone=mycache:20m max_size=2048m inactive=60m;
    proxy_temp_path /var/www/cache/tmp;
       
    fastcgi_connect_timeout 3000;
    fastcgi_send_timeout 3000;
    fastcgi_read_timeout 3000;
    fastcgi_buffer_size 256k;
    fastcgi_buffers 8 256k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    fastcgi_intercept_errors on;
       
    #
    client_header_timeout 600s;
    client_body_timeout 600s;
   # client_max_body_size 50m;
    client_max_body_size 100m;
    client_body_buffer_size 256k;
       
    gzip  on;
    gzip_min_length  1k;
    gzip_buffers     4 16k;
    gzip_http_version 1.1;
    gzip_comp_level 9;
    gzip_types       text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php;
    gzip_vary on;
       
    ## includes vhosts
    include vhosts/*.conf;
}
  
[root@web-node conf]# mkdir /usr/local/nginx/conf/vhosts
[root@web-node conf]# mkdir -p /var/www/cache
[root@web-node conf]# ulimit 65535
  
[root@web-node conf]# vim vhosts/ng.conf
upstream py-8001 {
      ip_hash;
      server 127.0.0.1:8001  max_fails=3 fail_timeout=15s;
      server 127.0.0.1:8002  max_fails=3 fail_timeout=15s;
}
                
  server {
      listen      80;
      server_name kevin.com www.kevin.com btc.kevin.com eth.kevin.com;
          
      access_log  /usr/local/nginx/logs/8001-access.log main;
      error_log  /usr/local/nginx/logs/8001-error.log;
          
 location / {
         proxy_pass http://py-8001;
         proxy_redirect off ;
         proxy_set_header Host $host;
         proxy_set_header X-Real-IP $remote_addr;
         proxy_set_header REMOTE-HOST $remote_addr;
         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_connect_timeout 300;
         proxy_send_timeout 300;
         proxy_read_timeout 600;
         proxy_buffer_size 256k;
         proxy_buffers 4 256k;
         proxy_busy_buffers_size 256k;
         proxy_temp_file_write_size 256k;
         proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_404;
         proxy_max_temp_file_size 128m;
         #proxy_cache mycache;                          
         #proxy_cache_valid 200 302 1h;
         #proxy_cache_valid 301 1d;
         #proxy_cache_valid any 1m;
        }
      
 location /static/ {
      alias /data/www/APPServer/staticfiles/;
}
}
  
接著配置禁止ip訪問,  只能通過域名訪問 (vhosts下有很多域名的conf配置,那麼只需要建立建立一個檔案,比如deny.ip.conf,輸入下面五行內容,這樣就全域性禁止了ip訪問,只能使用域名訪問了!))
[root@web-node ~]# cat /usr/local/nginx/conf/vhosts/deny.ip.conf
server{
listen 80 default;
server_name _;
return 500;
}
 
檢查nginx配置檔案是否正確
[root@r1014001 ~]# /usr/local/nginx/sbin/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下就只能使用域名訪問了, 使用ip訪問的話, 就會出現"500 Internal Server Error"的資訊, 即禁止ip訪問!
 
3) 安裝django (專案中使用的mysql是阿里雲上的rds)
[root@web-node ~]# yum install MySQL-python
[root@web-node ~]# pip3 install Django==1.11      //最好使用pip3的全路徑, 即"/usr/local/python3/bin/pip3 install Django==1.11", 否則可能會報錯 
[root@web-node ~]# pip3 install pymysql           //最好使用pip3的全路徑, 即"/usr/local/python3/bin/pip3 install pymysql", 否則可能會報錯
  
django專案存放路徑: /data/www/APPServer
靜態頁存放路徑: /data/www/APPServer/staticfiles/
靜態頁通過nginx訪問展示(匹配static的路徑), 動態頁面通過nginx轉發給python處理
  
將django專案程式碼拷貝到/data/www/APPServer 目錄中
[root@web-node ~]# mkdir -p /data/www/APPServer/
[root@web-node ~]# chown -R www.www /data/www/APPServer
[root@web-node ~]# cd /data/www/APPServer/
[root@web-node APPServer]# ls
db.sqlite3  django_auth_example  manage.py  staticfiles  templates  users
[root@web-node APPServer]# ls django_auth_example/
__init__.py  __init__.pyc  __pycache__  settings.py  settings.pyc  urls.py  urls.pyc  wsgi.py
[root@web-node APPServer]# ll staticfiles/strategy/
total 1552
-rw-r--r-- 1 www www  51215 Dec 11 17:55 all.css
-rw-r--r-- 1 www www  67742 Dec 11 17:55 bootstrap.bundle.min.js
-rw-r--r-- 1 www www 144877 Dec 11 17:55 bootstrap.min.css
-rw-r--r-- 1 www www 717611 Dec 11 17:55 echarts.min.js
-rw-r--r-- 1 www www  31000 Dec 11 17:55 font-awesome.min.css
-rw-r--r-- 1 www www   5187 Dec 11 17:55 index.js
-rw-r--r-- 1 www www  86351 Dec 11 17:55 jquery-3.1.0.min.js
-rw-r--r-- 1 www www  86927 Dec 11 17:55 jquery.min.js
-rw-r--r-- 1 www www    721 Dec 11 17:55 main.css
-rw-r--r-- 1 www www      0 Dec 11 17:55 main.js
-rw-r--r-- 1 www www   5872 Dec 11 17:55 master.js
-rw-r--r-- 1 www www   9662 Dec 11 17:55 tuzi.ico
-rw-r--r-- 1 www www 351295 Dec 11 17:55 v3-4b631620.css
  
啟動python程式, 由於是互動式的, 這裡通過tmux終端複用工具
[root@web-node ~]# yum install tmux
  
編寫python程式啟動和關閉指令碼
[root@web-node ~]# mkdir /data/script
[root@web-node ~]# cd /data/script
  
啟動指令碼 (這裡我啟動了兩個python程式程式, 並通過nginx進行代理轉發, 將請求負載轉發到這兩個python埠上. 其實一臺機器最好啟動一個python程式, 多臺機器啟動多個python程式並通過nginx轉發)
[root@web-node script]# vim py_start.sh
#!/bin/bash
tmux new -d -s bobo_session && tmux send -t bobo_session 'python /data/www/APPServer/manage.py runserver  0.0.0.0:8001' ENTER
tmux new -d -s bobo1_session && tmux send -t bobo1_session 'python /data/www/APPServer/manage.py runserver  0.0.0.0:8002' ENTER
  
================================================================================
溫馨提示:
上面的python程式啟動時, 埠前面最好不要加ip了, 比如"/usr/local/python3/bin/python3 /data/www/APPServer/manage.py runserver 8001"
這樣就只能通過nginx代理訪問了, 即http://172.16.60.211, 使用http://172.16.60.211:8001和http://172.16.60.211:8002就不能訪問了
================================================================================
  
關閉指令碼
[root@web-node script]# vim py_stop.sh
#!/bin/bash
tmux kill-session -t bobo_session && tmux kill-session -t bobo1_session
  
授予指令碼執行許可權
[root@web-node script]# chmod 755 ./*
[root@web-node script]# ll
total 8
-rwxr-xr-x 1 root root 267 Dec 12 16:55 py_start.sh
-rwxr-xr-x 1 root root  85 Dec 12 16:55 py_stop.sh
  
啟動nginx和python程式
[root@web-node ~]# /usr/local/nginx/sbin/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
  
[root@web-node ~]# /usr/local/nginx/sbin/nginx
  
[root@web-node ~]# sh /data/script/py_start.sh
  
[root@web-node ~]# ps -ef|grep nginx
root      1322     1  0 16:56 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
www       1323  1322  0 16:56 ?        00:00:00 nginx: worker process
www       1324  1322  0 16:56 ?        00:00:00 nginx: worker process
www       1325  1322  0 16:56 ?        00:00:00 nginx: worker process
www       1326  1322  0 16:56 ?        00:00:00 nginx: worker process
www       1327  1322  0 16:56 ?        00:00:00 nginx: cache manager process
www       1328  1322  0 16:56 ?        00:00:00 nginx: cache loader process
root      1397 12945  0 16:56 pts/0    00:00:00 grep --color=auto nginx
  
[root@web-node ~]# ps -ef|grep manage
www       1327  1322  0 16:56 ?        00:00:00 nginx: cache manager process
root      1370  1341  3 16:56 pts/4    00:00:00 python /data/www/APPServer/manage.py runserver 0.0.0.0:8002
root      1371  1336  3 16:56 pts/2    00:00:00 python /data/www/APPServer/manage.py runserver 0.0.0.0:8001
root      1374  1370  6 16:56 pts/4    00:00:00 /usr/bin/python /data/www/APPServer/manage.py runserver 0.0.0.0:8002
root      1375  1371  5 16:56 pts/2    00:00:00 /usr/bin/python /data/www/APPServer/manage.py runserver 0.0.0.0:8001
root      1399 12945  0 16:56 pts/0    00:00:00 grep --color=auto manage
  
[root@web-node ~]# lsof -i:80
COMMAND  PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
nginx   1322 root    7u  IPv4 68809825      0t0  TCP *:http (LISTEN)
nginx   1323  www    7u  IPv4 68809825      0t0  TCP *:http (LISTEN)
nginx   1324  www    7u  IPv4 68809825      0t0  TCP *:http (LISTEN)
nginx   1325  www    7u  IPv4 68809825      0t0  TCP *:http (LISTEN)
nginx   1326  www    7u  IPv4 68809825      0t0  TCP *:http (LISTEN)
  
[root@web-node ~]# lsof -i:8001
COMMAND  PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
python  1375 root    4u  IPv4 68810914      0t0  TCP *:vcom-tunnel (LISTEN)
  
[root@web-node ~]# lsof -i:8002
COMMAND  PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
python  1374 root    4u  IPv4 68811847      0t0  TCP *:teradataordbms (LISTEN)
  
[root@web-node ~]# tmux ls
bobo1_session: 1 windows (created Wed Dec 12 16:56:51 2018) [194x45]
bobo_session: 1 windows (created Wed Dec 12 16:56:51 2018) [194x45]
  
最後將nginx配置檔案中指定的域名kevin.com, www.kevin.com, btc.kevin.com, eth.kevin.com 解析到本機ip
然後輸入http://www.kevin.com 即可訪問django的web專案.

二. Nginx+uwsgi+Django (socker方式)
Django的部署可以有很多方式,採用nginx+uwsgi的方式是Django生產環境部署中比較常見的一種方式

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

這裡一定要注意 WSGI , uwsgi , uWSGI 這三個概念的區分:
1) WSGI是一種Web伺服器閘道器介面。它是一個Web伺服器(如nginx,uWSGI等伺服器)與web應用(如用Flask框架寫的程式)通訊的一種規範。
2) uwsgi是一種線路協議而不是通訊協議,在此常用於在uWSGI伺服器與其他網路伺服器的資料通訊。
3) uWSGI是實現了uwsgi和WSGI兩種協議的Web伺服器。

uwsgi協議是一個uWSGI伺服器自有的協議,它用於定義傳輸資訊的型別,每一個uwsgi packet前4byte為傳輸資訊型別描述,它與WSGI相比是兩樣東西。uwsgi是一種線路協議而不是通訊協議,在此常用於在uwsgi伺服器與其他網路伺服器的資料通訊。uwsgi協議是一個uwsgi伺服器自有的協議,它用於定義傳輸資訊的型別。uwsgi實現了WSGI的所有介面,是一個快速、自我修復、開發人員和系統管理員友好的伺服器。uwsgi程式碼完全用C編寫,效率高、效能穩定。

uWSGI的主要特點如下
-  超快的效能;
-  低記憶體佔用(實測為apache2的mod_wsgi的一半左右);
-  多app管理(終於不用冥思苦想下個app用哪個埠比較好了);
-  詳盡的日誌功能(可以用來分析app效能和瓶頸);
-  高度可定製(記憶體大小限制,服務一定次數後重啟等);

uwsgi作用
Django 是一個 Web 框架,框架的作用在於處理 request 和 reponse,其他的不是框架所關心的內容。所以怎麼部署 Django 不是 Django 所需要關心的。Django 所提供的是一個開發伺服器,這個開發伺服器,沒有經過安全測試,而且使用的是 Python 自帶的 simple HTTPServer 建立的,在安全性和效率上都是不行的而uwsgi 是一個全功能的 HTTP 伺服器,他要做的就是把 HTTP 協議轉化成語言支援的網路協議。比如把 HTTP 協議轉化成 WSGI 協議,讓 Python 可以直接使用。 
uwsgi 是一種 uwsgi 的內部協議,使用二進位制方式和其他應用程式進行通訊。

總之uwsgi真的是一個好東西, 用起來效能非常高. 如果使用nginx+uwsgi方式, nginx作為反向代理,和uwsgi間通過http互動。配置nginx和uwsgi通過socket結合的方式原理使用者傳送http請求到nginx,nginx通過socket把請求交給uwsgi,uwsgi拿到django的處理結果,通過socket返還給nginx,nginx通過http返回結果給使用者。操作如下:

安裝uwsgi
[root@web-node ~]# pip3 install uwsgi
  
編寫測試
[root@web-node ~]# vim /root/test.py
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"]
  
啟動測試
[root@web-node ~]# uwsgi --http :9009 --wsgi-file test.py
  
接著訪問http://172.16.60.211:9009/  , 即可看到"Hello World"的訪問資訊.
  
下面開始nginx+uwsgi的配置
[root@web-node ~]# ll /usr/local/nginx/conf/uwsgi*
-rw-r--r-- 1 root root 664 Dec 12 16:25 /usr/local/nginx/conf/uwsgi_params
-rw-r--r-- 1 root root 664 Dec 12 16:25 /usr/local/nginx/conf/uwsgi_params.default
  
手動編寫uwsgi.ini配置檔案 (由於這裡我啟動了兩個python程式, 即8001和8002埠, 所以這裡要編寫兩個uwsgi配置檔案)
[root@web-node ~]# vim /usr/local/nginx/conf/uwsgi1.ini
[uwsgi]
#the local unix socket file than commnuincate to Nginx
socket = 127.0.0.1:8001
 
# the base directory (full path)
chdir = /data/www/APPServer
 
# Django's wsgi file
wsgi-file = django_auth_example/wsgi.py
 
# maximum number of worker processes
processes = 4
 
#thread numbers startched in each worker process
threads = 2
 
[root@web-node ~]# vim /usr/local/nginx/conf/uwsgi2.ini 
[uwsgi]
#the local unix socket file than commnuincate to Nginx
socket = 127.0.0.1:8002
 
# the base directory (full path)
chdir = /data/www/APPServer
 
# Django's wsgi file
wsgi-file = django_auth_example/wsgi.py
 
# maximum number of worker processes
processes = 4
 
#thread numbers startched in each worker process
threads = 2
 
啟動uwsgi (先關閉之前啟動的python程式和nginx)
[root@web-node ~]# sh /data/script/py_stop.sh
[root@web-node ~]# /usr/local/nginx/sbin/nginx -s stop
  
[root@web-node ~]# uwsgi /usr/local/nginx/conf/uwsgi1.ini  
[root@web-node ~]# uwsgi /usr/local/nginx/conf/uwsgi2.ini
 
由於uwsgi啟動也是互動式, 所以還是需要用到tmux工具, 編寫uwsgi啟動和關閉指令碼
  
uwsgi啟動指令碼
[root@web-node ~]# vim /data/script/uwsgi_start.sh
#!/bin/bash
tmux new -d -s bobo_session && tmux send -t bobo_session 'uwsgi /usr/local/nginx/conf/uwsgi1.ini' ENTER
tmux new -d -s bobo1_session && tmux send -t bobo1_session 'uwsgi /usr/local/nginx/conf/uwsgi2.ini' ENTER
 
uwsgi關閉指令碼
[root@web-node ~]# vim /data/script/uwsgi_stop.sh
#!/bin/bash
tmux kill-session -t bobo_session && tmux kill-session -t bobo1_session
ps -ef|grep uwsgi|grep -v grep|awk '{print $2}'|xargs kill -9  >/dev/null 2>&1
 
執行uwsgi啟動
[root@web-node ~]# sh /data/script/uwsgi_start.sh
 
[root@web-node ~]# tmux ls
bobo1_session: 1 windows (created Wed Dec 12 22:49:49 2018) [136x29]
bobo_session: 1 windows (created Wed Dec 12 22:49:49 2018) [136x29]
 
[root@web-node ~]# lsof -i:8001
COMMAND   PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
uwsgi   21161 root    3u  IPv4 69341001      0t0  TCP localhost:vcom-tunnel (LISTEN)
uwsgi   21165 root    3u  IPv4 69341001      0t0  TCP localhost:vcom-tunnel (LISTEN)
uwsgi   21166 root    3u  IPv4 69341001      0t0  TCP localhost:vcom-tunnel (LISTEN)
uwsgi   21167 root    3u  IPv4 69341001      0t0  TCP localhost:vcom-tunnel (LISTEN)
 
[root@web-node ~]# lsof -i:8002
COMMAND   PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
uwsgi   21162 root    3u  IPv4 69341406      0t0  TCP localhost:teradataordbms (LISTEN)
uwsgi   21172 root    3u  IPv4 69341406      0t0  TCP localhost:teradataordbms (LISTEN)
uwsgi   21173 root    3u  IPv4 69341406      0t0  TCP localhost:teradataordbms (LISTEN)
uwsgi   21174 root    3u  IPv4 69341406      0t0  TCP localhost:teradataordbms (LISTEN)
 
[root@web-node ~]# ps -ef|grep uwsgi
root     21161 21128  0 22:49 pts/1    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     21162 21135  0 22:49 pts/2    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     21165 21161  0 22:49 pts/1    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     21166 21161  0 22:49 pts/1    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     21167 21161  0 22:49 pts/1    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     21172 21162  0 22:49 pts/2    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     21173 21162  0 22:49 pts/2    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     21174 21162  0 22:49 pts/2    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     21231 18304  0 22:50 pts/0    00:00:00 grep --color=auto uwsgi
 
接著進行nginx+uwsgi配置
[root@web-node ~]# vim /usr/local/nginx/conf/vhosts/ng.conf
upstream django {
    ip_hash;
    server 127.0.0.1:8001  max_fails=3 fail_timeout=15s;
    server 127.0.0.1:8002  max_fails=3 fail_timeout=15s;
}          
   server {
     listen      80;
     server_name kevin.com www.kevin.com btc.kevin.com eth.kevin.com;
     charset     utf-8;
         
     access_log  /usr/local/nginx/logs/8001-access.log main;
     error_log  /usr/local/nginx/logs/8001-error.log;
         
   location / {
     uwsgi_pass  django;
     include    /usr/local/nginx/conf/uwsgi_params;
     }
     
   location /static/ {
     alias /data/www/APPServer/staticfiles/;
   }
}
 
啟動nginx
[root@web-node ~]# /usr/local/nginx/sbin/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
 
[root@web-node ~]# /usr/local/nginx/sbin/nginx
 
[root@web-node ~]# ps -ef|grep nginx
root     21161 21128  0 22:49 pts/1    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     21162 21135  0 22:49 pts/2    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     21165 21161  0 22:49 pts/1    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     21166 21161  0 22:49 pts/1    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     21167 21161  0 22:49 pts/1    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     21172 21162  0 22:49 pts/2    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     21173 21162  0 22:49 pts/2    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     21174 21162  0 22:49 pts/2    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     21263     1  0 22:51 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
www      21264 21263  0 22:51 ?        00:00:00 nginx: worker process
www      21265 21263  0 22:51 ?        00:00:00 nginx: worker process
www      21266 21263  0 22:51 ?        00:00:00 nginx: worker process
www      21267 21263  0 22:51 ?        00:00:00 nginx: worker process
www      21268 21263  0 22:51 ?        00:00:00 nginx: cache manager process
www      21269 21263  0 22:51 ?        00:00:00 nginx: cache loader process
root     21271 18304  0 22:51 pts/0    00:00:00 grep --color=auto nginx
 
[root@web-node ~]# lsof -i:80
COMMAND   PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
nginx   21263 root    7u  IPv4 69341986      0t0  TCP *:http (LISTEN)
nginx   21264  www    7u  IPv4 69341986      0t0  TCP *:http (LISTEN)
nginx   21265  www    7u  IPv4 69341986      0t0  TCP *:http (LISTEN)
nginx   21266  www    7u  IPv4 69341986      0t0  TCP *:http (LISTEN)
nginx   21267  www    7u  IPv4 69341986      0t0  TCP *:http (LISTEN)
 
最後輸入http://www.kevin.com, 即可訪問django的web專案

Supervisor管理uwsgi (守護程式模式)

由於直接執行uwsgi是互動式的, 所以上面使用了tmux終端複用工具, 如果不使用tmux, 則可以使用supervisor, 使用supervisor管理uwsgi, 為了讓它後臺執行,需要讓它變成守護程式。supervisor的使用可以參考: https://www.cnblogs.com/kevingrace/p/7525200.html  .  以下是supervisor的安裝和管理記錄:

1) 安裝supervisor
[root@web-node ~]# pip3 install supervisor
會遇到如下報錯資訊:
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-ns8sn4n6/supervisor/
You are using pip version 9.0.1, however version 18.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
  
這是因為supervisor不支援python3, pip3使用的是python3.6.1版本
[root@web-node ~]# python -V
Python 3.6.1
  
1.1) 安裝pyenv
為了使用supervisor,我們需要python2.7的環境。而多版本python的管理,推薦使用pyenv。
  
安裝pyenv套裝
[root@web-node ~]# curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash
  
內容除了包含 pyenv 以外,還包含如下外掛:
- pyenv-doctor
- pyenv-installer
- pyenv-update
- pyenv-virtualenv
- pyenv-which-ext
  
=========================================================
溫馨提示:
以上https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer的訪問內容
, 可以將內容粘出來放在伺服器的一個shell指令碼檔案中, 然後執行該指令碼用以安裝pyenv
  
該指令碼的百度下載地址:  https://pan.baidu.com/s/1wW9ylrmc4Q9wxu_i3-1wYA
提取密碼: rhtj
  
執行指令碼進行安裝(執行前授予755許可權)
# chmod 755 pyenv-installer
# /bin/bash pyenv-installer
=========================================================
  
路徑新增
[root@web-node ~]# ll -d /root/.pyenv
drwxr-xr-x 11 root root 331 Dec 13 10:08 /root/.pyenv
  
[root@web-node ~]# vim ~/.bash_profile              //新增下面內容
export PATH="/root/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
  
使之生效
[root@web-node ~]# source ~/.bash_profile
  
檢視安裝情況
[root@web-node ~]# pyenv -v
pyenv 1.2.8
  
常用命令
- 檢視可安裝的python版本列表:pyenv install -l
- 安裝指定版本的python:pyenv install 2.7.3
- 檢視已安裝的python:pyenv versions
- 檢視當前設為預設的python版本:pyenv version
  
1.2) 安裝python2.7環境
pyenv安裝指定版本的python
[root@web-node python]# pyenv install 2.7.13
Installing Python-2.7.13...
Installed Python-2.7.13 to /root/.pyenv/versions/2.7.13
  
[root@web-node ~]# /root/.pyenv/versions/2.7.13/bin/python2.7 -V
Python 2.7.13
  
檢視pyenv已安裝的python
[root@web-node ~]# pyenv versions
  system
* 2.7.13 (set by /root/.pyenv/version)
  2.7.13/envs/supervisor
  
檢視當前pyenv設為預設的python版本
[root@web-node ~]# pyenv version
2.7.13 (set by /root/.pyenv/version)
  
1.3) 安裝虛擬環境
新建supervisor虛擬環境
[root@web-node ~]# pyenv virtualenv 2.7.13 supervisor
  
啟用虛擬環境
[root@web-node ~]# source /root/.pyenv/versions/2.7.13/envs/supervisor/bin/activate supervisor
(supervisor) [root@web-node ~]#
或者
(supervisor) [root@web-node ~]# source activate supervisor
(supervisor) [root@web-node ~]#
  
安裝supervisor
(supervisor) [root@web-node ~]# yum install supervisor
(supervisor) [root@web-node ~]# pip install supervisor
  
生成配置檔案
(supervisor) [root@web-node ~]# mkdir -p /etc/supervisor/
(supervisor) [root@web-node ~]# echo_supervisord_conf > /etc/supervisord.conf
  
修改配置檔案 (檔案最底行新增下面內容)
(supervisor) [root@web-node ~]# vim /etc/supervisord.conf
[include]
files = /etc/supervisor/*.conf
  
執行
(supervisor) [root@web-node ~]# /root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisord -c /etc/supervisord.conf
  
(supervisor) [root@web-node ~]# ps -ef|grep supervisord
root     30765     1  0 10:57 ?        00:00:00 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/python2.7 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisord -c /etc/supervisord.conf
root     30798 10184  0 10:57 pts/1    00:00:00 grep --color=auto supervisord
  
1.4) 編輯supervisord.service
(supervisor) [root@web-node ~]# cp /usr/lib/systemd/system/supervisord.service /usr/lib/systemd/system/supervisord.service.bak
(supervisor) [root@web-node ~]# vim /usr/lib/systemd/system/supervisord.service        //內容修改為(之前的內容清空, 複製下面的內容)
[Unit]
Description=Process Monitoring and Control Daemon
After=rc-local.service nss-user-lookup.target
  
[Service]
Type=forking
ExecStart=/root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisord -c /etc/supervisord.conf
ExecReload=/root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisorctl reload     
ExecStop=/root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisorctl shutdown    
  
[Install]
WantedBy=multi-user.target
  
1.5) 重啟supervisor (多測試幾次)
(supervisor) [root@web-node ~]# ps aux | grep supervisord
root     31663  0.0  0.1 215176 13856 ?        Ss   11:03   0:00 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/python2.7 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisord -c /etc/supervisord.conf
root     31781  0.0  0.0 112704   976 pts/1    S+   11:03   0:00 grep --color=auto supervisord
  
由於上面的supervisord程式是使用配置檔案手動啟動的, 首次要使用下面的命令關閉,然後使用"systemctl start/stop supervisord" 才會生效
如果第一次不使用下面命令關閉, 而首次就使用"systemctl stop supervisord" 則關閉不了.
(supervisor) [root@web-node ~]# /root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisorctl shutdown
Shut down
(supervisor) [root@web-node ~]# ps aux | grep supervisord                                            
root     31857  0.0  0.0 112704   972 pts/1    S+   11:04   0:00 grep --color=auto supervisord
  
(supervisor) [root@web-node ~]# systemctl start supervisord
(supervisor) [root@web-node ~]# ps aux | grep supervisord
root     31892  0.0  0.1 217312 13872 ?        Ss   11:04   0:00 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/python2.7 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisord -c /etc/supervisord.conf
root     31919  0.0  0.0 112704   972 pts/1    S+   11:04   0:00 grep --color=auto supervisord
  
(supervisor) [root@web-node ~]# systemctl stop supervisord                                            
(supervisor) [root@web-node ~]# ps aux | grep supervisord
root     31986  0.0  0.0 112704   976 pts/1    S+   11:04   0:00 grep --color=auto supervisord
  
(supervisor) [root@web-node ~]# systemctl start supervisord
(supervisor) [root@web-node ~]# ps aux | grep supervisord
root     32037  0.0  0.1 217312 13868 ?        Ss   11:04   0:00 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/python2.7 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisord -c /etc/supervisord.conf
root     32064  0.0  0.0 112704   976 pts/1    S+   11:04   0:00 grep --color=auto supervisord
  
1.6) 設定開機啟動
(supervisor) [root@web-node ~]# systemctl enable supervisord
Created symlink from /etc/systemd/system/multi-user.target.wants/supervisord.service to /usr/lib/systemd/system/supervisord.service.
  
2) 守護uwsgi
先關閉之前使用tmux啟動的uwsgi程式
(supervisor) [root@web-node ~]# ps -ef|grep uwsgi
root     29088 29055  0 00:53 pts/4    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     29089 29061  0 00:53 pts/5    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     29092 29089  0 00:53 pts/5    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     29093 29089  0 00:53 pts/5    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     29094 29089  0 00:53 pts/5    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     29098 29088  0 00:53 pts/4    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     29099 29088  0 00:53 pts/4    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     29100 29088  0 00:53 pts/4    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     32579 10184  0 11:09 pts/1    00:00:00 grep --color=auto uwsgi
  
(supervisor) [root@web-node ~]# tmux ls
bobo1_session: 1 windows (created Thu Dec 13 00:53:19 2018) [136x29]
bobo_session: 1 windows (created Thu Dec 13 00:53:19 2018) [136x29]
  
(supervisor) [root@web-node ~]# sh /data/script/uwsgi_stop.sh
Killed
  
(supervisor) [root@web-node ~]# ps -ef|grep uwsgi
root     32689 10184  0 11:09 pts/1    00:00:00 grep --color=auto uwsgi
  
(supervisor) [root@web-node ~]# tmux ls
failed to connect to server
  
2.1) 配置supervisor, 以守護程式方式管理uwsgi
先關閉上面啟動的supervisord
(supervisor) [root@web-node supervisor]# systemctl stop supervisord
(supervisor) [root@web-node supervisor]# ps aux | grep supervisord
root      2467  0.0  0.0 112704   972 pts/1    S+   11:27   0:00 grep --color=auto supervisord
 
因為nginx和uwsgi通過socket方式互動,所以需要修改uwsgi.ini的配置為:
(supervisor) [root@web-node supervisor]# cd /usr/local/nginx/conf/
(supervisor) [root@web-node conf]# cp uwsgi1.ini uwsgi1.ini.bak
(supervisor) [root@web-node conf]# cp uwsgi2.ini uwsgi2.ini.bak
(supervisor) [root@web-node conf]# vim uwsgi1.ini
[uwsgi]
socket = :8001                      
chdir = /data/www/APPServer
wsgi-file = django_auth_example/wsgi.py
static-map = '/static=static'
master = true
processes = 2
enable-threads = true
  
(supervisor) [root@web-node conf]# vim uwsgi2.ini
[uwsgi]
socket = :8002               
chdir = /data/www/APPServer
wsgi-file = django_auth_example/wsgi.py
static-map = '/static=static'
master = true
processes = 2
enable-threads = true
  
接著在/etc/supervisor中新建檔案bobo.conf和bobo1.conf(這裡啟動了兩個埠, 所以也要配置兩個)
(supervisor) [root@web-node supervisor]# vim bobo.conf
[program:bobo]
command=/usr/local/python3/bin/uwsgi /usr/local/nginx/conf/uwsgi1.ini
directory=/usr/local/nginx/conf/
startsecs=0
stopwaitsecs=0
autostart=true
autorestart=true
  
(supervisor) [root@web-node supervisor]# vim bobo1.conf
[program:bobo1]
command=/usr/local/python3/bin/uwsgi /usr/local/nginx/conf/uwsgi2.ini
directory=/usr/local/nginx/conf/
startsecs=0
stopwaitsecs=0
autostart=true
autorestart=true
  
重啟supervisor
(supervisor) [root@web-node supervisor]# ps aux | grep supervisord
root      5177  0.0  0.0 112704   972 pts/1    S+   11:47   0:00 grep --color=auto supervisord
(supervisor) [root@web-node supervisor]# systemctl start supervisord      
  
(supervisor) [root@web-node supervisor]# ps aux | grep supervisord
root      5218  0.0  0.1 217568 14104 ?        Ss   11:47   0:00 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/python2.7 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisord -c /etc/supervisord.conf
root      5253  0.0  0.0 112704   972 pts/1    S+   11:47   0:00 grep --color=auto supervisord

(supervisor) [root@web-node supervisor]# systemctl status supervisord   
● supervisord.service - Process Monitoring and Control Daemon
   Loaded: loaded (/usr/lib/systemd/system/supervisord.service; enabled; vendor preset: disabled)
   Active: active (running) since Thu 2018-12-13 13:35:46 CST; 26s ago
  Process: 11883 ExecStop=/root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisorctl shutdown (code=exited, status=0/SUCCESS)
  Process: 12681 ExecStart=/root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisord -c /etc/supervisord.conf (code=exited, status=0/SUCCESS)
 Main PID: 12684 (supervisord)
   CGroup: /system.slice/supervisord.service
           ├─12684 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/python2.7 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/superv...
           ├─12717 /usr/local/python3/bin/uwsgi /usr/local/nginx/conf/uwsgi1.ini
           ├─12718 /usr/local/python3/bin/uwsgi /usr/local/nginx/conf/uwsgi2.ini
           ├─12721 /usr/local/python3/bin/uwsgi /usr/local/nginx/conf/uwsgi1.ini
           ├─12722 /usr/local/python3/bin/uwsgi /usr/local/nginx/conf/uwsgi1.ini
           ├─12723 /usr/local/python3/bin/uwsgi /usr/local/nginx/conf/uwsgi2.ini
           └─12724 /usr/local/python3/bin/uwsgi /usr/local/nginx/conf/uwsgi2.ini

Dec 13 13:35:46 web-node systemd[1]: Starting Process Monitoring and Control Daemon...
Dec 13 13:35:46 web-node systemd[1]: Started Process Monitoring and Control Daemon.
Warning: supervisord.service changed on disk. Run 'systemctl daemon-reload' to reload units.
  
(supervisor) [root@web-node supervisor]# lsof -i:8001
COMMAND  PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
uwsgi   5244 root    3u  IPv4 70530592      0t0  TCP *:vcom-tunnel (LISTEN)
uwsgi   5250 root    3u  IPv4 70530592      0t0  TCP *:vcom-tunnel (LISTEN)
uwsgi   5251 root    3u  IPv4 70530592      0t0  TCP *:vcom-tunnel (LISTEN)
  
(supervisor) [root@web-node supervisor]# lsof -i:8002
COMMAND  PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
uwsgi   5245 root    3u  IPv4 70531513      0t0  TCP *:teradataordbms (LISTEN)
uwsgi   5248 root    3u  IPv4 70531513      0t0  TCP *:teradataordbms (LISTEN)
uwsgi   5249 root    3u  IPv4 70531513      0t0  TCP *:teradataordbms (LISTEN)
  
========================================================
附帶溫馨提示
直接重啟supervisor專案bobo和專案bobo1的命令
(supervisor) [root@web-node supervisor]# supervisorctl -c /etc/supervisord.conf restart bobo
bobo: stopped
bobo: started
  
(supervisor) [root@web-node supervisor]# supervisorctl -c /etc/supervisord.conf restart bobo1
bobo1: stopped
bobo1: started
========================================================
  
上面在nginx中vhosts/ng.conf檔案中配置的轉發關係不用修改.
需要知道的事: 此時django專案中的的靜態資源並不是通過uwsgi獲取, 而是通過nginx直接獲取的(匹配static的path路徑訪問靜態資源)
  
此時輸入http://www.kevin.com, 即可訪問django的web專案!
  
最後退出supervisor環境
(supervisor) [root@web-node supervisor]# source deactivate
pyenv-virtualenv: deactivate 2.7.13/envs/supervisor
[root@web-node supervisor]#
  
退出supervisor環境後, uwsgi守護程式並沒有受到影響。
  
再次進入supervisor環境
[root@web-node supervisor]# source activate supervisor
pyenv-virtualenv: activate supervisor
pyenv-virtualenv: prompt changing will be removed from future release. configure `export PYENV_VIRTUALENV_DISABLE_PROMPT=1' to simulate the behavior.
(supervisor) [root@web-node supervisor]#

相關文章