使用nginx+uwsgi+django發布web服務


WSGI是Web服務器網關接口。它是一個規范,描述了Web服務器如何與Web應用程序通信,以及Web應用程序如何鏈接在一起以處理一個請求,(接收請求,處理請求,響應請求)
基於wsgi運行的框架有bottle,DJango,Flask,用於解析動態HTTP請求
支持WSGI的服務器
    wsgiref
        python自帶的web服務器
    Gunicorn
        用於linux的 python wsgi Http服務器,常用於各種django,flask結合部署服務器。
    mode_wsgi
        實現了Apache與wsgi應用程序的結合
    uWSGI
        C語言開發,快速,自我修復,開發人員友好的WSGI服務器,用於Python Web應用程序的專業部署和開發。
在部署python程序web應用程序時,可以根據性能的需求,選擇合適的wsgi server,不同的wsgi server區別在於並發支持上,有單線程,多進程,多線程,協程的區別,其功能還是近似,無非是請求路由,執行對應的函數,返回處理結果。

Django部署
Django的主要部署平台是 WSGI,這是用於Web服務器和應用程序的Python標准。
Django的 startproject管理命令設置一個簡單的默認WSGI配置,可以根據需要為您的項目進行調整,並指示任何符合WSGI的應用程序服務器使用。
application 
使用WSGI部署的關鍵概念是應用程序服務器用於與代碼通信的 application 可調用。它通常在服務器可訪問的Python模塊中作為名為 application 的對象提供。

startproject 命令創建包含這樣的 application 可調用的文件 <project_name>/wsgi.py. ,它被Django的開發服務器和生產WSGI部署使用。
WSGI服務器從其配置中獲取 application 可調用的路徑。 Django的內置服務器,即 runserver 命令,從 WSGI_APPLICATION 設置讀取它。
為什么使用nginx、uwsgi
1 首先nginx 是對外的服務接口,外部瀏覽器通過url訪問nginx,

2nginx 接收到瀏覽器發送過來的http請求,將包進行解析,分析url,如果是靜態文件請求就直接訪問用戶給nginx配置的靜態文件目錄,直接返回用戶請求的靜態文件,

如果不是靜態文件,而是一個動態的請求,那么nginx就將請求轉發給uwsgi,uwsgi 接收到請求之后將包進行處理,處理成wsgi可以接受的格式,並發給wsgi,wsgi 根據請求調用應用程序的某個文件,某個文件的某個函數,最后處理完將返回值再次交給wsgi,wsgi將返回值進行打包,打包成uwsgi能夠接收的格式,uwsgi接收wsgi 發送的請求,並轉發給nginx,nginx最終將返回值返回給瀏覽器。

3要知道第一級的nginx並不是必須的,uwsgi完全可以完成整個的和瀏覽器交互的流程,但是要考慮到某些情況

1 安全問題,程序不能直接被瀏覽器訪問到,而是通過nginx,nginx只開放某個接口,uwsgi本身是內網接口,這樣運維人員在nginx上加上安全性的限制,可以達到保護程序的作用。

2負載均衡問題,一個uwsgi很可能不夠用,即使開了多個work也是不行,畢竟一台機器的cpu和內存都是有限的,有了nginx做代理,一個nginx可以代理多台uwsgi完成uwsgi的負載均衡。

3靜態文件問題,用django或是uwsgi這種東西來負責靜態文件的處理是很浪費的行為,而且他們本身對文件的處理也不如nginx好,所以整個靜態文件的處理都直接由nginx完成,靜態文件的訪問完全不去經過uwsgi以及其后面的東西。
1.單機啟動django項目,性能低,默認使用wsgiref模塊,性能低的wsgi協議

python3 manager.py runserver 0.0.0.0:8000   > wsgiref模塊中

2.高並發啟動django,django是沒有這個功能的,而uWSGI模塊,遵循uwsgi協議,支持多進程處理django請求

uwsgi  通過他,啟動你的django,而不再是python3 manager.py runserver 0.0.0.0:8000


3.公司中一般用 nginx + uwsgi + django + virtualenv  + supervisord(進程管理工具)

 

基礎開發環境配置

yum groupinstall "Development tools"
yum install zlib-devel bzip2-devel pcre-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel

安裝nginx、python3和虛擬環境virtualenv

安裝django1.11

# 我們把django安裝到我們的虛擬環境venv里面,當然也可以安裝到全局
source /home/venv/bin/activate # 激活虛擬環境
pip3 install django==1.11 #創建django項目mysite 項目在/home里面,記得注意自己的django是不是在虛擬環境安裝的 django-admin startproject mysite #創建app01 python3 manage.py startapp app01

mysite/settings.py

#settings.py設置
ALLOWED_HOSTS = ['*']
install app01  # 注意,linux不會像pycharm那幫幫我們配置app,這里必須手動配置,要不然項目找不到app

mysite/urls.py

from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^hello_django/', views.hello),
]

app01/views.py

from django.shortcuts import render,HttpResponse

# Create your views here.
def hello(request):
    print('request is :',request)
    return HttpResponse('django is ok ')

安裝uWSGI

進入虛擬環境venv,安裝uwsgi
(venv) [root@slave 192.168.11.64 /opt]$pip3 install uwsgi
檢查uwsgi版本
(venv) [root@slave 192.168.11.64 /opt]$uwsgi --version
2.0.17.1
#檢查uwsgi python版本
uwsgi --python-version
運行簡單的uWSGI
#啟動一個python  這個test.py創建到/home
uwsgi --http :8000 --wsgi-file test.py  # 此命令也要在/home里面執行
http :8000: 使用http協議,端口8000
wsgi-file test.py: 加載指定的文件,test.py
#test.py
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"] # python3

uWsgi熱加載python程序

在啟動命令后面加上參數
uwsgi --http :8088 --module mysite.wsgi --py-autoreload=1 
#發布命令 注意這兩條命令的區別
command= /home/venv/bin/uwsgi --uwsgi 0.0.0.0:8000 --chdir /opt/mysite --home=/home/venv --module mysite.wsgi
#此時修改django代碼,uWSGI會自動加載django程序,頁面生效

運行django程序

#mysite/wsgi.py  確保找到這個文件 下面的命令要在/home/mysite里面運行,注意虛擬環境
uwsgi --http :8000 --module mysite.wsgi
module mysite.wsgi: 加載指定的wsgi模塊

uwsgi配置文件

uwsgi(uwsgi的配置文件是自己創建的)支持ini、xml等多種配置方式,本文以 ini 為例, 在/etc/目錄下新建mysite_uwsgi.ini,添加如下配置:
# 注意不要將漢字注釋寫道ini配置文件內,不然提示編碼錯誤或者找不到文件
# mysite_uwsgi.ini file
[uwsgi]

# Django-related settings
# the base directory (full path)
chdir           = /home/mysite  # 運行的項目目錄
# Django's wsgi file
module          = mysite.wsgi  # 這個參數是指定的項目,在這里配置,發布命令就無需加這個參數了
# the virtualenv (full path)
home            = /home/venv  # 指定虛擬環境,如果項目不在虛擬環境運行,這條可不寫
# process-related settings
# master
master          = true  # 以主程序運行
# maximum number of worker processes
processes       = 1  # 進程,指定啟動幾個進程
# the socket (use the full path to be safe
socket          = 0.0.0.0:8109  # 指定端口 瀏覽器請求uwsgi的方式為http協議,而不是socket方式,所以如果是瀏覽器請求需要將配置文件的socket變成http
# ... with appropriate permissions - may be needed
# chmod-socket    = 664
# clear environment on exit
vacuum          = true  # 退出的時候清空環境

指定配置文件啟動命令

uwsgi --ini  /etc/mysite_uwsgi.ini  # 虛擬環境內運行

配置nginx結合uWSGI

worker_processes  1;
error_log  logs/error.log;
pid        logs/nginx.pid;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    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  logs/access.log  main;
    sendfile        on;
    keepalive_timeout  65;
  #nginx反向代理uwsgi
    server {
        listen       80;
        server_name 0.0.0.0; # 這個地方寫0.0.0.0或者自己服務器ip都可
        location / {
      #nginx自帶ngx_http_uwsgi_module模塊,起到nginx和uwsgi交互作用 #通過uwsgi_pass設置服務器地址和協議,講動態請求轉發給uwsgi處理 include /opt/nginx1-12/conf/uwsgi_params;  # uwsgi_parse都是配置信息,使用include將這些信息鏈接進來
         uwsgi_pass 0.0.0.0:8109; # 把請求丟給后端的應用程序
            root   html;
            index  index.html index.htm;
        }
      #nginx處理靜態頁面資源
      location /static{
        alias /opt/nginx1-12/static;   
         }
     #nginx處理媒體資源
     location /media{
        alias /opt/nginx1-12/media;  
         }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

 配置完啟動nginx

supervisor

supervisor 是基於 python 的任務管理工具,用來自動運行各種后台任務,當然你也能直接利用 nohup 命令使任務自動后台運行,但如果要重啟任務,每次都自己手動 kill 掉任務進程,這樣很繁瑣,而且一旦程序錯誤導致進程退出的話,系統也無法自動重載任務。

由於supervisor在python3下無法使用,因此只能用python2去下載!!!!!!

#注意此時已經退出虛擬環境了!!!!!
yum install python-setuptools
easy_install supervisor

通過命令生成supervisor的配支文件

echo_supervisord_conf > /etc/supervisord.conf

然后再/etc/supervisord.conf末尾添加上如下代碼!!!!!!

supervisord.conf配置文件參數解釋
[program:xx]是被管理的進程配置參數,xx是進程的名稱
[program:mydjango]
command=/home/venv/bin/uwsgi --uwsgi 0.0.0.0:8109 --chdir /home/mysite --home=/home/venv/ --module mysite.wsgi  ; 程序啟動命令
autostart=true       ; 在supervisord啟動的時候也自動啟動
startsecs=10         ; 啟動10秒后沒有異常退出,就表示進程正常啟動了,默認為1秒
autorestart=true     ; 程序退出后自動重啟,可選值:[unexpected,true,false],默認為unexpected,表示進程意外殺死后才重啟
startretries=3       ; 啟動失敗自動重試次數,默認是3
user=tomcat          ; 用哪個用戶啟動進程,默認是root
priority=999         ; 進程啟動優先級,默認999,值小的優先啟動
redirect_stderr=true ; 把stderr重定向到stdout,默認false
stdout_logfile_maxbytes=20MB  ; stdout 日志文件大小,默認50MB
stdout_logfile_backups = 20   ; stdout 日志文件備份數,默認是10
; stdout 日志文件,需要注意當指定目錄不存在時無法正常啟動,所以需要手動創建目錄(supervisord 會自動創建日志文件)
stdout_logfile=/opt/apache-tomcat-8.0.35/logs/catalina.out
stopasgroup=false     ;默認為false,進程被殺死時,是否向這個進程組發送stop信號,包括子進程
killasgroup=false     ;默認為false,向進程組發送kill信號,包括子進程
[program:mydjango]
#command=/opt/venv/bin/uwsgi --ini  /etc/uwsgi_nginx.ini  #這里是結合virtualenv的命令 和supervisor的精髓!!!!
command= /home/venv/bin/uwsgi --uwsgi 0.0.0.0:8109 --chdir /opt/mysite --home=/home/venv --module mysite.wsgi
#--home指的是虛擬環境目錄  --module找到 mysite/wsgi.py  

完成之后,啟動nginx

source /home/venv/bin/activate
ps -ef|grep nginx
# root     29842 10036  0 00:45 pts/0    00:00:00 grep --color=auto nginx 表示nginx未啟動
/opt/nginx1-12/sbin/nginx
ps -ef|grep nginx
# root     29875     1  0 00:45 ?        00:00:00 nginx: master process /opt/nginx1-12/sbin/nginx
# nobody   29876 29875  0 00:45 ?        00:00:00 nginx: worker process
# root     29887 10036  0 00:45 pts/0    00:00:00 grep --color=auto nginx
# 啟動了

最后啟動supervisor,完成uWSGI啟動django,nginx反向代理

supervisord -c /etc/supervisord.conf #啟動supervisor
# 啟動完成之后,直接在瀏覽器輸入ip地址,無需輸入端口就能訪問django項目了
supervisorctl # 查看啟動效果,看到mydjango RUNNING pid 30484, uptime 0:00:51啟動成功 supervisorctl
-c /etc/supervisord.conf restart mydjango #重啟mydjango項目 supervisorctl -c /etc/supervisord.conf [start|stop|restart] [program-name|all]

 重新加載supervisor

一、添加好配置文件后

二、更新新的配置到supervisord    

supervisorctl update
三、重新啟動配置中的所有程序

supervisorctl reload
四、啟動某個進程(program_name=你配置中寫的程序名稱)

supervisorctl start program_name
五、查看正在守候的進程

supervisorctl
六、停止某一進程 (program_name=你配置中寫的程序名稱)

pervisorctl stop program_name
七、重啟某一進程 (program_name=你配置中寫的程序名稱)

supervisorctl restart program_name
八、停止全部進程

supervisorctl stop all
注意:顯示用stop停止掉的進程,用reload或者update都不會自動重啟。

django的靜態文件與nginx配置

mysite/settings.py
STATIC_ROOT='/opt/nginx1-12/static'
STATIC_URL = '/static/'
STATICFILES_DIRS=[
    os.path.join(BASE_DIR,"static"),
]

上述的參數STATIC_ROOT用在哪?

通過python3 manage.py collectstatic 收集所有你使用的靜態文件保存到STATIC_ROOT!

STATIC_ROOT 文件夾 是用來將所有STATICFILES_DIRS中所有文件夾中的文件,以及各app中static中的文件都復制過來
# 把這些文件放到一起是為了用nginx等部署的時候更方便

 還需要在nginx配置文件配置static

# /opt/nginx1-12/conf/nginx.conf 里面添加下面的代碼
        location /static {
            alias /opt/nginx1-12/static;
        }
#注意加到server里面(和location / 同級)

添加完記得重啟nginx

/opt/ngin1-12/sbin/nginx -s reload

這樣訪問django項目就不會報靜態文件404了。

結束!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM