Requests: عدد كبير جدا من الملفات المفتوحة

تم إنشاؤها على ٥ نوفمبر ٢٠١١  ·  81تعليقات  ·  مصدر: psf/requests

أقوم بإنشاء منشئ تحميل أساسي وبدأت في الوصول إلى حدود واصف الملفات ، ولم أر أي وثائق تتعلق بكيفية تحرير الموارد ، لذلك إما أن أفعل ذلك بشكل خاطئ وتحتاج المستندات إلى تحديث ، أو أن الطلبات تسرّب واصفات الملفات في مكان ما (بدون دعم) من أجل الحفاظ على الحياة ، أشعر بالارتباك قليلاً بشأن سبب ترك أي ملفات مفتوحة على الإطلاق)

Bug Contributor Friendly

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

"عدد كبير جدًا من الملفات المفتوحة" هو نتيجة الخطأ الناجم عن بقاء المقابس في CLOSE_WAIT.
لذا لن يصلح ulimit مجرد حل بديل.

ال 81 كومينتر

أين تستخدم requests.async ؟

كلا ، كانت جميع الطلبات عبارة عن طلبات بسيطة بشكل معقول.get / Orders.post ، ما زلت أرى بعضها هناك

$ lsof | grep localhost | wc -l
110

جميعها باستثناء 4/5 منها بالتنسيق

Python    82117 daleharvey  123u    IPv4 0xffffff800da304e0       0t0      TCP localhost:61488->localhost:http (CLOSE_WAIT)

أنا محير قليلاً من هذا ، لأكون صادقًا.

هههه ، أخذ لقطة أخرى لإعادة إنتاجها بشكل موثوق ، إذا لم أستطع الاقتراب

لقد رأيت هذا يحدث لي ، ولكن فقط عندما أستخدم الوحدة غير المتزامنة مع أكثر من 200 اتصال متزامن.

مرحبا،
لقد حصلت على نفس المشكلة تمامًا باستخدام الطلبات وترقيع القرود باستخدام gevent: بعض الاتصالات تبقى في CLOSE_WAIT.
ربما مشكلة مع gevent ذلك.

قد تكون مشكلة ulimit -n. جرب بقيمة أعلى.

"عدد كبير جدًا من الملفات المفتوحة" هو نتيجة الخطأ الناجم عن بقاء المقابس في CLOSE_WAIT.
لذا لن يصلح ulimit مجرد حل بديل.

tamiel كيف نصلح هذا؟

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

لقد بحثت في الأمر ، ويبدو أن هناك مشكلة في جميع المكتبات التي تستخدم HTplib.HTTPSConnection.

نشر مثالا هنا:

https://gist.github.com/1512329

لقد واجهت للتو خطأً مشابهًا جدًا باستخدام تجمع غير متزامن مع اتصالات HTTP فقط - ما زلت أقوم بالتحقيق ولكن تمرير حجم المجموعة إلى خريطة غير متزامنة يجعل الخطأ يتكاثر بسرعة.

أي إصلاحات لهذا؟ هذا يجعل الطلبات غير قابلة للاستخدام مع gevent ..

كل شيء عن CLOSE_WAIT s. فقط يجب أن تغلقهم. لست متأكدًا من سبب استمرار فتحهما رغم ذلك.

هل هي قضية urllib3؟ إن الاضطرار إلى إغلاق هذه بأنفسنا ليس فكرة رائعة أشعر بها.

إنها مسألة عامة. يمكننا الاحتفاظ بالمحادثة هنا.

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

بشكل عام ، أعني أنها مشكلة خطيرة للغاية تؤثر على جميع المعنيين.

فكيف نحل هذا؟ نريد حقًا استخدام الطلبات + النوم للمضي قدمًا

أود أن أعرف الإجابة على ذلك.

يبدو أن سبب التسرب هو معالجة إعادة التوجيه الداخلية ، مما يؤدي إلى إنشاء طلبات جديدة قبل استهلاك الاستجابات المعلقة. في اختبار acdha @ 730c0e2e2bef77968a86962f9d5f2bebba4d19ec لديه إصلاح غير مُرضٍ ولكنه فعال ببساطة عن طريق إجبار كل استجابة ليتم استهلاكها قبل المتابعة.

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

399 لديه إصلاح يعمل بشكل جيد في منشئ التحميل غير المتزامن (https://github.com/acdha/webtoolbox/blob/master/bin/http_bench.py) مع آلاف الطلبات و fd ulimit

لقد واجهت نفس المشكلة عند استخدام غير متزامن - ألغيت حلًا بديلًا عن طريق تقسيم الطلبات وحذف الردود / استدعاء gc.collect

أعتقد أنني كنت أواجه هذا اليوم بالاتصال بخادم مرخص لا يسمح إلا بـ 5 اتصالات.

باستخدام غير المتزامن يمكنني فقط الحصول على 4 أشياء قبل أن تتوقف مؤقتًا لمدة 60 ثانية.

باستخدام GET العادي مع الاستهلاك ، يمكنني إحضار حوالي 150 شيئًا بشكل متسلسل في أقل من 40 ثانية.

لم أقم بعمل kludge بعد منذ أن رأيت هذه المشكلة.

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

ERROR: Internal Python error in the inspect module.
Below is the traceback from this internal error.
Traceback (most recent call last):
    File "/Library/Python/2.7/site-packages/IPython/core/ultratb.py", line 756, in structured_traceback
    File "/Library/Python/2.7/site-packages/IPython/core/ultratb.py", line 242, in _fixed_getinnerframes
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/inspect.py", line 1035, in getinnerframes
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/inspect.py", line 995, in getframeinfo
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/inspect.py", line 456, in getsourcefile
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/inspect.py", line 485, in getmodule
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/inspect.py", line 469, in getabsfile
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.py", line 347, in abspath
OSError: [Errno 24] Too many open files

Unfortunately, your original traceback can not be constructed.

بشكل غريب ، أعتقد أنه عند استخدام مترجم Python العادي فقط ، أحصل على "Max Retries Error" ولكني أعتقد أن هذه مشكلة أخرى معي أثناء تنفيذ الطلبات على نفس المجال ، لكنني لست متأكدًا.

واجهت هذا في أول مشروع لدي حيث كان allow_redirects صحيحًا ؛ يبدو أنه ناتج عن سلسلة إعادة التوجيه التي تتسرب من كائنات الاستجابة التي لم يتم تحريرها حتى مع الجلب المسبق = صحيح. تم إصلاحه في اختباري الأولي:

        [i.raw.release_conn() for i in resp.history]
        resp.raw.release_conn()

هممم ..

إعداد acdha :

requests.defaults.defaults['allow_redirects'] = False

قبل أن أقدم أي طلبات ، لا يزال ينتج عن نفس الخطأ ، لكنني أعتقد أن هذا ليس خيارًا للتنفيذ الخاص بي لأن جميع الطلبات التي أقدمها ستتطلب إعادة توجيه = /

dalanmiller كيف حالك معالجة ردودك؟ كنت أستخدم سابقًا async.map مع خطاف استجابة ويبدو أنه أكثر ثباتًا باستخدام حلقة بسيطة تزيد عن async.imap :

for resp in requests.async.imap(reqs, size=8):
    try:
        print resp.status_code, resp.url
    finally:
        [i.raw.release_conn() for i in resp.history]
        resp.raw.release_conn()

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

كنت فقط أستخدم حلقة for من خلال قائمة عناوين url وأقوم بطلب. احصل على كل منها بإعداداتي وما شابه.

for u in urls:
    response_list.append(requests.get(u))

لقد حاولت استخدام اللصق الخاص بك وهو يعمل لحوالي 50 طلبًا في قائمة الطول البالغ عددها 900 ، حتى أبدأ في الحصول على "تجاوز الحد الأقصى لأخطاء إعادة المحاولة مع عنوان url" لبقية الطلبات. هذا خطأ قياسي جدًا على الرغم من ضرب نفس النطاق مرارًا وتكرارًا ، أليس كذلك؟

مرحبًا ، كنت أزحف إلى قائمة ضخمة من عناوين url ، 35 ألفًا ، وحصلت على نفس الخطأ في _ بعض_ الطلبات.

أحصل على عناوين url في أجزاء من 10 ، مثل هذا:

responses = requests.async.map([requests.async.get(u, params=self.params()) for u in chunk]) # chunk is a list of 10

في مكان ما في نطاق 20 كيلو ، بدأت أتلقى الخطأ 24 ، ثم كان جيدًا حتى 30 كيلو ثم مرة أخرى.

هل هناك المزيد من المعلومات التي قد تكون مهتمًا بها لتضييق نطاقها؟

ذهب requests.async . قد ترغب في التفكير في الانتقال إلى grequests.

حسنا شكرا. سيكون من الجيد ذكر هذا في المستندات.

نوع من المستجد عندما يتعلق الأمر بطلبات السحب وكتابة الوثائق لكنني طعنت بها وأرسلتها. الرجاء التعليق أو النقد :)

https://github.com/kennethreitz/requests/pull/665

حسنًا ، هذا يحدث حتى بدون استخدام غير متزامن ، مع طلبات فقط ، بعد 6 آلاف طلب.

كنت أظن ذلك.

بالنسبة لي ، حدث خطأ "عدد كبير جدًا من الملفات المفتوحة" بعد تنزيل ملفات بحجم 1 كيلو بالضبط. كان الحل الذي قدمته هو تعطيل خاصية البقاء على قيد الحياة ، والحصول على الطلبات في أجزاء (شكرًا lsof -p PID | wc -l عددًا غير متزايد من الاتصالات أثناء التنفيذ.

rsess = requests.session()
rsess.config['keep-alive'] = False

rs = [grequests.get(l, session=rsess) for l in links]

for s in chunks(rs,100):
    responses = grequests.map(s, size=concurrency)
    for r in responses:
        try:
            print(r.status_code, r.url)
        finally:
            r.raw.release_conn()

[1] التقسيم: http://stackoverflow.com/a/312464

إغلاق أثناء التأجيل لإصلاح urllib3.

@ kennethreitz ما هو رقم إصدار urllib3؟

يبدو أن هذه هي المشكلة http://bugs.python.org/issue16298

يمكن أن تكون silvexis مرتبطة بشكل جيد جدًا بخلل urllib3 ، والآن أتمنى أن يكون أحدهم قد أجاب على @ piotr-dobrogost: P

هل لا يزال أي شخص آخر يواجه هذه المشكلة؟

لم أسمع أي تقارير عنها. أنت؟

إنها مشكلة تكوين الصندوق ، وليست مشكلة الإطار. انظر إلى تكوين kernel لنظام التشغيل الخاص بك. في BSD يطلق عليه kern.maxfiles . هناك موضوع حول ulimit في أنظمة Linux: http://stackoverflow.com/questions/34588/how-do-i-change-the-number-of-open-files-limit-in-linux
آمل أن يساعد ذلك ، ولا أعرف كيفية تغيير هذه المعلمة على Windows.

مع التنبيه بأننا ما زلنا نشغل إصدارًا قديمًا من الطلبات ، فلدينا الكود التالي الرهيب للتعامل مع هذا:

    if self._current_response is not None:
            # Requests doesn't have a clean API to actually close the
            # socket properly. Dig through multiple levels of private APIs
            # to close the socket ourselves. Icky.
            self._current_response.raw.release_conn()
            if self._current_response.raw._fp.fp is not None:
                sock = self._current_response.raw._fp.fp._sock
                try:
                    logger.debug('Forcibly closing socket')
                    sock.shutdown(socket.SHUT_RDWR)
                    sock.close()
                except socket.error:
                    pass

(أعتقد أن self._current_response هو كائن استجابة الطلبات)

حسنًا ، أين سلسلة الإغلاق مكسورة؟ لدينا طريقة Response.close() تستدعي release_conn() ، فما الذي يجب أن يحدث في release_conn() حتى ينجح هذا؟

Lukasa تم إصلاح هذا بالتأكيد في urllib3 لأنني كنت جزءًا من المناقشة. مع ميل نحو التحفظ في تقديري ، أود أن أقول إنه موجود منذ طلبات 1.2.x إن لم يكن 1.1.x.

نعم ، أعتقد أن هذا تم إصلاحه. ما لم نرى شيئًا ما في 1.2.3 ، سأستمر في افتراض أن هذا ثابت.

أرى تسريب CLOSE_WAIT مع 2.0.2 ، هل لديك اختبارات وحدة للتأكد من عدم وجود تراجع في هذا الموضوع؟

لا ، لا نفعل. AFAIK urllib3 ليس كذلك. هل يمكنك إعادة إنتاج التسرب بسهولة؟

نستخدم الطلب في تطبيقنا الداخلي منذ يوم الإثنين ، ونبلغ اليوم 1024 maxfiles ..

بعد ساعتين من إعادة التشغيل ، لدينا 40 CLOSE_WAIT كما أخبر lsof.

لذلك أعتقد أننا سنكون قادرين على التكاثر في بيئة مطورة ، نعم. سأبيقك على اتصال

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

لقد قمت بالتثبيت باستخدام pip ، لكنني استخدم python 2.6 ، لقد رأيت إصلاحًا على python2.7 من أجل
هذا الخطأ. هل monkeypatch للإصدار الأقدم؟

بيير

يوم الجمعة ، 29 تشرين الثاني (نوفمبر) 2013 الساعة 5:33 مساءً ، كتب إيان كورداسكو [email protected] :

tardyp https://github.com/tardyp أيضًا ، كيف قمت بتثبيت الطلبات؟ أنا
أعتقد أن كل معالجي حزمة نظام التشغيل يزيلون urllib3. إذا لم يفعلوا ذلك
حافظ على ذلك محدثًا وأنت تستخدم إصدارًا قديمًا ، يمكن أن يكون
بدلا من ذلك. إذا كنت تستخدم النقطة ، فلا تتردد في فتح إصدار جديد لـ
تتبع هذا بدلاً من إضافة مناقشة إلى هذا.

-
قم بالرد على هذه الرسالة الإلكترونية مباشرة أو tHubhttps: //github.com/kennethreitz/requests/issues/239#issuecomment -29526302
.

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

لمعلوماتك https://github.com/shazow/urllib3/issues/291 تم إرجاعه بسبب الأخطاء.

هل يجب علينا إعادة فتح هذا؟
أواجه نفس المشكلة!

polvoazul لا توجد طريقة لهذه المشكلة نفسها ، والتي تم الإبلاغ عنها في الأصل في عام 2011 ، لذلك لا أعتقد أن إعادة الفتح صحيحة. ومع ذلك ، إذا كنت تقوم بتشغيل الإصدار الحالي من الطلبات (2.4.3) ويمكنك إعادة إظهار المشكلة ، فسيكون فتح مشكلة جديدة أمرًا صحيحًا.

Lukasa أحتاج إلى المساعدة。 أستخدم طلبات الأحداث + التي تُنشئ دائمًا الكثير من الجوارب التي لا يمكنها تحديد البروتوكول。 طلباتي هي 2.4.3 ، هل تتسبب طلبات الحدث + في حدوث هذه المشكلة؟

أنا آسف mygoda ، لكن من المستحيل معرفة ذلك. إذا كنت لا تقيد عدد الطلبات التي يمكن أن تكون معلقة في أي وقت ، فهذا ممكن بالتأكيد ، لكن هذه مشكلة معمارية خارج نطاق الطلبات.

Lukasa شكرًا لك。 أعتقد أن لهذا 。 مشروعي هو pyvmomi . هذا الاتصال طويل الأمد. أنا دائما في حيرة من أمري لماذا يمكن أن تعقد الكثير لا يمكن التعرف على بروتوكول جورب

تواجه نفس المشكلة الآن ، تشغيل 120 موضوع ، تسبب أكثر من 100000 ملف مفتوح ، أي حل الآن؟

mygoda تستخدم فترات رائعة。

@ 1a1a11a _ ما هي الملفات التي تفتحها؟ ستكون هذه خطوة أولى مفيدة لفهم هذه المشكلة.

@ 1a1a11a ما هو إصدار الطلبات الذي تستخدمه؟ ما هو إصدار بيثون؟ ما نظام التشغيل؟ هل يمكننا الحصول على أي معلومات؟

أنا أستخدم الطلب 2.9.1 ، python 3.4 ، ubuntu 14.04 ، في الأساس ، أنا أكتب زاحف باستخدام 30 موضوعًا مع وكلاء للزحف إلى بعض مواقع الويب. لقد قمت حاليًا بتعديل حد الملف لكل عملية إلى 655350 ، وإلا فسيتم الإبلاغ عن خطأ.

ما زلت أتلقى الخطأ "فشل في إنشاء اتصال جديد: [Errno 24] عدد كبير جدًا من الملفات المفتوحة" من request.packages.urllib3.connection.VerifiedHTTPSConnection. "أنا أستخدم Python 3.4 ، ويطلب 2.11.1 وطلبات آجلة 0.9.7. أنا أقدر أن الطلبات الآجلة مكتبة منفصلة ، ولكن يبدو أن الخطأ يأتي من الطلبات. أحاول تقديم 180 ألف طلب غير متزامن عبر SSL. لقد قسمت هذه الطلبات إلى مقاطع من 1000 ، لذلك أنا انتقل فقط إلى الألف التالي بعد حل جميع الكائنات المستقبلية. أنا أقوم بتشغيل Ubuntu 16.04.2 والحد الافتراضي للملفات المفتوحة هو 1024. سيكون من الجيد فهم السبب الكامن وراء هذا الخطأ. هل تنشئ مكتبة الطلبات ملف مفتوح لكل طلب فردي؟ وإذا كان الأمر كذلك ، فلماذا؟ هل هذا ملف شهادة SSL؟ وهل تغلق مكتبة الطلبات تلقائيًا تلك الملفات المفتوحة عند حل الكائن المستقبلي؟

طلبات يفتح العديد من الملفات. يتم فتح بعض هذه الملفات للشهادات ، ولكن يتم فتحها بواسطة OpenSSL وليس بواسطة الطلبات ، لذلك لا يتم الاحتفاظ بها. بالإضافة إلى ذلك ، سيتم فتح الطلبات أيضًا ، إذا لزم الأمر ، ملف .netrc ، ملف المضيفين ، والعديد من الملفات الأخرى.

ستتم خدمتك بشكل أفضل باستخدام أداة مثل strace لتحديد الملفات المفتوحة. هناك قائمة صارمة باستدعاءات النظام التي تؤدي إلى تخصيص واصفات الملفات ، لذلك يجب أن تكون قادرًا بسرعة معقولة على تعدادها. سيتيح لك ذلك أيضًا معرفة ما إذا كانت هناك مشكلة أم لا. ولكن ، نعم ، أتوقع أنه إذا كنت تقوم بنشاط بإجراء 1000 اتصال عبر HTTPS ، فيمكننا بسهولة استخدام أكثر من 1000 FDs في ذروة الحمل.

لقد عانيت من هذه المشكلة أيضًا ووجدت أن استخدام opensnoop على OS X كان جيدًا للسماح لي برؤية ما كان يحدث إذا واجه أي شخص نفس المشكلات.

أشاهد أيضًا هذا الخطأ بشكل متكرر عند استدعاء requests.post(url, data=data) بشكل متكرر إلى خادم HTTP (وليس HTTPS). يعمل على Ubuntu 16.04.3 ، Python 3.5.2 ، يطلب 2.9.1

ما هو data ؟

بضع مئات من كيلو بايت نص

ليس كائن ملف؟

لا ، أنا أقوم بتكوين استعلام كبير في الذاكرة.

هل تقوم بتشغيل هذا الرمز في مواضيع متعددة؟

لا ، موضوع واحد ، الإرسال إلى المضيف المحلي

يبدو أنه من المستحيل تقريبًا بالنسبة لنا تسريب العديد من FDs بعد ذلك: يجب أن نستخدم اتصال TCP نفسه بشكل متكرر أو نغلقه بقوة. تريد أن تتحقق ما هو الخادم الخاص بك؟

انا لدي هذه المشكلة. Python 2.7 تطلب 2.18.4 و urllib3 1.22.
تشغيل كود متعدد الخيوط (غير متعدد المعالجة). الاتصال بـ 6 عناوين URL كحد أقصى في وقت واحد ، وإنشاء جلسة جديدة وإغلاقها يدويًا لكل عنوان.

أواجه نفس المشكلة على Python 3.5 ، requests==2.18.4

mcobzarenco هل أنت متأكد من أنك (ضمنيًا) تغلق الاتصال الأساسي للاستجابة؟ لن يؤدي مجرد إعادة الرد إلى إغلاق الاتصال. عند قراءة response.content ، تتم قراءة البيانات فعليًا وبعد ذلك لن يبقى المقبس في CLOSE_WAIT.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات