Home » Posts tagged "fastcgi"

當 Daemon 死掉時自動重新跑起...

以前確保 daemon 掛掉時會重新跑起來大概有幾個方式,像是用 Monit 顧,然後再用 /etc/inittab 確保 Monit 不會掛掉...

systemd 的年代,因為 systemd 已經被保護起來,而重跑這個功能在 systemd 裡就有支援,不需要用 Monit 這類程式了。

manual 裡搜尋 restart 可以看到幾個參數:

  • Restart=
  • RestartForceExitStatus=
  • RestartPreventExitStatus=
  • RestartSec=

這次是遇到 SmokePing 的 FastCGI daemon 每隔幾天會自己死掉,導致 nginx 丟出 503 然後被 UptimeRobot 偵測到而拋出警告。

但這個問題只有在一台伺服器會發生,而 log 裡也沒翻到可以繼續 debug 的錯誤訊息,試著猜測一些情境去搜尋引擎找也沒翻到... 就決定先 workaround 來處理,然後就發現現在已經不太需要用 Monit 來處理這個問題了。

在 nginx 環境中把 Trac 裝到子目錄下的設法

以前的「Nginx + FastCGI + Trac」提到給的範例是把 Trac 裝在 / 下的方法。如果是裝在 /trac 或是其他路徑時就需要修改了。

一開始試著改會出現這樣的錯誤:

No handler matched request to /trac/report/7

然後研究調整後,發現 Trac 純粹是吃 FastCGI 給的參數去判斷要怎麼處理 url routing,在 trac.ini 內 url 相關參數主要還是用在其他地方... (像是信件通知時用的 url)

首先是把檔案簡化,這是 2016 年寫的:

    location / {
        auth_basic "trac realm";
        auth_basic_user_file /srv/domain.example.com/.htpasswd;

        include fastcgi.conf;
        fastcgi_param AUTH_USER $remote_user;
        fastcgi_param HTTPS on;
        fastcgi_param PATH_INFO $fastcgi_script_name;
        fastcgi_param REMOTE_USER $remote_user;
        fastcgi_param SCRIPT_NAME "";
        fastcgi_pass unix:/var/run/trac/trac.sock;
    }

發現現在 fastcgi.conf 內都會處理 HTTPS 了,所以拿掉 HTTPS 的處理,然後把 location 的判斷改用 regex 去抓 /trac 後的東西,所以先變成這樣:

    location ~ /trac(/.*) {
        auth_basic "trac realm";
        auth_basic_user_file /srv/domain.example.com/.htpasswd;

        include fastcgi.conf;
        fastcgi_param AUTH_USER $remote_user;
        fastcgi_param PATH_INFO $fastcgi_script_name;
        fastcgi_param REMOTE_USER $remote_user;
        fastcgi_param SCRIPT_NAME "";
        fastcgi_pass unix:/var/run/trac/trac.sock;
    }

最後是把 PATH_INFO 改傳 $1 (在 / 的情境下 $fastcgi_script_name 剛好就會是 routing 用的 PATH_INFO 資訊,所以當時直接拿來用),把 SCRIPT_NAME 改成 /trac

也就是跟 Trac 說基底在 /trac,後面的路徑才是你的 routing engine 要處理的東西,所以變成:

    location ~ /trac(/.*) {
        auth_basic "trac realm";
        auth_basic_user_file /srv/domain.example.com/.htpasswd;

        include fastcgi.conf;
        fastcgi_param AUTH_USER $remote_user;
        fastcgi_param PATH_INFO $1;
        fastcgi_param REMOTE_USER $remote_user;
        fastcgi_param SCRIPT_NAME "/trac";
        fastcgi_pass unix:/var/run/trac/trac.sock;
    }

沒寫下來就會花不少時間重新摸...

Nginx + FastCGI + Trac

先前試著逼自己用 Phabricator,用了一個多月後發現設計的邏輯還是跟 Trac 差了不少,算是為了 Facebook 特化的產品吧。在這一個月查資料的過程也發現當初 Wikimedia 要採用的時候也花了不少力氣送 patch 回官方,然後針對不少地方客製化調整。

另外比較痛的地方是 plugin 的支援能力還沒有很好,變成很多東西都要改主體... 而且效能也不太好 (不支援 PHP 7.0 還蠻痛的),在比較低階的 VPS 上跑特別明顯。

這幾天花了點時間把 Trac 給架起來,之前都是用 FreeBSD ports 架,但已經愈來愈沒有再接觸 FreeBSD 了,所以這次在 Ubuntu 上用 pyenv 裝起來再用 pip 裝起來。

另外一個跟之前不同的,是先前都用 Apachemod_wsgi,在低階的 VPS 上則是要找省資源的方案,這次則是用 nginx + FastCGI 去接,比起之前複雜不少...

最主要是參考了官方的文件以及「Gentoo下使用nginx+fastcgi部署trac」這邊的說明達到效果,重點是這段 location 的設定:

    location / {
        auth_basic "trac realm";
        auth_basic_user_file /srv/domain.example.com/.htpasswd;

        include fastcgi.conf;
        fastcgi_param AUTH_USER $remote_user;
        fastcgi_param HTTPS on;
        fastcgi_param PATH_INFO $fastcgi_script_name;
        fastcgi_param REMOTE_USER $remote_user;
        fastcgi_param SCRIPT_NAME "";
        fastcgi_pass unix:/var/run/trac/trac.sock;
    }

    location /.well-known/acme-challenge/ {
        alias /var/www/dehydrated/;
    }

網路上有找到用 location ~ (/.*) 去 match,然後拉出 $1PATH_INFO 用的,這這會使得這段 location 的優先權太高 (參考官方對於 location 的順序說明),而蓋掉下面 Let's Encrypt 的 acme challenge 過程,所以還是得這樣搞。

另外是自己一個人用,就用 .htpasswd 的方式認證了,沒必要弄 LDAP 之類的認證...

接下來就是裝一堆 plugin 並且調整 css/js 與 SQL query 了...

把 nginx 換到 1.6 後 PHP 遇到的問題

升級完 nginx 後就變成白頁了,觀察發現靜態檔案不受影響,所以看起來是與 PHP 溝通有問題,所以應該是 FastCGI 類的問題,用一些關鍵字找了一下,很快就解決了。

解法出自這邊:「Nginx 1.6 + php5-fpm socket communication fail」。

總結原文的解法,本來是 include fastcgi_params; 的請改成 include fastcgi.conf;。(我裝的 ppa 版本已經有 fastcgi.conf,不需要像原文提到自己修改)

用 nginx + FastCGI 接 HHVM...

看到「HHVM, Nginx and Laravel」這篇文章,加上 Rackspace 香港的機器用起來很愉快,就開一台起來測試...

文章內的方法都 okay,只是在裝 HHVM 前少了一步把 key 加到 apt 內的指令:

apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 5A16E7281BE7A449

補上去以後 apt-get update 才會動 :p

速度上當然是沒話說,而且使用的習慣很接近 drop-in replacement 了... (更新檔案後不需要自己另外 purge cache,HHVM 會自己偵測到)

晚點來測試看看 ApacheFastCGI 接 HHVM,如果可行的話就更好了?(.htaccess 啊...)

HHVM 2.3.0 支援 FastCGI...

HHVM 官方的 blog 上看到 2.3.0 的消息:「HHVM 2.3.0 and Travis CI」。

GitHub 上的「FastCGI」這頁就有提到要怎麼透過 FastCGI 界面跟 Apache 配合,熟悉 nginx 的人也應該可以輕鬆對應過去。

另外一個重要的事情是 Travis CI 支援 HHVM 了,可以看到大量的專案加上 HHVM 測試:YiiSlimphpBBJoomlaDoctrineCodeIgniterIdiormPHPUnitParis

既然支援 FastCGI 了,來找機會測試看看...

Debian 上 Apache 2.2 設定 FastCGI 模式 PHP 的方式...

Debian 上只有 mod_fcgid 可以用,沒有 mod_fastcgi,兩者設定方式不一樣,花了一些時間測試...

最後是參考「Debian, apache2, virtualhosts, FastCGI and PHP5」這篇文章的說明,先弄到「會動」的情況。

首先是把該裝的裝起來 (apache2-mpm-workerlibapache2-mod-fcgidphp5-cgi),接下來在 /etc/apache2/sites-available/default 裡面修改兩個部份。

首先是針對 /var/wwwOptions 加上 ExecCGI。另外找個地方加上:

AddHandler fcgid-script .php
FCGIWrapper /usr/lib/cgi-bin/php5 .php

然後重跑 apache 就會動了,放個 phpinfo(); 的程式到 /var/www 下測試就可以確認了。

在 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 的作法)

Archives