#python #docker #curl #python-requests #pycurl
#python #docker #curl #python-запросы #pycurl
Вопрос:
Я пытаюсь ПОЛУЧИТЬ данные из внешней службы, используя Python, из контейнера Docker. Мне нужно достичь двух разных конечных точек, скажем:
endpointA = "https://myhost:1234/resA" # Requests take about 1 minute to complete
endpointB = "https://myhost:1234/resB" # Requests take about 8 minutes to complete
Я пытался использовать две разные библиотеки, запросы:
import requests
headers = {'Authorization': 'Basic XXXXXXXXXXXXXXXXXXXXXX', 'Content-Type': 'application/json'}
response = requests.get(endpointA, verify=False, headers=headers)
и Pycurl:
import pycurl
headers = ['Authorization: Basic XXXXXXXXXXXXXXXXXXXXXX', 'Content-Type: application/json']
buffer = BytesIO()
c = pycurl.Curl()
c.setopt(c.VERBOSE, True)
c.setopt(c.URL, endpointA)
c.setopt(c.WRITEDATA, buffer)
c.setopt(c.SSL_VERIFYPEER, False)
c.setopt(c.SSL_VERIFYHOST, False)
c.setopt(c.HTTPHEADER, headers)
c.perform()
c.close()
Мой код выполняется без проблем с локального (возвращаются как endpointA, так и endpointB).
При запуске внутри контейнера Docker запросы к endpointA работают, но запрос к endpointB вызывает исключения через 300 секунд:
в случае запросов:
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/urllib3/connectionpool.py", line 670, in urlopen
httplib_response = self._make_request(
File "/usr/local/lib/python3.8/site-packages/urllib3/connectionpool.py", line 426, in _make_request
six.raise_from(e, None)
File "<string>", line 3, in raise_from
File "/usr/local/lib/python3.8/site-packages/urllib3/connectionpool.py", line 421, in _make_request
httplib_response = conn.getresponse()
File "/usr/local/lib/python3.8/http/client.py", line 1347, in getresponse
response.begin()
File "/usr/local/lib/python3.8/http/client.py", line 307, in begin
version, status, reason = self._read_status()
File "/usr/local/lib/python3.8/http/client.py", line 276, in _read_status
raise RemoteDisconnected("Remote end closed connection without"
http.client.RemoteDisconnected: Remote end closed connection without response
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/requests/adapters.py", line 439, in send
resp = conn.urlopen(
File "/usr/local/lib/python3.8/site-packages/urllib3/connectionpool.py", line 726, in urlopen
retries = retries.increment(
File "/usr/local/lib/python3.8/site-packages/urllib3/util/retry.py", line 403, in increment
raise six.reraise(type(error), error, _stacktrace)
File "/usr/local/lib/python3.8/site-packages/urllib3/packages/six.py", line 734, in reraise
raise value.with_traceback(tb)
File "/usr/local/lib/python3.8/site-packages/urllib3/connectionpool.py", line 670, in urlopen
httplib_response = self._make_request(
File "/usr/local/lib/python3.8/site-packages/urllib3/connectionpool.py", line 426, in _make_request
six.raise_from(e, None)
File "<string>", line 3, in raise_from
File "/usr/local/lib/python3.8/site-packages/urllib3/connectionpool.py", line 421, in _make_request
httplib_response = conn.getresponse()
File "/usr/local/lib/python3.8/http/client.py", line 1347, in getresponse
response.begin()
File "/usr/local/lib/python3.8/http/client.py", line 307, in begin
version, status, reason = self._read_status()
File "/usr/local/lib/python3.8/http/client.py", line 276, in _read_status
raise RemoteDisconnected("Remote end closed connection without"
urllib3.exceptions.ProtocolError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
в случае pycurl:
Traceback (most recent call last):
File "test.py", line 230, in get_data
c.perform()
pycurl.error: (52, 'Empty reply from server')
Это происходит только из Docker, так как с моей консоли все работает нормально.
Я пробовал оба изображения Docker на python: 3.6 и python: 3.8.
Я также попытался свернуть обе конечные точки изнутри контейнера, и сервер отвечает правильно.
Комментарии:
1. Поскольку запуск конечной точки B занимает 8 минут, я предполагаю, что это очень ресурсоемкий процесс. Я думаю, что происходит то, что контейнер docker для endpointB использует процессор или память более чем на 100%, что приведет к отсутствию ответа на запрос GET, следовательно, вы ошибка. Это конкретно 300 секунд, потому что именно столько времени может потребоваться, чтобы превысить 100% mem. Вы можете проверить это, запустив конечную точку B, затем ssh в контейнер отслеживает использование с помощью
watch htop
. Процесс завершится сбоем, если использование mem превысит 100%. Вы можете исправить это, выделив больше ресурсов движку docker.2. Спасибо за ответ, но здесь не повезло. Процесс перегружен ресурсами на стороне сервера, мой клиент только ожидает и получает ответ (несколько КБ). В любом случае, я попытался выделить больше ресурсов, но проблема остается, и мониторинг не показывает проблем с ресурсами.
Ответ №1:
Вы можете проверить, завершает ли docker соединение, используя nc -l
вне контейнера и nc
в контейнере для подключения к первому nc, затем оставив их обоих в покое на 10 минут, а затем отправив что-либо, чтобы убедиться, что соединение все еще работает.
Для устранения неполадок в pycurl см.http://pycurl.io/docs/latest/troubleshooting.html#transfer-related-issues.