Tenho certeza de que todo desenvolvedor web enfrentou a tarefa de atualização imediata da IU da WEB por evento no back-end. Um exemplo clássico é um bate-papo na web (se você já escreveu seu fogo web chat, você pode pular de ler mais, muito provavelmente você já sabe tudo abaixo).
No X5, encontro essas tarefas com uma frequência invejável. Devo dizer que todos os tipos de chats, chatbots e outras interações do usuário final do RealTime estão em alta agora. Neste artigo, quero resumir minha experiência neste assunto e compartilhá-la com os leitores de Habr.
Formulação do problema
Precisamos de um transporte universal e eficiente para entregar eventos da WEB UI (navegador do usuário) para o servidor e de volta do servidor para a WEB UI

Opção nº 1 - PESQUISAS PERIÓDICAS
a maneira mais fácil e ineficaz
O significado fica claro a partir do nome, do lado do Cliente2 periodicamente, por exemplo, uma vez a cada 1 segundo, solicitações como “O que há?” São enviadas ao servidor.

Essa abordagem tem duas desvantagens significativas:
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
- . . .
. js/sdk (6Kb) web-.
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 (. « »)
:
Golang . Golang
$ 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
