ホームページ  >  記事  >  PHPフレームワーク  >  Swoole 上級: コルーチンを使用して同時サーバーを作成する

Swoole 上級: コルーチンを使用して同時サーバーを作成する

WBOY
WBOYオリジナル
2023-06-14 23:39:12759ブラウズ

同時実行性の高いネットワーク アプリケーション シナリオでは、長距離プロセス通信フレームワークとして Swoole が開発者にますます好まれています。 Swoole は豊富なネットワーク プログラミング API を提供し、開発者が非同期プログラミングにコルーチンを使用できるようにし、同時処理能力を向上させます。この記事では、Swoole とコルーチンを使用して単純な並行サーバーを作成する方法を紹介します。

1. 環境設定

作業を始める前に、Swoole 拡張機能をインストールする必要があります。インストール方法については、Swoole の公式ドキュメントを参照してください。この記事ではPHP7.2バージョンを使用しています。

2. サーバー プログラム フレームワーク

Swoole の TCP サーバーを使用する必要があります。特定の実装では、次の側面を考慮する必要があります:

  1. プロトコル形式を定義する

ネットワーク アプリケーションでは、通常、標準のデータ送信形式を定義する必要があります。この例では、以下に示すように、カスタム プロトコル形式を使用できます。

class MyProtocol {
    const HEADER_SIZE = 4;
    const MAX_PACKAGE_SIZE = 1024 * 1024;

    public static function encode($data) {
        $package = json_encode($data, JSON_UNESCAPED_UNICODE);
        return pack('N', strlen($package)) . $package;
    }

    public static function decode($buffer) {
        if(strlen($buffer) < self::HEADER_SIZE) {
            return false;
        }

        $length = unpack('N', substr($buffer, 0, self::HEADER_SIZE))[1];
        if($length > self::MAX_PACKAGE_SIZE) {
            return false;
        }

        if(strlen($buffer) < self::HEADER_SIZE + $length) {
            return false;
        }

        $package = substr($buffer, self::HEADER_SIZE, $length);
        return json_decode($package, true);
    }
}

プロトコル形式には、データ パケットの長さを格納する 4 バイトのヘッダーと、実際のデータの JSON 文字列表現が含まれています。この形式はさまざまなメッセージ タイプをサポートし、送信の信頼性とスケーラビリティを実現できます。

  1. ビジネス処理の定義

ビジネス ロジック処理は、次に示すように、Server クラスのコールバック関数で定義されます。

class Server {
    private $serv;

    public function __construct() {
        $this->serv = new SwooleServer('0.0.0.0', 9501);
        $this->serv->set(array(
            'worker_num' => 4,
            'daemonize' => false,
            'max_conn' => 10000,
            'dispatch_mode' => 3,
            'open_tcp_keepalive' => 1,
            'tcp_keepidle' => 600,
            'tcp_keepinterval' => 60,
            'tcp_keepcount' => 5,
        ));
        $this->serv->on('Connect', array($this, 'onConnect'));
        $this->serv->on('Receive', array($this, 'onReceive'));
        $this->serv->on('Close', array($this, 'onClose'));
        $this->serv->start();
    }

    public function onConnect($serv, $fd, $reactorId) {
        echo "Client: {$fd}-{$reactorId} Connect.
";
    }

    public function onReceive($serv, $fd, $reactorId, $data) {
        $message = MyProtocol::decode($data);
        if($message) {
            // Handle message & reply to client
            $this->serv->send($fd, MyProtocol::encode(array('status' => 0, 'message' => 'OK')));
        } else {
            // Invalid message, close connection
            $this->serv->close($fd);
        }
    }

    public function onClose($serv, $fd, $reactorId) {
        echo "Client: {$fd}-{$reactorId} Close.
";
    }
}

new Server();

各接続について、サーバーは、接続、メッセージの受け入れ、接続の終了などの操作を処理する 3 つのメソッドを定義し、それに応じて応答する必要があります。

3. コルーチンの使用

Swoole は、非同期プログラミングの制御フローを管理し、同期プログラミング エクスペリエンスを提供するコルーチン API を提供します。コルーチン関数は、コルーチン シリーズ API を通じて実装できます。以下は、コルーチンを使用した後の新しいコードです。このコードは、コルーチンを使用して、クライアント接続やメッセージ受信などの非同期 IO 操作を処理します。

class Server {
    private $serv;

    public function __construct() {
        $this->serv = new SwooleServer('0.0.0.0', 9501);
        $this->serv->set(array(
            'worker_num' => 4,
            'daemonize' => false,
            'max_conn' => 10000,
            'dispatch_mode' => 3,
            'open_tcp_keepalive' => 1,
            'tcp_keepidle' => 600,
            'tcp_keepinterval' => 60,
            'tcp_keepcount' => 5,
        ));
        $this->serv->on('Connect', array($this, 'onConnect'));
        $this->serv->on('Receive', array($this, 'onReceive'));
        $this->serv->on('Close', array($this, 'onClose'));
        $this->serv->start();
    }

    public function onConnect($serv, $fd, $reactorId) {
        go(function() use($fd, $reactorId) {
            echo "Client: {$fd}-{$reactorId} Connect.
";
        });
    }

    public function onReceive($serv, $fd, $reactorId, $data) {
        go(function() use($serv, $fd, $reactorId, $data) {
            $message = MyProtocol::decode($data);
            if($message) {
                // Handle message & reply to client
                $serv->send($fd, MyProtocol::encode(array('status' => 0, 'message' => 'OK')));
            } else {
                // Invalid message, close connection
                $serv->close($fd);
            }
        });
    }

    public function onClose($serv, $fd, $reactorId) {
        go(function() use($fd, $reactorId) {
            echo "Client: {$fd}-{$reactorId} Close.
";
        });
    }
}

new Server();

go(function()) を使用して、実行するタスクをコルーチンに追加します。不要なコールバック関数や制御プロセスを手動で管理する煩雑な操作を回避しながら、コード量が削減されます。

4. 導入方法

Swoole が提供するコマンド ライン ツールを使用して、サーバーの実行プロセスを簡単に管理できます。たとえば、次のように Swoole TCP サーバーを起動します。

php server.php

サーバーをバックグラウンドで実行し続ける必要がある場合は、デーモン化オプションを設定できます。

php server.php --daemonize

コマンド ライン ツールを使用します。 Swoole が提供する、サーバーのオープン、再起動、停止などの操作を行うためのツールです。

swoole_server [start|stop|reload|restart|shutdown]

Swoole を使用すると、効率的な同時ネットワーク アプリケーションを簡単に実装できます。コルーチンを使用して記述された Swoole TCP サーバーは、コード構造が簡素化されるだけでなく、パフォーマンスも向上し、従来のマルチプロセスまたはマルチスレッド サーバーと比較して、より優れた処理パフォーマンスが得られ、サーバーのリソース消費を大幅に節約できます。

以上がSwoole 上級: コルーチンを使用して同時サーバーを作成するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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