官網: http://gearman.org/php
一篇文章:html
利用Gearman實現異步任務處理node
1、問題分析git
問題:在性能測試過程當中,發現用戶管理平臺在進行圖片上傳時,性能不佳。github
分析:通過代碼分析得知,主要的瓶頸是圖片上傳後,還須要根據圖片組件所在頁面模塊容器進行一系列處理:圖片生成縮略圖,裁剪圖片,加水印等,這些處理在高併發的狀況下,會消耗大量cpu資源,致使系統響應速度很是慢。sql
舊的處理方式:數據庫
次控端調用前臺接口進行上傳圖片後,前臺程序先上傳圖片,接着,進行圖片壓縮等處理,而後再返回結果給次控端。編程
整個過程是串行的,次控端須要等待前臺的結果後,再顯示給用戶。這個過程存在時間浪費,圖片的處理能夠提交到後臺再進行處理,不須要立刻處理。ubuntu
所以,考慮採用Gearman進行異步任務處理。centos
新的處理方式:
次控端調用前臺接口上傳圖片,前臺保存要上傳的圖片後,提早返回信息給次控端,接着,調用Gearman增長一個任務,而後,由Gearman自動指派任務給服務器進行任務處理。採用新的處理方式後,次控端操做體驗更加快捷。
2、Gearman詳細介紹
簡介:
官網:http://gearman.org/
Gearman是一個分佈式的程序框架。Gearman提供了一個通用的應用程序,能夠工做在更加適合處理這項任務的其餘計算機或其餘處理器上。它容許並行處理,載入平衡處理,並且能夠在不一樣語言間進行調用。它能夠應用於各類各樣的應用場合。換句話說,它是一個進行分佈式處理的強健系統。如下是關於Gearman的一些長處:
l 開源:徹底開源,免費的。
l 多語言:有許多語言接口,並且支持的語言數量一直在增長。
l 靈活:不依賴於任何特定的設計。
l 快速:簡單的協議和接口,能夠減小現有應用程序的開銷。
l 嵌入:輕量,能夠以最小的代價引入到現有程序。
l 沒有單點故障:具備較強的容錯性。
框架:
、
(摘自官網)
Gearman Client:提供客戶端調用,API能夠是多種語言,目前在智能建站裏應用的是PHP語言
Gearman Job Server:調度者,負責把來自客戶端的請求分發到不一樣服務器或不一樣處理器上的Worker。
Gearman Worker:負責任務處理,並返回結果。
說明:應用程序經過Client API調用建立客戶端請求,Job Server把請求分發到不一樣的worker上進行處理,Worker接收到請求並進行處理後返回結果。
如下是Gearman中三個基本模塊的調用關係圖:
(摘自官網)
Client與Worker是能夠由不一樣的語言來寫的,例如:Client由PHP來寫,Worker由C語言來寫。這樣就能夠很方便地把不一樣的語言編寫的接口進行各自的接口封裝。
無論是把Worker放到單獨服務器,仍是放到集羣服務器,Worker均可以正常運行。
Client發送任務到Job Server中,由Job Server負責調度,Job Server會自動檢測空閒的Worker,併發送任務到這個空閒的Worker,Worker進行任務處理。所以,Gearman框架能夠實現資源負載平衡。
Gearman框架具備很強的擴展性。這個框架支持多核心CPU。若是Worker所在的服務器太繁忙,能夠把服務器的CPU換成更多核心的CPU,如16核CPU,這樣就能夠在這臺服務器上建立16個Worker實例來進行處理。固然,Gearman也支持服務器的擴展,能夠很方便地擴展出更多的Worker服務器來處理請求。惟一須要作的事情就是:啓動新服務器,安裝好Worker程序,並修改配置便可。
若是服務器掛掉了,Gearman會如何處理呢?咱們能夠同時運行多個Job Server,Client和Worker鏈接到配置好的Job Server。若是這臺Job Server出現故障,則配置到這臺的Client和Worker會自動鏈接到另一臺可用的Job Server。這裏建議你們,至少要有兩臺以上的Job Server,利用冗餘來提升系統的容錯性。
安裝:
Job Server (gearmand)
gearmand (C)
A job server written in C/C++ under the BSD license that contains all of the latest protocol additions. Development for this is very active, with threading, persistent queues, and pluggable protocols now supported. Replication and better statistics reporting are coming soon. This installs an executable calledgearmand
(usually in /usr/local/sbin). The C library, libgearman, is bundled in the same package.
./configure --prefix=/opt
安裝報錯:
checking whether the Boost::Program_Options library is available... yes
configure: error: Could not find a version of the library!
安裝boost:
configure: error: could not find gperf
安裝之:yum install gperf
(apt-get install gperf
Linux下生成hash函數代碼的工具。)
configure: error: Unable to find libuuid
仍是錯誤。
所以,只有去官網下載:
http://sourceforge.net/projects/libuuid/
用源碼安裝方式安裝。
而後,再次從新執行gearman目錄下的./configure。呼呼~~~~~,終於再也不出錯了,此次順利執行完畢。
(能夠加參數,如:./configure --with-sqlite3=/usr/local/sqlite3 --with-boost=/usr/local/boost-1.57 --with-boost-libdir=/usr/local/boost-1.57/lib
--with-memcached=[PATH]
absolute path to memcached executable
(若是報錯libcurl
安裝:
aptitude install libcurl4-openssl-dev
報錯uuid錯誤:
libgearman/.libs/libgearman.so: undefined reference to `uuid_generate_time_safe@UUID_2.20'
libgearman/.libs/libgearman.so: undefined reference to `uuid_unparse@UUID_1.0'
collect2: error: ld returned 1 exit status
make[1]: *** [t/sqlite] Error 1\
須要蔥這裏 http://sourceforge.net/projects/e2fsprogs/files/e2fsprogs/v1.42.5/ 下載並安裝e2fsprogs, 注意configure的參數必須是:./configure --prefix=/usr/local/e2fsprogs --enable-elf-shlibs,而後把uuid目錄拷過去 cp -r lib/uuid/ /usr/include/ 和 cp -rf lib/libuuid.so* /usr/lib 以後make clean重試便可!
.安裝e2fsprogs (必須用源碼安裝,yum安裝的很差使)ubuntu好像不行。
./configure –enable-elf-shlibs make make install cp -r lib/uuid/ /usr/include/ cp -rf lib/libuuid.so* /usr/lib
)
安裝 gearmand
後,構建 PHP 擴展。您能夠從 PECL 獲取這個 tarball,也能夠從 Github 複製該存儲庫。
$ wget http://pecl.php.net/get/gearman-0.6.0.tgz |
有了這些代碼後,就能夠開始構建擴展了:
$ phpize |
./configure 後面能夠設置php-config路徑:
./configure --prefix=/opt --with-php-config=/usr/local/php/bin/php-config
http://ju.outofmemory.cn/entry/105792
仍是報錯:
configure: error: Please install libgearman
咱們在安裝gearman的時候,已經有libgearman了,可是在編譯擴展的時候,卻用額外安裝的lib,在運行的時候,不免出現性能方面的問題
在./configure的時候指定下gearman的路徑就是了,沒必要下降額外安裝libgearman及下降版本(http://blog.csdn.net/aidenliu/article/details/7406390)
./configure --prefix=/opt --with-php-config=/usr/local/php/bin/php-config --with-gearman=/opt/gearmand/
( 安裝php擴展的時候,缺乏 libgearman ,這在安裝gearman的時候應該已經安裝好了,在安裝gearman的時候./configure 不要加參數便可)
這個 Gearman 守護程序一般被安裝在 /usr/sbin。能夠從命令行直接啓動此守護程序,也能夠將這個守護程序添加到啓動配置中,以便在機器每次重啓時就能夠啓動這個守護程序。
接下來,須要安裝 Gearman 擴展。打開 php.ini 文件(能夠經過 php --ini
命令快速找到這個文件),而後添加代碼行 extension = gearman.so
:
$ php --ini |
保存此文件。要想驗證擴展是否啓用,請運行 php --info
,而後查找 Gearman:
$ php --info | grep "gearman support" |
此外,還能夠用一個 PHP 代碼片斷來驗證構建和安裝是否得當。將這個小應用程序保存到 verify_gearman.php:
<?php |
接下來,從命令行運行此程序:
$ php verify_gearman.php |
若是這個版本號與以前構建和安裝的 Gearman 庫的版本號相匹配,那麼系統就已準備好了。
咱們前面提到過,一個 Gearman 配置有三個角色:
email_all
或analyze
。藉助以下的命令行,能夠當即體驗 Gearman:
$ sudo /usr/sbin/gearmand --daemon |
gearman
運行一個 worker。這個 worker 須要一個名字並能運行任何命令行實用工具。例如,能夠建立一個 worker 來列出某個目錄的內容。-f
參數命名了該 worker 所提供的函數:
$ gearman -w -f ls -- ls -lh |
gearman
生成一個請求。一樣,用 -f
選項來指定想要從中得到幫助的那個服務: $ gearman -f ls < /dev/null |
從 PHP 使用 Gearman 相似於以前的示例,唯一的區別在於這裏是在 PHP 內建立 producer 和 consumer。每一個 consumer 的工做均封裝在一個或多個 PHP 函數內。
清 單 1 給出了用 PHP 編寫的一個 Gearman worker。將這些代碼保存在一個名爲 worker.php 的文件中。
1.Worker.php
<?php $worker= new GearmanWorker(); $worker->addServer(); $worker->addFunction("title", "title_function"); while ($worker->work()); function title_function($job) { return ucwords(strtolower($job->workload())); } ?>
清 單 2 給出了用 PHP 編寫的一個 producer,或 client。將此代碼保存在一個名爲 client.php 的文件內。
<?php $client= new GearmanClient(); $client->addServer(); print $client->do("title", "AlL THE World's a sTagE"); print "\n"; ?>
[root@localhost code]# php Client.php
PHP Deprecated: GearmanClient::do(): Use GearmanClient::doNormal() in /opt/code/Client.php on line 4
All The Worlds's A Stags
把上面do改爲doNormal
如今,能夠用以下的命令行鏈接客戶機與 worker 了:
$ php worker.php & |
這個 worker 應用程序繼續運行,準備好服務另外一個客戶機。
這個 worker 應用程序繼續運行,準備好服務另外一個客戶機。
在一個 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 個做業。Gearman 的一個出色例子能夠在 Narada 這個開源搜索引擎(參見 參 考資料)中找到。
Gearman 的將來版本將收集並報告統計數據、提供高級監視和緩存做業結果等。爲了跟蹤這個 Gearman 項目,能夠訂閱它的 Google 組,或訪問 Freenode 上它的 IRC 頻道 #gearman
。
http://www.oschina.net/question/12_7687
安裝參考:
http://blog.chinaunix.net/uid-27177626-id-4325909.html
一篇文章:
PHP利用Gearman實現異步/並行多進程處理數據http://www.zrwm.com/?p=888
Gearman是一個可進行任務調度分發,提供並行數據處理的分佈式計算框架,支持多種編程語言.
它由三部分組成:
Gearman的一些使用場景:
下面的簡單例子僅爲說明PHP如何使用Gearman,不具有實際生產意義.
一個簡單的worker:
[root@centos192 worker]# cat myworker.php <?php $worker = new GearmanWorker(); $worker->addServer('192.168.1.192', 4730); $worker->addFunction('sayhello', function(GearmanJob $job){ $name = $job->workload(); return "hello, " . $name; }); $worker->addFunction('logMsg', function(GearmanJob $job){ $msg = $job->workload(); file_put_contents(__DIR__ . '/Msg.log', $msg, FILE_APPEND); }); while ($worker->work()){ usleep(50000); }
以守護進程方式啓動worker:
# nohup php myworker.php >/dev/null 2>&1 &
addFuntion另外方式:
$gmworker->addFunction("reverse", "reverse_fn");
function reverse_fn($job)
{
return strrev($job->workload());
}
一個發送任務處理請求的client:
[root@centos191 client]# cat myclient.php <?php $name = $argv[1]; if (empty($name)) { echo "Usage: $argv[0] {name}"; exit(1); } try { $client = new GearmanClient(); $client->addServer('192.168.1.192', 4730); } catch(Exception $e){ echo "oops", $e->getMessage(); exit(1); } // 同步處理(Blocking),返回直接的處理結果 $result = $client->doNormal('sayhello', $name); echo $result . PHP_EOL; // 異步處理(Non-Blocking),僅返回一個處理狀態的句柄 $job_handle = $client->doBackground('logMsg', $name); echo $job_handle . PHP_EOL;
運行myclient.php:
[root@centos191 client]# php myclient.php "Jose" hello, Jose H:centos192:5
http://php.net/manual/zh/gearmanclient.donormal.php
GearmanClient::doNormal — Run a single task and return a result
public string GearmanClient::doNormal ( string , string [, string ] )
$function_name$workload$uniquefunction_name
由程序自動執行的已註冊函數。
workload
被處理的序列化數據。
unique
用於標識特定任務的惟一性 ID。
一個發出並行處理任務請求的例子tasksclient:
[root@centos191 client]# cat tasksclient.php <php try { $client = new GearmanClient(); $client->addServer('192.168.1.192', 4730); } catch(Exception $e){ echo "oops", $e->getMessage(); exit(1); } $client->setCompleteCallback(function(GearmanTask $task){ echo 'Completed task:: id :', $task->unique(), ' , handled result:', $task->data(), PHP_EOL; }); $client->addTask('sayhello', 'Jose', null, 1); $client->addTask('sayhello', 'John', null, 2); $client->addTaskBackground('logMsg', 'Peter'); $client->runTasks();
運行tasksclient:
[root@centos191 client]# php tasksclient.php Completed task:: id :2 , handled result:hello, John Completed task:: id :1 , handled result:hello, Jose
我最開始沒有修改addServer的ip,致使php taskslinet.php一直處於運行狀態,沒有結果輸出。這說明只要不返回結果,程序一直運行。
查查當前註冊的worker及function(顯示格式:FD IP-ADDRESS CLIENT-ID : FUNCTION ...)
[root@centos192 worker]# (echo "workers"; sleep 0.1) | nc 127.0.0.1 4730 32 192.168.1.192 - : sayhello logMsg 33 127.0.0.1 - : .
查看當前隊列狀況(顯示格式FUNCTION\tTOTAL\tRUNNING\tAVAILABLE_WORKERS):
[root@centos192 worker]# (echo "status"; sleep 0.1) | nc 127.0.0.1 4730 sayhello 0 0 1 logMsg 0 0 1 .
第一列是function名稱,第2列顯示隊列中的任務數,第3列顯示正在運行的任務數,第四列顯示可用的worker數.
上面例子中直接啓動worker腳本做爲守護進程,沒法監控到worker進程是否存活.
使用Unix進程監控supervisord則可輕鬆解決這個問題.
將以下配置添加到supervisord的配置中,便可實現由supervisord來啓動和監控myworker.
[program:myworker] command=/usr/local/php5415/bin/php myworker.php process_name=%(program_name)s_%(process_num)02d ;修改numprocs便可同時開啓多個worker進程 numprocs=1 directory=/data/www/gearman/worker autostart=true autorestart=true user=gearmand stopsignal=KILL
gearman安裝後在bin目錄下有2個程序gearman,gearmanadmin,它用來Run Administrative commands against a server.
Provice help about the program.
Create a function from the server.
Connect to the host
Port number or service to use for connection
Drop a function from the server.
Fetch the version number for the server.
Fetch the verbose setting for the server.
Status for the server.
Workers for the server.
Shutdown server.
bin目錄下的gearman用來命令行操做命令。Command line client for Gearmand
Common options
Function name to use for jobs (can give many)
Job server host
Print this help menu
Gearman server port
Timeout in milliseconds
Create a pidfile for the process
In client mode run one job per line, in worker mode send data packet for each line
Same as -n, but strip off the newline
Client options
Run jobs in the background
Run jobs as high priority
Run jobs as low priority
Prefix all output lines with functions names
Send job without reading from standard input
Unique key to use for job
Worker options*
Number of jobs for worker to run before exiting
Run in worker mode
With gearman you can run client and worker functions from the command line.
The environmental variable GEARMAN_SERVER can be used to specify multiple gearmand servers. Please see the c:func:’gearman_client_add_servers’ for an explanation of the required syntax.
http://gearman.info 是一個gearman文檔的網站,不錯。
http://php.net/manual/zh/gearmanclient.donormal.php php官方關於gearman的文檔。
很好的博客:http://www.livingelsewhere.net/tag/gearman/
http://www.php-oa.com/2010/09/05/perl-gearman-distributed.html
http://blog.chinaunix.net/uid-27177626-id-4325909.html
http://www.cppblog.com/guojingjia2006/archive/2013/01/07/197076.html
http://www.2cto.com/kf/201312/262636.html
http://www.cppblog.com/guojingjia2006/archive/2013/01/07/197076.html