Ubuntu+uWSGI部署Django項目【鴻篇巨製,事無巨細】

背景

任務:

  影片翻譯項目需要在兩個伺服器上進行通訊(國內&海外的阿里服務器)。

  因為python是主語言,選用了Django 來快速部署API。

  註:Django中文文檔//docs.djangoproject.com/zh-hans/3.0/

啰嗦:

  本地創建項目很輕鬆,但部署到伺服器上困難重重。

  將過程記錄下來,一來記錄心得和經驗,二來幫助後來者,少走彎路。

準備

  • 本地跑通的項目。
  • 一台伺服器(阿里雲、騰訊雲、AWS、Vultr等等)
  • 連接Linux的ssh工具(MobaXterm或xshell 中國伺服器都可以,國外建議xshell 更穩定
  • 百折不撓的精神(非常重要!)

PS:

MobaXterm安裝使用詳細說明

//segmentfault.com/a/1190000000483148

防止SSH斷開連接:

//blog.csdn.net/u014636245/article/details/83855860

 

環境

  • Local
    • OS:  Windows 10 Pro (64bit)
    • Terminal:  xshell
    • Hosting service: 阿里雲
  • Server
    • Ubuntu 18.04
    • root用戶下

步驟

  1. Python3 & Pip的安裝
  2. 創建Django項目(或者導入)
  3. 安裝與配置uWSGI
  4. 安裝與配置Nginx

重要提示:以下程式碼均沒有加上sudo,如果有哪裡因為許可權問題失敗了,可以加上sudo再試一下。

 

Python3 與 Pip 的安裝

更新一下系統(防止有的包找不到)

$ apt-get update
$ apt-get upgrade

 

安裝依賴庫 

$ apt-get install build-essential libtool
$ apt-get install libpcre3 libpcre3-dev zlib1g-dev openssl

  

安裝python3和pip3

$ apt-get install python3.7 
$ apt-get install python3-pip

 

創建、啟動虛擬環境

安裝虛擬環境

python3 -m pip install virtualenv

  

創建存放虛擬環境和項目的文件夾 

確保當前目錄是root目錄

cd ~  

注意分清 : (當前用戶家目錄)和 / (系統根目錄)的區別。

$ mkdir -p /root/www/project/env
$ mkdir -p /root/www/project/【ytb_api】

註: -p 遞歸創建目錄,即使上級目錄不存在,會按目錄層級自動創建目錄

【ytb_api】修改為你的項目名

 

創建虛擬環境 

# virtualenv -p [python3路徑] [項目路徑]
$ cd /root/www/project/env $ virtualenv -p /usr/bin/python3 ENV

註:如果不知道python3路徑,可以用 which python3

如果不了解虛擬環境的使用,看這兩篇文章就夠了:

//kuanghy.github.io/2015/12/04/virtualenv

//docs.python.org/zh-cn/3/tutorial/venv.html

 

啟動虛擬環境

$ source /root/www/project/env/ENV/bin/activate

命令行的最前面出現(ENV)即代表處於虛擬環境下。

註:

source: 執行文件並從文件中載入變數及函數到執行環境。

 

安裝Django 並創建/導入項目

安裝Django

python3 -m pip install django

注意此處pip前 要加python3 -m 的原因:

直接pip會安裝到python2上,需要通過pip去指定安裝到Python3.x下

詳見文章://blog.csdn.net/Cloudox_/article/details/78616378

 

測試Django項目是否正常

將本地項目文件夾拖拽進www/project/ 目錄下。

runserver 運行一下,看看程式是否正常

$ python3 manage.py runserver

有如下顯示,說明沒問題

Django version 2.2, using settings 'firstpage.settings'
Starting development server at //127.0.0.1:8000/
Quit the server with CONTROL-C.

 

Uwsgi 安裝和配置

安裝uWSGI伺服器

$ python3 -m pip install uwsgi

 

開啟阿里雲安全組和防火牆

# 防火牆部分,開啟8000埠訪問許可權
sudo ufw status
sudo ufw allow 8000

阿里雲用戶需要在控制台打開入方向的8000埠許可權。

 

測試 uwsgi監聽埠是否成功 

在項目根目錄下,創建一個test.py文件,內容如下 

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

運行uWSGI,確保當前工作目錄在你創建並安裝uwsgi的虛擬環境下:

$ uwsgi --http :8000 --wsgi-file test.py

 特別注意:阿里雲用戶需要提前打開入方向的8000埠許可權。
如果默認80埠開,可以將下面的8000埠,改成80埠測試

 

在地址欄中輸入 你的域名:埠號,網頁上顯示Hello World則表示uWSGI成功運行 

同時代表了以下通訊是正常進行的

web client < -- > uWSGI < -- > Python App

  

將Django項目指定給uWSGI

$ uwsgi --http :8000 --wsgi-file /www/project/ytb_api/ytb_api/wsgi.py

 

如果此處卡住了,看後面的常見問題

外網瀏覽器訪問埠,如果顯示出小火箭,說明uWSGI<–>Django通了。

成功的小火箭

 

業務部分的包安裝:(讀者請跳過)

###------業務部分------
# 1、安裝oss2
python3 -m pip install oss2

# 2、安裝阿里雲sdk
python3 -m pip install aliyun-python-sdk-core-v3

# 3、安裝youtube-dl
python3 -m pip install youtube-dl

# 4、安裝依賴
python3 -m pip install six

# 5、安裝ffmpeg
sudo apt-get install ffmpeg

如果你斷開連接,那麼服務也終止了,所以需要用配置ini文件來啟動uwsgi,這樣uwsgi可以後台貯存。

 

創建uWSGI ini配置文件

本地創建一個uwsgi.ini文件

內容如下(請一定珍惜,因為參考了很多,摸索了很多,踩坑了很多,總結出來的一份配置):

[uwsgi]
### Django-related settings

# socket = :8000  # 如果需要配置nginx,則需要此項
http = :8000

# the base directory (full path)
# 項目路徑,項目的根目錄
chdir = /root/www/project/local_api

# Django's wsgi file
# 配置項目路徑,項目的所在目錄
module = local_api.wsgi

# the virtualenv (full path)
# 虛擬環境。注意這裡不是env,而是home
home = /root/www/project/env/ENV



### process-related settings

# maximum number of worker processes
# 最大進程個數
# 同時啟動uwsgi進程的個數,這個進程與nginx中的workers是不一樣的,
# uwsgi中的每個進程每次只能處理一個請求(進程越多可以同時處理的請求越多),
# nginx採用的非同步非阻塞的方式來處理請求的,每個進程可以接受處理多個請求。
processes = 10
# 每個進程的執行緒數
threads = 4

# 啟動一個主進程來管理其他進程,processes的進程都是這個master進程的子進程,如果kill這個master進程,相當於殺死所有的uwsgi進程
master = true

# 允許用內嵌的語言啟動執行緒。這將允許你在app程式中產生一個子執行緒
enable-threads=true

# clear environment on exit
#當伺服器退出的時候自動刪除unix socket文件status和pid文件
vacuum = true

# 設置日誌目錄
daemonize = /root/www/project/local_api/uwsgi.log

# 設置最大日誌文件大小
log-maxsize = 5000000 

# 設置用於uwsgi包解析的內部快取區大小為64k。默認是4k。
buffer-size = 32768

# 為每個工作進程設置請求數的上限。當一個工作進程處理的請求數達到這個值,那麼該工作進程就會被回收重用(重啟)。你可以使用這個選項來默默地對抗記憶體泄漏
max-requests = 5000 

# 通過使用POSIX/UNIX的setrlimit()函數來限制每個uWSGI進程的虛擬記憶體使用數。這個配置會限制uWSGI的進程佔用虛擬記憶體不超過256M。如果虛擬記憶體已經達到256M,並繼續申請虛擬記憶體則會使程式報記憶體錯誤,本次的http請求將返回500錯誤。
# limit-as = 256 

# 一個請求花費的時間超過了這個harakiri超時時間,那麼這個請求都會被丟棄,並且當前處理這個請求的工作進程會被回收再利用(即重啟)
http-timeout = 500
harakiri = 500

# uwsgi.pid文件用來重啟和停止uwsgi服務
pidfile = %(chdir)/uwsgi/uwsgi.pid

在項目根路徑下,新建個uwsgi文件夾(用於存放uwsgi服務的pid文件) 

將剛才本地創建的uwsgi.ini拖拽進項目根路徑下

目錄結構:

 

文件啟動和終止uwsgi

### ------ini運行uwsgi------
# 啟動
uwsgi --ini uwsgi.ini

# 停止
uwsgi --stop uwsgi/uwsgi.pid

 

運行成功有此提示:

 啟動成功會有個uwsgi.log文件,是記錄請求的文件。

好了,如果順利走到這,那麼恭喜你。

 

關於不用Nginx:

由於我只是中國國外各部署一個API用以接收請求,然後之間相互通訊,不涉及靜態頁面,

而且uwsgi伺服器性能目前業務就可以滿足,所以不上Nginx,但是以後業務量上來了,

Nginx的負載均衡和大並發的非同步非阻塞的處理請求,就可能需要了。

如果需要,以後再弄。

 

 

常見問題:

(1) 未在Django中未設置設置被允許的域名

DisallowedHost at /
Invalid HTTP_HOST header: ..... You may need to add "你的域名" to ALLOWED_HOSTS  

需要在settings.py中設置被允許的域名字

ALLOWED_HOSTS = ['XXX.XXX.XXX.XXX']

 

(2) 沒有報錯,遠程就是無法訪問

解決方法:
查看防火牆狀態

sudo ufw status

開啟對應的埠號,如8000埠

sudo ufw allow 8080

其次,查看阿里雲安全組設置,是否開啟相關的埠號。

 

小結

  因為公司把這個影片翻譯的項目全權交給我,所以一切都是自己摸(踩)索(坑)。

  從調研、選技術路徑、MVP(最小單元試錯)、測試對比分析結果、後端功能程式碼、部署,

  甚至包括運維,一下子學了很多,賊開心。

 

  下面是此項目的心得:

  1、參考文章的方法

  跟著一個寫的比較詳細的 靠譜的部落格作為主線,跟著一步步走,

  遇到問題再去找別的教程或者去官網查,要多看,博採眾長,畢竟博觀才能約取。

  2、進一步思考

  每個步驟的含義,每個參數的含義,參數不設置成不成,會有哪些影響,

  為什麼要用uwsgi,需不需要弄Nginx等等等等,都是提升能力的好機會。

  3、耐心很重要

  一定要有耐心,新接觸一個東西,出各種問題很正常,要耐下心來逐一解決,多請教別人。

  

  謝謝大家,祝各位部署順利。

 

參考內容:

官方文檔

uwsgi:

//uwsgi-docs-zh.readthedocs.io/zh_CN/latest/tutorials/Django_and_nginx.html

//docs.djangoproject.com/zh-hans/3.0/howto/deployment/wsgi/uwsgi/

//uwsgi-docs.readthedocs.io/en/latest/Options.html

Django:

//docs.djangoproject.com/zh-hans/3.0/

文章:

 //blog.csdn.net/Lo_Bamboo/article/details/80141880

//www.chuangzhidou.com/2019/04/02/django-deploy/

//segmentfault.com/a/1190000014361352

//www.hongweipeng.com/index.php/archives/1814/

//blog.csdn.net/zhf0425/article/details/102662417?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2

//zhuanlan.zhihu.com/p/51012932

//www.cnblogs.com/fnng/p/5268633.html

//gaussic.github.io/2016/08/03/django-uwsgi-deploy/

//www.cnblogs.com/zhuminghui/p/9212998.html

//www.jianshu.com/p/0e85cf58e677

//zhuanlan.zhihu.com/p/29083368

//blog.csdn.net/Miss_Audrey/article/details/81874038

//www.runoob.com/django/django-nginx-uwsgi.html