問題タブ [eventsource]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
node.js - Websocket トランスポートの信頼性 (再接続中の Socket.io データ損失)
使用済み
NodeJS、Socket.io
問題
U1とU2という 2 人のユーザーがいて、Socket.io 経由でアプリに接続されているとします。アルゴリズムは次のとおりです。
- U1がインターネット接続を完全に失う (例: インターネットをオフにする)
- U2はU1にメッセージを送信します。
- インターネットがダウンしているため、 U1はまだメッセージを受信していません
- サーバがハートビートタイムアウトによりU1切断を検出
- U1は socket.io に再接続します
- U1はU2からメッセージを受信しません。ステップ 4 でメッセージが失われていると思います。
考えられる説明
なぜそれが起こるのか理解していると思います:
- on ステップ 4サーバーはソケット インスタンスとU1へのメッセージのキューも削除します
- さらに、ステップ 5 でU1とサーバーは新しい接続を作成します (再利用されません)。そのため、メッセージがまだキューに入れられていても、以前の接続はとにかく失われます。
助けが必要
この種のデータ損失を防ぐにはどうすればよいですか? 私は人々が永遠にアプリにハングアップするわけではないので、ハートビートを使用する必要があります。また、アプリの新しいバージョンをデプロイするときにダウンタイムをゼロにしたいので、再接続する可能性を引き続き与える必要があります。
PS私が「メッセージ」と呼ぶものは、データベースに保存できる単なるテキストメッセージではなく、配信を保証する必要がある貴重なシステムメッセージです。そうしないと、UIが台無しになります。
ありがとう!
追加1
私はすでにユーザー アカウント システムを持っています。さらに、私のアプリケーションはすでに複雑です。私はすでにこの種のものを持っているので、オフライン/オンラインのステータスを追加しても役に立ちません。問題は異なります。
ステップ 2 を確認してください。このステップでは、U1 がオフラインになるかどうかを技術的に判断することはできません。おそらく、インターネットの状態が悪いために、U1 が 2 秒間接続を失っただけです。したがって、U2 は彼にメッセージを送信しますが、U1 はインターネットがまだダウンしているため、メッセージを受信しません (ステップ 3)。ステップ 4 は、オフライン ユーザーを検出するために必要です。たとえば、タイムアウトは 60 秒です。最終的に、さらに 10 秒後に U1 のインターネット接続が確立され、彼は socket.io に再接続します。しかし、サーバー上で U1 がタイムアウトにより切断されたため、U2 からのメッセージは空間で失われます。
それが問題です。私は 100% 配信したくありません。
解決
- {} ユーザーのエミット (エミット名とデータ) を収集します。ランダムなemitID で識別されます。送信する
- クライアント側でエミットを確認します(emitIDでエミットをサーバーに送り返します)
- 確認された場合 - emitID で識別される {} からオブジェクトを削除します
- ユーザーが再接続した場合 - このユーザーの {} を確認し、{} 内の各オブジェクトに対してステップ 1 を実行してループします。
- 切断または/および接続時に、必要に応じてユーザーの {} をフラッシュします
解決策2(ちょっと)
2020 年 2 月 1 日追加。
これは実際には Websocket のソリューションではありませんが、それでも便利だと思う人がいるかもしれません。Websockets から SSE + Ajax に移行しました。SSE を使用すると、クライアントから接続して永続的な TCP 接続を維持し、サーバーからリアルタイムでメッセージを受信できます。クライアントからサーバーにメッセージを送信するには、単純に Ajax を使用します。レイテンシーやオーバーヘッドなどのデメリットはありますが、SSEはTCP接続なので信頼性を保証します。
Express を使用しているため、SSE にはこのライブラリhttps://github.com/dpskvn/express-sseを使用しますが、自分に合ったものを選択できます。
SSE は IE およびほとんどの Edge バージョンではサポートされていないため、 https ://github.com/Yaffle/EventSource というポリフィルが必要になります。
javascript - SSE イベントソースの確認を取得する方法
このコードを使用して、ブラウザ クライアントに SSE メッセージを送信しています。
https://nodejs.org/api/http.html#http_response_write_chunk_encoding_callback
ノードサーバー
クライアントには、次の JavaScript を使用しています。
すべてが正常に動作していますが、クライアントが実際に受信したことをサーバーがどのように確認するのでしょうか? SSE は TCP を使用していると思いますが、承認を受け取る方法はありますか?
ruby-on-rails - javascript スロットル/デバウンス関数に似た Rails/Ruby メソッドを作成する方法
このアプリケーションでは、ヒットする外部サービスのコールバック ルートを公開します。コールバックを受け取ると、クライアント/ブラウザー側で Eventsource を使用し、サーバー側で cramp を使用して、クライアント側サブスクライバーに更新を公開します。ただし、この外部サービスから大量のコールバック リクエストが殺到し、大量の更新をクライアントに公開することもあります。メッセージを公開するために受け取ったコールバックの間に設定された時間待機する、JavaScriptのデバウンス関数に似たRails側の方法はありますか?
既に sidekiq + スレッドを使用しているため、これらのツールを使用した提案を受け付けています。
php - PHP ストリーム ソケットと eventSource の組み合わせ
私は PHP のソケットについて学ぼうとしていますが、たくさん読んだ結果、stream_socket_server()
.
以下のようなコードを使用して、Linux の 2 つの端末間で基本的なチャットを行いました。次のステップは、Web 上にチャットまたは通知システムを構築することです。
私が期待したこと:
eventSource.html のイベント リスナーは、while ループでイベントをリッスンし、server.php を実行している Linux 端末から受信したメッセージを出力します。
何が起こっている:
eventSource.html の観点からは、すべて正常に機能しています。したがって、この目的全体を取り除き、メッセージを標準の文字列に置き換えるだけで、毎秒正常にHello World
出力されます。<li>message:{Hello World}</li>
<li>message: {}</li>
ただし、端末からデータを読み込もうとすると、毎秒以外は何も表示されません。server.php を実行するとクライアントを待機し、次に eventSource.html を実行すると正常に接続されることに注意してください。
これがどのように機能するかを誤解していますか?while ループでは 1 秒ごとにそのストリーム内のデータを探すと想定しました。
それとも、ソケットの学習に関して完全に間違った道を進んでいますか。
server.php (Linux のターミナルからロードします)
client.php は以下の eventSource.html から読み込まれます
eventSource.html
json - EventSource を使用した Server Sent Events (SSE) は、POST でパラメーターを渡すことができますか
Html5 Server Sent Events を使用しています。サーバー側は Java Servlet です。サーバーに渡したいjson配列データがあります。
配列のサイズが小さい場合、サーバー側はクエリ文字列を取得できます。ただし、配列のサイズが大きい場合。(おそらく数千文字以上)、サーバーはクエリ文字列を取得できません。POST メソッドを使用しnew EventSource(...)
て、クエリ文字列の長さの制限を回避できるサーバーに json 配列を渡すことは可能ですか?