Socket.io: Safari يسقط الاتصال بمقبس الويب بسبب عدم النشاط عندما لا تكون الصفحة في التركيز

تم إنشاؤها على ٢٥ أبريل ٢٠١٧  ·  26تعليقات  ·  مصدر: socketio/socket.io

اتريد:

  • [x] أبلغ عن خطأ
  • [] طلب ميزة

السلوك الحالي

لست متأكدًا مما إذا كانت هذه مشكلة معروفة (حاولت البحث ولكن لم أجد شيئًا). يبدو أن Safari لنظام التشغيل Mac يقوم بإسقاط اتصالات Websocket بصمت بسبب عدم النشاط / الخمول إذا لم تكن الصفحة / علامة التبويب قيد التركيز.

خطوات إعادة الإنتاج (إذا كان السلوك الحالي خطأ)

جعل علامة التبويب / الصفحة Safari غير موضع التركيز ؛ أحداث سجل websocket.

سلوك متوقع

يجب أن تظل مآخذ الويب على قيد الحياة عبر وظيفة نبضات القلب. لا أرى هذا السلوك في المتصفحات الأخرى لذلك من غير المحتمل أن يكون الرمز الخاص بي.

اقامة

  • نظام التشغيل: Mac OSX 10.12.4 (16E195)
  • المتصفح: Safari 10.1 (12603.1.30.0.34)
  • الإصدار socket.io: 1.7.3

معلومات أخرى (مثل stacktraces والمشكلات ذات الصلة واقتراحات كيفية الإصلاح)

هل من المحتمل أن يكون هذا نوعًا من ميزة توفير الطاقة التي تتجاوز / تتجاهل دقات القلب؟

bug

التعليق الأكثر فائدة

أعتقد أن هذا لأن الإصدار الحالي من socket.io يعتمد على setTimeout من جانب العميل ، والتي قد لا تكون موثوقة كما هو متوقع.

سنقوم بتضمين هذا في الإصدار 3 ، لأنه تغيير كسر.

ذات صلة: https://github.com/primus/primus/issues/348

ال 26 كومينتر

تشغيل الخادم مع DEBUG = * يُظهر ما يلي:
socket.io:client client close with reason ping timeout +0ms
socket.io:socket closing socket - reason ping timeout +0ms

الذي أفترض أنه يعني أن Safari أغلق الاتصال ، وليس خادم المقبس أو مثيل العميل. ومع ذلك ، فإن أغرب شيء هو أنني لاحظت أن Safari يعيد الاتصال في بعض الأحيان بعد حوالي 30 ثانية إلى دقيقة واحدة ولكن في أحيان أخرى لا يحدث ويظل غير متصل حتى يتم التركيز على الصفحة. من المحبط للغاية محاولة تصحيح مثل هذا السلوك غير المتسق.

يبدو أنه في بعض الأحيان يعيد الاتصال بشكل متقطع في وقت لاحق (مثل 10 دقائق). مرة أخرى ، غير متسق تمامًا في ظل بيئات اختبار متطابقة.

twistedpixel تأخر إعادة الاتصال أسي (أي شيء مثل: انتظر 500 مللي ثانية ، حاول إعادة الاتصال ، انتظر 1000 مللي ثانية ، حاول إعادة الاتصال ...) ( المصدر ) ، لذلك قد يفسر ذلك السلوك.

ماذا عن الإجبار على إعادة الاتصال عندما تحصل النافذة على التركيز مرة أخرى؟

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

قد يكون مرتبطًا بـ https://github.com/primus/primus/issues/348.

شكرًا على المعلومات ولكن المشكلة الرئيسية هي أنني بحاجة إلى توصيل مقبس الويب بشكل دائم لأنه يُستخدم لإرسال التنبيهات إلى المستخدم أثناء تواجده بعيدًا. لذلك ، فإن التركيز على النافذة لإعادة الاتصال ليس مثاليًا.

أعتقد أنه في الواقع شيء أكثر إشكالية خاصة بجهازي / التثبيت على أي حال. لقد لاحظت السلوك في الأصل على iMac الخاص بي ، لذا قررت مسح MacBook الخاص بي بإصدار جديد من Safari ولا أرى السلوك هناك على الإطلاق. لقد تركت علامة تبويب مصغرة ليوم كامل ولم يتم قطع الاتصال مرة واحدة. لذلك حاولت العودة إلى iMac وإزالة جميع مكونات الإنترنت الإضافية وتعطيل جميع الإضافات ولكن ما زلت أرى هذا السلوك.

لا يبدو أن Apple توفر أي طريقة لإعادة تثبيت Safari تمامًا بخلاف حذف تفضيلاته وبعض الملفات الأخرى. أو مسح الجهاز. يريد جزء مني أن يبدأ من جديد ، لكن المطور بداخلي يكره عدم معرفة السبب.

في الواقع ، إلى وجهة نظرك حول إعادة الاتصال الأسية: من المؤكد أن إعادة الاتصال الأولى ، كما تقول ، ستكون حوالي 500 مللي ثانية بعد قطع الاتصال ... فلماذا يتجاهلها الخادم؟ يجب أن يكون هناك شيء يمنعه من إعادة الاتصال.

إنه أمر غريب بعض الشيء لأنني إذا قمت بإلصاق socket.connect() في حدث قطع الاتصال ، فسيتم الاتصال مرة أخرى بشكل جيد. يجب أن تفعل ذلك كل بضع دقائق لكنها لا تزال تفعل ذلك دون أن تفشل. لذلك أنا في حيرة شديدة من سبب عدم حدوث إعادة الاتصال! سأفعل المزيد من الحفر وأرى ما إذا كان بإمكاني معرفة السبب.

هذا هو السلوك المعتاد للمتصفح في الوقت الحاضر ، حتى على أجهزة سطح المكتب ، للأسف.

أعتقد أنني أعرف ما يحدث. سفاري هو حقا المشكلة.

أعتقد أن جميع المتصفحات تحدد قيم setTimeout و setInterval عند 1000 عندما لا تكون علامة التبويب موضع التركيز. سفاري - بغباء - قبعات عليه في 1000 و لا شيء مثل إضافة أضعافا مضاعفة تأخير أن النتائج في كل تكرار أخذ مضاعف طالما أن الأخير. هذا هو السبب في أن الاتصال يموت. يتم تأخير / إسقاط المهلات الداخلية الخاصة بـ socket.io ، موضحًا سبب عدم حدوث عمليات إعادة الاتصال في الوقت المناسب.

لذلك ، قررت شركة Apple بشكل أساسي أن تتعارض مع التيار ، كالعادة ، مما أدى إلى تجربة مستخدم سيئة. إنهم جيدون حقًا في هذا هذه الأيام.

لم أكتشف سبب تأثيره على iMac وليس MacBook (كنت أتوقع العكس) لكنني سأستمر في الاختبار وأرى ما إذا كان بإمكاني تحديد السبب الدقيق.

twistedpixel ليس فقط Safari. راجع http://blog.strml.net/2017/01/chrome-56-now-aggressively-throttles.html

في Primus ، عملنا على حل المشكلة من خلال عكس اتجاه رسائل نبضات القلب (https://github.com/primus/primus/pull/534).

lpinca طوال الوقت الذي كنت أحاول فيه اكتشاف هذه المشكلة ، كنت أتساءل عن هذا الشيء بالذات. شكرا للمعلومة! لقد كنت أبحث في Primus لكنني لم أرغب في إعادة تشكيل قاعدة التعليمات البرمجية بالكامل قريبًا. يبدو أنه يمكن أن يستحق كل هذا الجهد.

نقطتي فيtwistedpixel هي أنه يمكن فعل الشيء نفسه على الأرجح في Engine.IO ، لذا لا داعي للترحيل إلى Primus.

لا يبدو أن FWIW ، Safari Tech Preview تتأثر بالاختناق الإضافي. ربما تراجعت شركة آبل عن قرارها. لا يزال يختنق إلى 1000 مللي ثانية ولكن لا يبدو أنه يضيف أي شيء آخر.

أواجه نفس المشكلة على iOS 12 Safari. إذا أعدت فتح سفاري ، فسيختفي اتصال websocket. هل هناك حل بديل نظيف لإبقاء المقبس على قيد الحياة؟

يقوم AFAIK iOS Safari بتعليق بعض العمليات عندما يكون Safari في الخلفية (لمنع استنزاف البطارية) ومن المؤكد أن اتصالات Websocket هي إحدى هذه العمليات. من غير المحتمل أن تجد حلاً على الأجهزة المحمولة.

حسنا. ولكن لا يزال بإمكاني إعادة الاتصال إذا قمت بإضافة مستمع حدث مثل onwindowfocus أو شيء من هذا القبيل؟

هل قام أي شخص بتنفيذ حل بديل؟ نحن مهتمون بالنظر في الخيارات ونتساءل عما إذا كان الآخرون يقومون بالتجربة بالفعل

بدلاً من استخدام أحداث التركيز ، ستحتاج إلى استخدام Page Visibility API لاكتشاف متى تكون نافذة تطبيق الجوال في الخلفية.

لقد اصطدمت بالمشكلة مع Azure SignalR وبفضل اقتراح techpeace الذي يستخدم حاليًا واجهة برمجة تطبيقات Page Visibility لإغلاق الاتصال على إخفاء الصفحة وإعادة توصيله مرة أخرى عندما تكون الصفحة مرئية. أحداث متعددة. جارٍ البحث حاليًا في إلغاء الأحداث .. كما أن النصائح العامة الموجودة على الويب لا تشجع على أي نوع من المعالجة بناءً على اكتشاف وكيل المستخدم .. لذا فإن الحل الذي أقدمه هو استخدام واجهة برمجة تطبيقات رؤية الصفحة بغض النظر عن وكيل المستخدم.

حلول

لقد اختبرت لعدة ساعات مع جميع هذه المتصفحات الثلاثة ، غيرت قيم pingTimeout & pingInterval . ما وجدته من الحلول:

  1. تعيين pingTimeout > = 30000 مللي ثانية

    • أو -

  2. تعيين pingInterval <= 10000 مللي ثانية

أعتقد أن الحل الأفضل هو تغيير pingTimeout = 30000 . الافتراضي pingInterval هو 25000 مللي ثانية وزيادة وتيرة اتصال الخادم مع العملاء لكل 10 ثوانٍ يمكن أن يكون ثرثاريًا جدًا بالنسبة للمشاريع على نطاق واسع.

أعتقد أن هذا لأن الإصدار الحالي من socket.io يعتمد على setTimeout من جانب العميل ، والتي قد لا تكون موثوقة كما هو متوقع.

سنقوم بتضمين هذا في الإصدار 3 ، لأنه تغيير كسر.

ذات صلة: https://github.com/primus/primus/issues/348

darrachequesne ، أواجه ذلك أيضًا عندما أكون على الهاتف المحمول إذا كانت شاشة هاتفي في وضع الاستعداد وفتحت المتصفح مرة أخرى على الهاتف المحمول ، يقوم المقبس io بفصل الدردشة. الرجاء إصلاح هذا. سيكون راحة ضخمة.

أي تحديث لهذا الخطأ في مقبس io؟

في تطبيقي عندما يحاول المستخدم تحميل ملف من متصفح الهاتف المحمول ، وعندما يفتح مربع حوار التحميل ، يفصله socket io إذا استغرق الأمر 15 ثانية أو أكثر لتحديد ملف.

إذا قاموا بالتبديل إلى صفحة أو علامة تبويب أخرى ، بعد 15 ثانية ، يقوم المقبس io بفصلهم مرة أخرى ، هل هناك على أي حال لإصلاح ذلك والحفاظ على توصيل / توصيل المقبس حتى لو لم يكن المستخدم في الصفحة / المستند مركّزًا؟

تضمين التغريدة

لقد أصلحت هذه المشكلة مع Visibility API.

المشكلة الرئيسية في Safari بالنسبة لي - ليس لديها وقت لإغلاق المقبس على visual.hidden === true ، لذلك تحتاج إلى إغلاق مقبس الويب بعد إلغاء قفل الجهاز ، وبدء تشغيله مرة أخرى.

@ JustFly1984 هل لديك بعض التعليمات البرمجية

هذا يحدث الآن مع MacOS Safari أيضًا ، لمعلوماتك.

calendeeanilanar نحن لا تستخدم sockets.io و WebSockets مجرد محض، وأيضا نحن نستخدم React.js، لذلك رمز معقد جدا. الفكرة الرئيسية هي أن لدينا <ContextProvider /> لكل واجهة برمجة تطبيقات ، وأن الرؤية في الأعلى ، ومقابس ويب في الأسفل ، ومقابس ويب تستخدم سياق من الرؤية.

شكرا لردكم لي JustFly1984. في الواقع ، في النهاية ، لم أكن بحاجة إلى واجهة برمجة تطبيقات الرؤية. أنا ببساطة بحاجة إلى إضافة المهلات. بمجرد القيام بذلك ، لم تعد لدي مشكلات الاتصال على iOS Safari.

// 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 التقييمات