盡管一個(gè) Web 應(yīng)用程序的大部分內(nèi)容都與表示有關(guān),但它的價(jià)值與競(jìng)爭(zhēng)優(yōu)勢(shì)卻可能體現(xiàn)在若干專有服務(wù)或算法方面。如果這類處理過(guò)于復(fù)雜或拖沓,最好是進(jìn)行異步執(zhí)行,以免 Web 服務(wù)器對(duì)傳入的請(qǐng)求沒(méi)有響應(yīng)。實(shí)際上,將一個(gè)計(jì)算密集型的或?qū)iT(mén)化的功能放在一個(gè)或多個(gè)獨(dú)立的專用服務(wù)器上運(yùn)行,效果會(huì)更好。
常用的縮略詞
- API:應(yīng)用程序編程接口
- HTTP:超文本傳輸協(xié)議
- LAMP:Linux、Apache、MySQL 與 PHP
PHP 的 Gearman 庫(kù)能把工作分發(fā)給一組機(jī)器。Gearman 會(huì)對(duì)作業(yè)進(jìn)行排隊(duì)并少量分派作業(yè),而將那些復(fù)雜的任務(wù)分發(fā)給為此任務(wù)預(yù)留的機(jī)器。這個(gè)庫(kù)對(duì) Perl、Ruby、C、Python 及 PHP 開(kāi)發(fā)人員均可用,并且還可以運(yùn)行于任何類似 UNIX® 的平臺(tái)上,包括 Mac OS X、 Linux® 和 Sun Solaris。
向一個(gè) PHP 應(yīng)用程序添加 Gearman 非常簡(jiǎn)單。假設(shè)您將 PHP 應(yīng)用程序托管在一個(gè)典型的 LAMP 配置上,那么 Gearman 將需要一個(gè)額外的守護(hù)程序以及一個(gè) PHP 擴(kuò)展。截止到 2009 年 11 月,Gearman 守護(hù)程序的最新版本是 0.10,并且有兩個(gè) PHP 擴(kuò)展可以用 — 一個(gè)用 PHP 包裹了 Gearman C 庫(kù),另一個(gè)用純 PHP 編寫(xiě)。我們要用的是前者。
請(qǐng)注意:對(duì)于本文而言,producer 指的是生成工作請(qǐng)求的機(jī)器;consumer 是執(zhí)行工作的機(jī)器;而 agent 則是連接 producer 與適當(dāng) consumer 的中介。
安裝 Gearman
向一個(gè)機(jī)器添加 Gearman 需要兩步:第一步構(gòu)建并啟動(dòng)這個(gè)守護(hù)程序,第二步構(gòu)建與 PHP 版本相匹配的 PHP 擴(kuò)展。這個(gè)守護(hù)程序包包括構(gòu)建此擴(kuò)展所需的所有庫(kù)。
首先,下載 Gearman 守護(hù)程序 gearmand 的最新源代碼,解壓縮這個(gè) tarball,構(gòu)建并安裝此代碼(安裝需要有超級(jí)用戶的權(quán)限,即根用戶權(quán)限)。
$ 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 后,構(gòu)建 PHP 擴(kuò)展。您可以從 PECL 獲取這個(gè) tarball,也可以從 Github 復(fù)制該存儲(chǔ)庫(kù)。
$ 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
有了這些代碼后,就可以開(kāi)始構(gòu)建擴(kuò)展了:
$ phpize $ ./configure $ make $ sudo make install
這個(gè) Gearman 守護(hù)程序通常被安裝在 /usr/sbin??梢詮拿钚兄苯訂?dòng)此守護(hù)程序,也可以將這個(gè)守護(hù)程序添加到啟動(dòng)配置中,以便在機(jī)器每次重啟時(shí)就可以啟動(dòng)這個(gè)守護(hù)程序。
接下來(lái),需要安裝 Gearman 擴(kuò)展。打開(kāi) php.ini 文件(可以通過(guò) php --ini 命令快速找到這個(gè)文件),然后添加代碼行 extension = gearman.so:
$ php --ini Loaded Configuration File: /etc/php/php.ini $ vi /etc/php/php.ini ... extension = gearman.so
保存此文件。要想驗(yàn)證擴(kuò)展是否啟用,請(qǐng)運(yùn)行 php --info,然后查找 Gearman:
$ php --info | grep "gearman support" gearman gearman support => enabled libgearman version => 0.10
此外,還可以用一個(gè) PHP 代碼片段來(lái)驗(yàn)證構(gòu)建和安裝是否得當(dāng)。將這個(gè)小應(yīng)用程序保存到 verify_gearman.php:
接下來(lái),從命令行運(yùn)行此程序:
$ php verify_gearman.php 0.10
如果這個(gè)版本號(hào)與之前構(gòu)建和安裝的 Gearman 庫(kù)的版本號(hào)相匹配,那么系統(tǒng)就已準(zhǔn)備好了。
運(yùn)行 Gearman
我們前面提到過(guò),一個(gè) Gearman 配置有三個(gè)角色:
- 一個(gè)或多個(gè) producer 生成工作請(qǐng)求。每個(gè)工作請(qǐng)求命名它所想要的函數(shù),例如 email_all 或 analyze。
- 一個(gè)或多個(gè) consumer 完成請(qǐng)求。每個(gè) consumer 命名它所提供的一個(gè)或多個(gè)函數(shù)并向 agent 注冊(cè)這些功能。一個(gè) consumer 也可以被稱為是一個(gè) worker。
- 代理對(duì)與之建立連接的那些 consumer 提供的所有服務(wù)進(jìn)行集中編制。它將 producer 與恰當(dāng)?shù)?consumer 聯(lián)系起來(lái)。
借助如下的命令行,可以立即體驗(yàn) Gearman:
- 啟動(dòng)這個(gè) agent,即 Gearman 守護(hù)程序:
$ sudo /usr/sbin/gearmand --daemon
- 用命令行實(shí)用工具 gearman 運(yùn)行一個(gè) worker。這個(gè) worker 需要一個(gè)名字并能運(yùn)行任何命令行實(shí)用工具。例如,可以創(chuàng)建一個(gè) worker 來(lái)列出某個(gè)目錄的內(nèi)容。-f 參數(shù)命名了該 worker 所提供的函數(shù):
$ gearman -w -f ls -- ls -lh
- 最后的一個(gè)代碼塊是一個(gè) producer,或用來(lái)生成查找請(qǐng)求的一個(gè)作業(yè)。也可以用 gearman 生成一個(gè)請(qǐng)求。同樣,用 -f 選項(xiàng)來(lái)指定想要從中獲得幫助的那個(gè)服務(wù):
$ 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 類似于之前的示例,惟一的區(qū)別在于這里是在 PHP 內(nèi)創(chuàng)建 producer 和 consumer。每個(gè) consumer 的工作均封裝在一個(gè)或多個(gè) PHP 函數(shù)內(nèi)。
清單 1 給出了用 PHP 編寫(xiě)的一個(gè) Gearman worker。將這些代碼保存在一個(gè)名為 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 編寫(xiě)的一個(gè) producer,或 client。將此代碼保存在一個(gè)名為 client.php 的文件內(nèi)。
清單 2. Client.php
addServer(); print $client->do("title", "AlL THE World's a sTagE"); print "\n"; ?>
現(xiàn)在,可以用如下的命令行連接客戶機(jī)與 worker 了:
$ php worker.php & $ php client.php All The World's A Stage $ jobs [3]+ Running php worker.php &
這個(gè) worker 應(yīng)用程序繼續(xù)運(yùn)行,準(zhǔn)備好服務(wù)另一個(gè)客戶機(jī)。
Gearman 的高級(jí)特性
在一個(gè) Web 應(yīng)用程序內(nèi)可能有許多地方都會(huì)用到 Gearman??梢詫?dǎo)入大量數(shù)據(jù)、發(fā)送許多電子郵件、編碼視頻文件、挖據(jù)數(shù)據(jù)并構(gòu)建一個(gè)中央日志設(shè)施 — 所有這些均不會(huì)影響站點(diǎn)的體驗(yàn)和響應(yīng)性??梢圆⑿械靥幚頂?shù)據(jù)。而且,由于 Gearman 協(xié)議是獨(dú)立于語(yǔ)言和平臺(tái)的,所以您可以在解決方案中混合編程語(yǔ)言。比如,可以用 PHP 編寫(xiě)一個(gè) producer,用 C、Ruby 或其他任何支持 Gearman 庫(kù)的語(yǔ)言編寫(xiě) worker。
一個(gè)連接客戶機(jī)和 worker 的 Gearman 網(wǎng)絡(luò)實(shí)際上可以使用任何您能想象得到的結(jié)構(gòu)。很多配置能夠運(yùn)行多個(gè)代理并將 worker 分配到許多機(jī)器上。負(fù)載均衡是隱式的:每個(gè)可操作的可用 worker(可能是每個(gè) worker 主機(jī)具有多個(gè) worker)從隊(duì)列中拉出作業(yè)。一個(gè)作業(yè)能夠同步或異步運(yùn)行并具有優(yōu)先級(jí)。
Gearman 的最新版本已經(jīng)將系統(tǒng)特性擴(kuò)展到了包含持久的作業(yè)隊(duì)列和用一個(gè)新協(xié)議來(lái)通過(guò) HTTP 提交工作請(qǐng)求。對(duì)于前者,Gearman 工作隊(duì)列保存在內(nèi)存并在一個(gè)關(guān)系型數(shù)據(jù)庫(kù)內(nèi)存有備份。這樣一來(lái),如果 Gearman 守護(hù)程序故障,它就可以在重啟后重新創(chuàng)建這個(gè)工作隊(duì)列。另一個(gè)最新的改良通過(guò)一個(gè) memcached 集群增加隊(duì)列持久性。memcached 存儲(chǔ)也依賴于內(nèi)存,但被分散于幾個(gè)機(jī)器以避免單點(diǎn)故障。
Gearman 是一個(gè)剛剛起步卻很有實(shí)力的工作分發(fā)系統(tǒng)。據(jù) Gearman 的作者 Eric Day 介紹,Yahoo! 在 60 或更多的服務(wù)器上使用 Gearman 每天處理 600 萬(wàn)個(gè)作業(yè)。新聞聚合器 Digg 也已構(gòu)建了一個(gè)相同規(guī)模的 Gearman 網(wǎng)絡(luò),每天可處理 400,000 個(gè)作業(yè)。