Real-Time Web applications with WebSockets
- 2. About me
● WEB developer since 2009
● Symfony developer at SmartGamma
since 2013
● https://github.com/stas-zozulja
● https://www.facebook.com/stas.zozulj
a
Real-Time Web applications with Websocket
- 3. Real-Time Web applications with Websocket
Agenda
● What is Real-Time Web?
● Transport mechanisms
● Real-Time in PHP (Ratchet)
● && everywhere (Pushpin)
- 4. 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
- 5. 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
- 6. Do I need real-time?
YES! You do!
● Better UX - instant data updates
● Chatting, notification, signaling
● Activity streams
● Data visualization
● User collaboration
- 8. Long polling
Delayed HTTP request. After response (or timeout)
new request is opening by client.
● Uni-directional
● Overhead
(headers in each request)
- 11. WebSocket handshake
Request:
GET /chat HTTP/1.1
Host: ws.example.com:8080/chat
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: T6IDGBEmb...
Connection: Upgrade
Upgrade: websocket
Response:
HTTP/1.1 101 Switching protocols
Connection: Upgrade
Sec-WebSocket-Accept: xTComwY...
Upgrade: websocket
X-Powered-By: Ratchet/0.3.4
ws://
wss://
https://tools.ietf.org/html/rfc6455
http://caniuse.com/#feat=websockets
Support:
● IE 10+
● FF 6+
● Chrome 14+
● iOS 4.2+
● Android 4.4+
● Safari 5+
- 12. Our context
● Live streaming app
● REST API for mobile clients (iOS, Android)
● WEB part
● Build Real-time counter of viewers
or
- 13. 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 implementation
http://reactphp.org/
- 14. & Step 1. Implement MessageComponentInterface
- 16. & Step 3. Write Console command that runs a server
- 17. & Next steps. WAMP Subprotocol.
● WAMP – Web Application Messaging
Protocol.
● RPC and Pub/Sub patterns
● Autobahn client libraries
http://wamp-proto.org/
http://autobahn.ws/
- 18. &
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
- 21. Pushpin
a 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/
- 23. 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/wiki
https://github.com/fanout/pushpin/blob/master/docs/websocket-over-http.md
- 24. 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 message
TEXT, BINARY – content messages
PING, PONG – ping/pong messages
CLOSE - Close message with 16-bit close code
DISCONNECT - Indicates connection closed uncleanly
- 25. 1. From client to Pushpin (port 7999):
GET /chat HTTP/1.1
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: T6IDGBEmb...
Connection: Upgrade
Upgrade: websocket
2. From Pushpin to backend:
POST /chat HTTP/1.1
Sec-WebSocket-Extensions: grip
Content-Type:
application/websocket-events
Accept:
application/websocket-events
OPENrn
2. Response:
HTTP/1.1 200 OK
Sec-WebSocket-Extensions: grip
Content-Type:
application/websocket-events
OPENrn
WebSocket over HTTP connection flow
3. Form Pushpin to client:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBi...
Sec-WebSocket-Extensions: grip
- 26. 1. From client to Pushpin (port 7999):
//sending message
WebSocket.send(“Hello there! I’m client!”);
2. From Pushpin to backend:
POST /chat HTTP/1.1
Sec-WebSocket-Extensions: grip
Content-Type:
application/websocket-events
Accept:
application/websocket-events
TEXT 18rn
Hello there! I’m client!
2. Response:
HTTP/1.1 200 OK
Sec-WebSocket-Extensions: grip
Content-Type:
application/websocket-events
TEXT 12rn
Hello! I’m server!
TEXT 2Frn
c:{"type": "subscribe", "channel":
"mychannel"}rn
WebSocket over HTTP message flow
3. On client:
//receiving message
WebSocket.onMesssage(event) …
//event.data is “Hello! I’m server!”
- 27. PublishSubscribe. 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
- 28. 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
theren"
}
}
}
]
}' http://localhost:5561/publish/
- 29. 1. From client to Pushpin:
GET /chat HTTP/1.1
Sec-WebSocket-Version: 13
Sec-WebSocket-Key:
T6IDGBEmb...
Connection: Upgrade
Upgrade: websocket
2. Request:
POST /chat HTTP/1.1
Sec-WebSocket-Extensions: grip
Content-Type:
application/websocket-
events
Accept:
application/websocket-
events
OPENrn
2. Response:
HTTP/1.1 200 OK
Sec-WebSocket-Extensions: grip
Content-Type:
application/websocket-
events
OPENrn
So, all we need is to handle Requests from Pushpin
in our application. A GOOD job for Symfony, isn't it?
3. Form Pushpin to client:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBi...
Sec-WebSocket-Extensions: grip
- 30. PHP Library to work with Pushpin on server side
composer require fanout/gripcontrol
https://github.com/fanout/php-
gripcontrol
- 34. Symfony Bundle
$ composer require gamma/pushpin-bundle
# config.yml
gamma_pushpin:
proxy:
control_uri: 'http://localhost:5561/'
web_socket:
json_events:
base_namespace: 'DomainWebsocketEvents'
mappings:
chatMessage:
class: 'ChatChatMessage'
chatRoomEnter:
class: 'ChatChatRoomEnter'
chatRoomLeave:
class: 'ChatChatRoomLeave'
&