背景: PHP の非同期コールバックに関しては、実際のところ、PHP 言語の実行メカニズムをエレガントに実装することは不可能です。このキューの処理を実装するために swoole と呼ばれる拡張機能があると非常に便利です。以前、Zhang Yan 兄弟は https と呼ばれるキュー処理 (libevent に基づいた) を書きました。その後、Han Tianfeng 兄弟は、(自作の epoll に基づいて) CPU の IO を完全に満たすための非同期 IO 実装にさらに注目した swoole を書きました。とにかく、私はまだ見ていないので、時間があれば勉強します) しかし、swoole のファンおよびコンサルタントとして、非同期の問題は依然として大きな需要があります。 PHP 業界、特に非同期ログ書き込みと URL アクセス、電子メールの非同期送信、コンピューター室データベース間の特殊な小規模同期、非同期キューの監査、データベースとキャッシュ インターフェイスのクエリ、フレームワーク下部のインターフェイス アクセスのトラブルシューティング エラーの返還。 、これらは現在、大規模な同時 Web サイトの場合は非同期で解決する必要がありますが、非同期リターン非同期、コールバックも非同期コールバックを実装します (実際に大規模な同時実行では PHP プロセスがブロックされる可能性があり、プロセスが非同期リターンを待機することになり、新しい接続が時間内に処理されなくなる可能性があります)。 php-fpm process avalanche) は、実際のアプリケーションで定期的に処理されます。その方法は、以下の swoole も処理用に新しいポートを開きます。 httpsqs では、1 つの配信が到着すると、PHP デーモンがキューを読み取ります。これは、非常にビジーな場合、非同期処理の戻りが遅くなり、待ち時間が長すぎると思います。実際には、非同期とキューは主にデータのスローと問題の解決に使用されますが、swoole はこの領域で非同期だけでなく非同期コールバックも備えているため、上記のシナリオを解決します。最初に記事をコピーして、時間があれば実装を勉強させてください:-)、非同期コールバックについて質問がある場合は、メッセージを残してください。
—————————————————————————————————————————— —————————————————————
非同期タスクキューについて
ユーザーが弊社 Web サイトを開きました。あとは、メール送信が必要なエージェントのリストを確認し、決済メールを送信するだけです。
電子メールを送信する必要がある場合は、それを実行する関数を記述するだけです。ネットワークが多少遅れる可能性があることを考慮すると、ユーザーは Web ページが電子メールの送信を完了するまで待ってから Web ページを閉じることは許容されます。
10 通のメールを公開したい場合は、for ループを使用して 10 回ループし、メール送信操作を実行します。現時点では、おそらく 10 倍のネットワーク遅延があると、ユーザーは少し焦るでしょうが、ほとんど待つことができません。
100 通のメールを送信すると、for ループが 100 回繰り返され、ユーザーが直接立ち上がります。なんと壊れた Web サイトでしょう。
しかし現実的には、おそらく 10,000 件を超えるメールがあるでしょう。この遅延の問題にはどう対処すればよいでしょうか?
その答えは、非同期を使用することです。 「電子メール送信」操作をカプセル化し、バックグラウンドで非同期に 10,000 回実行します。この場合、ユーザーが Web ページを送信した後の待機時間は、「電子メール タスク リクエストをキューにプッシュする」時間だけです。また、バックグラウンド サービスはユーザーの目に見えない場所で実行されます。
「非同期キュー」の実装に関しては、mysqlテーブルやredisを使って送信するメールを保存し、毎分定期的に送信リストを読み込んで処理する人もいます。これは、スケジュールされた非同期タスク キューです。ただし、現在送信されているタスクは 1 分まで実行されませんが、これは一部のリアルタイム アプリケーション シナリオではまだ高速ではありません。一部のシナリオでは、タスクが送信されるとすぐに実行される必要がありますが、ユーザーは結果が返されるまで待つ必要はありません。
クラウド プラットフォーム SAE および BAE には、上記の問題を解決するためのタスクキュー サービスがあります。また、自分でサーバーを想定している場合は、どのように解決すればよいでしょうか?この記事では、PHP を使用して swoole を拡張し、リアルタイムの非同期タスク キューを実装するソリューションを検討します。
swoole をインストールします
pecl インストール:
pecl install swoole
php.ini が書き込まれていないことを示すプロンプトが表示されたら、コマンド ライン プロンプトを確認します。 PHP.ini の後に手動で追加します:
extension = "swoole.so"
Server
スクリプトを配置する予定のディレクトリに新しいサーバーを作成します (自分で作成することもできます) .php のコードは次のとおりです:
<?phpclass Server{ private $serv; public function __construct() { $this->serv = new swoole_server("0.0.0.0", 9501); $this->serv->set(array( 'worker_num' => 1, //一般设置为服务器CPU数的1-4倍 'daemonize' => 1, //以守护进程执行 'max_request' => 10000, 'dispatch_mode' => 2, 'task_worker_num' => 8, //task进程的数量 "task_ipc_mode " => 3 , //使用消息队列通信,并设置为争抢模式 //"log_file" => "log/taskqueueu.log" ,//日志 )); $this->serv->on('Receive', array($this, 'onReceive')); // bind callback $this->serv->on('Task', array($this, 'onTask')); $this->serv->on('Finish', array($this, 'onFinish')); $this->serv->start(); } public function onReceive( swoole_server $serv, $fd, $from_id, $data ) { //echo "Get Message From Client {$fd}:{$data}n"; // send a task to task worker. $serv->task( $data ); } public function onTask($serv,$task_id,$from_id, $data) { $array = json_decode( $data , true ); if ($array['url']) { return $this->httpGet( $array['url'] , $array['param'] ); } } public function onFinish($serv,$task_id, $data) { //echo "Task {$task_id} finishn"; //echo "Result: {$data}n"; } protected function httpGet($url,$data){ if ($data) { $url .='?'.http_build_query($data) ; } $curlObj = curl_init(); //初始化curl, curl_setopt($curlObj, CURLOPT_URL, $url); //设置网址 curl_setopt($curlObj, CURLOPT_RETURNTRANSFER, 1); //将curl_exec的结果返回 curl_setopt($curlObj, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curlObj, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($curlObj, CURLOPT_HEADER, 0); //是否输出返回头信息 $response = curl_exec($curlObj); //执行 curl_close($curlObj); //关闭会话 return $response; }}$server = new Server();
サーバーは非同期でメモリ内に常駐しているため、コマンド ラインから起動する必要があります。コマンドラインで上記のコードを実行してサービスを開始します。
php Server.php
実行後はコマンドラインウィンドウを閉じてください。サービスはバックグラウンドでデーモンとして実行されます
クライアント
サービスを開始した後、サービスを呼び出す方法を見てみましょう。新しいテスト ファイル Client_test.php を作成します
コードは次のとおりです。
<?phpclass Client{ private $client; public function __construct() { $this->client = new swoole_client(SWOOLE_SOCK_TCP); } public function connect() { if( !$this->client->connect("127.0.0.1", 9501 , 1) ) { echo "Connect Error"; } $data = array( "url" => "http://192.168.10.19/send_mail" , "param" => array( "username"=>'test', "password" => 'test' ) ); $json_data = json_encode($data); $this->client->send( $json_data ); }}$client = new Client();$client->connect();
上記のコードでは、url はタスクのアドレス、param は必須の送信パラメータです。
コードを保存し、コマンド ラインまたはブラウザで Client_test.php を実行して、非同期タスク キューを実装します。入力した URL は、各非同期タスクが送信された後、HTTP GET 経由で非同期的に実行されます。
表示して閉じる
Swoole には、あまり便利な閉じる方法がないようです。したがって、プロセスを閉じることによってのみ直接閉じることができます。
表示コマンド:
ps -ef | php
単一プロセスを終了する:
kill -9 {プロセス番号}
すべてのプロセスを終了するコマンド:
killall -9 php
Seventh Stardust のブログからの抜粋: http://blog.star7th.com/2016/01/1905.html