ホームページ >バックエンド開発 >PHPチュートリアル >PHP は Gearman 拡張機能をインストールして、非同期タスクや段階的なタスクを実装します。

PHP は Gearman 拡張機能をインストールして、非同期タスクや段階的なタスクを実装します。

WBOY
WBOYオリジナル
2016-06-20 12:44:51991ブラウズ

1. はじめに

Gearman は、タスクをキューに入れ、一連のマシンに自動的に割り当てるプログラム フレームワークです。 Gearman はクロス言語およびクロスプラットフォームであり、非同期バックグラウンド タスクを実装するのに非常に便利です。 PHP 公式コレクション: http://php.net/manual/zh/book.gearman.php


上に示したように、Gearman リクエストの処理には 3 つの役割が含まれます。クライアント -> ジョブ -> ワーカー。

クライアント: リクエストのイニシエーター。C、PHP、Perl、MySQL UDF などです。
ジョブ: リクエスト スケジューラは、クライアントによって発行されたリクエストを調整し、適切なワークに転送する責任があります。
ワーカー: C、PHP、Perl などのリクエスト ハンドラー。

2. インストール

1. サーバーをインストールします:

公式ダウンロードについては、https://launchpad.net/gearmand にアクセスしてください。

yum install boost-devel* gperf* libevent-devel* libuuid-devel
wget https://launchpad.net/gearmand/1.2/1.1.12/+download/gearmand-1.1.12。 tar.gz
tar zxvf gearmand…
cd gearmand…
./configure
make && make install

この拡張機能をインストールするには、最初にいくつかの依存関係をインストールする必要があります。デフォルトで使用することをお勧めします。 ./configure を直接指定し、パスなどを指定しないでください。

FAQ 1: boost>=1.39 が見つからないというメッセージが表示されます。明らかにインストールされていますが、gcc-c++ がインストールされていないマシンもあります。 yum install gcc-c++ で十分です。

FAQ 2: インストール完了後に起動に失敗します。Gearmand -d または gearmand -d -u root を起動できません。 gearmand -vvv デバッグ モードでは、オプション -v が定義されていないことを示すプロンプトが表示されます。この時点で、gearand の新しいバージョンのバグが発生しているはずです。ログを確認すると、「000000 [ main ]ソケット() (プロトコルでサポートされていないアドレス ファミリ) -> libgearman-server/gearmand.」というエラーが表示されるはずです。 cc:470"。解決策は、起動時にパラメーター -L 0.0.0.0 を追加して、バインドを ipv4 アドレスのみに制限し、ipv6 を無視することです。または、1.0.2 以下のバージョンをインストールします。公式フィードバック投稿を参照してください: https://bugs.launchpad.net/gearmand/+bug/1134534

参考リンク: http://www.usamurai.com/2013/05/01/install-gearman - from-source-in-centos/

2. gearman の PHP 拡張機能をインストールします

拡張機能をダウンロードします: http://pecl.php.net/package/gearman

wget http://pecl.php.net/get/gearman-1.1.2.tgz
tar zxvf gearman-1….
cd gearman-1 …
phpize
./configure
make && make install

インストールはすぐに完了し、so ファイルへのパスが最後に表示されます (/usr/lib64/php/modules/

) php.ini =”/usr/lib64/php/modules/gearman.so” の末尾に拡張子を追加し、Apache を再起動し、php –info |grep “gearman” または php -m を出力するか、Web ページに phpinfo() を出力します。インストールが成功したことを確認します。

FAQ: 設定時に php-config が見つからないというメッセージが表示された場合は、それを指定してください。たとえば、-with-php-config=/usr/local/php/bin/php-config のように、ディレクトリだけを記述するのではなく、必ず完全に指定してください。

3. 例

クライアント:

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

$client=newGearmanClient()

$client->addServer; ('127.0.0.1', 4730);//このマシンは直接 addServer() できますが、デフォルトのサーバーはポート 4730 を使用します

$client->setCompleteCallback('completeCallBack');// 最初にバインドします。 Valid

$result1=$client->do('say','do');//do は同期的に実行され、処理され、処理結果を返します。

$result2=$client->doBackground('say','doBackground');//非同期的に、処理ハンドルのみが返されます。

$result3=$client->addTask('say','addTask');//タスクをキューに同期的に追加しますか?コールバック関数はタスクを追加することで設定できます。

$result4=$client->addTaskBackground('say','addTaskBackground');//バックグラウンド タスクをキューに非同期的に追加しますか?

$client->runTasks();//キュー内のタスクを実行しますが、do シリーズでは runTask() は必要ありません。

echo'result1:';

var_dump($result1);

echo'
'; 🎜>

echo'result2:';

var_dump($result2);

echo'

echo'result3:';

var_dump($result3)

echo'

echo'result4:';

var_dump($result4);

echo'
';

// バインディング コールバック関数、addTask にのみ有効

functioncompleteCallBack($task)

{

echo'CompleteCallback!処理結果:'.$task->data().'
'

}

ワーカー:

1

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

$worker=newGearmanWorker();

$worker->addServer();

$worker->addFunction('say',function(GearmanJob$job){

    $workload=$job->workload();//接收client传递的数据

    echo'receive data:'.$workload.PHP_EOL;

    returnstrrev($workload);//仅作反转处理

});

 

//无际循环运行,gearman内部已有处理,不会出现占用过高死掉的情况

while($worker->work()){

    if($worker->returnCode() !== GEARMAN_SUCCESS){

        echo'error'.PHP_EOL;

    }

}

2 3 4 5 6 7 8 9 10 11 12 13 14 15
<🎜> $worker=newGearmanWorker(); <🎜> <🎜> $worker->addServer(); <🎜> <🎜> $worker->addFunction ('say',function(GearmanJob$job){ <🎜> <🎜> $workload=$job->workload();// クライアントから渡されたデータを受信 echo'receive data: '. $workload.PHP_EOL; returnstrrev($workload); // 逆処理のみ // 無限ループ処理、gearman は内部処理があり、使いすぎによる死亡はありません while($worker->work()){ if($worker->returnCode( ) !== GEARMAN_SUCCESS){ echo'error'.PHP_EOL } }

上記のクライアント出力:

CompleteCallback!ハンドル結果:ksaTdda
result1:string(2) “od”
result2:string(17) “H:iZ943bixttyZ:87″
result3:object(GearmanTask)#2 (0) { }
result4:object(GearmanTask)#3 (0) { }

ワーカー出力:

データ受信:do
データ受信:doBackground
データ受信:addTaskBackground
accept data:addTask

4. PCntl 拡張機能は大まかなマルチワーカー保護を実装します

ワーカーはバックグラウンドに留まらなければならず、ジョブを処理するためにジョブサーバーから呼び出される準備が常に整っているため、ワーカーは死ぬことはできません。オンラインです。解決策は、スケジュールされたタスクを通じてワーカーを再起動することです。これは良い解決策です。マルチプロセス保護の話もありますが、実際には PHP を実装するのは困難です。解決策の 1 つは、メインプロセスからフォークされたサブプロセスが起動してワーカーを実行することです。ワーカーはメインプロセスのサブプロセスです。メインプロセスは子プロセスを監視し、ワーカーが終了すると、すぐに新しいプロセスが開始されます。しかし、メインプロセスが停止したらどうなるでしょうか?メインプロセスはビジネス処理を実行しないため、死亡する確率は子プロセスワーカーが死亡する確率よりもはるかに小さくなります。

次の例では、メインプロセスは 5 つのサブプロセスを開始します。つまり、5 つのワーカーを開始してそれらを監視します。

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

宣言(ティック) = 1 );

$num= 5; //子プロセスの最大数

$child= 0; //現在の子プロセス数

// 信号処理関数

functionig_handler($sig)

{

global$child;

switch($sig) {

caseSIGCHLD :

$child--;

echo'SIGCHLD を受け取りました!' プロセス'.PHP_EOL; 🎜>

caseSIGINT:

$child--;

echo'SIGINT を受け取りました!これで「.$child」ができました。プロセス'.PHP_EOL;

休憩;

caseSIGTERM:

$child--;

echo'SIGTERMを受け取りました!これで「.$child」ができました。プロセス'.PHP_EOL;   

休憩;

デフォルト:

# コード...

break;

}

}

// インストール信号处処理器

pcntl_signal(SIGTERM,"sig_handler");//进程キル時に発行されるシグナル

// pcntl_signal(SIGHUP, "sig_handler");// 終了時に発行されるシグナル

pcntl_signal(SIGINT,"sig_handler");// 中断信号、例: Ctrl+C

pcntl_signal(SIGCHLD,"sig_handler");//进程退出信号

while(true)

{

$child++;

$parentpid=getmypid();

$pid= pcntl_fork();//一分二、父进程和子进程都市执行以下代码

if($pid== -1)

{

exit("フォークできません!");//出错

}elseif($pid> 0){

//父进程处理代码

echo「私は親です。私の PID は「.$pid」です。」私の親 PID は '.$parentpid.PHP_EOL;

if($child>=$num)

{

pcntl_wait($status);// 待機中、待機中结束、子进程成を僵尸进程にする

}

}elseif($pid== 0){

//子进程代

エコーアイ私は子で、親の PID は '.$parentpid です。" 私の PID は ".getmypid()。" 現在 $child プロセスがあります。".PHP_EOL;       

//具体的な代価

pcntl_exec('/usr/bin/php',array('/var/www/test/mywork.php'));

}

pcntl_signal_dispatch();// 信号を分割し、取り付けられた信号処理装置が受信できるようにします。

// php5.3 より低いこの関数数は無能ですが、开头の宣言 (ティック = 1); 表示実行一条低級命令、

//就检查次信号、結果检测に注釈の信号、就调使用その信号処理器

sleep(rand(3,5));//100% 占有を防止

}

参考リンク:http://huoding.com/2012/10/30/196、http://www.zrwm.com/?cat=80

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
前の記事:Laravelの学習次の記事:Laravelの学習