104، "إعادة تعيين الاتصال بواسطة خطأ في مأخذ الأقران، أو متى يغلق النتيجة المقبس في RST بدلا من الزعنفة؟

StackOverflow https://stackoverflow.com/questions/383738

سؤال

نحن نتطور خدمة ويب بيثون وموقع عميل على الويب بالتوازي. عندما نصنع طلب HTTP من العميل إلى الخدمة، ترفع مكالمة واحدة باستمرار مقبس.Error في Socket.py، في قراءة:

(104، "إعادة تعيين الاتصال بواسطة PEER")

عندما أستمع في Wireshark، تبدو الردود "الجيدة" و "السيئة" متشابهة للغاية:

  • بسبب حجم رأس Oauth، يتم تقسيم الطلب إلى حزمتين. تستجيب الخدمة لكل من ACK
  • ترسل الخدمة الاستجابة، حزمة واحدة لكل رأس (HTTP / 1.0 200 "موافق، ثم رأس التاريخ، إلخ). يستجيب العميل لكل مع ACK.
  • (طلب جيد) الخادم يرسل الزعنفة، ACK. يستجيب العميل مع زعنفة، ACK. يرد الخادم ACK.
  • (طلب سيء) يرسل الخادم RST، ACK، لا يرسل العميل استجابة TCP، يتم رفع المقبس.عدد على جانب العميل.

كل من خدمة الويب والعميل يعمل على مربع Gentoo Linux X86-64 تشغيل Glibc-2.6.1. نحن نستخدم Python 2.5.2 داخل نفس virtual_env.

العميل هو تطبيق Django 1.0.2 الذي يتصل HTTPLIB2 0.4.0 لإجراء الطلبات. نحن نتوقع طلبات مع خوارزمية توقيع OAUTH، مع وضع الرمز المميز OAuth دائما على سلسلة فارغة.

الخدمة قيد التشغيل Werkzeug 0.3.1، والتي تستخدم Python's Wsgiref.simple_server. ركضت تطبيق WSGI من خلال WSGiref.Validator بدون أي مشاكل.

يبدو أن هذا يجب أن يكون من السهل التصحيح، ولكن عندما أتبع طلب جيد على جانب الخدمة، فإنه يبدو تماما مثل الطلب السيئ، في Socket._socketobject.close () وظيفة، تحويل طرق المفوض إلى طرق وهمية. عند إرسال أو SendTo (لا أتذكر أي طريقة) يتم إيقاف تشغيلها، يتم إرسال الزعنفة أو RST، ويبدأ العميل المعالجة.

يبدو أن "إعادة تعيين الاتصال بواسطة PEER" لوضع اللوم على الخدمة، لكنني لا أثق ب HTTPLIB2 أيضا. هل يمكن للعميل أن يكون خطأ؟

** المزيد من التصحيح - يبدو وكأنه خادم على Linux **

لدي ماك بوك، لذلك حاولت تشغيل الخدمة على موقع واحد والعميل على الويب. يستدعي عميل Linux خادم OS X دون الخطأ (ACK FIN). يدعو عميل OS X إلى خدمة Linux مع الخطأ (RST ACK، و A (54، "إعادة تعيين الاتصال بواسطة PEER")). لذلك، يبدو أن الخدمة تعمل على Linux. هل هو x86_64؟ سيئة glibc؟ Wsgiref؟ لا تزال تبحث...

** مزيد من الاختبارات - WSGiref تبدو ضخمة **

لقد ذهبنا إلى الإنتاج مع Apache و Mod_WSGI، وذهبت إعادة تعيين الاتصال. انظر إجابتي أدناه، لكن نصيحتي هي تسجيل إعادة تعيين الاتصال وإعادة المحاولة. سيتيح ذلك تشغيل الخادم الخاص بك موافق في وضع التطوير، وسوى في الإنتاج.

هل كانت مفيدة؟

المحلول

لقد تلقيت هذه المشكلة. يرى Python "إعادة تعيين الاتصال بواسطة PEER" مشكلة.

لديك (على الأرجح) تدير Afoul من قضايا توقيت صغيرة بناء على قفل فورتر فوري العالمي الثعبان.

يمكنك (في بعض الأحيان) تصحيح هذا مع time.sleep(0.01) وضعت استراتيجيا.

"أين؟" أنت تسأل. يضربني. هذه الفكرة هي توفير بعض التزامن أفضل موضوع أفضل في طلبات العميل وحولها. حاول وضعه فقط قبل يمكنك تقديم الطلب بحيث يتم إعادة تعيين GIL ومترجم Python لإزالة أي خيوط في انتظار.

نصائح أخرى

لا تستخدم WSGiref للإنتاج. استخدم Apache و MOD_WSGI، أو أي شيء آخر.

نستمر في رؤية إعادة تعيين الاتصال هذه، في بعض الأحيان بشكل متكرر، مع WSGiref (الخلفية المستخدمة من قبل خادم اختبار Werkzeug، وربما الآخرين مثل خادم اختبار Django). كان حلنا لتسجيل الخطأ، أعد محاولة المكالمة في حلقة، والتخلي عن عشرة فشل. HTTPLIB2 يحاول مرتين، لكننا بحاجة إلى عدد قليل أكثر. يبدو أنهم يأتون إلى عناقيد أيضا - مضيفا أن النوم الثاني قد يؤدي إلى مسح المشكلة.

لم نر إعادة تعيين اتصال عند التشغيل من خلال Apache و Mod_WSGI. لا أعرف ما يفعلونه بطريقة مختلفة، (ربما يقنعونهم فقط)، لكنهم لا يظهرون.

عندما طلبنا من مجتمع Dev المحلي للمساعدة، أكد شخص ما أن يرون الكثير من إعادة تعيين اتصال مع WSGiref الذي يذهب بعيدا عن خادم الإنتاج. هناك خطأ هناك، ولكن سيكون من الصعب العثور عليه.

أدرك أنك تستخدم بيثون، لكنني وجدت مقالة Java هذه مفيدة.

http://java.sun.com/javase/6/docs/technotes/guides/net/articles/connection_release.html.

عادة، ستحصل على RST إذا قمت بإغلاقه الذي لا يصيح (أي يتم فيها التخلص من البيانات من خلال المكدس إذا لم يتم إرسالها و Ack'd) وزعزعا عاديا إذا سمحت بالإغلاق لظلعة (أي إغلاق ينتظر البيانات في العبور لتكون ACK'd).

ربما يكون كل ما عليك فعله هو تعيين المقبس الخاص بك إلى LINR بحيث يمكنك إزالة شرط السباق بين إغلاق غير مباشر عند المقبس ووصل ACKS؟

كان لدي نفس المشكلة مع القيام بتحميل ملف كبير جدا باستخدام عميل Python-Budels ينشر إلى Backend Nginx + UWSGI.

إن ما انتهى به الأمر كان السبب كان الجزء الخلفي كان الحد الأقصى على حجم الملف الأقصى لحجم الملفات أقل مما كان يحاول العميل إرساله.

الخطأ لا يظهر مطلقا في سجلات UWSGI الخاصة بنا لأن هذا الحد كان في الواقع يفرضه Nginx.

إزالتها الحد الأقصى في Nginx الخطأ.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top