盡管一個 Web 應用程序的大部分內容都與表示有關,但它的價值與競爭優勢卻可能體現在若干專有服務或算法方面。如果這類處理過于復雜或拖沓,最好是進行異步執行,以免 Web 服務器對傳入的請求沒有響應。實際上,將一個計算密集型的或專門化的功能放在一個或多個獨立的專用服務器上運行,效果會更好。
常用的縮略詞
- API:應用程序編程接口
- HTTP:超文本傳輸協議
- LAMP:Linux、Apache、MySQL 與 PHP
PHP 的 Gearman 庫能把工作分發給一組機器。Gearman 會對作業進行排隊并少量分派作業,而將那些復雜的任務分發給為此任務預留的機器。這個庫對 Perl、Ruby、C、Python 及 PHP 開發人員均可用,并且還可以運行于任何類似 UNIX® 的平臺上,包括 Mac OS X、 Linux® 和 Sun Solaris。
向一個 PHP 應用程序添加 Gearman 非常簡單。假設您將 PHP 應用程序托管在一個典型的 LAMP 配置上,那么 Gearman 將需要一個額外的守護程序以及一個 PHP 擴展。截止到 2009 年 11 月,Gearman 守護程序的最新版本是 0.10,并且有兩個 PHP 擴展可以用 — 一個用 PHP 包裹了 Gearman C 庫,另一個用純 PHP 編寫。我們要用的是前者。
請注意:對于本文而言,producer 指的是生成工作請求的機器;consumer 是執行工作的機器;而 agent 則是連接 producer 與適當 consumer 的中介。
安裝 Gearman
向一個機器添加 Gearman 需要兩步:第一步構建并啟動這個守護程序,第二步構建與 PHP 版本相匹配的 PHP 擴展。這個守護程序包包括構建此擴展所需的所有庫。
首先,下載 Gearman 守護程序 gearmand 的最新源代碼,解壓縮這個 tarball,構建并安裝此代碼(安裝需要有超級用戶的權限,即根用戶權限)。
$ wget http://launchpad.net/gearmand/trunk/\ 0.10/+download/gearmand-0.10.tar.gz $ tar xvzf gearmand-0.10.tar.gz $ cd gearmand-0.10 $ ./configure $ make $ sudo make install
安裝 gearmand 后,構建 PHP 擴展。您可以從 PECL 獲取這個 tarball,也可以從 Github 復制該存儲庫。
$ wget http://pecl.php.net/get/gearman-0.6.0.tgz $ cd pecl-gearman # # or # $ git clone git://github.com/php/pecl-gearman.git $ cd pecl-gearman
有了這些代碼后,就可以開始構建擴展了:
$ phpize $ ./configure $ make $ sudo make install
這個 Gearman 守護程序通常被安裝在 /usr/sbin。可以從命令行直接啟動此守護程序,也可以將這個守護程序添加到啟動配置中,以便在機器每次重啟時就可以啟動這個守護程序。
接下來,需要安裝 Gearman 擴展。打開 php.ini 文件(可以通過 php --ini 命令快速找到這個文件),然后添加代碼行 extension = gearman.so:
$ php --ini Loaded Configuration File: /etc/php/php.ini $ vi /etc/php/php.ini ... extension = gearman.so
保存此文件。要想驗證擴展是否啟用,請運行 php --info,然后查找 Gearman:
$ php --info | grep "gearman support" gearman gearman support => enabled libgearman version => 0.10
此外,還可以用一個 PHP 代碼片段來驗證構建和安裝是否得當。將這個小應用程序保存到 verify_gearman.php:
接下來,從命令行運行此程序:
$ php verify_gearman.php 0.10
如果這個版本號與之前構建和安裝的 Gearman 庫的版本號相匹配,那么系統就已準備好了。
運行 Gearman
我們前面提到過,一個 Gearman 配置有三個角色:
- 一個或多個 producer 生成工作請求。每個工作請求命名它所想要的函數,例如 email_all 或 analyze。
- 一個或多個 consumer 完成請求。每個 consumer 命名它所提供的一個或多個函數并向 agent 注冊這些功能。一個 consumer 也可以被稱為是一個 worker。
- 代理對與之建立連接的那些 consumer 提供的所有服務進行集中編制。它將 producer 與恰當的 consumer 聯系起來。
借助如下的命令行,可以立即體驗 Gearman:
- 啟動這個 agent,即 Gearman 守護程序:
$ sudo /usr/sbin/gearmand --daemon
- 用命令行實用工具 gearman 運行一個 worker。這個 worker 需要一個名字并能運行任何命令行實用工具。例如,可以創建一個 worker 來列出某個目錄的內容。-f 參數命名了該 worker 所提供的函數:
$ gearman -w -f ls -- ls -lh
- 最后的一個代碼塊是一個 producer,或用來生成查找請求的一個作業。也可以用 gearman 生成一個請求。同樣,用 -f 選項來指定想要從中獲得幫助的那個服務:
$ gearman -f ls < /dev/null drwxr-xr-x@ 43 supergiantrobot staff 1.4K Nov 15 15:07 gearman-0.6.0 -rw-r--r--@ 1 supergiantrobot staff 29K Oct 1 04:44 gearman-0.6.0.tgz -rw-r--r--@ 1 supergiantrobot staff 5.8K Nov 15 15:32 gearman.html drwxr-xr-x@ 32 supergiantrobot staff 1.1K Nov 15 14:04 gearmand-0.10 -rw-r--r--@ 1 supergiantrobot staff 5.3K Jan 1 1970 package.xml drwxr-xr-x 47 supergiantrobot staff 1.6K Nov 15 14:45 pecl-gearman
從 PHP 使用 Gearman
從 PHP 使用 Gearman 類似于之前的示例,惟一的區別在于這里是在 PHP 內創建 producer 和 consumer。每個 consumer 的工作均封裝在一個或多個 PHP 函數內。
清單 1 給出了用 PHP 編寫的一個 Gearman worker。將這些代碼保存在一個名為 worker.php 的文件中。
清單 1. Worker.php
addServer(); $worker->addFunction("title", "title_function"); while ($worker->work()); function title_function($job) { return ucwords(strtolower($job->workload())); } ?>
清單 2 給出了用 PHP 編寫的一個 producer,或 client。將此代碼保存在一個名為 client.php 的文件內。
清單 2. Client.php
addServer(); print $client->do("title", "AlL THE World's a sTagE"); print "\n"; ?>
現在,可以用如下的命令行連接客戶機與 worker 了:
$ php worker.php & $ php client.php All The World's A Stage $ jobs [3]+ Running php worker.php &
這個 worker 應用程序繼續運行,準備好服務另一個客戶機。
Gearman 的高級特性
在一個 Web 應用程序內可能有許多地方都會用到 Gearman。可以導入大量數據、發送許多電子郵件、編碼視頻文件、挖據數據并構建一個中央日志設施 — 所有這些均不會影響站點的體驗和響應性。可以并行地處理數據。而且,由于 Gearman 協議是獨立于語言和平臺的,所以您可以在解決方案中混合編程語言。比如,可以用 PHP 編寫一個 producer,用 C、Ruby 或其他任何支持 Gearman 庫的語言編寫 worker。
一個連接客戶機和 worker 的 Gearman 網絡實際上可以使用任何您能想象得到的結構。很多配置能夠運行多個代理并將 worker 分配到許多機器上。負載均衡是隱式的:每個可操作的可用 worker(可能是每個 worker 主機具有多個 worker)從隊列中拉出作業。一個作業能夠同步或異步運行并具有優先級。
Gearman 的最新版本已經將系統特性擴展到了包含持久的作業隊列和用一個新協議來通過 HTTP 提交工作請求。對于前者,Gearman 工作隊列保存在內存并在一個關系型數據庫內存有備份。這樣一來,如果 Gearman 守護程序故障,它就可以在重啟后重新創建這個工作隊列。另一個最新的改良通過一個 memcached 集群增加隊列持久性。memcached 存儲也依賴于內存,但被分散于幾個機器以避免單點故障。
Gearman 是一個剛剛起步卻很有實力的工作分發系統。據 Gearman 的作者 Eric Day 介紹,Yahoo! 在 60 或更多的服務器上使用 Gearman 每天處理 600 萬個作業。新聞聚合器 Digg 也已構建了一個相同規模的 Gearman 網絡,每天可處理 400,000 個作業。