63
Démons en PHP de inetd à ZeroMQ

Démons en PHP, de inetd à ZeroMQ

Embed Size (px)

DESCRIPTION

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.

Citation preview

Page 1: Démons en PHP, de inetd à ZeroMQ

Démons en PHPde inetd à ZeroMQ

Page 2: Démons en PHP, de inetd à ZeroMQ

Introduction

Démons basés sur (x)inetd

Démons multi-processus

Démons mono-processus

Démons en PHP

ZeroMQ

Page 3: Démons en PHP, de inetd à ZeroMQ

Introduction

Page 4: Démons en PHP, de inetd à ZeroMQ

« Démon » ?

Nom masculinBarbarisme (daemon)

« Disk And Execution MONitor »

Programme indépendantTourne en tâche de fond

Serveur logicielAccepte des connexions entrantes

Page 5: Démons en PHP, de inetd à ZeroMQ

Démons applicatifs

Crontab (crond)

Périphériques (devfsd)

X server

Démons réseau

Apache (httpd)

Impression (lpd / cupsd)

Connexion distante (sshd)

Quelques exemples

Page 6: Démons en PHP, de inetd à ZeroMQ

Mais pourtant...

Le démon d'une application web, c'est Apache / Lighttpd / Nginx !

C'est de moins en moins vrai

Page 7: Démons en PHP, de inetd à ZeroMQ

Démon HTTP

Application PHP

Démon traitement

images

Traitement images

Stockage

Navigateurweb

Page 8: Démons en PHP, de inetd à ZeroMQ

Démon HTTP

Application PHP

Navigateurweb

File de messages

images vidéos sms

Page 9: Démons en PHP, de inetd à ZeroMQ

Serveur websocket

Serveur de jeu

Navigateurweb

Univers de jeu

Démon HTTP

Page 10: Démons en PHP, de inetd à ZeroMQ

Inconvénients

Connaissances requises

Consommation mémoire

Avantages

Développement rapide

Bonnes performances

Réutilisation de code

Démons en PHP

Page 11: Démons en PHP, de inetd à ZeroMQ
Page 12: Démons en PHP, de inetd à ZeroMQ

Benchmark

ATOM N270 1.6 GHz − RAM 1 GO

Connexion uniqueTemps de connexionEnvoi et réception (2 messages)

Connexions multiples100 / 1000 connexionsTemps de connexionEnvoi et réception (1 message)

Implémentation de référence en C

Page 13: Démons en PHP, de inetd à ZeroMQ

#include <stdio.h>

#include <stdlib.h>

#include <strings.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <unistd.h>

#include <netinet/in.h>

#include <signal.h>

int main(void)

{

int sock;

int client_sock;

struct sockaddr_in addr;

struct sockaddr_in client_addr;

socklen_t addr_sz;

size_t sz;

int offset = 0;

char buffer[512];

bzero(&addr, sizeof(addr));

addr.sin_port = htons(11142);

addr.sin_family = AF_INET;

addr.sin_addr.s_addr = htonl(INADDR_ANY);

sock = socket(AF_INET, SOCK_STREAM, 0);

Exemple : myecho

Code C signal(SIGCHLD, SIG_IGN);

bind(sock, (struct sockaddr*)&addr,

sizeof(addr));

listen(sock, 5000);

addr_sz = sizeof(client_addr);

while (1)

{

client_sock = accept(sock, (struct

sockaddr*)&client_addr,

&addr_sz);

if (fork() == 0)

{

close(sock);

while ((sz = read(client_sock, buffer,

512)) > 0)

{

write(client_sock, buffer, sz);

}

close(client_sock);

exit(0);

}

}

close(sock);

return (0);

}

Page 14: Démons en PHP, de inetd à ZeroMQ

# telnet localhost 11142Trying 127.0.0.1...

Connected to localhost.

Escape character is '^]'.

Hello

Hello

Test 1

Test 1

Test 2

Test 2

Exemple : myecho

Exécution

Page 15: Démons en PHP, de inetd à ZeroMQ

Benchmark : connexion unique

Type Connexion Échange 1 Échange 2

C 5 µs 3 µs 2 µs

Page 16: Démons en PHP, de inetd à ZeroMQ

Benchmark : connexions multiples

Type100

connexions100

messages1000

connexions1000

messagesMaximum

C 0.04 s 0.05 s 6.5 s 0.2 s > 1000

Page 17: Démons en PHP, de inetd à ZeroMQ

Démons baséssur (x)inetd

Page 18: Démons en PHP, de inetd à ZeroMQ

Écoute plusieurs ports

Instancie un programme à chaque connexion entrante

Transmission sur les entrées-sorties standards

(x)inetd : super-démon

Page 19: Démons en PHP, de inetd à ZeroMQ

#!/usr/bin/php

<?php

while (!feof(STDIN)) {

$s = fgets(STDIN);

print($s);

}

?>

Exemple : myecho

/home/amaury/myecho.php

Code PHP

Page 20: Démons en PHP, de inetd à ZeroMQ

service myecho

{

type = UNLISTED

user = root

wait = no

port = 11138

server = /home/amaury/myecho.php

protocol = tcp

socket_type = stream

}

Exemple : myecho

/etc/xinetd.d/myecho

Configuration xinetd

Page 21: Démons en PHP, de inetd à ZeroMQ

Inconvénients

Consommation mémoire

Lenteur d'instanciation

Couche intermédiaire

Avantages

Développement rapide

Aucune dépendance

Isolation des processus

(x)inetd

Page 22: Démons en PHP, de inetd à ZeroMQ

Benchmark : connexion unique

Type Connexion Échange 1 Échange 2

C 5 µs 3 µs 2 µs

xinetd 5 µs 31 ms 2 µs

Page 23: Démons en PHP, de inetd à ZeroMQ

Benchmark : connexions multiples

Type100

connexions100

messages1000

connexions1000

messagesMaximum

C 0.04 s 0.05 s 6.5 s 0.2 s > 1000

xinetd 0.4 s 1.8 s - - < 120

Page 24: Démons en PHP, de inetd à ZeroMQ

Démonsmulti-processus

Page 25: Démons en PHP, de inetd à ZeroMQ

Simple : inetd internalisé

Un processus attend les connexions

Création d'un nouveau sous-processus à chaque connexion entrante

Principe

Page 26: Démons en PHP, de inetd à ZeroMQ

#!/usr/bin/php

<?php

daemonize();

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

}

Exemple : myecho

Code PHP

Page 27: Démons en PHP, de inetd à ZeroMQ

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

}

Exemple : myecho

Code PHP

Page 28: Démons en PHP, de inetd à ZeroMQ

Inconvénients

Consommation mémoire

Gestion des signaux

PHP non multi-thread

Avantages

Latence réduite

Aucune dépendance

Isolation des processus

Multi-processus

Page 29: Démons en PHP, de inetd à ZeroMQ

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

Page 30: Démons en PHP, de inetd à ZeroMQ

Benchmark : connexions multiples

Type100

connexions100

messages1000

connexions1000

messagesMaximum

C 0.04 s 0.05 s 6.5 s 0.2 s > 1000

xinetd 0.4 s 1.8 s - - < 120

multi 3 s 0.05 s 60.5 s 0.2 s > 1000

Page 31: Démons en PHP, de inetd à ZeroMQ

Démonsmono-processus

Page 32: Démons en PHP, de inetd à ZeroMQ

Un seul processus

> attend les nouvelles connexions

> répond aux requêtes

Principe

Page 33: Démons en PHP, de inetd à ZeroMQ

Mono

I/O rapides

Partage de données

Seul moyen de gérer beaucoup de connexions

Multi

I/O lentes

Code simple

Limites vite atteintes

Mono versus multi-processus

Page 34: Démons en PHP, de inetd à ZeroMQ

#!/usr/bin/php

<?php

daemonize();

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

}

}

Exemple : myecho

Code PHP

Page 35: Démons en PHP, de inetd à ZeroMQ

function closeSocket($sock, &$allSockets) {

fclose($sock);

$key = array_search($sock, $allSockets);

unset($allSockets[$key]);

}

function process($socket) {

$s = fgets($socket);

fwrite($socket, $s);

}

Exemple : myecho

Code PHP

Page 36: Démons en PHP, de inetd à ZeroMQ

Inconvénients

Délai exponentiel

Blocage sur I/O lentes

Fragilité relative(consommation mémoire, plantage applicatif, ...)

Avantages

Ressources préservées

Aucune dépendance

Partage de données

Mono-processus

Page 37: Démons en PHP, de inetd à ZeroMQ

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

Page 38: Démons en PHP, de inetd à ZeroMQ

Benchmark : connexions multiples

Type100

connexions100

messages1000

connexions1000

messagesMaximum

C 0.04 s 0.05 s 6.5 s 0.2 s > 1000

xinetd 0.4 s 1.8 s - - < 120

multi 3 s 0.05 s 60.5 s 0.2 s > 1000

mono 0.04 s 0.05 s 57.5 s 3.6 s > 1000

Page 39: Démons en PHP, de inetd à ZeroMQ

ZeroMQ

Page 40: Démons en PHP, de inetd à ZeroMQ

Bibliothèque de fonctions réseau

Gestion de files de messages

Protocole spécifique

37 langages supportés

Redéfinition des concepts réseau

Présentation

Page 41: Démons en PHP, de inetd à ZeroMQ

Méthodes de transport

Inter-threads inproc

Inter-processus ipc

Inter-machines tcp

Page 42: Démons en PHP, de inetd à ZeroMQ

Découplage du sens de connexion

ServeurClient

Page 43: Démons en PHP, de inetd à ZeroMQ

Découplage du sens de connexion

ServeurClient

Page 44: Démons en PHP, de inetd à ZeroMQ

Socket multi-connexion

ServeurClient

Client

Client

port A

port B

Page 45: Démons en PHP, de inetd à ZeroMQ

Polling

Serveur

Socket TCP

Socket TCP

Socket ZMQ

Socket ZMQ

STDIN

Page 46: Démons en PHP, de inetd à ZeroMQ

Connexion REQ/REP

ServeurClientREQ

Page 47: Démons en PHP, de inetd à ZeroMQ

Connexion REQ/REP

ServeurClientREP

Page 48: Démons en PHP, de inetd à ZeroMQ

Connexion PUSH/PULL

ServeurClientPUSH

Page 49: Démons en PHP, de inetd à ZeroMQ

Connexion PUSH/PULL

ServeurClientPULL

Page 50: Démons en PHP, de inetd à ZeroMQ

Connexion PUB/SUB

ClientPUB

Serveur

Client

Client

Page 51: Démons en PHP, de inetd à ZeroMQ

Connexion PUB/SUB

ClientServeur

Client

Client

SUB

SUB

SUB

Page 52: Démons en PHP, de inetd à ZeroMQ

Load-balancing

ClientServeur

Client

Client

PULL

PUSH

Page 53: Démons en PHP, de inetd à ZeroMQ

Load-balancing

ClientServeur

Client

Client

PULLPUSH

Page 54: Démons en PHP, de inetd à ZeroMQ

Load-balancing

ClientServeur

Client

ClientPULL

PUSH

Page 55: Démons en PHP, de inetd à ZeroMQ

Pipeline

Worker

Worker

Worker

Client

Client

Client

Page 56: Démons en PHP, de inetd à ZeroMQ

# 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

ZeroMQ : Installation

Linux Ubuntu 11.10

Page 57: Démons en PHP, de inetd à ZeroMQ

#!/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);

}

Exemple : myecho

Code PHP : serveur ZMQ

Page 58: Démons en PHP, de inetd à ZeroMQ

#!/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 : '$response'\n");

Exemple : myecho

Code PHP : client ZMQ

Page 59: Démons en PHP, de inetd à ZeroMQ

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

Page 60: Démons en PHP, de inetd à ZeroMQ

Benchmark : connexions multiples

Type100

connexions100

messages1000

connexions1000

messagesMaximum

C 0.04 s 0.05 s 6.5 s 0.2 s > 1000

xinetd 0.4 s 1.8 s - - < 120

multi 3 s 0.05 s 60.5 s 0.2 s > 1000

mono 0.04 s 0.05 s 57.5 s 3.6 s > 1000

zmq 0.05 s 0.12 s 0.6 s 0.8 s > 1000

Page 61: Démons en PHP, de inetd à ZeroMQ

Conclusion

Page 62: Démons en PHP, de inetd à ZeroMQ

Faciles et rapides à coder

Vraiment performant

(x)inetd, mono/multi-processus, ZeroMQ, libevent, eio, ...

Démons en PHP

Page 63: Démons en PHP, de inetd à ZeroMQ

geek-directeur-technique.com/zeromq

[email protected]