Maison  >  Article  >  cadre php  >  L'attribut reusePort dans Workerman qu'il faut connaître

L'attribut reusePort dans Workerman qu'il faut connaître

醉折花枝作酒筹
醉折花枝作酒筹original
2021-07-23 16:01:353001parcourir

Workerman est un framework de socket PHP asynchrone open source et hautes performances développé uniquement en PHP. Prend en charge les connexions longues TCP et de nombreux protocoles tels que websocket et MQTT. Aujourd'hui, nous allons présenter l'attribut reusePort dans Workerman. Vous pouvez vous y référer si nécessaire.

L'attribut reusePort dans Workerman qu'il faut connaître

Workerman est un framework de serveur PHP Socket hautes performances. Vous pouvez utiliser Workerman pour programmer directement au niveau de la couche TCP. La routine de programmation de base est :

$w = new Workerman\Worker('tcp://0.0.0.0:80');
$w->count = 4;
$w->onMessage = function(Workerman\COnnection\TcpConnection $connection, array $data) {
    $connection->send('Hello World');
};
Worker::runAll();

Pendant le processus d'utilisation, je me demande si vous avez remarqué le paramètre reusePort Il est défini sur false par défaut. A quoi sert ce paramètre ? Dans quelles circonstances devons-nous le définir sur true pour améliorer les performances ?

1. Le rôle de reuseport

Concernant le paramètre reusePort, le document officiel de Workerman explique ceci :

Après avoir activé la réutilisation du port d'écoute, plusieurs processus non liés sont autorisés à écouter le même port, et le noyau du système effectue le chargement. . Balance, détermine quel processus transférer la connexion de socket pour le traitement, évite l'effet de troupeau tonitruant et peut améliorer les performances des applications de connexion courte multi-processus.

Si vous n'avez pas étudié en profondeur la programmation réseau Linux, il est difficile de comprendre cette phrase. Voici une brève explication :

Le programme serveur reçoit généralement les demandes des clients en écoutant un certain numéro de port sur le serveur. Sous Linux, la carte réseau du serveur + le numéro de port sont extraits dans un Socket.

Afin d'améliorer les performances, les programmes serveur généraux disposent de plusieurs processus (communément appelés Worker) qui surveillent le même Socket lors de leur exécution. Lorsqu'aucune connexion client n'arrive, ces Workers sont dans un état suspendu et ne consomment pas de ressources CPU.

Si une connexion client arrive à un certain moment, le noyau Linux réveillera ces Workers en même temps et les laissera rivaliser pour gérer la connexion.

En conséquence, un seul Worker aura la possibilité de gérer la connexion. , et les autres travailleurs continueront après l'échec de la compétition. Retour à l'état suspendu. Le processus de réveil d'un Worker consomme des ressources CPU. Plus le nombre de Workers est élevé, plus les ressources CPU sont consommées, ce qui entraîne un gaspillage de ressources. C'est ce qu'on appelle souvent l'Effet Troupeau Foudroyant.

Vous vous demandez peut-être : pourquoi ne pas réveiller un seul travailleur à la fois ? Malheureusement, le noyau Linux ne possède pas une telle fonctionnalité.

Heureusement, la fonctionnalité de réutilisation est ajoutée à Linux 3.9 et versions ultérieures. A quoi sert cette fonctionnalité ?

Avant la réutilisation, un numéro de port ne pouvait être surveillé que par un seul Socket. Avec la réutilisation, cette restriction est levée : un numéro de port peut être surveillé par plusieurs Sockets en même temps.

Comme mentionné précédemment, le noyau Linux ne peut pas réveiller un seul Worker à la fois, mais le noyau peut envoyer uniformément des connexions client à un groupe de Sockets écoutant sur le même port.

Comme le montre la figure, chaque Worker possède son propre Socket, tous écoutant sur le même port. Lorsqu'une connexion client arrive, le noyau transmet la connexion à un Socket, et ce Socket ne réveillera que le Worker auquel il appartient. Cela résout intelligemment l'Effet Thundering Herd et améliore les performances globales.

De cela, nous pouvons conclure : si la version de votre noyau Linux est 3.9 ou supérieure, alors lorsque vous utilisez Workerman, vous pouvez définir reusePort sur true pour améliorer l'efficacité de l'exécution du programme.

2. Comment Workerman utilise reuseport

Bien qu'il vous suffit de définir reusePort sur true dans Workerman, vous pouvez profiter de cette fonctionnalité avancée de Linux. Mais dans le code source de Workerman, ce n'est pas aussi simple que d'activer un paramètre du noyau. Workerman cache de nombreux détails de conception pour vous, jetons un coup d'œil. La classe

Worker est la classe la plus importante de Workerman. Il existe une fonction listen() :

protected function listen()
{
    ...
    if (!$this->_mainSocket) {
        ...
        $this->_mainSocket = stream_socket_server(...);
        ...
    }
    ...
}

listen() La fonction de la fonction est de créer un Socket dans le processus en cours et de commencer à écouter les demandes.

Lorsque reusePort est false, le processus principal appelle la fonction listen() avant de créer le Worker :

protected function initWorkers() {
    ....
    if (!$worker->reusePort) {
        $worker->listen();
    }
    ....
}

Ensuite, le processus principal crée le Worker via pcntl_fork(). pcntl_fork() a une fonctionnalité : les variables du processus enfant créé (Worker) sont copiées du processus parent, y compris le mainSocket créé par le processus parent. Par conséquent, lorsque reusePort est **false**, tous les Workers copient le mainSocket du processus parent. Par conséquent, lorsque reusePort vaut ∗∗false∗∗, tous les Workers copient le _mainSocket du processus parent, c'est-à-dire partagent un Socket.

Mais lorsque reusePort est true, la situation est différente. Le processus principal n'appellera pas listen() avant de créer un Worker. Au lieu de cela, après avoir créé un Worker, chaque Worker lancera l'appel listen() :

protected static function forkOneWorkerForLinux($worker) {
    ...
    $pid = pcntl_fork();
    if ($pid === 0) {
        if ($worker->reusePort) {
            $worker->listen();
        }
        ...
    }
    ...
}

Le résultat est que chaque sous-processus (Worker) crée son propre Socket.

Une dernière chose, si vous souhaitez que le noyau active la fonction de réutilisation, vous devez définir manuellement le contexte Socket :

if ($this->reusePort) {
    $context = stream_context_create();
    stream_context_set_option($context, 'socket', 'so_reuseport', 1);
}

推荐学习:php视频教程

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