Flask+Nginx+Gunicorn+Redis+Mysql搭建一個小站
首先簡單介紹一下這幾個東東。
Flask是一個輕量級的Web應用框架, 基于Werkzeug和 Jinja2 模板引擎,使用 Python編寫,可擴展強。
Nginx是一個高性能的 HTTP 和 反向代理服務器,在高并發方面表現非常不錯。
Gunicorn 是一個Python WSGI UNIX的HTTP服務器,從Ruby的獨角獸(Unicorn )項目移植,能與很多Web框架兼容,只需非常簡單的執行,輕量級的資源消耗,以及相當迅速。
Redis是一個高性能的key-value存儲系統,支持集合、列表、字典等復雜的數據結構,數據既可以保存在內存中也可以持久化到硬盤,對關系數據庫起到很好的補充。
前段時間做了個小站,目前已上線,使用到了這幾個東東。算起來學習python后臺開發有4個月了,但是水平還是菜鳥級別,所以本文也就簡單講講配置問題以及該項目的架構,如有錯誤,請各位看官指正。由于是小站,目前訪問人數也不是特別多,每天幾十萬IP,所以現在就一臺服務器。前端使用nginx做反向代理和動靜分離(把css、js、image、html等靜態文件直接通過nginx轉發,不通過后端處理),后端使用gunicorn+flask的方式,剛開始就直接使用flask跑,但是有一次就出現502了,發現由于flask是單進程處理請求的,不像Tornado的異步,同時訪問的人數稍微過多,就會出現阻塞的情況,導致nginx出現502的問題。gunicorn可以指定多個工作進程,底層實現應該是通過調用fork函數創建子進程,這樣就可以很好的利用服務器多核的特性了,實現并發功能。進程數應該指定多少呢,可以參考gunicorn官網上的一個例子:workers = multiprocessing.cpu_count() * 2 + 1。為了減少服務端的壓力,對訪問比較多的頁面做了靜態化處理,然后把訪問和變化都比較頻繁的數據使用redis做緩存處理,關系數據庫使用的是mysql,網站的圖片使用CDN的。
flask和redis的安裝就不講述了,也十分簡單,下面主要講nginx和gunicorn的配置。
1.安裝和配置nginx
首先安裝pcre,讓安裝Nginx支持rewrite,這個功能還是挺重要的
wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.20.tar.bz2
bzip2 -d pcre-8.20.tar.bz2
tar xvf pcre-8.20.tar
cd pcre-8.20.tar/
./configure
sudo make && sudo make install
安裝nginx
wget http://sysoev.ru/nginx/nginx-1.0.0.tar.gz
tar zxvf nginx-1.0.0.tar.gz
cd nginx-1.0.0
./configure
sudo make && sudo make install
啟動nginx
sudo /usr/local/nginx/sbin/nginx
關閉nginx
sudo /usr/local/nginx/sbin/nginx -s stop
重啟nginx
sudo /usr/local/nginx/sbin/nginx -s reload
或者
sudo kill -HUP `cat /usr/local/nginx/logs/nginx.pid`
( kill -HUP 殺掉某進程 并重新讀取配置文檔 啟動該進程)
測試:打開瀏覽器,輸入ip,如果一切正常將會看到:Welcome to nginx!
可能會出現的問題:
啟動nginx時出現
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
解決辦法:
ps -ef | grep nginx查看nginx是否已啟動
如果已經啟動:sudo kill -9 ‘nginx pid’
否則 sudo netstat -nltp查看80端口被哪個應用給占了
然后sudo kill -9 pid
配置nginx
假設我的應用監聽的端口是8888,本機ip是192.168.60.146,修改hosts文件,添加:
192.168.60.146 www.app.com
這樣你在本機訪問www.app.com這個域名的時候,系統就不會提交到DNS域名解析服務器,而是直接訪問配置的IP地址192.168.60.146,十分方便,但是hosts是不支持通配符的,像*.app.com,這樣就無法設置二級域名了,解決方案可以參考我的這篇文章http://codingnow.cn/unix/431.html。
接下來就要配置當用戶訪問www.app.com這個域名時,如何能訪問到我們的應用呢,此時就需要配置nginx了。
建立用戶及用戶組
sudo /usr/sbin/groupadd zjh sudo /usr/sbin/useradd -g zjh zjh
配置nginx.conf,一般位于/usr/local/nginx/conf/目錄下
#運行用戶組和用戶 user zjh zjh;啟動進程,通常設置成和cpu的數量相等
worker_processes 1;
全局錯誤日志及PID文件
error_log logs/error.log; pid logs/nginx.pid;
工作模式及連接數上限
events {
單個后臺worker process進程的最大并發鏈接數
worker_connections 1024;
epoll是多路復用IO(I/O Multiplexing)中的一種方式,但是僅用于linux2.6以上內核,可以大大提高nginx的性能
use epoll; }
設定http服務器,利用它的反向代理功能提供負載均衡支持
http {
設定mime類型,類型由mime.types文件定義
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 off;
sendfile 指令指定 nginx 是否調用 sendfile 函數(zero copy 方式)來輸出文件,對于普通應用,
必須設為 on,如果用來進行下載等應用磁盤IO重負載應用,可設置為 off,以平衡磁盤與網絡I/O處理速度,降低系統的uptime.
sendfile on; tcp_nopush on; tcp_nodelay on;
開啟gzip壓縮
gzip on; gzip_min_length 1000; gzip_proxied any; gzip_types text/plain text/css text/xml application/x-javascript application/xml application/atom+xml text/javascript
連接超時時間
keepalive_timeout 65; proxy_read_timeout 200; proxy_next_upstream error;
fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k; fastcgi_temp_file_write_size 128k;
include sites/*.conf; }</pre>
在/usr/local/nginx/conf/目錄下創建一個sites目錄,里面存放具體應用的配置文件,便于管理。這里創建app.conf,內容如下
server {偵聽80端口
listen 80;
定義使用www.xx.com訪問
server_name www.app.com; client_max_body_size 10M;
設定本虛擬主機的訪問日志
access_log logs/app.log main;
默認請求
location / { #請求轉向本機ip:8888 proxy_pass http://192.168.60.146:8888; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } #配置靜態文件轉發 location ~.*(js|css|png|gif|jpg|mp3|ogg)$ { root /home/zhoujianghai/temp/data/app/medias/; } #配置靜態頁面轉發 location ~.*(html)$ { root /home/zhoujianghai/temp/data/app/app_static_pages/; }
}</pre>
重啟nginx,在瀏覽器訪問:www.app.com 就會訪問到你的應用程序了
2. 安裝和配置Gunicorn
sudo easy_install gunicorn編寫配置文件gunicorn.conf
workers = 4
bind = ‘192.168.60.146:8888′
proc_name = ‘app’
pidfile = ‘/tmp/app.pid’執行:
gunicorn --config gunicorn.conf app:app解釋一下app:app,前面的app代表當前運行的module名,也就是文件名,后面的app是創建的Flask對象。當然我實際的項目中module名不是app,這里只是作為demo。現在你可以通過
ps -ef | grep app來查看有多少app進程。
下面是一個最簡單的flask應用demo:app.py,因為使用gunicorn來運行,所以就沒有調用run方法。關于Flask的快速入門可以參考這一篇:http://codingnow.cn/python/409.html#!/usr/bin/env pythoncoding=utf-8
import sys reload(sys) sys.setdefaultencoding('utf-8')
from flask import Flask app = Flask(name)</pre>來自:http://codingnow.cn/server/539.html