ホームページ  >  記事  >  バックエンド開発  >  PHP を使用してデーモン タスクのバックグラウンド実行とマルチスレッドを実装する (php-resque の使用手順)

PHP を使用してデーモン タスクのバックグラウンド実行とマルチスレッドを実装する (php-resque の使用手順)

WBOY
WBOYオリジナル
2016-06-23 13:29:271476ブラウズ

バックグラウンド タスクを処理するメッセージ キューによって引き起こされる問題

たとえば、メールを送信する場合、メール サーバーへの接続に 5 ~ 10 秒、またはそれ以上かかることがよくあります。成功したプロンプト メッセージがユーザーに送信され、電子メールの送信操作がバックグラウンドでゆっくりと処理されるため、明らかにユーザー エクスペリエンスが向上します。

同様のニーズを実現するために、Web プロジェクトでは、よく知られた製品である MemcacheQ、RabbitMQ などのメッセージ キュー (Message Queue) を使用するのが一般的な実装方法です。

率直に言うと、メッセージ キューは最も単純な先入れ先出しキューであり、キューのメンバーはテキストの一部です。メッセージ キューは非常に単純であるため、メッセージ キューを保持すると、これは単に電子メールを送信するタスクであるため、少し混乱するように感じます。これにより、多くの問題が発生します。

メッセージ キューは文字列型のみを格納できます。電子メールの送信などの「タスク」をメッセージ キュー内の「メッセージ」に変換するにはどうすればよいですか?

メッセージ キューはデータの保存と入力のみを担当し、プログラム自体を実行することはできません。メッセージキューからデータを一つずつ取り出し、タスクに変換して実行します。

メッセージ キューがいつデータを生成するかを予測できないため、タスク実行プログラムには、バックグラウンドに常駐するデーモン プロセスであるメッセージ キューを監視する機能も必要です。

一般的な Web アプリケーション PHP は CGI モードで実行され、メモリに常駐することはできません。 PHP には CLI モードもあることはわかっていますが、PHP CLI を使用してデーモン プロセスを実装できますか?また、それはどの程度効率的ですか?

デーモンが実行されているとき、Web アプリケーションはバックグラウンド デーモンと対話して、プロセスを開始/終了する機能を実現し、プロセスの実行ステータスを取得できますか?

バックグラウンドタスクの設計と役割分担

上記の質問に対して、私がこれまでに見つけた最良の答えは、PHP からのものではなく、Ruby プロジェクト Resque からのものです。それはまさに、Resque が問題を明確かつシンプルに解決しているからです。バックグラウンド タスクによって引き起こされる問題に対処するため、Resque の設計は Python、php、NodeJs、および他の言語 (Python の pyres や PHP の php-resque など) にもクローン化されています。Resque 実装にはさまざまな言語バージョンがあります。もちろん、このブログでは、php-resque を使用してバックグラウンド タスクを実行する方法を説明する例として PHP バージョンを使用します。一部の詳細は Ruby バージョンと異なる場合がありますが、この記事では PHP バージョンが優先されます。

Resque はこれらの問題を次のように解決します:

バックグラウンドタスクの役割分担

実際、上記の問題からわかるように、1 つのメッセージキューだけではすべての問題を解決することはできず、介入するには新しい役割が必要です。 Resque では、バックグラウンド タスクは 3 つの役割によって完了するように抽象化されます。

ジョブ | タスク: ジョブは、バックグラウンドで完了する必要があるタスクです。たとえば、この記事の例として電子メールの送信を抽象化できます。ジョブに。 Resque では、ジョブはクラスです。

Queue: これは上記のメッセージ キューであり、Resque ではキューは Redis によって実装されます。 Resque は、キューへのジョブの挿入/キューからのジョブの削除などの機能を実装できるシンプルなキュー マネージャーも提供します。

ワーカー | エグゼキューター: キューからジョブを取り出して実行する責任を負い、デーモン プロセスとしてバックグラウンドで実行できます。

この分割に基づいて、Resque でのバックグラウンド タスクの基本的なプロセスは次のようになります:

バックグラウンド タスクを独立したクラスとして記述し、このクラスがジョブになります。

バックグラウンド プログラムを使用する必要がある場合、システムはジョブ クラスの名前と必要なパラメーターをキューに入れます。

コマンドラインからワーカーを開き、ワーカーが処理する必要があるキューをパラメータで指定します。

ワーカーはデーモンプロセスとして実行され、キューを定期的にチェックします。

キューにジョブがある場合、ワーカーはジョブを取り出して実行します。つまり、ジョブ クラスをインスタンス化し、クラス内のメソッドを実行します。

これで、バックグラウンドタスクを完了できます。

Resque には、もう 1 つの非常に重要な設計があります。ワーカーは 1 つまたは複数のキューを処理でき、ワーカーのプロセス/スレッドの数を増やすことでキューの実行速度を高速化できます。

php-resqueのインストール

なお、php-resqueはプロセスの開発と管理を伴うため、phpのPCNTL関数を使用するため、Linuxでのみ動作し、phpはPCNTL関数をコンパイルする必要があることに注意してください。 。 Windows を使用して同じ作業を実行したい場合、PHP の他の言語バージョンは Windows でのバックグラウンド タスクには非常に適していないことがわかります。

Ubuntu12.04LTS を例に挙げます。apt を使用して Ubuntu によってインストールされた PHP は、デフォルトで何も設定せずに PCNTL 関数をコンパイルします。

Redis をインストールする

apt-get install redis-server

Composer をインストールする

apt-get install curlcd /usr/local/bincurl -s http://getcomposer.org/installer | phpchmod a+x composer.pharalias composer='/usr/local/bin/composer.phar'
を使用します。 php-resque をインストールする Composer

Web ディレクトリが /opt/htdocs にあると仮定します


apt-get install git git-corecd /opt/htdocsgit clone git://github.com/chrisboulton/php-resque.gitcd php-resquecomposer install

php-resque の使用法

Worker の作成

実際、php-resque には簡単な例が示されています。 job.php ファイルは最も単純なジョブです:

class PHP_Job{    public function perform()    {        sleep(120);        fwrite(STDOUT, 'Hello!');    }}


このジョブは、120 秒後に文字 Hello! を STDOUT に出力することです。

在Resque的设计中,一个Job必须存在一个perform方法,Worker则会自动运行这个方法。

将Job插入队列

php-resque也给出了最简单的插入队列实现 demo/queue.php:

if(empty($argv[1])) {    die('Specify the name of a job to add. e.g, php queue.php PHP_Job');}require __DIR__ . '/init.php';date_default_timezone_set('GMT');Resque::setBackend('127.0.0.1:6379');$args = array(    'time' => time(),    'array' => array(        'test' => 'test',    ),);$jobId = Resque::enqueue('default', $argv[1], $args, true);echo "Queued job ".$jobId."\n\n";

在这个例子中,queue.php需要以cli方式运行,将cli接收到的第一个参数作为Job名称,插入名为'default'的队列,同时向屏幕输出刚才插入队列的Job Id。在终端输入:

php demo/queue.php PHP_Job

结果可以看到屏幕上输出:

Queued job b1f01038e5e833d24b46271a0e31f6d6

即Job已经添加成功。注意这里的Job名称与我们编写的Job Class名称保持一致:PHP_Job

查看Job运行情况

php-resque同样提供了查看Job运行状态的例子,直接运行:

php demo/check_status.php b1f01038e5e833d24b46271a0e31f6d6

可以看到输出为:

Tracking status of b1f01038e5e833d24b46271a0e31f6d6. Press [break] to stop. Status of b1f01038e5e833d24b46271a0e31f6d6 is: 1

我们刚才创建的Job状态为1。在Resque中,一个Job有以下4种状态:

Resque_Job_Status::STATUS_WAITING = 1; (等待)

Resque_Job_Status::STATUS_RUNNING = 2; (正在执行)

Resque_Job_Status::STATUS_FAILED = 3;  (失败)

Resque_Job_Status::STATUS_COMPLETE = 4; (结束)

因为没有Worker运行,所以刚才创建的Job还是等待状态。

运行Worker

这次我们直接编写demo/resque.php:

<?php    date_default_timezone_set('GMT');    require 'job.php';    require '../bin/resque';

可以看到一个Worker至少需要两部分:

可以直接包含Job类文件,也可以使用php的自动加载机制,指定好Job Class所在路径并能实现自动加载

包含Resque的默认Worker: bin/resque

在终端中运行:

QUEUE=default php demo/resque.php

前面的QUEUE部分是设置环境变量,我们指定当前的Worker只负责处理default队列。也可以使用

QUEUE=* php demo/resque.php

来处理所有队列。

运行后输出为

#!/usr/bin/env php*** Starting worker

用ps指令检查一下:

ps aux | grep resque

可以看到有一个php的守护进程已经在运行了

1000      4607  0.0  0.1  74816 11612 pts/3    S+   14:52   0:00 php demo/resque.php

再使用之前的检查Job指令

php demo/check_status.php b1f01038e5e833d24b46271a0e31f6d6

2分钟后可以看到

Status of b1f01038e5e833d24b46271a0e31f6d6 is: 4

任务已经运行完毕,同时屏幕上应该可以看到输出的Hello!

至此我们已经成功的完成了一个最简单的Resque实例的全部演示,更复杂的情况以及遗留的问题会在下一次的日志中说明。

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