2012年4月28日 星期六

在 ec2 (ubuntu)上使用 web.py 透過 nginx 與 fastcgi 佈署 web application


最近要在 amazon ec2 (ubuntu 11) 上使用 python + Redis 開發一套簡單的 api , 因此選擇了一套 lightweight 的 http framework 來 handle REST http requests , 因為也是初學 python , 因此首先選擇嘗試較輕量化的 web.py 而不是大多數人使用的 django 

在 web.py 的官方網站 中提到了三種主要 deployment 的方式 , 分別是透過 apache , lighttpd 與 nginx , 分別試過這三種途徑以及自身需求後[1] , 覺得透過 nginx + fastcgi 的方式算是相對簡潔與高效的作法 , 在此簡單記錄步驟並且補充官網上沒提到的一些值得注意的細節

step 1: 下載必要的套件

sudo apt-get install python-flup
sudo apt-get install nginx
sudo apt-get install fast-cgi

step 2: 創建佈署 app 時對應的 server 設定檔

將原始設定檔拷貝一份, 並且在 HTTP { /.../ } 中加入以下 

location / {
        fastcgi_param REQUEST_METHOD $request_method;
        fastcgi_param QUERY_STRING $query_string;
        fastcgi_param CONTENT_TYPE $content_type;
        fastcgi_param CONTENT_LENGTH $content_length;
        fastcgi_param GATEWAY_INTERFACE CGI/1.1;
        fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
        fastcgi_param REMOTE_ADDR $remote_addr;
        fastcgi_param REMOTE_PORT $remote_port;
        fastcgi_param SERVER_ADDR $server_addr;
        fastcgi_param SERVER_PORT $server_port;
        fastcgi_param SERVER_NAME $server_name;
        fastcgi_param SERVER_PROTOCOL $server_protocol;
        fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_script_name;
        fastcgi_pass 127.0.0.1:9002;
}


step 3 : 修改 python script 加入 fast-cgi 的接口

例如:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import web

urls = ("/.*", "hello")
app = web.application(urls, globals())

class hello:
    def GET(self):
        return 'Hello, world!'

if __name__ == "__main__":
    web.wsgi.runwsgi = lambda func, addr=None: web.wsgi.runfcgi(func, addr)
    app.run()


主要是在 app.run() 前加入 web.wsgi.runwsgi = lambda func, addr=None: web.wsgi.runfcgi(func, addr) 


修改前可以先試試 #python your_script.py , 沒特別指定 port 的話預設是跑在 port 8080 , 看 script 是否有誤 , 這裡常會碰到的問題是 8080 被佔住的問題 , 如果被佔住用指令檢查一下並且 kill 掉該 process 即可

step 4 : start & stop script

假設我們的 web.py 主程式名為 code.py , 並且放在 /home/ubuntu/www 下
則 :

# sudo spawn-fcgi -d /hom/ubuntu/www -f /home/ubuntu/www/code.py -a 127.0.0.1 -p 9002

如果成功的話 , fcgi 會給出一個 pid , 之後關閉要透過這個 pid , 或者 # pgrep -f "python /home/ubuntu/www/code.py" 找回 pid , 並且透過 sudo kill -9 pid 來關閉 fcgi

常見的怪問題都是發生在這個步驟中, 例如 502 bad gateway 等, 一開始會以為是 nginx 的問題 , 但經過自己的經驗, 502 一般都是 fast-cgi 沒有成功啟動所造成 (即使如此 , 系統還是有可能會給出成功啟動的訊息! ), 可以在 spawn-fcgi 的指令中 , 加入 -n 參數來看詳細的資訊 或者是在執行指令後, 透過 sudo nentstat -antup 來看是否有成功 spawn fcgi process


step 5 : start & stop nginx service

使用 # sudo nginx -c /home/ubuntu/www/my_nginx.conf 來啟動 , 並且可以透過 sudo service nginx stop 來停止


[1] 由於會搭配 redis 作為後台資料庫 ,在記憶體的資源取捨下放棄 apache 這個較為廣為使用的但較吃記憶體的套件

沒有留言:

張貼留言