Вызов urllib блокируется в пуле соединений на очень низкой частоте
Я использую сторонний API, который использует urllib (не уверен, какая версия), через некоторое время вызов будет заблокирован, и последним входом в службу будет "Сброс сброшенного соединения...", который можно найти из исходного кода пула соединений.py в urllib3:
connnectionpool.py
def _get_conn(self, timeout=None):
"""
Get a connection. Will return a pooled connection if one is available.
If no connections are available and :prop:`.block` is ``False``, then a
fresh connection is returned.
:param timeout:
Seconds to wait before giving up and raising
:class:`urllib3.exceptions.EmptyPoolError` if the pool is empty and
:prop:`.block` is ``True``.
"""
conn = None
try:
conn = self.pool.get(block=self.block, timeout=timeout)
except AttributeError: # self.pool is None
raise ClosedPoolError(self, "Pool is closed.")
except Empty:
if self.block:
raise EmptyPoolError(self,
"Pool reached maximum size and no more "
"connections are allowed.")
pass # Oh well, we'll create a new connection then
# If this is a persistent connection, check if it got disconnected
if conn and is_connection_dropped(conn):
log.info("Resetting dropped connection: %s" % self.host)
conn.close()
if getattr(conn, 'auto_open', 1) == 0:
# This is a proxied connection that has been mutated by
# httplib._tunnel() and cannot be reused (since it would
# attempt to bypass the proxy)
conn = None
return conn or self._new_conn()
Затем я проверяю conn.close, думаю, он может быть заблокирован в закрытой функции:
def close(self):
"""
Close all pooled connections and disable the pool.
"""
# Disable access to the pool
old_pool, self.pool = self.pool, None
try:
while True:
conn = old_pool.get(block=False)
if conn:
conn.close()
except Empty:
pass # Done.
Таким образом, это означает, что old_pool не получает ничего, кроме блокировки здесь. Поскольку old_pool - это LifoQueue, а block=False означает возврат, если данные не получены, поэтому здесь нет проблем.
Тем не менее, я встретил блок через некоторое время (хотя и на очень низкой частоте), мне интересно, какая возможная причина для этого причина?
Спасибо за вашу помощь
===============================
На самом деле я использую Facebook Ads SDK для вызова API Facebook, который выдает последнее сообщение журнала перед блокировкой:
"logs/aam.log.bk.2015111802:[connectionpool.py:238 - _get_conn Wed, 18 Nov 2015 02:11:21;INFO] Resetting dropped connection: graph.facebook.com"
Вот почему я предполагаю, что это связано с conn.close в urllib, потому что, похоже, нет другого блока в Facebook Ads SDK и urllib3 (И еще одна странная вещь - Facebook SDK, похоже, использует запросы, отличные от urllib напрямую, поэтому я не знаю, почему это связано с urllib, научите меня, если знаете, я просто задаю один вопрос в службу поддержки FB)
Из исходного кода Facebook SDK он должен быть связан со следующим кодом в facebookads/api.py:
# Get request response and encapsulate it in a FacebookResponse
if method in ('GET', 'DELETE'):
response = self._session.requests.request(
method,
path,
params=params,
headers=headers,
files=files,
)
else:
response = self._session.requests.request(
method,
path,
data=params,
headers=headers,
files=files,
)
fb_response = FacebookResponse(
body=response.text,
headers=response.headers,
http_status=response.status_code,
call={
'method': method,
'path': path,
'params': params,
'headers': headers,
'files': files,
},
)
Как описал вопрос о происхождении, это происходит с очень низкой частотой, но это происходит в разных API, которые все делают вышеупомянутый вызов на более низком уровне.
Пожалуйста, скажите мне, если нужна другая информация, спасибо за вашу помощь ~