ホームページ >バックエンド開発 >PHPチュートリアル >PHP の純粋な非同期ノンブロッキング フレームワーク: swPromise
swPromise は、swoole に基づいた PHP Promise フレームワークです。
日常的な使用シナリオでは、一般的に PHP がインターフェイス集約層として使用されます。ビジネス リクエストは、複数のインターフェイス A->B->C を連続してリクエストする場合があります。このとき、インターフェイス B の応答時間が遅い場合 (重要なビジネスには長いタイムアウト待ち時間が必要です)、全体のリクエスト時間が長くなる原因となります。長すぎると、システムの応答性が大幅に低下します。このビジネス シナリオを考慮すると、プロセスの主な時間は、ネットワーク IO が戻るのを待つのに費やされます。非同期プログラミングが利用できれば、サービスのスループットが大幅に向上します(NodeJSの利点)。
インターフェースの応答時間が通常より長い場合、php-fpm プロセスの数が急激に増加し、その結果、プロセスのスケジューリングに大量の CPU リソースが浪費され、サービスがクラッシュすることもあります。 swPromise フレームワークは、この問題を解決するために開発されました。
非同期ノンブロッキング モードは、高性能ネットワーク プログラミングを実現する方法です。従来、非同期呼び出しを行うためにコードに多数のコールバック関数が実装されていたため、コードの可読性と保守性が大幅に低下していました。この問題を解決するために、主流のソリューションは次のとおりです:
カスタムイベントベースのソリューション
Promise/Deferred
高階関数改ざんコールバック関数
Coroutine (Generator)
Swoole は、PHP 言語用の高性能ネットワーク通信フレームワークであり、PHP 言語用の非同期マルチスレッド サーバーを提供します。 swoole は、カスタム イベントベースのソリューションを使用して、ネットワーク層の基本的なカプセル化を提供します。 swooleをベースに、ビジネス層の非同期開発フレームワークを拡張できます。
tsf (Tencent Server Framework) は、Swoole+PHP Generator によって実装されたコルーチンに基づいて、Tencent によって開始された PHP コルーチン ソリューションです。このフレームワークはコルーチン モードを使用し、swoole および swoole フレームワークに基づいて開発されています。非常に高いパフォーマンスを備えた、真の非同期でノンブロッキングの開発モデルを実現します。コア コードは、記事「Cooperative multitasking using coroutines (in PHP!)」から引用しています。 tsf は比較的複雑なユーザー モード タスク スケジューリング ロジックを使用しており、現時点では運用環境での使用例はありません。また、スウールフレームワークを使用しているため、やや重量感もございます。
swPromise の主な処理フローは CoreAsyncPromise クラスにあります。このクラスは基本的な then メソッドを実装し、Promise プロセスの遅延計算を通じて非同期プロセスの動的制御機能を保証します。このフレームワークは非常に基本的な Web フレームワークで、現時点では、一般的な Future (一般的な遅延計算)、HttpClientFuture、および ResponseFuture の 3 つの遅延計算クラスのみを実装しています。
このフレームワークは、Swoole および php-http-parser 拡張機能とともに使用する必要があります。2 番目の拡張機能は、http プロトコルを解析するために使用されます。
class Handler_Index extends \Core\Handler{ public function run($request, $response){ Promise::create ( Model::getUserInfo ( 'user1', 'haha' ) ) ->then (function(&$promise){ $user1 = $promise->get('user1'); if($user1){ return Model::getUserInfo ( 'user2', 'haha2' ) ->then(function(&$promise){ $user2 = $promise->get('user2'); $promise->accept(['user3'=>$user2['body']]); }); } else $promise->accept(); }) ->then ( Model::getUserInfo ( 'user4', 'haha4' ) ) ->then ( Model::getUserInfo ( 'user5', 'haha5' ) ) ->then ( new ResponseFuture ($response) ) ->start ( new PromiseContext () ); }}
このプロセスは、ユーザー haha の情報が最初に取得され、コンテキストの user1 フィールドに書き込まれることを示しています。データが取得できたら、haha2のユーザー情報を取得し、context user2フィールドに書き込みます。そして user2 の body フィールドを user3 フィールドに入れます。次に、haha4とhaha5の情報を取得します。最後に、すべてのデータが Web ページに出力されます。
最初の then では、if 条件を通じて Promise オブジェクトが返され、非同期プロセスの動的な制御が実現されていることがわかります。同様に、プロセス全体が then まで直列に接続され、同期コードの記述に近くなります。コールバックを使用すると、コードは非常に恐ろしいものになります。
class Handler_Index extends \Core\Handler{ public function run($request, $response){ Promise::create([ Model::getUserInfo ( 'user1', 'haha' ), Model::getUserInfo ( 'user2', 'haha2' ), ])->then( new ResponseFuture ($response) )->start(new PromiseContext ()); }}
このリクエストは、2 人のユーザー haha と hah2 のデータを並列で取得し、それを 2 つのフィールド user1 と user2 に分配します。
Handler_Sync はフレームワークの同期方法を実装します。なお、現状ではrejectメソッドや例外処理処理は実装されていないので、興味のある方はご自身で拡張していただければと思います。
現在、重大なバグが存在します。大量の http リクエストが完了する前に中断されると、swoole http サーバーがエラーとなって終了します。 nginx を swoole の前に置くと問題を解決できます。
起動
php run.php
テスト:
ab -n 10000 -c 100 "http://localhost:9502/async"ab -n 10000 -c 100 "http://localhost:9502/sync"
テスト後、バックエンドインターフェースの応答性能に問題がある場合、swPromiseは同時に大量の接続を処理してインターフェースを待つことができます。非常に低い CPU 負荷で返されるデータ。
プロジェクトのホームページ: http://www.open-open.com/lib/view/home/1447936600338