Centos部署Python3+Django+uWSGI+Nginx

背景:最近打算自己寫一個小網站,接口不多,就打算用Django來寫了,正好提升一下自己的python的代碼水平。這篇博客主要是用來記錄從本地運行到部署服務器這過程遇到的一些小問題。

提示:
如果是阿里云的服務器,我們要去阿里云的后臺管理業去配置安全規則,開放我們即將要使用的那些端口的權限,他很多的端口都是默認不開放的。

Djano簡單介紹

我使用的IDE是PyCharm,操作簡單,可直接創建Django項目,然后python版本選擇3.x。

簡單的說兩句Django。這個框架個人感覺上手容易,畢竟框架做了比較好的分層,不同文件的只能劃分也是很明確的,當然里面涉及一些配置參數什么的,這個大家可以去網上找Django的教程,先看看入門。

在目錄結構中我們可以看到一個venv的文件,這個算是給我們創建的一個虛擬環境,為應用提供了隔離的Python運行環境,解決了不同應用間多版本的沖突問題。這個大家可以自己去查一下加深理解。

在本地敲代碼的時候,使用到某些庫的時候我們會使用 pip install xxxxx 來安裝。使用了venv這種虛擬環境,所有的包默認安裝在本項目下,新的項目使用的話需要再安裝。

前期的本地工作就沒什么了,從網上找到教程一點一點的學習就可以了。當然了,我們要準備部署到服務器的時候,首先得保證本地能成功的運行,本地都跑不了,那配置到服務器上肯定也不會,別的不說,代碼首先別有問題。

必要依賴包的安裝

之前呢,搞過幾次java,當時記得是把項目打成war包,然后上傳,有點笨。把Django項目壓縮一下再上傳應該也是可以的。但是何必呢,我們直接把代碼傳到github(或者自己存代碼的地方)上面,然后在登上服務器,直接git clone多好~ 有的時候太緊張,或者把事情想的太難了。

我們在本地pip install的那些包,到了服務器那邊還是要再重新install的。

在服務器端,clone下項目來之后,cd到當前項目,我們可以把之前安裝的包再一個一個的重新pip install,但是太多了我們也不一定記得清楚有哪些,所以我們現在本地生成一個記錄引用的包的文件。

依賴文件生成 (本地操作)
pip freeze > requirements.txt
依賴文件安裝 (服務器端操作)
pip install -r requirement.txt

我們創建項目時候用的python的版本要跟服務器上面的版本相同,我的服務器系統是centos7,記得好像是自帶的是python2.x,然后我項目使用的python3.x, 所以我要在服務器上裝python3.x, 具體的安裝操作,大家自己搜索一下。

安裝完高版本的python之后,運行pip,可能會出現一些問題,我忘記當時的報錯了,好像是pip的版本問題,因為Django的版本,所以需要安裝pip3, 這地方安裝有些啰嗦,大家不要著急,慢慢的裝,遇到報什么錯就去相應的搜索一下。

有時候會提醒你升級pip,然你使用這個pip install --upgrade pip命令,個人建議不要亂試,我就是使用這個升級之后,pip和pip3都找不到了。

如果pip install顯示 ‘沒有那個文件或目錄’ 的時候,可以嘗試一下下面這個命令 python -m pip install xxx

如果沒什么別的報錯了的話我們繼續執行pip install -r requirement.txt來安裝我們需要的包。

下面我遇到了讓我糾結了一天的一個錯誤。

其實主要的問題就是在安裝mysqlclient的過程中mysql_config not found

我這還特地上Stack Overflow上問了問,也沒人回到我。我在網上搜索了關于這個問題的錯誤,嘗試了所有能嘗試的方法都沒能解決。

我搜索了一下,我的文件里壓根就沒有mysql_config這個文件,太氣了。

其中有幾個比較靠譜的方法,是讓安裝yum install mysql-devel這個東西,我也跟著做運行了這個命令,不過安裝出問題了,從終端上的提示來看,是有沖突,是與數據庫有沖突,很抱歉我忘記截圖了,但是我從網上的一片文章中也找到了一樣的問題,大家參看一下。

--> Running transaction check
---> Package mysql-devel.x86_64 0:5.1.69-1.el6_4 will be installed
--> Processing Dependency: mysql = 5.1.69-1.el6_4 for package: mysql-devel-5.1.69-1.el6_4.x86_64
--> Running transaction check
---> Package mysql.x86_64 0:5.1.69-1.el6_4 will be installed
--> Processing Conflict: MySQL-client-5.5.30-1.el6.x86_64 conflicts mysql
--> Processing Conflict: MySQL-server-5.5.30-1.el6.x86_64 conflicts mysql
--> Processing Conflict: mysql-5.1.69-1.el6_4.x86_64 conflicts MySQL
--> Finished Dependency Resolution
Error: mysql conflicts with MySQL-devel-5.5.30-1.el6.x86_64
 You could try using --skip-broken to work around the problem
 You could try running: rpm -Va --nofiles --nodigest

可以看得出來有幾個Conflict, 最可氣的是底下他還教你通過--skip-broken來避開這些沖突,我照做了,結果依然不管用,問題就出在這個沖突上。

好吧,你不是說跟MySQL沖突嗎,我就把MySQL卸載了再說(我很早之前學習MySQL的時候就安裝了)。

具體的MySQL移除過程我就不多說了,只提下面兩個點:
使用 rpm -qa|grep mysql查看mysql的安裝情況
rpm -e 文件名 --nodeps來移除
如果有不管用的地方大家看一下下面這兩篇文章,說的還不錯,借鑒一下。
http://834945712.iteye.com/blog/1979042
https://blog.csdn.net/lsa000/article/details/77374351

然后就是重新安裝MySQL,步驟可借鑒下面這篇文章
http://www.lxweimin.com/p/d679db1ab27f

反正我的項目在重新安裝了MySQL之后就好了,mysql_config文件也有了,再一次執行pip install -r requirement.txt,然后所有的包都順利的安裝完成。

最后執行python manager.py runserver,就可以看到我們的項目跑起來了 ~

但是呢,這樣運行使用Django自帶的WSGI Server運行的,是有性能缺陷的,并發承受能力不行 ~ 要不然為什么我們還要使用uWSGI+Nginx呢

具體差距看一下這篇對比文章
django自帶wsgi server vs 部署uwsgi+nginx后的性能對比

uWSGI

首先在使用之前,我們得先大致了解他們到底是什么東西,為什么要使用。

了解uWSGI

uWSGI旨在為部署分布式集群的網絡應用開發一套完整的解決方案。主要面向web及其標準服務。由于其可擴展性,能夠被無限制的擴展用來支持更多平臺和語言。uWSGI是一個web服務器,實現了WSGI協議,uwsgi協議,http協議等。

uWSGI又很多優點,具體對uWSGI的講解看這個
http://www.lxweimin.com/p/679dee0a4193

具體uWSGI的安裝我就不詳細的說了,網上教程很多,我想說的是配置文件的問題,因為我搜了很多關于uWSGI的文章,可能是由于我們每個人的項目的結構不同,或者別的愿意,所以總感覺這個配置文件很難寫。

網上大多數的教程在教我們使用uWSGI的時候會讓我們新建一個test.py的文件,然后uwsgi --http :8000 --wsgi-file test.py, 檢測是否能正常運行。

運行成功的話就說明uWSGI這個橋梁是起作用的~

下面這個說明我很喜歡

the web client <-> uWSGI <-> Python

但是我們使用uWSGI是為了服務于Django項目的,所以說我壓根就沒嘗試上面這一步,而是直接嘗試通過uwsgi命令來運行django項目。

這里會有一點小分歧,因為我從網上搜到的很多教程是說運行了一個.wsgi的文件,但是我整個項目中就沒有發現這么一個文件,只有一個wsgi.py的文件,所以我就是用了下面這個命令來運行整個項目
uwsgi --http :8000 --wsgi-file wsgi.py
注意后面wsgi.py的路徑問題.

結果還不錯,項目跑得起來了。

配置uwsgi

我其實并不是真的明白為什么要配置這個.ini文件,聽別人說是這樣的:

如果你喜歡用命令行的方式(如shell)敲命令,那可以省去任何配置。
但是,絕大多數人,還是不愿意記那么長的命令,反復敲的。所以uwsgi里,就給大家提供了多種配置,省去你啟動時候,需要敲一長串命令的過程。

配置的方式很多,我選擇使用ini的方式,也是因為網上教程多。

我們在根目錄下面建一個.ini的文件,由于最初跟著網上的教程學,所以起了個test.ini的名字。

下面是這個文件里面的內容,首先我得成人有很多我是不知道什么意思的,而且網上教程中的配置會有各種各樣的參數,這個以后我再慢慢研究。

http = :8000
chdir = /root/myblog/
module = blog.wsgi:application
processes = 4
threads = 2
master = true
enable-threads = true
daemonize = /root/searchmarket/marketSearch/uwsgi.log
buffer-size = 21573

稍微解釋一下,不一定多,可作參考。
chdir是當前項目的路徑
module算是wsgi.py這個文件的路徑嗎 ?好像是的,但是為什么要寫成這樣子呢 ?
(在我的項目中,myblog目錄下有一個blog文件夾,wsgi.py就在這個blog文件夾中~是在搞不懂為啥要寫成blog.wsgi而且后面還加上個 :application)
daemonize是放log日志的地方,自己創建好文件,路徑貼上。

差不多了...

然后運行uwsgi --ini test.ini這個命令就行了 ~

運行完之后,從終端里我看不出來倒是成功了沒有,我用postman請求了一下試了試,失敗的話我就從那個.log文件中看日志,然后處理問題。

成功的話,那就是uWSGI部分成功了。

注:也許會碰到端口占用的問題
我的端口使用的8000 然后執行這個命令lsof -i:8000, 然后你會看到PID, 然后kill xxx,就行了。
我發現了一個快速的方法
killall -9 uwsgi

Nginx

啟動Nginx

我使用的是yum安裝,簡單易操作。
yum -y install nginx 就OK了

然后nginx啟動頁非常簡單,直接nginx就好了。

在啟動nginx時候碰到一個小問題,我干了什么導致的我也不太清楚,反正就是報了這么個錯:

Job for nginx.service failed because the control process exited with error code

就是沒啟動的了,我忽然想起來之前看的一篇博客,在啟動之前他檢測了80端口的狀態,我就隱隱感覺是80端口已經被占用的緣故。

然后我運行了這個命令netstat -ntpl來查看當前活躍的鏈接

netstat -ntpl 查看一下80端口是否被占用

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:3306            0.0.0.0:*               LISTEN      14267/mysqld        
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      709/redis-server 12 
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      4225/nginx: master  
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1184/sshd           
tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN      4212/uwsgi    

發現nginx已經被我啟動過一次了,我也記不清楚了,反正現在啟動nginx沒有什么提示。(網上一些文章顯示有一個OK的提示)。

然后可以kill 4225, 在nginx,就好了 ~

用瀏覽器打開 xxx.xxx.xxx.xx:80 (xx代表我們服務器的ip),就可以看到nginx啟動成功的標識了。

配置Nginx

yum在線安裝會將nginx的安裝文件放在系統的不同位置,可以通過命令 rpm -ql nginx來查看安裝路徑

[root@sunxb ~]# rpm -ql nginx
/etc/logrotate.d/nginx
/etc/nginx
/etc/nginx/conf.d
/etc/nginx/conf.d/default.conf
/etc/nginx/fastcgi_params
/etc/nginx/koi-utf
/etc/nginx/koi-win
/etc/nginx/mime.types
/etc/nginx/modules
/etc/nginx/nginx.conf
/etc/nginx/scgi_params
/etc/nginx/uwsgi_params
/etc/nginx/win-utf
/etc/sysconfig/nginx
/etc/sysconfig/nginx-debug
/usr/lib/systemd/system/nginx-debug.service
/usr/lib/systemd/system/nginx.service
/usr/lib64/nginx
/usr/lib64/nginx/modules
/usr/libexec/initscripts/legacy-actions/nginx
/usr/libexec/initscripts/legacy-actions/nginx/check-reload
/usr/libexec/initscripts/legacy-actions/nginx/upgrade
/usr/sbin/nginx
/usr/sbin/nginx-debug
/usr/share/doc/nginx-1.14.0
/usr/share/doc/nginx-1.14.0/COPYRIGHT
/usr/share/man/man8/nginx.8.gz
/usr/share/nginx
/usr/share/nginx/html
/usr/share/nginx/html/50x.html
/usr/share/nginx/html/index.html
/var/cache/nginx
/var/log/nginx

配置config文件
vim /etc/nginx/conf.d/default.conf

然后把location / {} 里面改為如下

 location / {
       include  uwsgi_params;

       uwsgi_pass  127.0.0.1:8000;
       uwsgi_param UWSGI_SCRIPT blog.wsgi;
       uwsgi_param UWSGI_CHDIR /root/myblog;
       index  index.html index.htm;
       client_max_body_size 35m;
    }

uwsgi_pass 必須和uwsgi中的設置一致
UWSGI_CHDIR和UWSGI_SCRIPT 其實也跟uwsgi中差不多,一個項目路徑,一個wsgi文件的路徑。

保存之后,Nginx的配置就完成了。最后我們得稍微修改一下uwsgi中的一條配置。

之前在test.ini文件中是 http = :8000 我們要改為socket = :8000

重新運行uwsgi,重啟nginx。

結束。


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容