在 FreeBSD ports 裡用 local patch 修正問題...

FastCGITrac,遇到 Trac 常常出現 MySQL server has gone away 的問題,官方看起來非常的 open source style:我沒遇到,不太想要處理這個問題... XD

Anyway,這個問題可以透過「#3645 (MySQL connections don't reconnect after idle timeout) – The Trac Project」的 comment:8 給 workaround 掉,但我不希望在升級後問題又跑出來,所以就用「Apache 2.2 worker MPM 與 mod_fastcgi 的問題」這邊的解法來解了:

www/trac: NO_CHECKSUM=yes | PATCH_SITES=http://freebsd-patches.s3.amazonaws.com/trac/ | PATCHFILES=patch-trac__db__mysql_backend.py

不過 NO_CHECKSUM=yes 有點討厭,來找看看有沒有辦法「增加 checksum」而非「忽略 checksum」...

Munin 的設定...

Munin 是套資源監視軟體。跟其他資源監視軟體不一樣的地方?畫面漂亮啊 XDDD 拿台堆各種雜物的 database 來看:

Munin screenshot

等到 Munin 監視超過二十台時就會很明顯感覺到很吃資源,再多的時候就會開始罵三字經,罵完後拆一台獨立的機器跑,以免跑個 vim 都要卡三秒... XD

這時候就是該調整了:

  • munin.conf 的 graph_strategy 與 html_strategy 都改成 cgi,告訴 Munin 在更新時只要更新 rrd 資料,而圖片與 html 的資料讓 cgi 做就好,這可以大幅減少 i/o rate。
  • rrdcached 跑起來,讓 rrd 資料寫入次數更少。rrdcached 的預設參數要記得調整。
  • 將網站本來用 CGI 的部份改成 FastCGI,其實對 nginx 之類的 web server 反而是簡化了 (因為 nginx 內建只支援 FastCGI 而不支援 CGI)。

另外有些討厭的地方,strategy 設定不能放到 includedir 裡,一定得放 munin.conf 本體,這對於自建 ports 的人有點麻煩... (得用 pkg-install 與 @unexec 去堆設定,可以參考 ports-mgmt/portconf/etc/make.conf 的作法)

同時用 mod_deflate 與 mod_fastcgi 所產生的問題...

今天花了不少時間找到的問題...

問題是使用 mod_fastcgi 以及 mod_deflate 時,Content-Encoding 會是 gzip,但 Content-Length 會是未壓縮的長度。

也就是說,伺服器端在 header 提供的 Content-Length 可能寫 8KB,但實際上只丟出 2KB (壓縮後的大小),於是瀏覽器讀完這 2KB 後會停下來一直等,等到 Keep-Alive timeout 斷線 (在我機器上預設是 5 秒)。

在 timeout 斷線後 browser 會就抓到的資料直接解開執行 (因為這 2KB 都有抓到,於是都正確執行)。如果用瀏覽器這邊的 debugger 觀察,就會發現從 first byte 後 5.00 秒才 document ready。

解法有人在 2008 年給過:「Content-Length header should be set using ap_set_content_length」,不過因為 mod_fastcgi 一直沒出新的正式版,所以大家都還是拿到舊的版本。

所以,與之前修正 multi-threading 的問題一樣,往 ports 本身丟 patch:「Update www/mod_fastcgi to fix mod_deflate issue.」,修正後再測試就正常了。

mod_fcgid 與 PHP

先不論效能之類的問題,mod_fcgidPHP 的設定比 mod_fastcgi 簡單許多。(參考之前寫的「apache22 (worker) + mod_fastcgi + php5-fcgi」這篇文章)

首先是把 module load 進來:

LoadModule fcgid_module libexec/apache22/mod_fcgid.so

再來是把副檔名加上去,以及告知什麼副檔名要用什麼程式包:

AddHandler fcgid-script .php
FcgidWrapper /usr/local/bin/php-cgi .php

就這樣而已... 預設會跑一隻 php-cgi,需要的時候會再多拉幾隻。以他的方式看起來 code segment 不會共用,這種設定方式給小站台用還可以...

接下來看看有沒有辦法在 .htaccess 內直接吃本地的 FastCGI process...

FreeBSD 使用 FastCGI + PHP 5.3 提供的 php-fpm

這篇還是講 mod_fastcgi,而非目前歸到 Apache 下管的 mod_fcgid

PHP 5.3 已經內建 php-fpm,不過 ports 預設是不會裝上去的,所以首先先把 lang/php5 加上 php-fpm 支援。方法是 make config 後選擇 FPM。如果有裝 portconf 的人可以直接在 /usr/local/etc/ports.conf 裡加上:

lang/php5*: WITH_FPM=yes

這樣就會強制蓋過系統設定,強制把 php-fpm 裝進去。

接下來是設定的部份,首先是 php-fpm 的設定,這篇的文章只教預設值,會跑在 127.0.0.1:9000。所以只要在 /etc/rc.conf.local 內設定 php_fpm_enable="YES",然後跑 /usr/local/etc/rc.d/php-fpm start 就把 php-fpm 跑起來了。

然後是 apache 的設定,有好幾條要設:

LoadModule fastcgi_module libexec/apache22/mod_fastcgi.so
FastCgiConfig -maxClassProcesses 1
AddHandler php-fastcgi .php
Action php-fastcgi /php-fpm-handler.fcgi
FastCGIExternalServer /php-fpm-handler -host 127.0.0.1:9000
ScriptAlias /php-fpm-handler.fcgi /php-fpm-handler

我是跑 apache22-worker,上面的設定就可以了...