首先,這是一篇自首的白爛文,由於學藝不精,基礎不好,所以我的 Django Site 一直被
Internal Server Error 咬到,已經兩個星期沒有發生了,應該算解對了
事由
我的 Django Site 是用 Fastcgi 的方式,跑在 Lighttpd 後面,不過,我是用 supervisor 來控制 Django ,所以應該都不會死掉才對
問題
不管,跑 thread 或是 prefork ,跑久了,都會有 Internal Server Error 出現,也就是我的 Django Site 的 process 死了,一直找不到原因,不過發生這種情形的時候,大多 Django 的 process 已經 fork 到一大串啦,分析網站流量,應該還不至於出現這種情形才對,除了幾個背後跑的分析工作比較吃資源,所以一直以來,我都是蠻烏龜的先擺著(雖然男子漢,是絕不可以這樣的),不過,一星期,大概都有一次 Internal Server Error 發生,必須重跑 Django Site 才可以活過來
分析結果,大多是 Backgroud 的程式,使用資料庫太兇了,supervisor 以為我的 Django Site 掛了,所以就又幫我重開,可是舊的 Kill 不掉,就這樣,我的系統越跑越慢,慢到,資料庫不回應,就算掛了,Lighttpd 把 user request 送到,Django 的 Fastcgi 時,就變成 Internal Server Error
初步解法
真的很簡單
只要在 Lighttpd 的 fastcgi server 裡的設定,加
“max-procs” => 5,
這樣就會控制住總量啦,這樣,Lighttpd 和 supervisor 可以合作好一點
我是只要 5 隻就夠了,就在也沒有 Internal Server Error 了
期待,我的 Django Site 下一次真的被網友打到爆
Posts for: #Python
期待已久的 1.0
Django 最近 trunk 的變化可說是非常的快,為的就是,讓人期待已久的 1.0 可以早日現身,過了1.0 之後,開發團隊可是保證會維護版本的回住支援,也就是一般我們在做軟體開發時,到了對自己開發的東西非常有信心,可以掛保證的階段
Newform Admin 和 Gis 的 branch 都已經合併了,也做了無數的修正,看來這一個 1.0 要服用,還要有些勇氣才行
目前,更新到 trunk後,程式部份需更動
Admin 的定義從 Db Model 的定義之中獨立出來,得到更大的彈性,也可以進一步的客製化
File Upload 有了修改,不在是原本的 Dict object,變成,django/core/files/base.py 裡 class File 的繼承物件,記得改寫 file upload 的程式
FileField, ImageField 的介面也有一些修改
詳細請參考原廠文件 或是 Look the source
給阿怪 Lighttpd + Fastcgi + Django
我的環境
Debian testing
Python 2.5.2
MySQL 5.0.51a
Lighttpd 1.4.19
Django Django version 0.97-pre-SVN-7480
Django 專案位址,您要對應您自己的位址
/home/terry/digez
Python 的部份
要安裝 python-flup
Django 的部份
一般只要把 django 用 fastcgi 的方式跑起來,即可
在命令列執行方式,其中 socket 還有 pidfile 可以放在你喜歡的地方,注意權限沒有問題就可以,也可以用 TCP 的方式執行 fastcgi
可以在命令列下打 ./manage.py help runfcgi 得到更多的提示
/home/terry/digez/manage.py runfcgi socket=/home/terry/run/digez.sock pidfile=/home/terry/run/digez.pid
您可以把執行的方式,寫成 Linux 或是 FreeBSD 下的 init.d 的執行方式,也可以用 supervisord 的方式來監控啟動
init.d 的方式可以參考 http://code.djangoproject.com/wiki/InitdScriptForDebian
Lighttpd 的部份
至少必須把 fastcgi 的模組啟動
在 Debian 的環境下,用 root的權限,在命令列下打
lighttpd-enable-mod
來啟動,下面是我執行的結果
terry:# lighttpd-enable-mod
Available modules: auth cgi fastcgi proxy rrdtool simple-vhost ssi ssl status userdir
Already enabled modules: fastcgi simple-vhost
Enable module:
下面則是在 Lighttpd 下,我設的 virtual host,我所有的主機都是設定 virtual host 的方式
下面是整個 virtual host 的設定檔,我的環境下是放在 /etc/lighttpd/conf-enabled/10-simple-vhost.conf
有井字號開頭的,整行是註解
在這裡面要注意的是 socket file 的權限,如果是 執行 Lighttpd 的 user 是 www-data 的話,socket 檔案的權限就要是 www-data 可以的讀寫
設定裡那個叫 /mysite.fcgi 的檔案,是假的,不必真實存在
## Simple name-based virtual hosting
##
## Documentation: /usr/share/doc/lighttpd-doc/simple-vhost.txt
## http://www.lighttpd.net/documentation/simple-vhost.html
server.modules += ( “mod_simple_vhost” )
## The document root of a virtual host isdocument-root =
## simple-vhost.server-root + $HTTP[“host”] + simple-vhost.document-root
simple-vhost.server-root = “/var/www”
simple-vhost.document-root = “/blog/"
simple-vhost.default-host = “home.digez.com”
$HTTP[“host”] = “^(home.digez.com|stock.digez.com)$” {
server.document-root = “/home/terry/digez”
fastcgi.server = (
“/mysite.fcgi” => (
“main” => (
# Use host / port instead of socket for TCP fastcgi
#“host” => “127.0.0.1”,
#“port” => 8080,
“socket” => “/home/terry/run/digez.sock”,
“check-local” => “disable”,
)
),
)
alias.url = (
“/media/” => “/home/terry/django_src/django/contrib/admin/media/”,
“/site_media/” => “/home/terry/media/”,
)
url.rewrite-once = (
“^(/media.)$” => “$1”,
“^(/site_media.)$” => “$1”,
“^/favicon.ico$” => “/site_media/images/favicon.ico”,
“^(/.*)$” => “/mysite.fcgi$1”,
)
}
以上Lighttpd 設定更改過後,該重新啟動的要啟動過後才會生效,有關於 Lighttpd 設定還有多進階的方法,可以幫我們擋攻擊,或是增加效能 ;-)
測試一下 Django threading mode
之前有些一篇, prefork or threaded 之中提到的 Internal Server Error 大約找到原因了,還不是非常的確定就是了,原因是資料庫,覆載太重了,我太常跑一些有的沒的,我的電腦真是太可憐了,所以接下來,網站,應該會衝 threade 的模式試試看
prefork or threaded
開發好的網站程式最終還是會裝在網站伺服器上,開放對外面的服務,實際考驗你寫程式的效能,及整個架構能否負荷對所有網民的請求
這是最近試過的組合
Lighttpd + fastcgi + Django prefork
Lighttpd + fastcgi + Django threaded
Lighttpd + scgi + Django prefork
Lighttpd + scgi + Django threaded
用 apache 附的 ab 作壓力測試 ,concurrency 100, 1000 request 100, 1000
Django 都是使用 local unix sock 的方式跑,用預設的 maxchildren=50 請求頁面是一個 Django 的 cache 頁面,有 6個 MySQL 的查詢
環境
Debian Linux 2.6.24-1-686,Lighttpd 1.4.19,MySQL 5.0.51a, Python2.5.2,python-flup 1.0-1,python-mysqldb 1.2.2-6,Django version 0.97-pre-SVN-7480
IBM X60 CPU Intel Core Duo 1.83 RAM 1G
調整 Django 的架構方式得到的結論
效能上 scgi 和 fastcgi 並無太大的差別
所以只比較 prefork,threaded
效能
threaded > prefork
成功完成 web 請求數最多,最快
threaded Requests per second: 438.89 [#/sec] (mean)
prefork Requests per second: 129.53 [#/sec] (mean)
穩定度
prefork > threaded
threaded 模式運作一段時間後會出現 Internal Server Error,沒有回應
兩種模式,在壓力過大的時候,都會出現無法回應,要等待才能回復,這是正常的現象,因為,Lighttpd pass 給 Django,也要 Django 來得及回應
不過,在真實的運作中, threaded 出現的 Internal Server Error 是不會回復的,需重新啟動 Django 才行
結論就是,先不要對 threaded 的效能流口水,prefork 擋著先
希望有大大可以有建議
參考資料
http://www.alrond.com/en/2007/jan/25/performance-test-of-6-leading-frameworks/
http://timchen119.blogspot.com/2007/06/thread-dying-problem-may-fixed-in.html
supervisor 讓你的 Django 活久一點
過去曾經提過一篇Keep your daemon nerver die,有關 supervisor 的文章,今天,要小記一下, 用supervisord 來控制 Django ,若是發現程式運作發生問題,會自動幫你重新啟動
這是放在設定檔 /etc/supervisord.conf 裡的片段
digez 就是我自己取的名字,因為是要讓 supervisor 來監控,所以 daemonize 設成 false,要注意的是 sock file 的權限,必須是 user www-data 可以讀寫的權限,我的環境是 Debian testing, python 2.5.2
[program:digez]
command=/home/web/digez/manage.py runfcgi daemonize=false socket=/home/web/run/digez.sock pidfile=/home/web/run/digez.pid
user=www-data
autostart=true
autorestart=true
stdout_logfile=/var/log/digez.log
queryset-refactor merge
親愛的 Python 愛用者
Django 的 queryset-refactor 已經 merge 了
是男子漢的就衝吧,這才是有 guts
讓我們繼 unicode branch 之後,再一次感謝
Django 魔人 Malcolm,http://www.pointy-stick.com/blog/
說明
http://code.djangoproject.com/wiki/QuerysetRefactorBranch
假如程式語言是條船 Python Boat
http://compsci.ca/blog/if-a-programming-language-was-a-boat/
其中 Java ,Perl ,Ruby 的比喻的很好玩,Java 像是大商船,Perl 是拖船,Ruby 是快艇
對我來說,Python 是太空船,哈哈
PS: 台灣人有句諺語,是這樣說的,“不會駛船嫌溪彎” (請翻成台語),開船人的腦袋是最重要的,鐵達尼,還不是沉了
Google App Engine
發表了,愚人節說得是真的,以後可以把自己的 Application 放在 Web 上了,看了作 web host 的公司,皮要繃僅一點了,不過,國人很對國外的東西都很陌生,明明已經到了新一世紀了,還是很多的政府機關,公司團體有一些,非常少人用,開發出,只有 IE 能看的網頁,或是網路服務
資料來源
http://code.google.com/appengine/docs/whatisgoogleappengine.html
還可以跑 Django 耶,不過ORM 好像要脫掉
http://code.google.com/appengine/articles/django.html
Python setdefaultencoding
開發及程式執行環境,如果要執行環境的預設編碼
舉例,我要預設 utf8
1) 加入 import sys; sys.setdefaultencoding(‘utf-8’) /etc/pythonX.Y/sitecustomize.py
2) 加入 import sys; sys.setdefaultencoding(‘utf-8’) /usr/lib/pythonX.Y/sitecustomize.py
3) 程式開頭加入, reload(sys);sys.setdefaultencoding(‘utf-8’)
至於原因,及詳細細節請參考(不好意思,我說故事的能力還沒加強好)
http://blog.ianbicking.org/illusive-setdefaultencoding.html