Upload
stanislav-zozulja
View
73
Download
2
Embed Size (px)
Citation preview
Stas [email protected]
Real-Time Web applications with WebSockets
About me
● WEB developer since 2009
● Symfony developer at SmartGamma since 2013
● https://github.com/stas-zozulja
● https://www.facebook.com/stas.zozulja
Real-Time Web applications with Websocket
Real-Time Web applications with Websocket
Agenda
● What is Real-Time Web?● Transport mechanisms● Real-Time in PHP (Ratchet)● && everywhere (Pushpin)
What is Real-Time ?
https://www.leggetter.co.uk/2016/04/22/what-is-realtime.html
● Hard real-time- missed deadline?
System fault● Firm real-time
- missed? Result is zero
● Soft real-time- missed?
quality degrades
it's all about deadline
and Real-Time Web?Server pushes a data to Clients when some event occurs, while Clients does not need to poll a server for new data.
it's all about Push
https://www.leggetter.co.uk/2016/04/22/what-is-realtime.html
Do I need real-time?YES! You do!
● Better UX - instant data updates● Chatting, notification, signaling● Activity streams● Data visualization● User collaboration
Transport mechanisms
● Long polling● HTTP streaming● WebSockets
Long pollingDelayed HTTP request. After response (or timeout) new request is opening by client.
● Uni-directional● Overhead
(headers in each request)
HTTP StreamingRequest that never ends, response content is
chunked in portions, usually JSON. Only one direction.
WebSocket protocolProtocol providing bidirectional communication channel over a single TCP connection.
WebSocket handshakeRequest:GET /chat HTTP/1.1Host: ws.example.com:8080/chatSec-WebSocket-Version: 13Sec-WebSocket-Key: T6IDGBEmb...Connection: UpgradeUpgrade: websocket
Response:HTTP/1.1 101 Switching protocolsConnection: UpgradeSec-WebSocket-Accept: xTComwY...Upgrade: websocketX-Powered-By: Ratchet/0.3.4
ws:// wss://
https://tools.ietf.org/html/rfc6455http://caniuse.com/#feat=websockets
Support:● IE 10+● FF 6+● Chrome 14+● iOS 4.2+● Android 4.4+● Safari 5+
Our context● Live streaming app● REST API for mobile clients (iOS, Android)● WEB part● Build Real-time counter of viewers
or
Ratchet - WebSockets for PHP
http://socketo.me/
Built on top of ReactPHP
Components:● I/O (socket transport) – IOServer● HTTP Protocol handler – HTTPServer● WebSocket Protocol Handler – WSServer● SessionProvider – Symfony Session● WAMP Protocol Handler – WampServer
+● Your Application
MessageComponentInterface implementationhttp://reactphp.org/
& Step 1. Implement MessageComponentInterface
& Step 2. onMessage()
& Step 3. Write Console command that runs a server
& Next steps. WAMP Subprotocol.● WAMP – Web Application Messaging
Protocol.● RPC and Pub/Sub patterns● Autobahn client libraries
http://wamp-proto.org/http://autobahn.ws/
&
Cons● Horizontally scaling is hard
need to share a Connections between nodes● One exception can stop whole server
Use supervisord, try...catch, test Your code
Pros● Its PHP!● Easy to implement and use existing code
https://www.leggetter.co.uk/real-time-web-technologies-guide/
j.mp/realtime-tech-guide
https://fanout.io/
Pushpina reverse proxy for the real-time Web
http://pushpin.org/
● Pub/Sub● Long polling, HTTP Streaming or WebSockets● Works with any backend● Your API can be real-time with HTTP streaming● WebSocket over HTTP – what? :)
https://fanout.io/
Pushpin installation
Debian, Ubuntu:sudo apt-get install pushpinsudo service pushpin start
http://pushpin.org/docs/#install
MacOS X:brew install pushpinpushpin
Pushpin configuration
routes config file:* localhost:80,over_http
● route all connections from Pushpin to your backend
● over_http option to enable WebSocket-over-HTTP protocol
https://github.com/fanout/pushpin/wikihttps://github.com/fanout/pushpin/blob/master/docs/websocket-over-http.md
WebSocket-over-HTTP (GRIP protocol)
Pushpin encodes WebSocket events into a regular HTTP requests and passes them to your backend.
Events are:OPEN – opening WebSocket connection messageTEXT, BINARY – content messagesPING, PONG – ping/pong messagesCLOSE - Close message with 16-bit close codeDISCONNECT - Indicates connection closed uncleanly
1. From client to Pushpin (port 7999):GET /chat HTTP/1.1Sec-WebSocket-Version: 13Sec-WebSocket-Key: T6IDGBEmb...Connection: UpgradeUpgrade: websocket
2. From Pushpin to backend:POST /chat HTTP/1.1Sec-WebSocket-Extensions: gripContent-Type: application/websocket-eventsAccept: application/websocket-events
OPEN\r\n
2. Response:HTTP/1.1 200 OKSec-WebSocket-Extensions: gripContent-Type: application/websocket-events
OPEN\r\n
WebSocket over HTTP connection flow
3. Form Pushpin to client:HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: s3pPLMBi...Sec-WebSocket-Extensions: grip
1. From client to Pushpin (port 7999)://sending messageWebSocket.send(“Hello there! I’m client!”);
2. From Pushpin to backend:POST /chat HTTP/1.1Sec-WebSocket-Extensions: gripContent-Type: application/websocket-eventsAccept: application/websocket-events
TEXT 18\r\nHello there! I’m client!
2. Response:HTTP/1.1 200 OKSec-WebSocket-Extensions: gripContent-Type: application/websocket-events
TEXT 12\r\nHello! I’m server!TEXT 2F\r\nc:{"type": "subscribe", "channel": "mychannel"}\r\n
WebSocket over HTTP message flow
3. On client://receiving messageWebSocket.onMesssage(event) …
//event.data is “Hello! I’m server!”
Publish\Subscribe. Control messages.
Formatted as a JSON object following the c: prefix. The object has a type field that indicates the type of control message.
● subscribe: Subscribe connection to the channel specified by the channel field.
● unsubscribe: Unsubscribe connection from the channel specified by the channel field.
● detach: Terminate the session between Pushpin and the origin server, but retain the connection between the client and
http://pushpin.org/docs/#websockets
Examples:c:{"type": "subscribe", "channel": "test"}c:{"type": "unsubscribe", "channel": "test"}
Prefix c: is configurable
Publish data to a channel
POST request to a Pushpin’s internal publish port (5561 by default)
curl -d '{"items": [
{ "channel": "test", "formats": {
"ws-message": {"content": "hello there\
n"}
} } ]}' http://localhost:5561/publish/
1. From client to Pushpin:GET /chat HTTP/1.1Sec-WebSocket-Version: 13Sec-WebSocket-Key: T6IDGBEmb...Connection: UpgradeUpgrade: websocket
2. Request:POST /chat HTTP/1.1Sec-WebSocket-Extensions: gripContent-Type:
application/websocket-eventsAccept:
application/websocket-events
OPEN\r\n
2. Response:HTTP/1.1 200 OKSec-WebSocket-Extensions: gripContent-Type:
application/websocket-events
OPEN\r\n
So, all we need is to handle Requests from Pushpinin our application. A GOOD job for Symfony, isn't it?
3. Form Pushpin to client:HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: s3pPLMBi...Sec-WebSocket-Extensions: grip
PHP Library to work with Pushpin on server sidecomposer require fanout/gripcontrol
https://github.com/fanout/php-gripcontrol
Publishing from PHP
https://github.com/fanout/php-gripcontrol
Symfony Bundle
https://github.com/smart-gamma/pushpin-bundle
&
Features
● Works with WebSocket-over-HTTP Requests from Pushpin
● TEXT events deserialization into DTOs (events) specified by your configuration
● Handling WebSocketEvent with your specific handler
● Pushpin helpers to publishing to a channel, subscribing, detaching etc.
Live Demo&
http://ws-chat.smart-gamma.com
https://github.com/smart-gamma/simple-chat-demo
Symfony Bundle
$ composer require gamma/pushpin-bundle
# config.ymlgamma_pushpin:
proxy: control_uri: 'http://localhost:5561/'
web_socket: json_events: base_namespace: 'Domain\WebsocketEvents' mappings: chatMessage: class: 'Chat\ChatMessage' chatRoomEnter: class: 'Chat\ChatRoomEnter' chatRoomLeave: class: 'Chat\ChatRoomLeave'
&
Simple DTO object to hold event data&
Implement handler service for your event&
Controller to handle requests from Pushpin&
Test with wscat utility&
&
http://blog.fanout.io/2013/10/30/pushing-to-100000-api-clients-simultaneously/
Pros● It’s still PHP!● No need to run
long lived processes at backend● With HTTP Streaming You can
make a real-time API● Horizontally scalable
Cons● If you have multi nodes,
pushes should be sent to all Pushpin instances
● More HTTP requests to your application
● Push can be sent only to a channel
Load testing with thor utility
Thank You!