Estoy seguro de que todos los desarrolladores web se han enfrentado a la tarea de actualizar rápidamente la interfaz de usuario WEB por evento en el back-end. Un ejemplo clásico es un chat en la web (si ya ha escrito su fuego chat en la web, se puede saltar de seguir leyendo, más probable es que ya sabe todo lo de abajo).
En X5, encuentro este tipo de tareas con una frecuencia envidiable. Debo decir que todo tipo de chats, chatbots y otras interacciones de usuario final en tiempo real son tendencia ahora. En este artículo, quiero resumir mi experiencia en este asunto y compartirla con los lectores de Habr.
Formulación del problema
Necesitamos un transporte universal y eficiente para entregar eventos desde la interfaz de usuario WEB (navegador del usuario) al servidor y de regreso desde el servidor a la interfaz de usuario WEB.
Opción # 1 - ENCUESTAS PERIÓDICAS
la forma más fácil e ineficaz
El significado es claro por el nombre, desde el lado de Client2 periódicamente, por ejemplo, una vez cada 1 segundo, solicitudes como "¿Qué estás haciendo?" Se envían al servidor.
Este enfoque tiene dos inconvenientes importantes:
1-10 , , 1-10 , , , . , , 1-10 RPS.
— RealTime. , RealTime.
№2 -
long polling
№1, , , http-, (.. ), , , . , . , TimeOut
, , .
:
, .. http-, , , .
RealTime, .. , . , http . , , .. .
- №1.
№3 - SERVER SENT EVENT (SSE)
+ API
Server-Sent Events EventSource, . , EventSource . . , retry: ( )
!!! – !
, , , .
. , SSE , REST. http-. , , 1-10 ( ), - №1 :(, , , .
– . , . , , .
№4 - WEBSOCKET
WEBSOCKET SSE . SSE WEBSOCKET.
WEBSOCKET |
SSE |
: , |
: |
|
|
WebSocket |
HTTP |
FrontEnd <-> BackEnd Websocket Golang.
?
№1 - web- ( , app ..):
FrontEnd BackEnd (WS)
BackEnd (WS)
FrontEnd . (REST) (, )
3- .2, , .
2 - () , ,
BackEnd (WS)
FrontEnd (WS)
( )
:
(http://your_domain/ws)
Go «HUB»,
http http://your_domain/ws :
Go ( , ws )
http ws “CLIENT_CONNECTED”
// Message ...
type Message struct {
Type string `json:"type,omitempty"`
Event string `json:"event"`
Data string `json:"data"`
}
Event –
Data –
Type –
Type = publish, Data , Event
Type = broadcast, Data
Type = subscribe, , Event
Type = unsubscribe, , Event
-
. , MacBook Pro i5 8Gb 12K RPS
- . . .
SDK:
- , , .
– , SDK .
sdk :
<script src="http://localhost:9000/sdk/js" async onload="initEventTube()"></script>
localhost:9000 –
:
function initEventTube(){
var options={
connection:{
host:'localhost',
port:'9000'
}
}
var eventTube=new EventTube(options);
window.EventTube=eventTube;
window.EventTube.connect();
}
:
var self=this;
var subscriptionId=null;
window.EventTube.sub('YOUR_EVENT_NAME',function(data){
//
console.log(data);
}).then(function(subId){
//
subscriptionId = subId;
onsole.log('subId:',subId);
},function(err){
//
console.log(err);
});
:
window.EventTube.pub('YOUR_EVENT_NAME', 'YOUR_EVENT_DATA');
:
window.EventTube.unsub('YOUR_EVENT_NAME', 'OPTIONAL_SUB_ID');
. OPTIONAL_SUB_ID, , , . SUB_ID (. « »)
:
$ git clone git@github.com:colber/eventtube-server.git your_dir
$ cd your_dir
$ go run main.go
Docker
$ docker pull ptimofeev/eventtube:latest $ docker run --name eventtube --rm -p 9000:9000 ptimofeev/eventtube
: localhost:9000
$ git clone git@github.com:colber/eventtube-client.git your_dir
$ cd your_dir
$ yarn install
$ yarn serve
http://localhost:8080