Socket.io: ページにフォーカスがないときに非アクティブであるため、SafariがWebソケット接続をドロップする

作成日 2017年04月25日  ·  26コメント  ·  ソース: socketio/socket.io

あなたはしたい:

  • [x]バグを報告する
  • []機能をリクエストする

現在の動作

これが既知の問題であるかどうかはわかりません(検索しようとしましたが、何も見つかりませんでした)。 Safari for Macは、ページ/タブにフォーカスがない場合、非アクティブ/アイドルのためにWebSocket接続をサイレントにドロップしているように見えます。

再現手順(現在の動作がバグの場合)

Safariのタブ/ページにフォーカスがないようにします。 WebSocketイベントをログに記録します。

期待される動作

WebSocketは、ハートビート機能を介して存続させる必要があります。 他のブラウザでこの動作が見られないので、私のコードではない可能性があります。

セットアップ

  • OS:Mac OSX 10.12.4(16E195)
  • ブラウザ:Safari 10.1(12603.1.30.0.34)
  • socket.ioバージョン:1.7.3

その他の情報(例:スタックトレース、関連する問題、修正方法の提案)

これはおそらく、ハートビートをオーバーライド/無視するある種の省電力機能ですか?

bug

最も参考になるコメント

これは、socket.ioの現在のバージョンがクライアント側のsetTimeoutに依存しているためだと思います。これは、期待したほど信頼性が低い可能性があります。

これは重大な変更であるため、v3に含めます。

関連: https

全てのコメント26件

DEBUG = *でサーバーを実行すると、次のように表示されます。
socket.io:client client close with reason ping timeout +0ms
socket.io:socket closing socket - reason ping timeout +0ms

これは、ソケットサーバーやクライアントインスタンスではなく、Safariが接続を閉じたことを意味すると思います。 しかし奇妙なことは、私はSafariが、時には1分後に約30秒再接続気づいたが、ページが焦点に持ち込まれるまで、他の回は、それが切断されていないと滞在ないことです。 このような一貫性のない動作でデバッグしようとすると、非常にイライラします。

時々それは散発的にずっと後で(10分のように)再接続するようです。 繰り返しますが、同一のテスト環境では完全に一貫性がありません。

@twistedpixel再接続の遅延は指数関数的です(つまり、 試行ソース)。これにより、動作が説明される場合があります。

ウィンドウが再びフォーカスを取得したときに強制的に再接続するのはどうですか?

window.addEventListener("focus", () => socket.connect());

https://github.com/primus/primus/issues/348に関連している可能性があり

情報をありがとうございますが、主な問題は、ユーザーが不在のときにアラートを送信するために使用されるため、Webソケットを永続的に接続する必要があることです。 したがって、再接続するためのウィンドウフォーカスは理想的ではありません。

とにかく、それは実際には私のマシン/インストールに固有のより問題のあるものだと思います。 もともとiMacでの動作に気付いたので、MacBookを新しいバージョンのSafariでワイプすることにしましたが、動作はまったく見られません。 タブを1日最小化したままにしましたが、一度も切断されませんでした。 したがって、iMacに戻ってすべてのインターネットプラグインを削除し、すべての拡張機能を無効にしようとしましたが、それでもこの動作が見られました。

Appleは、設定やその他の特定のファイルを削除する以外に、Safariを完全に再インストールする方法を提供していないようです。 または、機械を拭きます。 私の一部はただ新しく始めたいと思っていますが、私の開発者は原因が何であるかを知らないことを嫌います。

実際、指数関数的な再接続についてのあなたのポイントまで:確かに最初の再接続は、あなたが言うように、切断後約500msになるでしょう...それで、なぜサーバーはそれを無視するのでしょうか? 再接続を起動するのを妨げる何かがあるはずです。

切断イベントでsocket.connect()を固定すると、再び正常に接続されるため、少し奇妙です。 それは数分ごとにそれをしなければなりませんが、それでも必ずそうします。 だから私はなぜ再接続が起こらないのか完全に困惑しています! もう少し掘り下げて、その理由を理解できるかどうかを確認します。

残念ながら、これはデスクトップでも、今日の典型的なブラウザの動作です。

私は何が起こっているのか知っていると思います。 Safariは確かに問題です。

タブにフォーカスがない場合、すべてのブラウザでsetTimeout値とsetInterval値の上限が1000になると思います。 Safariは-愚か- 1000年にキャップをし、指数関数的に各反復の結果が二重に限り最後として取ることの遅延を追加するようなものを行います。 これが接続が切断される理由です。 socket.ioの内部タイムアウトが遅延/ドロップされており、再接続が必要なときに行われない理由を説明しています。

そのため、基本的に、Appleはいつものように穀物に反対することを決定し、その結果、ユーザーエクスペリエンスが低下しました。 最近は本当に上手です。

MacBookではなくiMacに影響している理由はわかりませんが(逆のことを期待していました)、テストを続けて、正確な理由を特定できるかどうかを確認します。

@twistedpixelそれはSafariだけではありません。 http://blog.strml.net/2017/01/chrome-56-now-aggressively-throttles.htmlを参照してください

Primusでは、ハートビートメッセージの方向を逆にすることで問題を回避しました(https://github.com/primus/primus/pull/534)。

@lpincaこの問題を理解しようとしている間ずっと、私は

@twistedpixel私のポイントは、おそらくEngine.IOでも同じことができるので、Primusに移行する必要がないということです。

FWIW、Safari Tech Previewは、追加のスロットルの影響を受けていないようです。 おそらくAppleは彼らの決定を覆した。 それはまだ1000msに抑制されていますが、それ以上何も追加されていないようです。

iOS 12Safariでも同じ問題が発生しています。 サファリを再度開くと、WebSocket接続が失われます。 ソケットを存続させるためのクリーンな回避策はありますか?

AFAIK iOS Safariは、Safariがバックグラウンドで実行されると(バッテリーの消耗を防ぐため)、特定のプロセスを一時停止します。WebSocket接続はほぼ確実にそのようなプロセスの1つです。 モバイルデバイスで回避策が見つかる可能性はほとんどありません。

OK。 しかし、onwindowfocusなどのイベントリスナーを追加した場合でも、再接続できますか?

誰かが回避策を実装しましたか? 私たちはオプションを見ることに興味があり、他の人がすでに実験しているのだろうかと思います

フォーカスイベントを使用するのではなく、 Page Visibility APIを使用して、モバイルアプリウィンドウがバックグラウンドになったことを検出する必要があります。

Azure SignalRの問題にぶつかり、現在Page Visibility APIを使用してページ非表示の接続を閉じ、ページが表示されたら再接続するという@techpeaceの提案のおかげで、タブをすばやく切り替えると問題が発生しました。複数のイベント。 現在、イベントのデバウンスを検討しています。また、Webで見られる一般的なアドバイスは、ユーザーエージェントの検出に基づくあらゆる種類の処理を思いとどまらせます。したがって、私の解決策は、ユーザーエージェントに関係なくページ可視性APIを使用することです。

ソリューション

pingTimeoutpingInterval値を変更して、これら3つのブラウザーすべてで数時間テストしました。 私が解決策であるとわかったもの:

  1. pingTimeout > = 30000ミリ秒の設定

    • または-

  2. pingInterval <= 10000ミリ秒の設定

pingTimeout = 30000変更するのが最善の解決策だと思います。 デフォルトのpingInterval25000 msであり、サーバーがクライアントにpingを実行する頻度を10秒ごとに増やすと、_atscale_プロジェクトではおしゃべりになりすぎる可能性があります。

これは、socket.ioの現在のバージョンがクライアント側のsetTimeoutに依存しているためだと思います。これは、期待したほど信頼性が低い可能性があります。

これは重大な変更であるため、v3に含めます。

関連: https

@darrachequesneまた、モバイルで電話画面がスタンバイ状態になり、モバイルでブラウザを再度開くと、

ソケットioのこのバグに関する更新はありますか?

私のアプリでは、ユーザーがモバイルブラウザーからファイルをアップロードしようとしたときに、アップロードダイアログボックスが開いたときに、ファイルを選択するのに15秒以上かかると、socketioはユーザーを切断します。

15秒後に別のページまたはタブに切り替えた場合、socket ioは再びそれらを切断します。これを修正して、ユーザーがページ/ドキュメントに焦点を合わせていなくても、socket ioを存続/接続したままにする方法はありますか?

@darrachequesne

VisibilityAPIでこの問題を修正しました。

私にとってのSafariの主な問題-visible.hidden === trueのソケットを閉じる時間がないため、デバイスのロックが解除された後にWebSocketを閉じて、再度開始する必要があります。

@ JustFly1984そのためのサンプルコードはありますか。 可視性検出は正常に機能していますが、ソケットを再接続できません。

だから今、これはMacOS Safariでも起こっています、参考までに。

@calendee @anilanar私たちは<ContextProvider />があり、可視性が上にあり、WebSocketが下にあり、WebSocketが可視性からのコンテキストを使用しているという主なアイデア。

JustFly1984にご連絡いただきありがとうございます。 実際、結局、可視性APIは必要ありませんでした。 単にタイムアウトを追加する必要があります。 これを行うと、iOSSafariでの接続の問題は発生しなくなりました。

// Establish a Socket.io connection
// Initialize our Feathers client application through Socket.io
// with hooks and authentication.
client.configure(feathers.socketio(socket), {
  timeout: 2000,
});
// Use localStorage to store our login token
client.configure(feathers.authentication(), {
  timeout: 2000,
});
このページは役に立ちましたか?
0 / 5 - 0 評価

関連する問題

adammw picture adammw  ·  4コメント

kootoopas picture kootoopas  ·  4コメント

stnwk picture stnwk  ·  4コメント

gCurtisCT picture gCurtisCT  ·  4コメント

varHarrie picture varHarrie  ·  3コメント