Gearman 不一樣的用法~~

Gearman

你所知道的Gearman

可以導入大量數據、發送許多電子郵件、編碼視頻文件、挖據數據並構建一個中央日誌設施 — 所有這些均不會影響站點的體驗和響應性。可以並行地處理數據。而且,由於 Gearman 協議是獨立於語言和平台的,所以您可以在解決方案中混合編程語言。比如,可以用 PHP 編寫一個 producer,用 C、Ruby 或其他任何支持 Gearman 庫的語言編寫 worker。

你所應用Gearman



來自官網的範例:

Client:發送工作需求給Server

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
# Create our client object.
$client= new GearmanClient();
 
# Add default server (localhost).
$client->addServer();
 
echo "Sending job\n";
 
# Send reverse job
$result = $client->do("reverse", "Hello!");
if ($result)
  echo "Success: $result\n";

Worker:接手處理Server工作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# Create our worker object.
$worker= new GearmanWorker();
 
# Add default server (localhost).
$worker->addServer();
 
# Register function "reverse" with the server.
$worker->addFunction("reverse", "reverse_fn");
 
while (1)
{
  print "Waiting for job...\n";
 
  $ret= $worker->work();
  if ($worker->returnCode() != GEARMAN_SUCCESS)
    break;
}
 
# A much simple reverse function
function reverse_fn($job)
{
  $workload= $job->workload();
  echo "Received job: " . $job->handle() . "\n";
  echo "Workload: $workload\n"; 
  $result= strrev($workload);
  echo "Result: $result\n";
  return $result;
}

實際上!!

所遇到狀況可能是…

  • PHP Worker寫了一大堆.(發信一支,轉檔一支…)
  • PHP Worker跑了一大堆.(沒事的時候SLEEP 100…..但是現在很忙阿!!馬上調整程式嗎?)
  • PHP Worker跑了又沒做.(PHP開成常駐程式在跑.有很多狀況要處裡,很多狀況多到要ON CALL!!)
  • 程式碼更新後又要重新開啟常駐程式.(一個就算啦.但是幾百個會怎樣?)

路不轉人轉!!

有沒有辦法克服上述問題?!
有~~

看一下系統架構:


說明:
一般來說,Client發送的是工作.

1
$result = $client->do("reverse", "Hello!");

這行看起來是要叫Worker處理reverse 這項工作 而工作內容為Hello!.
現在我們用.

1
$result = $client->do("Group1bgs", "php TestGearman.php D3 123231 adsadasdq");

你可以看到我改變了原本作法.
php TestGearman.php PARMS1 PARMS2 PARMS3 工作作內容變成這樣.
這時你一定有疑問??搞啥這樣Worker怎摸接?
以下是我啟動的Work的方式:
GetGearman.php 回傳我的Aplication設定值.

  • Server:Jobs Server ip(可以連線多台SERVER)
  • Localname:此範例Group1
  • Threads:啟動幾個Worker

檔案:work.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#!/bin/bash
PWD=`eval pwd`
BASEDIR="${PWD}/$(dirname $0)"
export PATH=$PATH:/bin:/usr/bin:/usr/local/bin:${BASEDIR}
SERVER_HOT=`php ${BASEDIR}/GetGearman.php Server`
LOCAL_NAME=`php ${BASEDIR}/GetGearman.php Localname`
declare THREADS=`php ${BASEDIR}/GetGearman.php Threads`
LOG_DIR=`php ${BASEDIR}/GetGearman.php LOG_DIR`
WORK="${2}"
if [ "$WORK" = "" ]; then
    WORK="bgs"
fi
 
__start( ){
    declare a=0
    while [[ $a -lt $THREADS ]]; do
        (( a++ ))
        PIDFILE="${LOG_DIR}/GearmanWork${WORK}${a}.pid"
        PROMPT="-i ${PIDFILE} -h ${SERVER_HOT} -nw -f ${LOCAL_NAME}${WORK} xargs ${BASEDIR}/${WORK}.sh"
        gearman ${PROMPT} &
    done
}
 
__stop( ){
    declare a=0
    while [[ $a -lt $THREADS ]]; do
        (( a++ ))
        PIDFILE="${LOG_DIR}/GearmanWork${WORK}${a}.pid"
        if [ ! -r $PIDFILE ] ; then
            echo "warning, no pid${a} file found - gearman is not running ?"
            exit 1
        fi
        kill -TERM `cat $PIDFILE`
        rm -f $PIDFILE
    done
}
 
__show_usage( ) {
 
  echo "Usage: {start|stop|restart}"
  exit 1
}
 
testing1=$(echo "${SERVER_HOT}" | grep "ERROR")
if [ "${testing1}" != "" ]; then
    echo "${SERVER_HOT}"
    exit 1
fi
 
testing2=$(echo "${LOCAL_NAME}" | grep "ERROR")
if [ "${testing2}" != "" ]; then
    echo "${LOCAL_NAME}"
    exit 1
fi
 
case "$1" in
    start)
        echo "Starting GearmanWork... ${WORK}"
        __start
        ;;
    stop)
        echo "Stoping GearmanWork... ${WORK}"
        __stop
        ;;
    restart)
        $0 stop ${WORK}
        $0 start ${WORK}
        ;;
    *)
        __show_usage
        ;;
  esac

使用方式:

1
2
$ ./work.sh start 啟動
$ ./work.sh stop 停止

運作:

檔案bgs.sh:
負責執行工作 直接跑命令 以php來說已經不是常駐狀態下運作.還有輸出log以便錯誤狀況查測.(如果你的程式有錯誤也可以看到輸出的錯誤訊息)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/bash
RED=$'\e[1;31m'
GREEN=$'\e[1;32m'
YELLOW=$'\e[1;33m'
BLUE=$'\e[1;34m'
PURPLE=$'\e[1;35m'
CYAN=$'\e[1;36m'
WHITE=$'\e[1;37m'
GREY=$'\e[1;30m'
NOR=$'\e[m'
 
export PATH=$PATH:/bin:/usr/bin:/usr/local/bin:$(dirname $0)
PWD=`eval pwd`
BASEDIR="$(dirname $0)/../"
LOGDIR=$(php GetGearman.php LOG_DIR)
LOGFILE="${LOGDIR}/bgs.log"
time=$(date "+%Y/%m/%d %H:%M:%S")
time2=$(date "+%Y_%m_%d_%H_%M_%S")
logkey=${LOGDIR}/bgs/${time2}$(echo "${*}" | md5sum | cut -c 1-5).log
mkdir -p ${LOGDIR}/bgs
echo "$time $* ${logkey}" >> ${LOGFILE}
## cd ${BASEDIR}
echo "${YELLOW}***  ${RED}Running ${CYAN}${*} ${RED}...${NOR}" >> ${logkey}
(bash -c "${*}") | tee -a ${logkey} 2>&1

每次Worker執行的工作都是一次性的呼叫php,沒有常駐.
以我來說我的專案會以git做版本控管,在正式機器上會在crontab裡加入簡單的shell script每次更新 product的branch.
而我的Worker並不需要重起.因為每次都是獨立呼叫php,自然而然專案由git更新後執行的也是最新的程式碼.

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *