SlideShare una empresa de Scribd logo
1 de 53
Descargar para leer sin conexión
Asynchroniczny PHP
& komunikacja czasu
rzeczywistego z
wykorzystaniem
websocketów
who am i
Nazywam się Łukasz
Adamczewski
Pracuje w firmie Polcode jako
Starszy Programista PHP
Szukaj mnie na @lukeadamczewski
- czyli wasz język tego nie potrafi
CPU IO CPU
czas
IO
Model typowej aplikacji
W czym problem?
Model typowej aplikacji
CPU IO CPU
czas
IO
asynchroniczna instrukcja
CPU
Model non-blocking IO
IO
IO
CPU
IO
CPU
CZAS
różnyczaswykonywania
IO
oczekiwanie na koniec
poprzedniego zadania
Słów kilka o czasach dostępu czyli IO vs CPU
http://norvig.com/21-days.html#answers
fetch from L1 cache memory 0.5 nanosec
fetch from L2 cache memory 7 nanosec
fetch from main memory 100 nanosec
send 2K bytes over 1Gbps network 20,000 nanosec
read 1MB sequentially from memory 0,25 ms = 250,000 ns
Read 1 MB sequentially from SSD* 1 ms
Disk seek 10 ms
Read 1 MB sequentially from disk 20 ms
send packet US to Europe and back 150 ms
* Assuming ~1GB/sec SSD
getUser(432, function (user) {
console.log(user.name);
});
console.log('Done');
Typowy node.js
getUser(432, function (user) {
console.log(user.name);
});
console.log('Done');1
Typowy node.js
getUser(432, function (user) {
console.log(user.name);
});
console.log('Done');1
2
Typowy node.js
Node.JS - webserver “hello world”
var http = require('http');
var server = new http.Server();
server.on('request', function (req, res) {
res.writeHead(
200,
{'Content-Type':'text/plain'}
);
res.end('Hello World');
});
server.listen(8000, '127.0.0.1');
Node.JS - webserver “hello world”
var http = require('http');
var server = new http.Server();
server.on('request', function (req, res) {
res.writeHead(
200,
{'Content-Type':'text/plain'}
);
res.end('Hello World');
});
server.listen(8000, '127.0.0.1');
oczekiwanie na zdarzenie request
kod obsługi zdarzenia wysyłający
odpowiednie nagłówki do klienta HTTP
oraz wysyłający odpowiednią
wiadomość
Node.JS - webserver “hello world”
var http = require('http');
var server = new http.Server();
server.on('request', function (req, res) {
res.writeHead(
200,
{'Content-Type':'text/plain'}
);
res.end('Hello World');
});
server.listen(8000, '127.0.0.1');
oczekiwanie na zdarzenie request
kod obsługi zdarzenia wysyłający
odpowiednie nagłówki do klienta HTTP
oraz wysyłający odpowiednią
wiadomość
C10K problem
10k połączeń na jednym rdzeniu
Node.JS - webserver “hello world”
var http = require('http');
var server = new http.Server();
server.on('request', function (req, res) {
res.writeHead(
200,
{'Content-Type':'text/plain'}
);
res.end('Hello World');
});
server.listen(8000, '127.0.0.1');
oczekiwanie na zdarzenie request
kod obsługi zdarzenia wysyłający
odpowiednie nagłówki do klienta HTTP
oraz wysyłający odpowiednią
wiadomość
C10K problem
10k połączeń na jednym rdzeniu
Zróbmy to
w PHP!bo w czym problem?
<?php
$server = stream_socket_server('tcp://127.0.0.1:8000');
while ($conn = stream_socket_accept($server, -1)) {
fwrite($conn, "HTTP/1.1 200 OKrn");
fwrite($conn, "Content-Length: 3rnrn");
fwrite($conn, "Hi PHPersn");
fclose($conn);
}
$ curl 127.0.0.1:8000 -v
> GET / HTTP/1.1
> Host: 127.0.0.1:8000
< HTTP/1.1 200 OK
Hi PHPers
<?php
$server = stream_socket_server('tcp://127.0.0.1:8000');
while ($conn = stream_socket_accept($server, -1)) {
fwrite($conn, "HTTP/1.1 200 OKrn");
fwrite($conn, "Content-Length: 3rnrn");
fwrite($conn, "Hi PHPersn");
fclose($conn);
}
BLOCKING
IO
<?php
$server = stream_socket_server('tcp://127.0.0.1:8000');
while ($conn = stream_socket_accept($server, -1)) {
fwrite($conn, "HTTP/1.1 200 OKrn");
fwrite($conn, "Content-Length: 3rnrn");
fwrite($conn, "Hi PHPersn");
fclose($conn);
}
BLOCKING
IO
NON-BLOCKING
IO
// If mode is 0, the given stream will be switched to non-blocking mode
bool stream_set_blocking ( resource $stream , int $mode )
int stream_select ( array &$read , array &$write , array &$except , int
$tv_sec [, int $tv_usec = 0 ] )
$readable = $read ?: null;
$writable = $write ?: null;
$except = null;
if (stream_select($readable, $writable, $except, 1)) {
if ($readable) {
foreach ($readable as $stream) { /* code */ }
}
if ($writable) {
foreach ($writable as $stream) { /* code */ }
}
}
Pooling IO
tablica streamów do odczytu
tablica streamów do zapisu
streamy “faworyzowane”
Pooling IOPooling IO
$readable = $read ?: null;
$writable = $write ?: null;
$except = null;
if (stream_select($readable, $writable, $except, 1)) {
if ($readable) {
foreach ($readable as $stream) { /* code */ }
}
if ($writable) {
foreach ($writable as $stream) { /* code */ }
}
}
EVENT
LOOPCZYLI MOŻNA LEPIEJ
EVENT LOOP
➜ Zarządzanie streamami
➜ Ustawianie timerów jednorazowych i cyklicznych
➜ Ustawianie nextTicków i futureTicków
➜ Maksymalna czas zwłoki (timeout) może być zdefiniowany
➜ Jeżeli nie ma dalszych ticków, timerów lub streamów do obsłużenia -
event loop kończy pracę
Event Loop:
Istnieje kilka implementacji z docelowymi backendami:
● StreamSelectLoop - stream_select
● LibEventLoop - libevent pecl extension
● LibEvLoop - libev pecl extension (najszybszy)
● może kiedyś LibUV :)
Demultiplexer:
oczekuje na eventy dla zasobów np.
nowe połączenie i powiadamia
dispatcher, po czym przechodzi do
dalszego nasłuchiwania.
Dispatcher:
Komponent służący do rejestracji obsługi
zdarzeń. Odbiera synchronicznie event z
demultiplexera i wybiera właściwy event
handler, który następnie uruchamia.
Obsługa zdarzeń:
Event Handler który obsługuje
przekierowane do niego zdarzenie. Jest
to po prostu jeden ze zdefiniowanych
wcześniej callbacków.
Zasoby:
Czyli tutaj mamy wszystkie streamy które
chcemy obsługiwać. Mogą to być także
procesy czy np. uchwyty do plików.
Hello World Again
Instalacja z wykorzystaniem composera
curl -sS https://getcomposer.org/installer | php
php composer.phar require react/react
require 'vendor/autoload.php';
$loop = ReactEventLoopFactory::create();
$socket = new ReactSocketServer($loop);
$http = new ReactHttpServer($socket, $loop);
$http->on('request', function ($request, $response) {
$response->writeHead(200, ['Content-Type' =>
'text/plain']);
$response->end("Hi Phpersn");
});
$socket->listen(8000);
$loop->run();
Ekosystem
EVENT LOOP
STREAM
TICKS
SOCKET
HTTP
TIMER
CHILD PROCESSFILESYSTEM
PROMISES
EVENT LOOP
STREAM
TICKS
SOCKET
HTTP
TIMER
CHILD PROCESSFILESYSTEM
PROMISES
Ticki
umożliwiają wykonywanie określonych funkcji w ramach Event Loopa. Dzielą się na $loop-
>nextTick($callback) i $loop->futureTick($callback) .
Pierwszy jest wykonywany zawsze na początku każdej iteracji loopa, wykonywanie drugiego
jest zawsze oddelegowane jako ostatnia operacja w ramach iteracji.
Hint: zakolejkowane futureTicki nie będą wykonywane jeśli Event Loop nie ma więcej
zadań. NextTicki uzupełniają Event Loop nowymi zadaniami.
EVENT LOOP
STREAM
TICKS
SOCKET
HTTP
TIMER
CHILD PROCESSFILESYSTEM
PROMISES
Funkcja odmierzania czasu wykonywana w ramach Event Loop w kolejności zaraz po nextTicku.
● $loop->addTimer- jednorazowe wykonanie funkcji po upływie czasu (jak setTimeout)
● $loop->addPeriodicTimer- wykonuje funkcje cyklicznie (jak setInterval)
● $loop->cancelTimer - zatrzymje timer
● $loop->isTimerActive- sprawdza stan działania timera
Hint: nie polegaj na czasie odmierzanym przez timery w 100% ponieważ operacje przetwarzane w
Event Loop mogą zablokować je na jakiś czas wynikający z bieżących działań.
STREAM
SOCKET
HTTP
CHILD PROCESSFILESYSTEM
PROMISES
● Opakowuje natywny zasób stream.
● Rejestrowane w ramach Event Loop’a.
● Stream do odczytu i zapisu (ReadableStream / WriteableStream)
● Potkowość (ang. pipeline). WriteableStream może być ze sobą łączone, więc wyjście
jednego jest wejściem drugiego.
● Dane wczytywane / zapisywane do streamów są buforowane
Klasy Funkcjonalne:
CompositeStream- łączy streamy do odczytu i zapisu łącząc obydwie funkcjonalności
ThroughStream- umożliwia modyfikacje danch które stream zawiera - filtrowanie.
BufferedSink - konwertuje WriteableStreamdo Promise
STREAM
STREAM
SOCKET
HTTP
CHILD PROCESSFILESYSTEM
PROMISES
Dla funkcji asynchronicznych umożliwia natychmiastowy zwrot wartości, a raczej pewnej
zaliczki tej wartości.
Przykład - zamiana hosta na ip:
$factory = new ReactDnsResolverFactory();
$dns = $factory->create('8.8.8.8', $loop);
$dns->resolve('igor.io')->then(function ($ip) {
echo "Host: $ipn";
});
PROMISE
STREAM
SOCKET
HTTP
CHILD PROCESSFILESYSTEM
PROMISES
Komponent sieciowy umożliwiający tworzenie serwerów nasłuchujących nowych połączeń
oraz przetwarzających dane połączonych klientów.
$socket = new ReactSocketServer($loop);
$socket->on('connection', function ($conn) {
$conn->on('data', function ($data, $conn) {
$conn->write($data);
});
});
$socket->listen(1337);
SOCKET
Websockety
Komunikacja w czasie rzeczywistym
Websockety - zalety
➜ Wsparcie we wszystkich wiodących
przeglądarkach (> IE8)
➜ Dwukierunkowość komunikacji
➜ Niezależnie wysyłanie wiadomości
➜ Protokół oparty na HTTP
➜ Niewielki rozmiar pojedynczego pakietu
danych
WebsocketAPI - interfejs kliencki JavaScript
var websocket = new WebSocket('ws://localhost:8000' );
websocket.onopen = function(evt) {};
websocket.onclose = function(evt) {};
websocket.onmessage = function(evt) {};
websocket.onerror = function(evt) {};
Ratchet - WebSockets for PHP
class WS implements MessageComponentInterface {
function onOpen(ConnectionInterface $conn) {}
function onClose(ConnectionInterface $conn) {}
function onError(ConnectionInterface $conn, Exception $e) {}
function onMessage(ConnectionInterface $from, $msg) {
$from->send($msg);
}
}
$server = IoServer::factory(
new HttpServer(new WsServer(new WS())),
3000
);
$server->run();
The Web Application Messaging Protocol
The Bigger The Better
➜ Remote Procedure Calls (RPC)
➜ Publish & Subscribe
➜ Autobahn.JS
➜ integracja ZeroMQ
➜ integracja Redis
Autobahn.JS?
// dla wersji AUTOBAHNJS_VERSION="0.7.1"
var session = new ab.Session(
"ws://127.0.0.1:3000",
function () {
// zostaliśmy połączeni
},
function () {
// zostaliśmy rozłączeni
},
{
'skipSubprotocolCheck': true,
'maxRetries': 5,
'retryDelay': 2000
}
);
session.subscribe("http://phpers.pl/event/message", callback);
class WAMP implements RatchetWampWampServerInterface {
public function onPublish(ConnectionInterface $conn, $topic, $event, array
$exclude, array $eligible) {}
public function onCall(ConnectionInterface $conn, $id, $topic, array $params) {}
public function onSubscribe(ConnectionInterface $conn, $topic) {}
public function onUnSubscribe(ConnectionInterface $conn, $topic) {}
public function onOpen(ConnectionInterface $conn) {}
public function onClose(ConnectionInterface $conn) {}
public function onError(ConnectionInterface $conn, Exception $e) {}
}
$server = RatchetServerIoServer::factory(
new HttpServer(new WsServer(new WampServer(new WAMP()))),
3000
);
$server->run();
Ratchet + WAMP
$loop = ReactEventLoopFactory::create();
$pusher = new WAMP;
$context = new ReactZMQContext($loop);
$pull = $context->getSocket(ZMQ::SOCKET_PULL);
$pull->bind('tcp://127.0.0.1:5555');
$pull->on('message', array($pusher, 'onQueueAdded'));
$socket = new ReactSocketServer($loop);
$socket->listen(3000, '0.0.0.0');
$webServer = new IoServer(
new HttpServer(new WsServer(new WampServer($pusher))),
$socket
);
$loop->run();
ZeroMQ + Ratchet
ZeroMQ + Ratchet
$loop = ReactEventLoopFactory::create();
$pusher = new WAMP;
$context = new ReactZMQContext($loop);
$pull = $context->getSocket(ZMQ::SOCKET_PULL);
$pull->bind('tcp://127.0.0.1:5555');
$pull->on('message', array($pusher, 'onQueueAdded'));
$socket = new ReactSocketServer($loop);
$socket->listen(3000, '0.0.0.0');
$webServer = new IoServer(
new HttpServer(new WsServer(new WampServer($pusher))),
$socket
);
$loop->run();
$context = new ZMQContext();
$socket = $context->getSocket(
ZMQ::SOCKET_PUSH,
'websocket'
);
$socket->connect('tcp://127.0.0.1:5555');
$socket->send($payloadAsJSON);
ZeroMQ + Ratchet
$loop = ReactEventLoopFactory::create();
$pusher = new WAMP;
$context = new ReactZMQContext($loop);
$pull = $context->getSocket(ZMQ::SOCKET_PULL);
$pull->bind('tcp://127.0.0.1:5555');
$pull->on('message', array($pusher, 'onQueueAdded'));
$socket = new ReactSocketServer($loop);
$socket->listen(3000, '0.0.0.0');
$webServer = new IoServer(
new HttpServer(new WsServer(new WampServer($pusher))),
$socket
);
$loop->run();
$context = new ZMQContext();
$socket = $context->getSocket(
ZMQ::SOCKET_PUSH,
'websocket'
);
$socket->connect('tcp://127.0.0.1:5555');
$socket->send($payloadAsJSON);
public function onQueueAdded($payload) {
$payloadData = json_decode($payload, true);
// dalsze przetwarzanie
}
MAO?
➜ WAMP2
➜ voryx/Thruway (kompatybilny z nowym
Autobahn.JS)
➜ bixuehujin/reactphp-mysql
➜ DNode
➜ STOMP
➜ AR.Drone
➜ Whois
➜ Childprocess
Koniec!
Macie pytania?
Odniesienia i inspiracje
➜ http://blog.wyrihaximus.net/categories/reactphp/
➜ Presentation theme - SlidesCarnival
➜ Zdjęcia - Death to the Stock Photo
➜ http://www.slideshare.
net/SteveRhoades2/asynchronous-php-and-realtime-
messaging
➜ https://speakerdeck.com/jmikola/async-php-with-react
➜ https://speakerdeck.com/igorw/react-phpnw

Más contenido relacionado

La actualidad más candente

Deployment kodu z Capistrano
Deployment kodu z CapistranoDeployment kodu z Capistrano
Deployment kodu z CapistranoMichał Szajbe
 
Laravel workshops 1
Laravel workshops 1Laravel workshops 1
Laravel workshops 1Kamil Fojuth
 
TorqueBox - Ruby na sterydach
TorqueBox - Ruby na sterydachTorqueBox - Ruby na sterydach
TorqueBox - Ruby na sterydachmarekgoldmann
 
Ansible - Automatyzacja zadań IT
Ansible - Automatyzacja zadań ITAnsible - Automatyzacja zadań IT
Ansible - Automatyzacja zadań ITKamil Grabowski
 
ansible kmonticolo bezlogo
ansible kmonticolo bezlogoansible kmonticolo bezlogo
ansible kmonticolo bezlogoKamil Monticolo
 
TorqueBox - moc Javy, piękno Rubiego
TorqueBox - moc Javy, piękno RubiegoTorqueBox - moc Javy, piękno Rubiego
TorqueBox - moc Javy, piękno Rubiegomarekgoldmann
 
Cykl życia zapytania HTTP (pod maską)
Cykl życia zapytania HTTP (pod maską)Cykl życia zapytania HTTP (pod maską)
Cykl życia zapytania HTTP (pod maską)Laravel Poland MeetUp
 
Pan Oponka - Biografia
Pan Oponka - BiografiaPan Oponka - Biografia
Pan Oponka - BiografiaFilip Tepper
 
Jak zostać mobile deweloperem w 1 dzień
Jak zostać mobile deweloperem w 1 dzieńJak zostać mobile deweloperem w 1 dzień
Jak zostać mobile deweloperem w 1 dzieńPaweł Kondraciuk
 
Hugo - make webdev fun again
Hugo - make webdev fun againHugo - make webdev fun again
Hugo - make webdev fun againMarcin Gajda
 
Service workers - bądź online, nawet kiedy jesteś offline!
Service workers - bądź online, nawet kiedy jesteś offline!Service workers - bądź online, nawet kiedy jesteś offline!
Service workers - bądź online, nawet kiedy jesteś offline!The Software House
 
Aplikacje internetowe real-time w oparciu o React/Redux
Aplikacje internetowe real-time w oparciu o React/ReduxAplikacje internetowe real-time w oparciu o React/Redux
Aplikacje internetowe real-time w oparciu o React/ReduxDawid Rusnak
 
Optymalizacyjna magia, czyli jak wyciągać króliki z kapelusza
Optymalizacyjna magia, czyli jak wyciągać króliki z kapelusza Optymalizacyjna magia, czyli jak wyciągać króliki z kapelusza
Optymalizacyjna magia, czyli jak wyciągać króliki z kapelusza SzymonSadlo
 

La actualidad más candente (20)

Deployment kodu z Capistrano
Deployment kodu z CapistranoDeployment kodu z Capistrano
Deployment kodu z Capistrano
 
Torquebox
TorqueboxTorquebox
Torquebox
 
Ansible w praktyce
Ansible w praktyceAnsible w praktyce
Ansible w praktyce
 
Laravel workshops 1
Laravel workshops 1Laravel workshops 1
Laravel workshops 1
 
TorqueBox - Ruby na sterydach
TorqueBox - Ruby na sterydachTorqueBox - Ruby na sterydach
TorqueBox - Ruby na sterydach
 
Ansible - Automatyzacja zadań IT
Ansible - Automatyzacja zadań ITAnsible - Automatyzacja zadań IT
Ansible - Automatyzacja zadań IT
 
ansible kmonticolo bezlogo
ansible kmonticolo bezlogoansible kmonticolo bezlogo
ansible kmonticolo bezlogo
 
Infrastructure As Code
Infrastructure As CodeInfrastructure As Code
Infrastructure As Code
 
Monitoring sieci
Monitoring sieciMonitoring sieci
Monitoring sieci
 
TorqueBox - moc Javy, piękno Rubiego
TorqueBox - moc Javy, piękno RubiegoTorqueBox - moc Javy, piękno Rubiego
TorqueBox - moc Javy, piękno Rubiego
 
GlusterFS
GlusterFSGlusterFS
GlusterFS
 
PHP-PM. Hit czy kit?
PHP-PM. Hit czy kit?PHP-PM. Hit czy kit?
PHP-PM. Hit czy kit?
 
Cykl życia zapytania HTTP (pod maską)
Cykl życia zapytania HTTP (pod maską)Cykl życia zapytania HTTP (pod maską)
Cykl życia zapytania HTTP (pod maską)
 
Pan Oponka - Biografia
Pan Oponka - BiografiaPan Oponka - Biografia
Pan Oponka - Biografia
 
Jak zostać mobile deweloperem w 1 dzień
Jak zostać mobile deweloperem w 1 dzieńJak zostać mobile deweloperem w 1 dzień
Jak zostać mobile deweloperem w 1 dzień
 
Hugo - make webdev fun again
Hugo - make webdev fun againHugo - make webdev fun again
Hugo - make webdev fun again
 
Service workers - bądź online, nawet kiedy jesteś offline!
Service workers - bądź online, nawet kiedy jesteś offline!Service workers - bądź online, nawet kiedy jesteś offline!
Service workers - bądź online, nawet kiedy jesteś offline!
 
Aplikacje internetowe real-time w oparciu o React/Redux
Aplikacje internetowe real-time w oparciu o React/ReduxAplikacje internetowe real-time w oparciu o React/Redux
Aplikacje internetowe real-time w oparciu o React/Redux
 
Optymalizacyjna magia, czyli jak wyciągać króliki z kapelusza
Optymalizacyjna magia, czyli jak wyciągać króliki z kapelusza Optymalizacyjna magia, czyli jak wyciągać króliki z kapelusza
Optymalizacyjna magia, czyli jak wyciągać króliki z kapelusza
 
Dapper .NET - ORM
Dapper .NET - ORMDapper .NET - ORM
Dapper .NET - ORM
 

Destacado

Real-Time Web applications with WebSockets
Real-Time Web applications with WebSocketsReal-Time Web applications with WebSockets
Real-Time Web applications with WebSocketsStanislav Zozulia
 
Kogo Bronimy W Tym Roku
Kogo Bronimy W Tym RokuKogo Bronimy W Tym Roku
Kogo Bronimy W Tym Rokuguestad3fce
 
Email marketing na autopilocie 5 praktycznych scenariuszy wykorzystania aut...
Email marketing na autopilocie   5 praktycznych scenariuszy wykorzystania aut...Email marketing na autopilocie   5 praktycznych scenariuszy wykorzystania aut...
Email marketing na autopilocie 5 praktycznych scenariuszy wykorzystania aut...GetResponsePL
 
Jak dotrzeć do klienta w bezmiarze informacji?
Jak dotrzeć do klienta w bezmiarze informacji?Jak dotrzeć do klienta w bezmiarze informacji?
Jak dotrzeć do klienta w bezmiarze informacji?Wirtualna Polska
 
Łukasz Grala - WSKIZ 2009-04-07 It Academic - SQL Server 2008 - Nowości Adm...
Łukasz Grala - WSKIZ 2009-04-07 It Academic - SQL Server 2008 - Nowości   Adm...Łukasz Grala - WSKIZ 2009-04-07 It Academic - SQL Server 2008 - Nowości   Adm...
Łukasz Grala - WSKIZ 2009-04-07 It Academic - SQL Server 2008 - Nowości Adm...Łukasz Grala
 
Landing page bez video jest mono nie stereo
Landing page bez video jest mono nie stereoLanding page bez video jest mono nie stereo
Landing page bez video jest mono nie stereoGetResponsePL
 
Budowanie skutecznej strategii e-marketingowej | Mateusz Muryjas @ Igrzyska P...
Budowanie skutecznej strategii e-marketingowej | Mateusz Muryjas @ Igrzyska P...Budowanie skutecznej strategii e-marketingowej | Mateusz Muryjas @ Igrzyska P...
Budowanie skutecznej strategii e-marketingowej | Mateusz Muryjas @ Igrzyska P...Mateusz Muryjas
 
OFFON Agency Eventy
OFFON Agency EventyOFFON Agency Eventy
OFFON Agency EventyOFFON Agency
 
Event management - od pomysłu do realizacji czyli o czym NIE warto pamiętać
Event management - od pomysłu do realizacji czyli o czym NIE warto pamiętaćEvent management - od pomysłu do realizacji czyli o czym NIE warto pamiętać
Event management - od pomysłu do realizacji czyli o czym NIE warto pamiętaćGreenboard
 
Jak zwiększyć sprzedaż za pomocą monitoringu Internetu - Retail & Fashion 2015
Jak zwiększyć sprzedaż za pomocą monitoringu Internetu - Retail & Fashion 2015Jak zwiększyć sprzedaż za pomocą monitoringu Internetu - Retail & Fashion 2015
Jak zwiększyć sprzedaż za pomocą monitoringu Internetu - Retail & Fashion 2015Brand24
 
#eventcepcja Networking Izabela Górska (Business Link Warszawa)
#eventcepcja Networking Izabela Górska (Business Link Warszawa)#eventcepcja Networking Izabela Górska (Business Link Warszawa)
#eventcepcja Networking Izabela Górska (Business Link Warszawa)Edyta Kowal
 
Global Event Forum [FUTURE]
Global Event Forum [FUTURE]Global Event Forum [FUTURE]
Global Event Forum [FUTURE]GEF.FUTURE
 
RROLA STRATEGA I STRATEGII W AGENCJI REKLAMOWEJ / MELTING POT
RROLA STRATEGA I STRATEGII W AGENCJI REKLAMOWEJ / MELTING POTRROLA STRATEGA I STRATEGII W AGENCJI REKLAMOWEJ / MELTING POT
RROLA STRATEGA I STRATEGII W AGENCJI REKLAMOWEJ / MELTING POTDariusz Kieda
 
ReactPHP – reaktor jądrowy w PHP
ReactPHP – reaktor jądrowy w PHPReactPHP – reaktor jądrowy w PHP
ReactPHP – reaktor jądrowy w PHPThe Software House
 
Future web developer, you are going to be tremendously valuable
Future web developer, you are going to be tremendously valuableFuture web developer, you are going to be tremendously valuable
Future web developer, you are going to be tremendously valuablePolcode
 
Introduction to WAMP, a protocol enabling PUB/SUB and RPC over Websocket
Introduction to WAMP, a protocol enabling PUB/SUB and RPC over WebsocketIntroduction to WAMP, a protocol enabling PUB/SUB and RPC over Websocket
Introduction to WAMP, a protocol enabling PUB/SUB and RPC over Websocketsametmax
 
The Role of Enterprise Integration in Digital Transformation
The Role of Enterprise Integration in Digital TransformationThe Role of Enterprise Integration in Digital Transformation
The Role of Enterprise Integration in Digital TransformationKasun Indrasiri
 
Witamy w Planners / Welcome to Planners
Witamy w Planners / Welcome to PlannersWitamy w Planners / Welcome to Planners
Witamy w Planners / Welcome to PlannersPlannersPolska
 
Mobile-First SEO - The Marketers Edition #3XEDigital
Mobile-First SEO - The Marketers Edition #3XEDigitalMobile-First SEO - The Marketers Edition #3XEDigital
Mobile-First SEO - The Marketers Edition #3XEDigitalAleyda Solís
 

Destacado (20)

Real-Time Web applications with WebSockets
Real-Time Web applications with WebSocketsReal-Time Web applications with WebSockets
Real-Time Web applications with WebSockets
 
Kogo Bronimy W Tym Roku
Kogo Bronimy W Tym RokuKogo Bronimy W Tym Roku
Kogo Bronimy W Tym Roku
 
Email marketing na autopilocie 5 praktycznych scenariuszy wykorzystania aut...
Email marketing na autopilocie   5 praktycznych scenariuszy wykorzystania aut...Email marketing na autopilocie   5 praktycznych scenariuszy wykorzystania aut...
Email marketing na autopilocie 5 praktycznych scenariuszy wykorzystania aut...
 
Jak dotrzeć do klienta w bezmiarze informacji?
Jak dotrzeć do klienta w bezmiarze informacji?Jak dotrzeć do klienta w bezmiarze informacji?
Jak dotrzeć do klienta w bezmiarze informacji?
 
Łukasz Grala - WSKIZ 2009-04-07 It Academic - SQL Server 2008 - Nowości Adm...
Łukasz Grala - WSKIZ 2009-04-07 It Academic - SQL Server 2008 - Nowości   Adm...Łukasz Grala - WSKIZ 2009-04-07 It Academic - SQL Server 2008 - Nowości   Adm...
Łukasz Grala - WSKIZ 2009-04-07 It Academic - SQL Server 2008 - Nowości Adm...
 
Landing page bez video jest mono nie stereo
Landing page bez video jest mono nie stereoLanding page bez video jest mono nie stereo
Landing page bez video jest mono nie stereo
 
Budowanie skutecznej strategii e-marketingowej | Mateusz Muryjas @ Igrzyska P...
Budowanie skutecznej strategii e-marketingowej | Mateusz Muryjas @ Igrzyska P...Budowanie skutecznej strategii e-marketingowej | Mateusz Muryjas @ Igrzyska P...
Budowanie skutecznej strategii e-marketingowej | Mateusz Muryjas @ Igrzyska P...
 
OFFON Agency Eventy
OFFON Agency EventyOFFON Agency Eventy
OFFON Agency Eventy
 
Event management - od pomysłu do realizacji czyli o czym NIE warto pamiętać
Event management - od pomysłu do realizacji czyli o czym NIE warto pamiętaćEvent management - od pomysłu do realizacji czyli o czym NIE warto pamiętać
Event management - od pomysłu do realizacji czyli o czym NIE warto pamiętać
 
Jak zwiększyć sprzedaż za pomocą monitoringu Internetu - Retail & Fashion 2015
Jak zwiększyć sprzedaż za pomocą monitoringu Internetu - Retail & Fashion 2015Jak zwiększyć sprzedaż za pomocą monitoringu Internetu - Retail & Fashion 2015
Jak zwiększyć sprzedaż za pomocą monitoringu Internetu - Retail & Fashion 2015
 
#eventcepcja Networking Izabela Górska (Business Link Warszawa)
#eventcepcja Networking Izabela Górska (Business Link Warszawa)#eventcepcja Networking Izabela Górska (Business Link Warszawa)
#eventcepcja Networking Izabela Górska (Business Link Warszawa)
 
Global Event Forum [FUTURE]
Global Event Forum [FUTURE]Global Event Forum [FUTURE]
Global Event Forum [FUTURE]
 
RROLA STRATEGA I STRATEGII W AGENCJI REKLAMOWEJ / MELTING POT
RROLA STRATEGA I STRATEGII W AGENCJI REKLAMOWEJ / MELTING POTRROLA STRATEGA I STRATEGII W AGENCJI REKLAMOWEJ / MELTING POT
RROLA STRATEGA I STRATEGII W AGENCJI REKLAMOWEJ / MELTING POT
 
ReactPHP – reaktor jądrowy w PHP
ReactPHP – reaktor jądrowy w PHPReactPHP – reaktor jądrowy w PHP
ReactPHP – reaktor jądrowy w PHP
 
Future web developer, you are going to be tremendously valuable
Future web developer, you are going to be tremendously valuableFuture web developer, you are going to be tremendously valuable
Future web developer, you are going to be tremendously valuable
 
Introduction to WAMP, a protocol enabling PUB/SUB and RPC over Websocket
Introduction to WAMP, a protocol enabling PUB/SUB and RPC over WebsocketIntroduction to WAMP, a protocol enabling PUB/SUB and RPC over Websocket
Introduction to WAMP, a protocol enabling PUB/SUB and RPC over Websocket
 
The Role of Enterprise Integration in Digital Transformation
The Role of Enterprise Integration in Digital TransformationThe Role of Enterprise Integration in Digital Transformation
The Role of Enterprise Integration in Digital Transformation
 
Witamy w Planners / Welcome to Planners
Witamy w Planners / Welcome to PlannersWitamy w Planners / Welcome to Planners
Witamy w Planners / Welcome to Planners
 
Campus #culturecode
Campus #culturecodeCampus #culturecode
Campus #culturecode
 
Mobile-First SEO - The Marketers Edition #3XEDigital
Mobile-First SEO - The Marketers Edition #3XEDigitalMobile-First SEO - The Marketers Edition #3XEDigital
Mobile-First SEO - The Marketers Edition #3XEDigital
 

Similar a Asynchroniczny PHP & komunikacja czasu rzeczywistego z wykorzystaniem websocketów

Apache http server - proste i zaawansowane przypadki użycia
Apache http server - proste i zaawansowane przypadki użyciaApache http server - proste i zaawansowane przypadki użycia
Apache http server - proste i zaawansowane przypadki użyciaWojciech Lichota
 
[WHUG] Wielki brat patrzy - czyli jak zbieramy dane o użytkownikach allegro
[WHUG] Wielki brat patrzy - czyli jak zbieramy dane o użytkownikach allegro[WHUG] Wielki brat patrzy - czyli jak zbieramy dane o użytkownikach allegro
[WHUG] Wielki brat patrzy - czyli jak zbieramy dane o użytkownikach allegroallegro.tech
 
Microservieces and their communication (RabbitMQ/SIDEKIQ)
Microservieces and their communication (RabbitMQ/SIDEKIQ)Microservieces and their communication (RabbitMQ/SIDEKIQ)
Microservieces and their communication (RabbitMQ/SIDEKIQ)infakt
 
TV i video w Internecie
TV i video w InternecieTV i video w Internecie
TV i video w InternecieDivante
 
Camel-Drools - Javarsovia 2010
Camel-Drools - Javarsovia 2010Camel-Drools - Javarsovia 2010
Camel-Drools - Javarsovia 2010Maciek Próchniak
 
Mts 2013 tomasz kopacz - windows 8, office 365, workflow manager, windows a...
Mts 2013   tomasz kopacz - windows 8, office 365, workflow manager, windows a...Mts 2013   tomasz kopacz - windows 8, office 365, workflow manager, windows a...
Mts 2013 tomasz kopacz - windows 8, office 365, workflow manager, windows a...Tomasz Kopacz
 
Wstęp do projektowania usług internetowych: część 1 - rest
Wstęp do projektowania usług internetowych: część 1 - restWstęp do projektowania usług internetowych: część 1 - rest
Wstęp do projektowania usług internetowych: część 1 - restLukas Lesniewski
 
tRPC - czy to koniec GraphQL?
tRPC - czy to koniec GraphQL?tRPC - czy to koniec GraphQL?
tRPC - czy to koniec GraphQL?Brainhub
 
Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...
Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...
Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...Tomasz Kopacz
 
Warsztaty: Podstawy PHP - część 2 - omówienie składni języka PHP (wersja 7)
Warsztaty: Podstawy PHP - część 2 - omówienie składni języka PHP (wersja 7)Warsztaty: Podstawy PHP - część 2 - omówienie składni języka PHP (wersja 7)
Warsztaty: Podstawy PHP - część 2 - omówienie składni języka PHP (wersja 7)Codesushi.co (CODESUSHI LLC)
 
Info meet pomiary wydajności
Info meet pomiary wydajnościInfo meet pomiary wydajności
Info meet pomiary wydajnościmagda3695
 
OpenSSH Kombajn z Wodotryskiem
OpenSSH Kombajn z WodotryskiemOpenSSH Kombajn z Wodotryskiem
OpenSSH Kombajn z Wodotryskiemlinuxcamp
 
Automatyzacja utrzymania jakości w środowisku PHP
Automatyzacja utrzymania jakości w środowisku PHPAutomatyzacja utrzymania jakości w środowisku PHP
Automatyzacja utrzymania jakości w środowisku PHPLaravel Poland MeetUp
 
“Dziesięć serwerów poproszę!“, czyli co może Ci zaoferować definiowanie infra...
“Dziesięć serwerów poproszę!“, czyli co może Ci zaoferować definiowanie infra...“Dziesięć serwerów poproszę!“, czyli co może Ci zaoferować definiowanie infra...
“Dziesięć serwerów poproszę!“, czyli co może Ci zaoferować definiowanie infra...The Software House
 
Modsecurity-czy-Twoj-WAF-to-potrafi-Leszek-Mis-Linux-Polska
Modsecurity-czy-Twoj-WAF-to-potrafi-Leszek-Mis-Linux-PolskaModsecurity-czy-Twoj-WAF-to-potrafi-Leszek-Mis-Linux-Polska
Modsecurity-czy-Twoj-WAF-to-potrafi-Leszek-Mis-Linux-PolskaLeszek Mi?
 
infraxstructure: Robert Mroczkowski "Maszyny się uczą - admińskie rozmówki p...
infraxstructure: Robert Mroczkowski  "Maszyny się uczą - admińskie rozmówki p...infraxstructure: Robert Mroczkowski  "Maszyny się uczą - admińskie rozmówki p...
infraxstructure: Robert Mroczkowski "Maszyny się uczą - admińskie rozmówki p...PROIDEA
 

Similar a Asynchroniczny PHP & komunikacja czasu rzeczywistego z wykorzystaniem websocketów (20)

Apache http server - proste i zaawansowane przypadki użycia
Apache http server - proste i zaawansowane przypadki użyciaApache http server - proste i zaawansowane przypadki użycia
Apache http server - proste i zaawansowane przypadki użycia
 
Swoole w PHP. Czy to ma sens?
Swoole w PHP. Czy to ma sens?Swoole w PHP. Czy to ma sens?
Swoole w PHP. Czy to ma sens?
 
[WHUG] Wielki brat patrzy - czyli jak zbieramy dane o użytkownikach allegro
[WHUG] Wielki brat patrzy - czyli jak zbieramy dane o użytkownikach allegro[WHUG] Wielki brat patrzy - czyli jak zbieramy dane o użytkownikach allegro
[WHUG] Wielki brat patrzy - czyli jak zbieramy dane o użytkownikach allegro
 
Microservieces and their communication (RabbitMQ/SIDEKIQ)
Microservieces and their communication (RabbitMQ/SIDEKIQ)Microservieces and their communication (RabbitMQ/SIDEKIQ)
Microservieces and their communication (RabbitMQ/SIDEKIQ)
 
TV i video w Internecie
TV i video w InternecieTV i video w Internecie
TV i video w Internecie
 
Camel-Drools - Javarsovia 2010
Camel-Drools - Javarsovia 2010Camel-Drools - Javarsovia 2010
Camel-Drools - Javarsovia 2010
 
Mts 2013 tomasz kopacz - windows 8, office 365, workflow manager, windows a...
Mts 2013   tomasz kopacz - windows 8, office 365, workflow manager, windows a...Mts 2013   tomasz kopacz - windows 8, office 365, workflow manager, windows a...
Mts 2013 tomasz kopacz - windows 8, office 365, workflow manager, windows a...
 
CruiseControl.rb
CruiseControl.rbCruiseControl.rb
CruiseControl.rb
 
Wstęp do projektowania usług internetowych: część 1 - rest
Wstęp do projektowania usług internetowych: część 1 - restWstęp do projektowania usług internetowych: część 1 - rest
Wstęp do projektowania usług internetowych: część 1 - rest
 
tRPC - czy to koniec GraphQL?
tRPC - czy to koniec GraphQL?tRPC - czy to koniec GraphQL?
tRPC - czy to koniec GraphQL?
 
Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...
Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...
Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...
 
Android i REST
Android i RESTAndroid i REST
Android i REST
 
Warsztaty: Podstawy PHP - część 2 - omówienie składni języka PHP (wersja 7)
Warsztaty: Podstawy PHP - część 2 - omówienie składni języka PHP (wersja 7)Warsztaty: Podstawy PHP - część 2 - omówienie składni języka PHP (wersja 7)
Warsztaty: Podstawy PHP - część 2 - omówienie składni języka PHP (wersja 7)
 
Info meet pomiary wydajności
Info meet pomiary wydajnościInfo meet pomiary wydajności
Info meet pomiary wydajności
 
OpenSSH Kombajn z Wodotryskiem
OpenSSH Kombajn z WodotryskiemOpenSSH Kombajn z Wodotryskiem
OpenSSH Kombajn z Wodotryskiem
 
Automatyzacja utrzymania jakości w środowisku PHP
Automatyzacja utrzymania jakości w środowisku PHPAutomatyzacja utrzymania jakości w środowisku PHP
Automatyzacja utrzymania jakości w środowisku PHP
 
“Dziesięć serwerów poproszę!“, czyli co może Ci zaoferować definiowanie infra...
“Dziesięć serwerów poproszę!“, czyli co może Ci zaoferować definiowanie infra...“Dziesięć serwerów poproszę!“, czyli co może Ci zaoferować definiowanie infra...
“Dziesięć serwerów poproszę!“, czyli co może Ci zaoferować definiowanie infra...
 
Modsecurity-czy-Twoj-WAF-to-potrafi-Leszek-Mis-Linux-Polska
Modsecurity-czy-Twoj-WAF-to-potrafi-Leszek-Mis-Linux-PolskaModsecurity-czy-Twoj-WAF-to-potrafi-Leszek-Mis-Linux-Polska
Modsecurity-czy-Twoj-WAF-to-potrafi-Leszek-Mis-Linux-Polska
 
DSL - DYI
DSL - DYIDSL - DYI
DSL - DYI
 
infraxstructure: Robert Mroczkowski "Maszyny się uczą - admińskie rozmówki p...
infraxstructure: Robert Mroczkowski  "Maszyny się uczą - admińskie rozmówki p...infraxstructure: Robert Mroczkowski  "Maszyny się uczą - admińskie rozmówki p...
infraxstructure: Robert Mroczkowski "Maszyny się uczą - admińskie rozmówki p...
 

Más de Polcode

How to keep customers engaged to turn them into fans
How to keep customers engaged to turn them into fansHow to keep customers engaged to turn them into fans
How to keep customers engaged to turn them into fansPolcode
 
Expert Advice on ERP
Expert Advice on ERPExpert Advice on ERP
Expert Advice on ERPPolcode
 
User Experience (UX): Brand-Customer Interaction
User Experience (UX): Brand-Customer InteractionUser Experience (UX): Brand-Customer Interaction
User Experience (UX): Brand-Customer InteractionPolcode
 
The Difference Between UX and UI
The Difference Between UX and UIThe Difference Between UX and UI
The Difference Between UX and UIPolcode
 
5 Benefits of Utilizing Machine Learning in eLearning
5 Benefits of Utilizing Machine Learning in eLearning5 Benefits of Utilizing Machine Learning in eLearning
5 Benefits of Utilizing Machine Learning in eLearningPolcode
 
KrakowJS Conference Highlights
KrakowJS Conference HighlightsKrakowJS Conference Highlights
KrakowJS Conference HighlightsPolcode
 
Best Practices for Dropdowns
Best Practices for DropdownsBest Practices for Dropdowns
Best Practices for DropdownsPolcode
 
What’s Next for the Web?
What’s Next for the Web?What’s Next for the Web?
What’s Next for the Web?Polcode
 
Book Recommended By Our CTO
Book Recommended By Our CTOBook Recommended By Our CTO
Book Recommended By Our CTOPolcode
 
8 Biggest Web Design Trends For 2018 eCommerce
8 Biggest Web Design Trends For 2018 eCommerce8 Biggest Web Design Trends For 2018 eCommerce
8 Biggest Web Design Trends For 2018 eCommercePolcode
 
World Wide Web today
World Wide Web todayWorld Wide Web today
World Wide Web todayPolcode
 
Wordpress in numbers
Wordpress in numbersWordpress in numbers
Wordpress in numbersPolcode
 
Cryptocurrencies in e-commerce
Cryptocurrencies in e-commerceCryptocurrencies in e-commerce
Cryptocurrencies in e-commercePolcode
 
Why Choose WooCommerce?
Why Choose WooCommerce?Why Choose WooCommerce?
Why Choose WooCommerce?Polcode
 
A guide to vastly improving your eCommerce business by investing nothing more...
A guide to vastly improving your eCommerce business by investing nothing more...A guide to vastly improving your eCommerce business by investing nothing more...
A guide to vastly improving your eCommerce business by investing nothing more...Polcode
 
Boost your conversions by 40% and more with these 10 growth hacking tips!
Boost your conversions by 40% and more with these 10 growth hacking tips!Boost your conversions by 40% and more with these 10 growth hacking tips!
Boost your conversions by 40% and more with these 10 growth hacking tips!Polcode
 
10 reasons why Symfony is just the right fit for your project
10 reasons why Symfony is just the right fit for your project10 reasons why Symfony is just the right fit for your project
10 reasons why Symfony is just the right fit for your projectPolcode
 
Free, SaaS or Enterprise? You’re asking the wrong question!
Free, SaaS or Enterprise? You’re asking the wrong question!Free, SaaS or Enterprise? You’re asking the wrong question!
Free, SaaS or Enterprise? You’re asking the wrong question!Polcode
 
Improve your web and app development with the Symfony3 framework.
Improve your web and app development with the Symfony3 framework.Improve your web and app development with the Symfony3 framework.
Improve your web and app development with the Symfony3 framework.Polcode
 
Polcode’s (not so) secret recipe for an efficient software development process
Polcode’s (not so) secret recipe for an efficient software development processPolcode’s (not so) secret recipe for an efficient software development process
Polcode’s (not so) secret recipe for an efficient software development processPolcode
 

Más de Polcode (20)

How to keep customers engaged to turn them into fans
How to keep customers engaged to turn them into fansHow to keep customers engaged to turn them into fans
How to keep customers engaged to turn them into fans
 
Expert Advice on ERP
Expert Advice on ERPExpert Advice on ERP
Expert Advice on ERP
 
User Experience (UX): Brand-Customer Interaction
User Experience (UX): Brand-Customer InteractionUser Experience (UX): Brand-Customer Interaction
User Experience (UX): Brand-Customer Interaction
 
The Difference Between UX and UI
The Difference Between UX and UIThe Difference Between UX and UI
The Difference Between UX and UI
 
5 Benefits of Utilizing Machine Learning in eLearning
5 Benefits of Utilizing Machine Learning in eLearning5 Benefits of Utilizing Machine Learning in eLearning
5 Benefits of Utilizing Machine Learning in eLearning
 
KrakowJS Conference Highlights
KrakowJS Conference HighlightsKrakowJS Conference Highlights
KrakowJS Conference Highlights
 
Best Practices for Dropdowns
Best Practices for DropdownsBest Practices for Dropdowns
Best Practices for Dropdowns
 
What’s Next for the Web?
What’s Next for the Web?What’s Next for the Web?
What’s Next for the Web?
 
Book Recommended By Our CTO
Book Recommended By Our CTOBook Recommended By Our CTO
Book Recommended By Our CTO
 
8 Biggest Web Design Trends For 2018 eCommerce
8 Biggest Web Design Trends For 2018 eCommerce8 Biggest Web Design Trends For 2018 eCommerce
8 Biggest Web Design Trends For 2018 eCommerce
 
World Wide Web today
World Wide Web todayWorld Wide Web today
World Wide Web today
 
Wordpress in numbers
Wordpress in numbersWordpress in numbers
Wordpress in numbers
 
Cryptocurrencies in e-commerce
Cryptocurrencies in e-commerceCryptocurrencies in e-commerce
Cryptocurrencies in e-commerce
 
Why Choose WooCommerce?
Why Choose WooCommerce?Why Choose WooCommerce?
Why Choose WooCommerce?
 
A guide to vastly improving your eCommerce business by investing nothing more...
A guide to vastly improving your eCommerce business by investing nothing more...A guide to vastly improving your eCommerce business by investing nothing more...
A guide to vastly improving your eCommerce business by investing nothing more...
 
Boost your conversions by 40% and more with these 10 growth hacking tips!
Boost your conversions by 40% and more with these 10 growth hacking tips!Boost your conversions by 40% and more with these 10 growth hacking tips!
Boost your conversions by 40% and more with these 10 growth hacking tips!
 
10 reasons why Symfony is just the right fit for your project
10 reasons why Symfony is just the right fit for your project10 reasons why Symfony is just the right fit for your project
10 reasons why Symfony is just the right fit for your project
 
Free, SaaS or Enterprise? You’re asking the wrong question!
Free, SaaS or Enterprise? You’re asking the wrong question!Free, SaaS or Enterprise? You’re asking the wrong question!
Free, SaaS or Enterprise? You’re asking the wrong question!
 
Improve your web and app development with the Symfony3 framework.
Improve your web and app development with the Symfony3 framework.Improve your web and app development with the Symfony3 framework.
Improve your web and app development with the Symfony3 framework.
 
Polcode’s (not so) secret recipe for an efficient software development process
Polcode’s (not so) secret recipe for an efficient software development processPolcode’s (not so) secret recipe for an efficient software development process
Polcode’s (not so) secret recipe for an efficient software development process
 

Asynchroniczny PHP & komunikacja czasu rzeczywistego z wykorzystaniem websocketów

  • 1. Asynchroniczny PHP & komunikacja czasu rzeczywistego z wykorzystaniem websocketów
  • 2. who am i Nazywam się Łukasz Adamczewski Pracuje w firmie Polcode jako Starszy Programista PHP Szukaj mnie na @lukeadamczewski
  • 3. - czyli wasz język tego nie potrafi
  • 4. CPU IO CPU czas IO Model typowej aplikacji
  • 5. W czym problem? Model typowej aplikacji CPU IO CPU czas IO
  • 6. asynchroniczna instrukcja CPU Model non-blocking IO IO IO CPU IO CPU CZAS różnyczaswykonywania IO oczekiwanie na koniec poprzedniego zadania
  • 7. Słów kilka o czasach dostępu czyli IO vs CPU http://norvig.com/21-days.html#answers fetch from L1 cache memory 0.5 nanosec fetch from L2 cache memory 7 nanosec fetch from main memory 100 nanosec send 2K bytes over 1Gbps network 20,000 nanosec read 1MB sequentially from memory 0,25 ms = 250,000 ns Read 1 MB sequentially from SSD* 1 ms Disk seek 10 ms Read 1 MB sequentially from disk 20 ms send packet US to Europe and back 150 ms * Assuming ~1GB/sec SSD
  • 8. getUser(432, function (user) { console.log(user.name); }); console.log('Done'); Typowy node.js
  • 9. getUser(432, function (user) { console.log(user.name); }); console.log('Done');1 Typowy node.js
  • 10. getUser(432, function (user) { console.log(user.name); }); console.log('Done');1 2 Typowy node.js
  • 11. Node.JS - webserver “hello world” var http = require('http'); var server = new http.Server(); server.on('request', function (req, res) { res.writeHead( 200, {'Content-Type':'text/plain'} ); res.end('Hello World'); }); server.listen(8000, '127.0.0.1');
  • 12. Node.JS - webserver “hello world” var http = require('http'); var server = new http.Server(); server.on('request', function (req, res) { res.writeHead( 200, {'Content-Type':'text/plain'} ); res.end('Hello World'); }); server.listen(8000, '127.0.0.1'); oczekiwanie na zdarzenie request kod obsługi zdarzenia wysyłający odpowiednie nagłówki do klienta HTTP oraz wysyłający odpowiednią wiadomość
  • 13. Node.JS - webserver “hello world” var http = require('http'); var server = new http.Server(); server.on('request', function (req, res) { res.writeHead( 200, {'Content-Type':'text/plain'} ); res.end('Hello World'); }); server.listen(8000, '127.0.0.1'); oczekiwanie na zdarzenie request kod obsługi zdarzenia wysyłający odpowiednie nagłówki do klienta HTTP oraz wysyłający odpowiednią wiadomość C10K problem 10k połączeń na jednym rdzeniu
  • 14. Node.JS - webserver “hello world” var http = require('http'); var server = new http.Server(); server.on('request', function (req, res) { res.writeHead( 200, {'Content-Type':'text/plain'} ); res.end('Hello World'); }); server.listen(8000, '127.0.0.1'); oczekiwanie na zdarzenie request kod obsługi zdarzenia wysyłający odpowiednie nagłówki do klienta HTTP oraz wysyłający odpowiednią wiadomość C10K problem 10k połączeń na jednym rdzeniu
  • 15. Zróbmy to w PHP!bo w czym problem?
  • 16. <?php $server = stream_socket_server('tcp://127.0.0.1:8000'); while ($conn = stream_socket_accept($server, -1)) { fwrite($conn, "HTTP/1.1 200 OKrn"); fwrite($conn, "Content-Length: 3rnrn"); fwrite($conn, "Hi PHPersn"); fclose($conn); } $ curl 127.0.0.1:8000 -v > GET / HTTP/1.1 > Host: 127.0.0.1:8000 < HTTP/1.1 200 OK Hi PHPers
  • 17. <?php $server = stream_socket_server('tcp://127.0.0.1:8000'); while ($conn = stream_socket_accept($server, -1)) { fwrite($conn, "HTTP/1.1 200 OKrn"); fwrite($conn, "Content-Length: 3rnrn"); fwrite($conn, "Hi PHPersn"); fclose($conn); } BLOCKING IO
  • 18. <?php $server = stream_socket_server('tcp://127.0.0.1:8000'); while ($conn = stream_socket_accept($server, -1)) { fwrite($conn, "HTTP/1.1 200 OKrn"); fwrite($conn, "Content-Length: 3rnrn"); fwrite($conn, "Hi PHPersn"); fclose($conn); } BLOCKING IO NON-BLOCKING IO // If mode is 0, the given stream will be switched to non-blocking mode bool stream_set_blocking ( resource $stream , int $mode ) int stream_select ( array &$read , array &$write , array &$except , int $tv_sec [, int $tv_usec = 0 ] )
  • 19. $readable = $read ?: null; $writable = $write ?: null; $except = null; if (stream_select($readable, $writable, $except, 1)) { if ($readable) { foreach ($readable as $stream) { /* code */ } } if ($writable) { foreach ($writable as $stream) { /* code */ } } } Pooling IO
  • 20. tablica streamów do odczytu tablica streamów do zapisu streamy “faworyzowane” Pooling IOPooling IO $readable = $read ?: null; $writable = $write ?: null; $except = null; if (stream_select($readable, $writable, $except, 1)) { if ($readable) { foreach ($readable as $stream) { /* code */ } } if ($writable) { foreach ($writable as $stream) { /* code */ } } }
  • 22. EVENT LOOP ➜ Zarządzanie streamami ➜ Ustawianie timerów jednorazowych i cyklicznych ➜ Ustawianie nextTicków i futureTicków ➜ Maksymalna czas zwłoki (timeout) może być zdefiniowany ➜ Jeżeli nie ma dalszych ticków, timerów lub streamów do obsłużenia - event loop kończy pracę
  • 23.
  • 24.
  • 25. Event Loop: Istnieje kilka implementacji z docelowymi backendami: ● StreamSelectLoop - stream_select ● LibEventLoop - libevent pecl extension ● LibEvLoop - libev pecl extension (najszybszy) ● może kiedyś LibUV :)
  • 26. Demultiplexer: oczekuje na eventy dla zasobów np. nowe połączenie i powiadamia dispatcher, po czym przechodzi do dalszego nasłuchiwania.
  • 27. Dispatcher: Komponent służący do rejestracji obsługi zdarzeń. Odbiera synchronicznie event z demultiplexera i wybiera właściwy event handler, który następnie uruchamia.
  • 28. Obsługa zdarzeń: Event Handler który obsługuje przekierowane do niego zdarzenie. Jest to po prostu jeden ze zdefiniowanych wcześniej callbacków.
  • 29. Zasoby: Czyli tutaj mamy wszystkie streamy które chcemy obsługiwać. Mogą to być także procesy czy np. uchwyty do plików.
  • 31. Instalacja z wykorzystaniem composera curl -sS https://getcomposer.org/installer | php php composer.phar require react/react
  • 32. require 'vendor/autoload.php'; $loop = ReactEventLoopFactory::create(); $socket = new ReactSocketServer($loop); $http = new ReactHttpServer($socket, $loop); $http->on('request', function ($request, $response) { $response->writeHead(200, ['Content-Type' => 'text/plain']); $response->end("Hi Phpersn"); }); $socket->listen(8000); $loop->run();
  • 34. EVENT LOOP STREAM TICKS SOCKET HTTP TIMER CHILD PROCESSFILESYSTEM PROMISES Ticki umożliwiają wykonywanie określonych funkcji w ramach Event Loopa. Dzielą się na $loop- >nextTick($callback) i $loop->futureTick($callback) . Pierwszy jest wykonywany zawsze na początku każdej iteracji loopa, wykonywanie drugiego jest zawsze oddelegowane jako ostatnia operacja w ramach iteracji. Hint: zakolejkowane futureTicki nie będą wykonywane jeśli Event Loop nie ma więcej zadań. NextTicki uzupełniają Event Loop nowymi zadaniami.
  • 35. EVENT LOOP STREAM TICKS SOCKET HTTP TIMER CHILD PROCESSFILESYSTEM PROMISES Funkcja odmierzania czasu wykonywana w ramach Event Loop w kolejności zaraz po nextTicku. ● $loop->addTimer- jednorazowe wykonanie funkcji po upływie czasu (jak setTimeout) ● $loop->addPeriodicTimer- wykonuje funkcje cyklicznie (jak setInterval) ● $loop->cancelTimer - zatrzymje timer ● $loop->isTimerActive- sprawdza stan działania timera Hint: nie polegaj na czasie odmierzanym przez timery w 100% ponieważ operacje przetwarzane w Event Loop mogą zablokować je na jakiś czas wynikający z bieżących działań.
  • 36. STREAM SOCKET HTTP CHILD PROCESSFILESYSTEM PROMISES ● Opakowuje natywny zasób stream. ● Rejestrowane w ramach Event Loop’a. ● Stream do odczytu i zapisu (ReadableStream / WriteableStream) ● Potkowość (ang. pipeline). WriteableStream może być ze sobą łączone, więc wyjście jednego jest wejściem drugiego. ● Dane wczytywane / zapisywane do streamów są buforowane Klasy Funkcjonalne: CompositeStream- łączy streamy do odczytu i zapisu łącząc obydwie funkcjonalności ThroughStream- umożliwia modyfikacje danch które stream zawiera - filtrowanie. BufferedSink - konwertuje WriteableStreamdo Promise STREAM
  • 37. STREAM SOCKET HTTP CHILD PROCESSFILESYSTEM PROMISES Dla funkcji asynchronicznych umożliwia natychmiastowy zwrot wartości, a raczej pewnej zaliczki tej wartości. Przykład - zamiana hosta na ip: $factory = new ReactDnsResolverFactory(); $dns = $factory->create('8.8.8.8', $loop); $dns->resolve('igor.io')->then(function ($ip) { echo "Host: $ipn"; }); PROMISE
  • 38. STREAM SOCKET HTTP CHILD PROCESSFILESYSTEM PROMISES Komponent sieciowy umożliwiający tworzenie serwerów nasłuchujących nowych połączeń oraz przetwarzających dane połączonych klientów. $socket = new ReactSocketServer($loop); $socket->on('connection', function ($conn) { $conn->on('data', function ($data, $conn) { $conn->write($data); }); }); $socket->listen(1337); SOCKET
  • 40. Websockety - zalety ➜ Wsparcie we wszystkich wiodących przeglądarkach (> IE8) ➜ Dwukierunkowość komunikacji ➜ Niezależnie wysyłanie wiadomości ➜ Protokół oparty na HTTP ➜ Niewielki rozmiar pojedynczego pakietu danych
  • 41. WebsocketAPI - interfejs kliencki JavaScript var websocket = new WebSocket('ws://localhost:8000' ); websocket.onopen = function(evt) {}; websocket.onclose = function(evt) {}; websocket.onmessage = function(evt) {}; websocket.onerror = function(evt) {};
  • 43. class WS implements MessageComponentInterface { function onOpen(ConnectionInterface $conn) {} function onClose(ConnectionInterface $conn) {} function onError(ConnectionInterface $conn, Exception $e) {} function onMessage(ConnectionInterface $from, $msg) { $from->send($msg); } } $server = IoServer::factory( new HttpServer(new WsServer(new WS())), 3000 ); $server->run();
  • 44. The Web Application Messaging Protocol
  • 45. The Bigger The Better ➜ Remote Procedure Calls (RPC) ➜ Publish & Subscribe ➜ Autobahn.JS ➜ integracja ZeroMQ ➜ integracja Redis
  • 46. Autobahn.JS? // dla wersji AUTOBAHNJS_VERSION="0.7.1" var session = new ab.Session( "ws://127.0.0.1:3000", function () { // zostaliśmy połączeni }, function () { // zostaliśmy rozłączeni }, { 'skipSubprotocolCheck': true, 'maxRetries': 5, 'retryDelay': 2000 } ); session.subscribe("http://phpers.pl/event/message", callback);
  • 47. class WAMP implements RatchetWampWampServerInterface { public function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible) {} public function onCall(ConnectionInterface $conn, $id, $topic, array $params) {} public function onSubscribe(ConnectionInterface $conn, $topic) {} public function onUnSubscribe(ConnectionInterface $conn, $topic) {} public function onOpen(ConnectionInterface $conn) {} public function onClose(ConnectionInterface $conn) {} public function onError(ConnectionInterface $conn, Exception $e) {} } $server = RatchetServerIoServer::factory( new HttpServer(new WsServer(new WampServer(new WAMP()))), 3000 ); $server->run(); Ratchet + WAMP
  • 48. $loop = ReactEventLoopFactory::create(); $pusher = new WAMP; $context = new ReactZMQContext($loop); $pull = $context->getSocket(ZMQ::SOCKET_PULL); $pull->bind('tcp://127.0.0.1:5555'); $pull->on('message', array($pusher, 'onQueueAdded')); $socket = new ReactSocketServer($loop); $socket->listen(3000, '0.0.0.0'); $webServer = new IoServer( new HttpServer(new WsServer(new WampServer($pusher))), $socket ); $loop->run(); ZeroMQ + Ratchet
  • 49. ZeroMQ + Ratchet $loop = ReactEventLoopFactory::create(); $pusher = new WAMP; $context = new ReactZMQContext($loop); $pull = $context->getSocket(ZMQ::SOCKET_PULL); $pull->bind('tcp://127.0.0.1:5555'); $pull->on('message', array($pusher, 'onQueueAdded')); $socket = new ReactSocketServer($loop); $socket->listen(3000, '0.0.0.0'); $webServer = new IoServer( new HttpServer(new WsServer(new WampServer($pusher))), $socket ); $loop->run(); $context = new ZMQContext(); $socket = $context->getSocket( ZMQ::SOCKET_PUSH, 'websocket' ); $socket->connect('tcp://127.0.0.1:5555'); $socket->send($payloadAsJSON);
  • 50. ZeroMQ + Ratchet $loop = ReactEventLoopFactory::create(); $pusher = new WAMP; $context = new ReactZMQContext($loop); $pull = $context->getSocket(ZMQ::SOCKET_PULL); $pull->bind('tcp://127.0.0.1:5555'); $pull->on('message', array($pusher, 'onQueueAdded')); $socket = new ReactSocketServer($loop); $socket->listen(3000, '0.0.0.0'); $webServer = new IoServer( new HttpServer(new WsServer(new WampServer($pusher))), $socket ); $loop->run(); $context = new ZMQContext(); $socket = $context->getSocket( ZMQ::SOCKET_PUSH, 'websocket' ); $socket->connect('tcp://127.0.0.1:5555'); $socket->send($payloadAsJSON); public function onQueueAdded($payload) { $payloadData = json_decode($payload, true); // dalsze przetwarzanie }
  • 51. MAO? ➜ WAMP2 ➜ voryx/Thruway (kompatybilny z nowym Autobahn.JS) ➜ bixuehujin/reactphp-mysql ➜ DNode ➜ STOMP ➜ AR.Drone ➜ Whois ➜ Childprocess
  • 53. Odniesienia i inspiracje ➜ http://blog.wyrihaximus.net/categories/reactphp/ ➜ Presentation theme - SlidesCarnival ➜ Zdjęcia - Death to the Stock Photo ➜ http://www.slideshare. net/SteveRhoades2/asynchronous-php-and-realtime- messaging ➜ https://speakerdeck.com/jmikola/async-php-with-react ➜ https://speakerdeck.com/igorw/react-phpnw