Démons en PHP, de inetd à ZeroMQ

7,726 views

Published on

Version simplifiée de la conférence «Démons en PHP, de inetd à ZeroMQ», présentée pour la première fois le 6 juin 2012 au Forum PHP.

Published in: Technology
0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
7,726
On SlideShare
0
From Embeds
0
Number of Embeds
2,906
Actions
Shares
0
Downloads
42
Comments
0
Likes
6
Embeds 0
No embeds

No notes for slide

Démons en PHP, de inetd à ZeroMQ

  1. 1. Démons en PHP de inetd à ZeroMQ
  2. 2. Démons en PHPIntroductionDémons basés sur (x)inetdDémons multi-processusDémons mono-processusZeroMQ
  3. 3. Introduction
  4. 4. « Démon » ? Nom masculin Barbarisme (daemon) « Disk And Execution MONitor » Programme indépendant Tourne en tâche de fond Serveur logiciel Accepte des connexions entrantes
  5. 5. Quelques exemples Démons réseau Démons applicatifs Apache (httpd) Crontab (crond) Impression (lpd / cupsd) Périphériques (devfsd)Connexion distante (sshd) X server
  6. 6. Mais pourtant... Le démon dune application web, cest Apache / Lighttpd / Nginx ! Cest de moins en moins vrai
  7. 7. Navigateur Démon web HTTP Démon Applicationtraitement PHP images Stockage Traitement images
  8. 8. Navigateur Démon web HTTP Application PHPimages vidéos sms File de messages
  9. 9. Navigateur Démon web HTTP Serveur de jeuServeurwebsocket Univers de jeu
  10. 10. Démons en PHP Avantages InconvénientsDéveloppement rapide Connaissances requisesBonnes performances Consommation mémoire Réutilisation de code
  11. 11. Benchmark ATOM N270 1.6 GHz − RAM 1 GO Connexion unique Temps de connexion Envoi et réception (2 messages) Connexions multiples 100 / 1000 connexions Temps de connexion Envoi et réception (1 message) Implémentation de référence en C
  12. 12. Exemple : myecho Code C#include <stdio.h> signal(SIGCHLD, SIG_IGN);#include <stdlib.h> bind(sock, (struct sockaddr*)&addr,#include <strings.h> sizeof(addr));#include <sys/types.h> listen(sock, 5000);#include <sys/socket.h>#include <unistd.h> addr_sz = sizeof(client_addr);#include <netinet/in.h> while (1)#include <signal.h> { client_sock = accept(sock, (structint main(void) sockaddr*)&client_addr,{ &addr_sz); int sock; if (fork() == 0) int client_sock; { struct sockaddr_in addr; close(sock); struct sockaddr_in client_addr; while ((sz = read(client_sock, buffer, socklen_t addr_sz; 512)) > 0) size_t sz; { int offset = 0; write(client_sock, buffer, sz); char buffer[512]; } close(client_sock); bzero(&addr, sizeof(addr)); exit(0); addr.sin_port = htons(11142); } addr.sin_family = AF_INET; } addr.sin_addr.s_addr = htonl(INADDR_ANY); close(sock); return (0); sock = socket(AF_INET, SOCK_STREAM, 0); }
  13. 13. Exemple : myecho Exécution# telnet localhost 11142Trying 127.0.0.1...Connected to localhost.Escape character is ^].HelloHelloTest 1Test 1Test 2Test 2
  14. 14. Benchmark : connexion unique Type Connexion Échange 1 Échange 2 C 5 µs 3 µs 2 µs
  15. 15. Benchmark : connexions multiples 100 100 1000 1000Type Maximum connexions messages connexions messages C 0.04 s 0.05 s 6.5 s 0.2 s > 1000
  16. 16. Démons basés sur (x)inetd
  17. 17. (x)inetd : super-démonÉcoute plusieurs portsInstancie un programme àchaque connexion entranteTransmission sur les entrées-sorties standards
  18. 18. Exemple : myecho Code PHP#!/usr/bin/php<?phpwhile (!feof(STDIN)) { $s = fgets(STDIN); print($s);}?> /home/amaury/myecho.php
  19. 19. Exemple : myecho Configuration xinetdservice myecho{ type = UNLISTED user = root wait = no port = 11138 server = /home/amaury/myecho.php protocol = tcp socket_type = stream} /etc/xinetd.d/myecho
  20. 20. (x)inetd Avantages InconvénientsDéveloppement rapide Consommation mémoire Aucune dépendance Lenteur dinstanciationIsolation des processus Couche intermédiaire
  21. 21. Benchmark : connexion unique Type Connexion Échange 1 Échange 2 C 5 µs 3 µs 2 µs xinetd 5 µs 31 ms 2 µs
  22. 22. Benchmark : connexions multiples 100 100 1000 1000Type Maximum connexions messages connexions messages C 0.04 s 0.05 s 6.5 s 0.2 s > 1000xinetd 0.4 s 1.8 s - - < 120
  23. 23. Démonsmulti-processus
  24. 24. PrincipeSimple : inetd internaliséUn processus attend les connexionsCréation dun nouveau sous-processusà chaque connexion entrante
  25. 25. Exemple : myecho Code PHP#!/usr/bin/php<?phpdaemonize();$socket = stream_socket_server(tcp://0.0.0.0:11138, $errno, $errstr);while (true) { $clientSock = stream_socket_accept($socket, -1); if (pcntl_fork() === 0) { fclose($socket); process($clientSock); exit(0); } fclose($clientSock);}
  26. 26. Exemple : myecho Code PHPfunction daemonize() { pcntl_signal(SIGCHLD, SIG_IGN); if (pcntl_fork()) exit(0); posix_setsid();}function process($sock) { while (!feof($sock)) { $s = fgets($sock); fwrite($sock, $s); } fclose($sock);}
  27. 27. Multi-processus Avantages Inconvénients Latence réduite Consommation mémoire Aucune dépendance Gestion des signauxIsolation des processus PHP non multi-thread
  28. 28. Benchmark : connexion unique Type Connexion Échange 1 Échange 2 C 5 µs 3 µs 2 µs xinetd 5 µs 31 ms 2 µs multi 5 µs 8 µs 2 µs
  29. 29. Benchmark : connexions multiples 100 100 1000 1000Type Maximum connexions messages connexions messages C 0.04 s 0.05 s 6.5 s 0.2 s > 1000xinetd 0.4 s 1.8 s - - < 120multi 3s 0.05 s 60.5 s 0.2 s > 1000
  30. 30. Démonsmono-processus
  31. 31. PrincipeUn seul processus> attend les nouvelles connexions> répond aux requêtes
  32. 32. Mono versus multi-processus Multi Mono I/O lentes I/O rapides Code simple Partage de donnéesLimites vite atteintes Seul moyen de gérer beaucoup de connexions
  33. 33. Exemple : myecho Code PHP#!/usr/bin/php<?phpdaemonize();$socket = stream_socket_server(tcp://0.0.0.0:11138, $errno, $errs);$allSockets = array($socket);while (true) { $read = $allSockets; stream_select($read, $w=null, $e=null, null); foreach ($read as $sock) { if ($sock === $socket) $allSockets[] = stream_socket_accept($socket, -1); else if (feof($sock)) closeSocket($sock, $allSockets); else process($sock); }}
  34. 34. Exemple : myecho Code PHPfunction closeSocket($sock, &$allSockets) { fclose($sock); $key = array_search($sock, $allSockets); unset($allSockets[$key]);}function process($socket) { $s = fgets($socket); fwrite($socket, $s);}
  35. 35. Mono-processus Avantages InconvénientsRessources préservées Délai exponentiel Aucune dépendance Blocage sur I/O lentes Partage de données Fragilité relative (consommation mémoire, plantage applicatif, ...)
  36. 36. Benchmark : connexion unique Type Connexion Échange 1 Échange 2 C 5 µs 3 µs 2 µs xinetd 5 µs 31 ms 2 µs multi 5 µs 8 µs 2 µs mono 5 µs 3 µs 3 µs
  37. 37. Benchmark : connexions multiples 100 100 1000 1000Type Maximum connexions messages connexions messages C 0.04 s 0.05 s 6.5 s 0.2 s > 1000xinetd 0.4 s 1.8 s - - < 120multi 3s 0.05 s 60.5 s 0.2 s > 1000mono 0.04 s 0.05 s 57.5 s 3.6 s > 1000
  38. 38. ZeroMQ
  39. 39. PrésentationBibliothèque de fonctions réseauGestion de files de messagesProtocole spécifique37 langages supportésRedéfinition des concepts réseau
  40. 40. Méthodes de transportInter-threads inprocInter-processus ipcInter-machines tcp
  41. 41. Découplage du sens de connexion Client Serveur
  42. 42. Découplage du sens de connexion Client Serveur
  43. 43. Socket multi-connexionClient port AClient ServeurClient port B
  44. 44. Polling Socket ZMQ Socket TCP Socket ZMQSocket TCP STDIN Serveur
  45. 45. Connexion REQ/REP REQClient Serveur
  46. 46. Connexion REQ/REP REPClient Serveur
  47. 47. Connexion PUSH/PULL PUSHClient Serveur
  48. 48. Connexion PUSH/PULL PULLClient Serveur
  49. 49. Connexion PUB/SUB Client PUBServeur Client Client
  50. 50. Connexion PUB/SUB SUB Client SUBServeur Client SUB Client
  51. 51. Load-balancing PULL Client PUSHServeur Client Client
  52. 52. Load-balancing Client PUSH PULLServeur Client Client
  53. 53. Load-balancing Client PUSHServeur Client PULL Client
  54. 54. PipelineClient WorkerClient WorkerClient Worker
  55. 55. ZeroMQ : Installation Linux Ubuntu 11.10# apt-get install libzmq-dev# apt-get install php-pear# pear channel-discover pear.zero.mq# pecl install zero.mq/zmq-beta# echo "extension=zmq.so" > /etc/php5/conf.d/zmq.ini
  56. 56. Exemple : myecho Code PHP : serveur ZMQ#!/usr/bin/php<?php$ctx = new ZMQContext();$server = new ZMQSocket($ctx, ZMQ::SOCKET_REP);$server->bind(tcp://*:11141);while (true) { $message = $server->recv(); $server->send($message);}
  57. 57. Exemple : myecho Code PHP : client ZMQ#!/usr/bin/php<?php$ctx = new ZMQContext();$client = new ZMQSocket($ctx, ZMQ::SOCKET_REQ);$client->connect(tcp://localhost:11141);$client->send(bonjour);$response = $client->recv();print("Réponse : $responsen");
  58. 58. Benchmark : connexion unique Type Connexion Échange 1 Échange 2 C 5 µs 3 µs 2 µs xinetd 5 µs 31 ms 2 µs multi 5 µs 8 µs 2 µs mono 5 µs 3 µs 3 µs zmq 2 ms 2 ms 4 µs
  59. 59. Benchmark : connexions multiples 100 100 1000 1000Type Maximum connexions messages connexions messages C 0.04 s 0.05 s 6.5 s 0.2 s > 1000xinetd 0.4 s 1.8 s - - < 120multi 3s 0.05 s 60.5 s 0.2 s > 1000mono 0.04 s 0.05 s 57.5 s 3.6 s > 1000zmq 0.05 s 0.12 s 0.6 s 0.8 s > 1000
  60. 60. Conclusion
  61. 61. Démons en PHPFaciles et rapides à coderVraiment performant(x)inetd, mono/multi-processus,ZeroMQ, libevent, eio, ...
  62. 62. geek-directeur-technique.com/zeromq amaury@amaury.net

×