Maison >cadre php >Swoole >Swoole Advanced : Utiliser des coroutines pour écrire des serveurs simultanés

Swoole Advanced : Utiliser des coroutines pour écrire des serveurs simultanés

WBOY
WBOYoriginal
2023-06-14 23:39:12778parcourir

Dans les scénarios d'applications réseau à haute concurrence, Swoole, en tant que cadre de communication de processus à longue portée, est de plus en plus favorisé par les développeurs. Swoole fournit une riche API de programmation réseau, permettant aux développeurs d'utiliser des coroutines pour la programmation asynchrone, améliorant ainsi les capacités de traitement simultané. Cet article explique comment écrire un serveur simultané simple à l'aide de Swoole et de coroutines.

1. Configuration de l'environnement

Avant de commencer, nous devons installer l'extension Swoole. Pour la méthode d'installation, veuillez vous référer à la documentation officielle de Swoole. Cet article utilise la version PHP7.2.

2. Framework du programme serveur

Nous devons utiliser le serveur TCP de Swoole. La mise en œuvre spécifique doit prendre en compte les aspects suivants :

  1. Définir le format du protocole

Dans les applications réseau, il est généralement nécessaire de définir un standard de données. format de transmission. Dans cet exemple, nous pouvons utiliser un format de protocole personnalisé, comme indiqué ci-dessous :

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);
    }
}

Le format de protocole contient un en-tête de 4 octets pour stocker la longueur du paquet et une chaîne JSON représentant les données réelles. Ce format peut prendre en charge différents types de messages et assurer la fiabilité et l'évolutivité de la transmission.

  1. Définir le traitement métier

Le traitement de la logique métier est défini dans la fonction de rappel de la classe Server, comme indiqué ci-dessous :

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();

Pour chaque connexion, le serveur doit définir trois méthodes pour gérer sa connexion, accepter les messages, fermer la connexion et d’autres opérations, et réagissez en conséquence.

3. Utiliser des coroutines

Swoole fournit une API de coroutine pour gérer le flux de contrôle dans la programmation asynchrone et offrir une expérience de programmation synchrone. Les fonctions coroutine peuvent être implémentées via l'API de la série coroutine. Voici le nouveau code après avoir utilisé la coroutine, qui utilise la coroutine pour gérer les opérations d'E/S asynchrones telles que la connexion client et la réception de messages :

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();

Utilisez go(function()) pour ajouter des tâches à la coroutine pour l'exécution, réduisant ainsi la quantité de code, tout en évitant les fonctions de rappel inutiles et les opérations fastidieuses des processus manuels de contrôle de gestion.

4. Comment déployer

Avec l'outil de ligne de commande fourni par Swoole, nous pouvons simplement gérer le processus d'exécution du serveur. Par exemple, la façon dont nous démarrons un serveur TCP Swoole est la suivante :

php server.php

Si vous devez laisser le serveur fonctionner en arrière-plan, vous pouvez définir l'option démoniser :

php server.php --daemonize

Utilisez les outils de ligne de commande fournis par Swoole pour démarrer , redémarrez et arrêtez le serveur :

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

En utilisant Swoole, nous pouvons facilement implémenter des applications réseau simultanées efficaces. Le serveur Swoole TCP écrit à l'aide de coroutines simplifie non seulement la structure du code, mais offre également des performances plus élevées que les serveurs multi-processus ou multi-thread traditionnels, il peut obtenir de meilleures performances de traitement et économiser considérablement la consommation de ressources du serveur.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn