Requests: Terlalu banyak file yang terbuka

Dibuat pada 5 Nov 2011  ·  81Komentar  ·  Sumber: psf/requests

Saya membangun generator beban dasar dan mulai mengalami batasan deskriptor file, saya belum melihat dokumentasi apa pun yang berkaitan dengan cara melepaskan sumber daya, jadi entah saya salah melakukannya dan dokumen perlu diperbarui, atau permintaan membocorkan deskriptor file di suatu tempat (tanpa dukungan untuk keepalive saya sedikit bingung mengapa ada file yang dibiarkan terbuka sama sekali)

Bug Contributor Friendly

Komentar yang paling membantu

"Terlalu banyak file yang terbuka" adalah hasil dari bug yang disebabkan oleh soket yang tetap berada di CLOSE_WAIT.
Jadi ulimit tidak akan memperbaiki hanya membuat solusi.

Semua 81 komentar

Di mana Anda menggunakan requests.async ?

tidak, semua permintaan adalah requests.get / requests.post biasa saja, saya masih melihat beberapa di sana

$ lsof | grep localhost | wc -l
110

semua kecuali 4/5 di antaranya dalam format

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

Saya agak bingung dengan ini, jujur ​​saja.

Hah saya akan mengambil bidikan lain untuk mereproduksinya dengan andal, jika saya tidak bisa menutupnya

Saya telah melihat ini terjadi pada saya, tetapi hanya ketika saya menggunakan modul async dengan 200+ koneksi simultan.

Hai,
Saya mendapat masalah yang persis sama menggunakan request dan monkey patching dengan gevent: beberapa koneksi tetap berada di CLOSE_WAIT.
Mungkin masalah dengan gevent gitu.

Ini mungkin masalah ulimit -n. Coba dengan nilai yang lebih tinggi.

"Terlalu banyak file yang terbuka" adalah hasil dari bug yang disebabkan oleh soket yang tetap berada di CLOSE_WAIT.
Jadi ulimit tidak akan memperbaiki hanya membuat solusi.

@tamiel bagaimana kita memperbaikinya?

Saya akan melakukan lebih banyak tes secepatnya dan mencoba memperbaikinya.

Saya telah memeriksanya, dan tampaknya ada masalah dengan semua pustaka yang menggunakan httplib.HTTPSConnection.

Memposting contoh di sini:

https://gist.github.com/1512329

Saya baru saja menemukan kesalahan yang sangat mirip menggunakan kumpulan asinkron dengan hanya koneksi HTTP - Saya masih menyelidiki tetapi meneruskan ukuran kolam ke async.map membuat kesalahan berkembang biak dengan cepat.

Ada perbaikan untuk ini? Ini membuat Permintaan tidak dapat digunakan dengan gevent ..

Ini semua tentang CLOSE_WAIT s. Hanya harus menutupnya. Saya tidak yakin mengapa mereka masih buka.

Apakah ini masalah urllib3? Harus menutup ini sendiri bukanlah ide bagus yang kurasa.

Ini lebih merupakan masalah umum. Kita bisa tetap mengobrol disini.

Ok hanya untuk memberi Anda perspektif, kami mencoba untuk beralih dari httplib2 ke permintaan, dan kami tidak melihat masalah ini dengan httplib2. Jadi ini bukan masalah umum yang pasti.

Secara umum, maksud saya ini adalah masalah yang sangat serius yang mempengaruhi semua orang yang terlibat.

jadi bagaimana kita mengatasi ini? kami benar-benar ingin menggunakan permintaan + tidur untuk bergerak maju

Saya ingin tahu jawabannya.

Kebocoran ini tampaknya disebabkan oleh penanganan pengalihan internal, yang menyebabkan permintaan baru dibuat sebelum tanggapan yang tertunda dikonsumsi. Dalam pengujian acdha @ 730c0e2e2bef77968a86962f9d5f2bebba4d19ec memiliki

Ini memerlukan perubahan di dua tempat yang membuat saya ingin sedikit merefaktor antarmuka tetapi saya kehabisan waktu untuk melanjutkan saat ini.

399 memiliki perbaikan yang bekerja dengan baik di generator beban asinkron saya (https://github.com/acdha/webtoolbox/blob/master/bin/http_bench.py) dengan ribuan permintaan dan ulimit fd rendah

Saya mengalami masalah yang sama saat menggunakan async - mengurung solusi dengan memotong permintaan dan menghapus tanggapan / memanggil gc.collect

Saya yakin saya mengalami hal ini hari ini untuk menghubungkan ke server berlisensi yang hanya memungkinkan 5 koneksi.

Dengan menggunakan async, saya hanya dapat MENDAPATKAN 4 hal sebelum berhenti selama 60 detik.

Menggunakan GET normal dengan konsumsi saya dapat mengambil sekitar 150 hal secara berurutan dalam waktu kurang dari 40 detik.

Belum membuat kludge saya karena saya melihat masalah ini.

Baru saja mendapat kesalahan ini saat menggunakan ipython dan mendapat pesan ini. Ini hanya membuat setiap permintaan satu per satu, tetapi saya rasa saya mendapatkan sesuatu yang serupa saat menggunakan async.

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.

Anehnya, saya pikir ketika hanya menggunakan interpreter Python biasa saya mendapatkan "Max Retries Error" tetapi saya pikir itu adalah masalah lain dengan saya melakukan permintaan pada semua domain yang sama, tetapi tidak yakin.

Saya mengalami ini pada proyek pertama yang saya miliki di mana allow_redirects adalah True; hal itu tampaknya disebabkan oleh objek respons yang bocor rantai pengalihan yang tidak dirilis bahkan dengan prefetch = True. Ini memperbaikinya dalam pengujian awal saya:

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

Hmmm..

@acdha pengaturan:

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

sebelum saya membuat permintaan apa pun masih menghasilkan kesalahan yang sama, tetapi saya pikir ini bukan opsi untuk implementasi saya karena semua permintaan yang saya buat akan memerlukan pengalihan = /

@dalanmiller Bagaimana Anda memproses tanggapan Anda? Saya sebelumnya menggunakan async.map dengan hook respon dan _appears_ menjadi lebih stabil menggunakan loop sederhana di atas 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()

@haditsku

Saya baru saja menggunakan for loop melalui daftar url dan melakukan request.get pada masing-masing dengan pengaturan saya dan semacamnya.

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

Saya mencoba menggunakan pasta Anda dan itu bekerja untuk sekitar 50 permintaan dalam daftar panjang 900 saya, sampai saya mulai mendapatkan "kesalahan coba lagi maks melebihi dengan url" untuk sisanya. Ini adalah kesalahan standar yang cukup untuk memukul domain yang sama berulang kali, bukan?

Hei, saya sedang merayapi daftar besar url, 35k, dan mendapatkan kesalahan yang sama pada _some_ permintaan.

Saya mendapatkan url dalam potongan 10, seperti ini:

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

Di suatu tempat dalam kisaran 20k saya mulai mendapatkan kesalahan 24, lalu ok melalui 30k dan kemudian lagi.

Ada info lebih lanjut yang Anda tertarik untuk mempersempitnya?

requests.async hilang. Anda mungkin ingin mempertimbangkan untuk pindah ke grequests.

Baiklah terima kasih. Akan lebih baik untuk menyebutkan ini di dokumen.

Semacam noob ketika datang ke Permintaan Tarik dan dokumentasi penulisan tapi saya mencobanya dan mengirimkannya. Mohon komentar atau kritik :)

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

Oke, ini terjadi bahkan tanpa menggunakan asinkron, hanya dengan requests.get, setelah 6 ribu permintaan.

Saya curiga.

Bagi saya, kesalahan 'Terlalu banyak file yang terbuka' terjadi setelah mengunduh persis 1k file. Solusi saya adalah menonaktifkan properti keep-hidup, yang pernah mendapatkan permintaan dalam jumlah banyak ( @acdha terima kasih atas petunjuknya). lsof -p PID | wc -l menunjukkan jumlah koneksi yang tidak meningkat selama eksekusi.

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] memotong: http://stackoverflow.com/a/312464

Menutup sambil menunda perbaikan urllib3.

@kennethreitz Berapa nomor terbitan urllib3?

Sepertinya ini masalahnya http://bugs.python.org/issue16298

@silvexis bisa jadi terkait dengan bug urllib3, sekarang saya hanya berharap seseorang menjawab @ piotr-dobrogost: P

Apakah ada orang lain yang masih mengalami masalah ini?

Saya belum mendengar laporan apapun tentang itu. Apakah kamu?

Ini masalah konfigurasi kotak, bukan kerangka kerjanya. Lihat konfigurasi kernel OS Anda. Di BSD ini disebut kern.maxfiles . Ada utas tentang ulimit di sistem Linux: http://stackoverflow.com/questions/34588/how-do-i-change-the-number-of-open-files-limit-in-linux
Semoga membantu, dan saya tidak tahu cara mengubah parameter ini di Windows.

Dengan peringatan bahwa kami masih menjalankan permintaan versi lama, kami memiliki kode berikut, mengerikan, untuk menangani ini:

    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

(Saya pikir self._current_response adalah objek respons permintaan)

Hmm, di mana rantai penutupnya putus? Kami memiliki metode Response.close() yang memanggil release_conn() , jadi apa yang perlu dilakukan dalam release_conn() agar ini berfungsi?

@Lukasa ini pasti sudah diperbaiki di urllib3 karena saya adalah bagian dari diskusi. Dengan kecenderungan konservatif dalam perkiraan saya, saya akan mengatakan itu ada sejak permintaan 1.2.x jika bukan 1.1.x.

Ya, saya pikir ini sudah diperbaiki. Kecuali kita melihat sesuatu di 1.2.3, saya akan terus menganggap ini sudah diperbaiki.

Saya melihat kebocoran CLOSE_WAIT dengan 2.0.2, apakah Anda memiliki pengujian unit untuk memastikan tidak ada regresi pada topik?

Tidak, kami tidak. AFAIK urllib3 juga tidak. Dapatkah Anda mereproduksi kebocoran Anda dengan mudah?

Kami menggunakan permintaan di aplikasi internal kami sejak hari Senin, dan mencapai 1024 file maks hari ini ..

2 jam setelah reboot, kami memiliki 40 CLOSE_WAIT seperti yang diceritakan oleh lsof.

Jadi saya pikir kita bisa mereproduksi di lingkungan pengembang, ya. Saya akan tetap berhubungan dengan Anda

@tardyp juga, bagaimana Anda menginstal permintaan? Saya pikir semua pengelola paket OS menghapus urllib3. Jika mereka tidak terus memperbaruinya dan Anda menggunakan versi lama, itu bisa menjadi penyebabnya. Jika Anda menggunakan pip, silakan membuka masalah baru untuk melacaknya alih-alih menambahkan diskusi ke masalah ini.

Saya menginstal dengan pip, tetapi saya menggunakan python 2.6, saya telah melihat perbaikan pada python2.7 untuk
bug ini. Apakah Anda monkeypatch untuk versi yang lebih lama?

Pierre

Pada hari Jumat, 29 Nov 2013 jam 17:33, Ian Cordasco [email protected] :

@tardyp https://github.com/tardyp juga, bagaimana Anda menginstal permintaan? saya
pikir semua pengelola paket OS menghapus urllib3. Jika tidak
tetap perbarui itu dan Anda menggunakan versi lama, itu mungkin
menyebabkan sebagai gantinya. Jika Anda menggunakan pip, jangan ragu untuk membuka edisi baru
lacak ini dengan alih-alih menambahkan diskusi ke yang ini.

-
Balas email ini secara langsung atau lihat di Gi tHubhttps: //github.com/kennethreitz/requests/issues/239#issuecomment -29526302
.

@tardyp tolong buka masalah baru sedetail mungkin termasuk apakah permintaan yang Anda buat memiliki pengalihan dan apakah Anda menggunakan gevent. Juga, setiap detail tentang sistem operasi dan contoh bagaimana mereproduksinya akan sangat luar biasa.

FYI https://github.com/shazow/urllib3/issues/291 telah dikembalikan karena bug.

Haruskah kita membukanya kembali?
Saya mengalami masalah yang sama!

@polvoazul Tidak mungkin ini adalah masalah yang sama, yang awalnya dilaporkan pada tahun 2011, jadi menurut saya membuka kembali tidak benar. Namun, jika Anda menjalankan rilis permintaan saat ini (2.4.3) dan dapat mereproduksi masalah, membuka masalah baru akan menjadi benar.

@ Lukas saya butuh bantuan Anda。 saya menggunakan eventlet + permintaan, yang selalu membuat begitu banyak kaus kaki yang tidak dapat mengidentifikasi protokol。 permintaan saya adalah 2.4.3, apakah eventlet + permintaan menyebabkan masalah ini?

Maaf @mygoda , tapi tidak mungkin mengetahuinya. Jika Anda tidak membatasi jumlah permintaan yang dapat beredar pada satu waktu maka itu pasti mungkin, tetapi itu adalah masalah arsitektural di luar pengiriman permintaan.

@Lukasa terima kasih。 saya pikir masalah saya mirip dengan ini 。 proyek saya adalah pyvmomi . koneksi itu adalah koneksi panjang. Saya selalu bingung mengapa bisa menahan begitu banyak tidak dapat mengidentifikasi kaus kaki protokol

Mengalami masalah yang sama sekarang, menjalankan 120 utas, menyebabkan 100000+ file dibuka, ada solusi apa sekarang?

@mygoda kamu menggunakan periode yang luar biasa。

@ 1a1a11a _File_ apa yang Anda buka? Itu akan menjadi langkah pertama yang berguna untuk memahami masalah ini.

@ 1a1a11a versi permintaan apa yang Anda gunakan? Versi python apa? Sistem operasi apa? Bisakah kita mendapatkan informasi apapun?

Saya menggunakan request 2.9.1, python 3.4, ubuntu 14.04, pada dasarnya saya menulis crawler menggunakan 30 utas dengan proxy untuk merayapi beberapa situs web. Saat ini saya telah menyesuaikan batas file per proses menjadi 655350, jika tidak maka akan melaporkan kesalahan.

Saya masih menerima pesan kesalahan "Gagal membuat koneksi baru: [Errno 24] Terlalu banyak file terbuka" dari requests.packages.urllib3.connection.VerifiedHTTPSConnection. "Saya menggunakan Python 3.4, permintaan 2.11.1 dan permintaan-futures 0.9.7. Saya menghargai permintaan-futures adalah pustaka yang terpisah, tetapi sepertinya kesalahan berasal dari permintaan. Saya mencoba membuat 180k permintaan asinkron melalui SSL. Saya telah membagi permintaan itu menjadi segmen 1000, jadi saya hanya pindah ke 1000 berikutnya setelah semua objek masa depan telah diselesaikan. Saya menjalankan Ubuntu 16.04.2 dan batas file terbuka default saya adalah 1024. Akan lebih baik untuk memahami alasan yang mendasari kesalahan ini. Apakah perpustakaan permintaan membuat file terbuka untuk setiap permintaan individu? Dan jika demikian, mengapa? Apakah ini file sertifikat SSL? Dan apakah pustaka permintaan secara otomatis menutup file yang terbuka itu ketika objek di masa mendatang diselesaikan?

Permintaan membuka banyak file. Beberapa file tersebut dibuka untuk sertifikat, tetapi dibuka oleh OpenSSL dan bukan oleh Permintaan, jadi file tersebut tidak dipertahankan. Selain itu, Permintaan juga akan membuka, jika diperlukan, file .netrc , file host, dan banyak lainnya.

Anda akan mendapatkan layanan terbaik dengan menggunakan alat seperti strace untuk menentukan file mana yang dibuka. Ada daftar ketat panggilan sistem yang mengarah ke deskriptor file yang dialokasikan, jadi Anda harus dapat dengan cepat menghitungnya. Itu juga akan memberi tahu Anda apakah ada masalah atau tidak. Tapi, ya, saya berharap jika Anda secara aktif membuat 1000 koneksi melalui HTTPS maka pada beban puncak kita dapat dengan mudah menggunakan lebih dari 1000 FD.

Saya berjuang dengan masalah ini juga dan menemukan bahwa menggunakan opensnoop pada OS X bekerja sangat baik untuk membiarkan saya melihat apa yang terjadi jika ada yang mengalami masalah yang sama.

Saya juga sering melihat kesalahan ini ketika berulang kali memanggil requests.post(url, data=data) ke server HTTP (bukan HTTPS). Berjalan di Ubuntu 16.04.3, Python 3.5.2, meminta 2.9.1

Apakah data ?

Beberapa ratus kb teks

Bukan objek file?

Tidak, saya membentuk kueri besar di memori.

Apakah Anda menjalankan kode ini di beberapa utas?

Tidak, utas tunggal, memposting ke localhost

Tampaknya hampir tidak mungkin bagi kita untuk membocorkan FD sebanyak itu: kita harus berulang kali menggunakan koneksi TCP yang sama atau menutupnya secara agresif. Ingin memeriksa apa yang server Anda lakukan?

Saya mengalami masalah ini. Python 2.7, permintaan 2.18.4, urllib3 1.22.
Menjalankan kode multi-thread (bukan multi-proses). Menghubungkan ke paling banyak 6 URL sekaligus, membuat dan menutup sesi baru secara manual untuk masing-masing URL.

Saya mengalami masalah yang sama pada Python 3.5 , requests==2.18.4

@mcobzarenco apakah Anda yakin (secara implisit) menutup koneksi yang mendasari respons? Sekadar mengembalikan respons tidak akan menutup koneksi. Saat membaca response.content, data sebenarnya dibaca dan setelah itu soket tidak akan tinggal di CLOSE_WAIT.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

cnicodeme picture cnicodeme  ·  3Komentar

justlurking picture justlurking  ·  3Komentar

NoahCardoza picture NoahCardoza  ·  4Komentar

ReimarBauer picture ReimarBauer  ·  4Komentar

avinassh picture avinassh  ·  4Komentar