Я создаю базовый генератор нагрузки и начал работать с ограничениями файловых дескрипторов, я не видел никакой документации, касающейся того, как освобождать ресурсы, поэтому либо я делаю это неправильно, и документы нуждаются в обновлении, либо запросы утекают дескрипторы файлов где-то (без поддержки для поддержки активности меня немного смущает, почему какие-либо файлы вообще остаются открытыми)
Где вы используете requests.async
?
нет, все запросы были достаточно простыми request.get / requests.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, как это исправить?
Я сделаю больше тестов как можно скорее и постараюсь исправить.
Я изучил это и, похоже, проблема со всеми библиотеками, использующими httplib.HTTPSConnection.
Разместил здесь пример:
Я только что столкнулся с очень похожей ошибкой, используя асинхронный пул только с HTTP-соединениями - я все еще изучаю, но передача размера пула в async.map позволяет быстро воспроизвести ошибку.
Какие-нибудь исправления к этому? Это делает запросы непригодными для использования с gevent ..
Все дело в CLOSE_WAIT
s. Просто надо их закрыть. Я не уверен, почему они все еще открыты.
Это проблема с urllib3? Мне кажется, что закрывать их самостоятельно - не лучшая идея.
Это скорее общая проблема. Мы можем продолжить разговор здесь.
Хорошо, просто чтобы дать вам представление, мы пытаемся перейти от httplib2 к запросам, и мы не видим этой проблемы с httplib2. Так что это точно не общая проблема.
В общем, я имею в виду, что это очень серьезная проблема, которая затрагивает всех участников.
так как мы это решим? мы действительно хотим использовать запросы + дремоту двигаться вперед
Я хотел бы знать ответ на этот вопрос.
Утечка, по-видимому, связана с обработкой внутреннего перенаправления, которая вызывает создание новых запросов до того, как ожидающие ответы будут использованы. При тестировании acdha @ 730c0e2e2bef77968a86962f9d5f2bebba4d19ec имеет
Это потребовало изменений в двух местах, из-за чего мне захотелось немного реорганизовать интерфейс, но сейчас у меня нет времени, чтобы продолжить.
Я столкнулся с той же проблемой при использовании async - решил обходной путь, разбив запросы и удалив ответы / вызвав gc.collect
Мне кажется, я столкнулся с этим сегодня, когда подключался к лицензированному серверу, который разрешает только 5 подключений.
Используя async, я смог ПОЛУЧИТЬ только 4 вещи, прежде чем он приостановился на 60 секунд.
Используя обычный GET с потреблением, я мог получить около 150 вещей последовательно менее чем за 40 секунд.
Еще не сделал свой кладж с тех пор, как увидел эту проблему.
Только что получил эту ошибку при использовании ipython и получил это сообщение. Это просто выполнение каждого запроса по одному, но я думаю, что получил нечто подобное при использовании 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.
Как ни странно, я думаю, что при использовании обычного интерпретатора Python я получаю «Max Retries Error», но я думаю, что это еще одна проблема, когда я выполняю запросы во всем том же домене, но не уверен.
Я столкнулся с этим в первом своем проекте, где allow_redirects был True; По всей видимости, это вызвано утечкой объектов ответа в цепочке перенаправления, которые не выпускаются даже с prefetch = True. Это исправило это в моем первоначальном тестировании:
[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()
@acdha
Я просто использовал цикл for через список URL-адресов и делал request.get для каждого с моими настройками и т. Д.
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
Где-то в диапазоне 20k я начал получать ошибку 24, затем все было нормально через 30k, а затем снова.
Есть дополнительная информация, которая может вас заинтересовать, чтобы сузить круг вопросов?
requests.async
больше нет. Вы можете подумать о переходе на grequests.
Все хорошо, спасибо. Было бы хорошо упомянуть об этом в документации.
Что-то вроде новичка, когда дело доходит до запросов на вытягивание и написания документации, но я попробовал и отправил. Прокомментируйте или покритикуйте :)
Хорошо, это происходит даже без использования async, с помощью только requests.get, после 6K запросов.
Я подозревал это.
Для меня ошибка «Слишком много открытых файлов» возникла после загрузки ровно 1k файлов. Мое решение заключалось в том, чтобы отключить свойство keep-alive, когда-либо получать запросы кусками ( @acdha спасибо за подсказку). 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
Кто-нибудь еще сталкивается с этой проблемой?
Я не слышал об этом. Ты?
Это проблема конфигурации коробки, а не фреймворка. Посмотрите конфигурацию ядра вашей ОС. В BSD это называется kern.maxfiles
. В системах Linux есть поток о ulimit
: 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 тоже не работает. Сможете ли вы легко воспроизвести утечку?
Мы используем request в нашем внутреннем приложении с понедельника и сегодня достигли 1024 maxfiles.
Через 2 часа после перезагрузки у нас 40 CLOSE_WAIT, как сообщает lsof.
Так что я думаю, что мы сможем воспроизводить в среде разработки, да. Я буду держать тебя на связи
@tardyp тоже, как вы устанавливали запросы? Я думаю, что все разработчики пакетов ОС убирают urllib3. Если они не обновляют это, и вы используете старую версию, это может быть причиной. Если вы используете pip, не стесняйтесь открывать новую проблему, чтобы отслеживать это, вместо того, чтобы добавлять обсуждение к этому.
Я установил с помощью pip, но я использую python 2.6, я видел исправление на python2.7 для
этот баг. Вы обновляете более старую версию?
Пьер
Пт, 29 ноября 2013 г., в 17:33, Ян Кордаско [email protected] написал:
@tardyp https://github.com/tardyp тоже, как вы устанавливали запросы? я
думаю, что все разработчики пакетов ОС вырезают urllib3. Если они этого не сделают
обновляйте его, и вы используете старую версию, это может быть
причина вместо этого. Если вы используете pip, не стесняйтесь открывать новый выпуск в
отслеживайте это с помощью вместо добавления обсуждения к этому.-
Ответьте на это письмо напрямую или просмотрите его на Gi tHubhttps: //github.com/kennethreitz/requests/issues/239#issuecomment -29526302
.
@tardyp, пожалуйста, откройте новую проблему с как можно более подробной информацией, в том числе о том, имеют ли ваши запросы перенаправления и используете ли вы gevent. Кроме того, любые подробности об операционной системе и пример того, как ее воспроизвести, были бы фантастическими.
К вашему сведению, https://github.com/shazow/urllib3/issues/291 был отменен из-за ошибок.
Должны ли мы снова открыть это?
У меня такая же проблема!
@polvoazul Нет никакого
@Lukasa, мне нужна твоя помощь。 я использую eventlet + запросы ,, которые всегда создают так много sock, которые не могут идентифицировать протокол。 мои запросы - 2.4.3, это eventlet + запросы вызывают эту проблему?
Мне очень жаль, @mygoda , но это невозможно узнать. Если вы не ограничиваете количество запросов, которые могут быть невыполненными в любой момент времени, это, безусловно, возможно, но это архитектурная проблема, выходящая за рамки компетенции запросов.
Имея такую же проблему сейчас, при запуске 120 потоков, вызывающих более 100000 открытых файлов, есть ли решение прямо сейчас?
@mygoda, у тебя
@ 1a1a11a _Какие_ файлы у вас открыты? Это было бы первым полезным шагом к пониманию этой проблемы.
@ 1a1a11a какую версию запросов вы используете? Какая версия питона? Какая операционная система? Можем ли мы получить какую-нибудь информацию?
Я использую запрос 2.9.1, python 3.4, ubuntu 14.04, в основном я пишу краулер, использующий 30 потоков с прокси для сканирования какого-либо веб-сайта. В настоящее время я установил ограничение на количество файлов для каждого процесса до 655350, в противном случае будет отображаться сообщение об ошибке.
Я все еще получаю сообщение об ошибке «Не удалось установить новое соединение: [Errno 24] Слишком много открытых файлов» из requests.packages.urllib3.connection.VerifiedHTTPSConnection. «Я использую Python 3.4, запросы 2.11.1 и запросы-фьючерсы» 0.9.7. Мне нравится, что запросы-фьючерсы - это отдельная библиотека, но похоже, что ошибка возникает из-за запросов. Я пытаюсь выполнить 180 тыс. Асинхронных запросов через SSL. Я разделил эти запросы на сегменты по 1000, поэтому я переходите к следующей 1000 только после того, как все будущие объекты будут разрешены. Я использую Ubuntu 16.04.2, и мое ограничение на количество открытых файлов по умолчанию - 1024. Было бы хорошо понять основную причину этой ошибки. Создает ли библиотека запросов открыть файл для каждого отдельного запроса? И если да, то почему? Является ли это файлом сертификата SSL? И закрывает ли библиотека запросов автоматически эти открытые файлы при разрешении будущего объекта?
Запросы открывает много файлов. Некоторые из этих файлов открываются для сертификатов, но они открываются OpenSSL, а не запросами, поэтому они не обслуживаются. Кроме того, запросы также при необходимости открывают файл .netrc
файл hosts и многие другие.
Лучше всего использовать такой инструмент, как strace
чтобы определить, какие файлы открываются. Существует строгий список системных вызовов, которые приводят к выделению файловых дескрипторов, поэтому вы должны достаточно быстро уметь их перечислить. Это также позволит вам узнать, есть ли проблема. Но да, я ожидал, что если вы активно устанавливаете 1000 подключений по HTTPS, то при пиковой нагрузке мы могли бы легко использовать более 1000 FD.
Я тоже боролся с этой проблемой и обнаружил, что использование opensnoop
в OS X отлично работает, позволяя мне видеть, что происходит, если кто-то сталкивается с теми же проблемами.
Я также часто вижу эту ошибку при многократном вызове requests.post(url, data=data)
на сервер HTTP
(не HTTPS). Работает на Ubuntu 16.04.3, Python 3.5.2, запросы 2.9.1
Что такое data
?
Текст в несколько сотен килобайт
Не файловый объект?
Нет, формирую в памяти большой запрос.
Вы запускаете этот код в нескольких потоках?
Нет, один поток, отправка на localhost
В таком случае кажется почти невозможным утечка такого количества FD: мы должны многократно использовать одно и то же TCP-соединение или агрессивно его закрывать. Хотите узнать, чем занимается ваш сервер?
У меня такая проблема. Python 2.7, запросы 2.18.4, urllib3 1.22.
Запуск многопоточного кода (не многопоточного). Подключение максимум к 6 URL-адресам за один раз, создание и закрытие нового сеанса для каждого вручную.
У меня такая же проблема с Python 3.5
, requests==2.18.4
@mcobzarenco , вы уверены, что (неявно) закрываете базовое соединение ответа? Простой возврат ответа не приведет к закрытию соединения. При чтении response.content данные фактически считываются, и после этого сокет не останется в CLOSE_WAIT.
Самый полезный комментарий
«Слишком много открытых файлов» - это результат ошибки, вызванной тем, что сокеты остаются в CLOSE_WAIT.
Так что ulimit не исправит, просто найдет обходной путь.