Simplicity is the ultimate sophistication

Time is a tangled web. Try not to dwell on all the loose ends..

Prepare Flask Environment

建立Flask環境

我的環境是從KVM裡面的VM開始, 作業系統是CentOS 7.

有關KVM的VM

有幾點要注意一下:

  • 一開始裝就要設好網路 免得麻煩.
  • KVM Bridge 頗難搞 要有耐心, 搞清楚自己的環境, 不要隨便Google一篇就想上.
  • KVM整體來說頗方便, 只是一些小東西要轉個彎, 不過網路上資源真的夠豐富.
  • Snapshot就等於是SL大法, 要記得用.

如果使用VirtualBox

這東西不用錢, PC, MAC都可用, Snapshot更是神器, 沒事養幾台在電腦裡面真的方便到不行.

雖然叉題, 不過還是想講講我的做法. 我有一台VirtualBox的VM專門用在金融網站上, 隨時更新作業系統. 另外還有兩台VMs, 一台專門用來上那種我單單看就覺得必死的網站, 另外一台則是可能會有問題的網站, 前一台用完馬上倒回前一版, 輕鬆愜意.

跟KVM一樣, 網路先想好, 然後再設定. 如果要能夠用遠端去看網頁, 建議是設定成bridge network就ok.

設定CentOS 7

  • 確定你有sudo的權限, sudo -v 可以查.
  • 確定你有網路, ifconfig 可以幫你. 如果沒有這個指令, sudo yum install -y net-tools可以安裝net-tools
  • 接下來就要討論一下我們怎麼把Flask呈現出去, 有下面幾種方法, 可以根據狀況來選擇:
    • WSGI, 這玩意就是為了中介web server跟web app/framework之間用的, 原生就是for Python, 2003到現在.
    • Apache的mod_wsgi, 這個就是針對上面那個做了一個Apache專用的.
    • uWSGI, 這東西大部分的人都跟nginx, lighttp一起玩.
    • FastCGI, 這邊我貼Wikipedia的連結, 這個幾乎到處都可以用的東西, 這邊就跳過了.
    • CGI, If you dont knwo this, check the link.

接下來我們討論安裝流程

假設現在有了機器, 在開始建立自己的開發環境之前, 需要注意

  1. 如果機器是用最小安裝, 可能你要試著安裝一些必要的元件, 一般來說我習慣nano, 所以登入後第一件事就是sudo yum install -y net-tools nano wget curl, curlwget都是用來當成client端存取internet的工具. 如果yum install失敗, 請確認你的網路.
  2. 檢查你的firewall, 我是現在都轉到CentOS 7了, 所以command是sudo systemctl status firewalld, 如果是active, 那當設好環境要測試時, 就得根據你要開的port去做設定.
  3. 裝好pip, 這個就是類似套件管理員的工具, 很重要, 必備. 安裝的方式我是建議用wget下載get-pip.py, wget https://bootstrap.pypa.io/get-pip.py 然後用python安裝, sudo python get-pip.py (如果你是root就不用sudo了).

WSGI的設定

這邊我們就用Tornado, 來當Web Server, 其實只要兩個指令環境就好了:

1
2
sudo pip install tornado
sudo pip install flask

我們先試試怎麼使用Tornado, 下面這個就是官方的範例, 只是改變port:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mport tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")

application = tornado.web.Application([
    (r"/", MainHandler),
])

if __name__ == "__main__":
    application.listen(80)
    tornado.ioloop.IOLoop.instance().start()

隨便存個檔index.py,然後跑sudo python index.py, 接下來你就可以從外面連到那台機器, 應該就會看到”Hello, woeld”.

那要掛上Flask的話, 可以參考bdarnellsample, 也就是用Tornadotornado.wsgi.WSGIContainer(wsgi_application)裝載Flask來跑, 不過這兩個有點先天上設計的差異, Tornadonon-blocking的設計, 然而Flasknon-async的framework, 所以掛載在下面的做法我沒有繼續嘗試.

不過同時利用TornadoFor Realtime, 然後用Flask來處理其他的部分, Serge Koval有寫一篇極佳的文-Python Realtime來描述怎麼用Flask, Tornado來做Online Game的架構.

這邊簡單介紹一下, Realtime就是可以視為Client跟Server之間保持一個連線. 為啥要保持一個連線, 因為HTTP RequestHeader成本太高, 在Websocket之前就只能靠Comet)來做. 這邊要注意的是客戶群的瀏覽器版本, 免得機器都裝好了才發現客戶不能用.

uWSGI 的設定

準備一台VM For nginx

頗簡單

掛上repository

sudo rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm

安裝

sudo yum install nginx

啟動

sudo systemctl start nginx.service

設定成開機就啟動

sudo systemctl enable nginx.service

如果外面連不到, 請參考上面有關firewall的部分

主要的VM

首先掛上uWSGI, uWSGI需要clangclang還是gccgcc的支援以及header files and a static library for Python, 所以要先裝

sudo yum install -y gcc clang
sudo yum install -y python-devel

接下來裝pip, 好了就可以安裝uWSGI

sudo pip install uwsgi

然後我們可以先試試看uWSGI, 開個檔案(這邊我用testuwsgi.py)寫入下面

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

在Console直接執行, 記得port的firewall記得打開才能夠外部存取

uwsgi --http :5000 --wsgi-file testuwsgi.py

如果一切okay, 我們就可繼續安裝Flask

sudo pip install flask

開個檔案(test.py)然後用console跑

from datetime import datetime
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return 'Hello from Flask! (%s)' % datetime.now().strftime('%Y-%m-%d %H:%M:%S')

然後用console跑

uwsgi --http 0.0.0.0:5000 --module test --callable app

這裏的test就是檔名, callable的object就是Flask開給uwsgi的.

結果應該像是:

Hello from Flask! (2015-02-03 23:33:44)

測試成功後我們就可以回過頭來設定nginx

在安裝nginxVM中設定Reverse Proxy

在CentOS7裡面nginx的設定檔在/etc/nginx/nginx.conf, 在http content裡面加上

upstream flask {
    server FIRST.MACHIME.IP.ADDRESS:5000;
}

以及

server {
    listen 80;
    server_name THIS.MACHINE.IP.ADDRESS;
    charset utf-8;
    location / {
        proxy_pass http://flask;
    }
}

然後在外面的機器打看看安裝nginxVM, 看看有沒有得到預設的結果. 沒有的話打開/var/log/nginx/error.log看看結果.

假如遇到connect() to failed (13: Permission denied) while connecting to upstream, 試試看先把Selinux的httpd_can_network_connect打開看看:

sudo setsebool httpd_can_network_connect=1

Apache的mod_wsgi的設定

首先是裝上Apache

yum install -y httpd

然後把port打開

sudo firewall-cmd --zone=dmz --add-port=80/tcp --permanent
sudo firewall-cmd --reload

啟動並且讓Apache開機就啟動

sudo systemctl enable httpd.service
sudo systemctl start httpd.service

安裝mod_wsgi

yum -y install mod_wsgi

接下來在建立YOURAPP.wsgi

import sys
sys.stdout = sys.stderr
sys.path.append("/Your/Application/Folder/")

最後在Apache上面掛上設定檔

nano /etc/httpd/conf.d/YourApplicationName.conf

內容大致如下

<VirtualHost *>
    ServerName YOUR.MACHINE.IP.ADDRESS

    WSGIDaemonProcess YourAPPName user=apache group=apache threads=5
    WSGIScriptAlias /SUBPATH /Your/Application/Folder/YOURAPP.wsgi
    <Directory /Your/Application/Folder>
        WSGIProcessGroup YourAPPName
        WSGIApplicationGroup %{GLOBAL}
        Order deny,allow
        Allow from all
    </Directory>
</VirtualHost>

然後重新啟動Apache就可以試試看了

Flask的文件頗完整, 可以參考看看.