すべてのWeb開発者は、バックエンドのイベントごとにWEBUIを迅速に更新するという課題に直面していると確信しています。典型的な例はWebチャットです(Fire Webチャットを既に作成している場合は、さらに読むことをスキップできます。おそらく、以下のすべてをすでに知っているでしょう)。
X5では、うらやましい頻度でそのようなタスクに遭遇します。あらゆる種類のチャット、チャットボット、その他のリアルタイムのエンドユーザーとのやり取りが現在トレンドになっていると言わざるを得ません。この記事では、この問題に関する私の経験を要約し、Habrの読者と共有したいと思います。
問題の定式化
イベントをWEBUI(ユーザーのブラウザー)からサーバーに配信し、サーバーからWEB UIに戻すには、ユニバーサルで効率的なトランスポートが必要です。
オプション#1-定期的な調査
最も簡単で最も効果のない方法
名前から明らかな意味は、Client2側から定期的に、たとえば1秒に1回、「何をしているの?」などのリクエストがサーバーに送信されます。
このアプローチには2つの重大な欠点があります。
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