Итак, я пытался понять это уже около недели. Вот такой ход:
Я использую CURL в PHP для извлечения данных из API. По мере того, как ответ на вызов API становится больше (одновременное получение более 15 тыс. Записей), я заметил, что любой вызов API, который занимает 5 или более минут (в течение нескольких секунд), не возвращается на мои серверы CentOS и Suse. Итак, я протестировал вызов API из CLI через CURL и получил ту же проблему. Как ни странно, если я запускаю команду CURL через OS X, команда работает нормально и возвращается через ~ 7 минут или около того.
Вот команда (creds с цензурой), которую я запускаю через CURL:
curl -m 0 -k --trace-ascii trace.txt --trace-time -X GET -H "tenant-code: 1cmPx7tqVDVTdN1GSelwycFUmICmASnLCmNQsV72" -H "Authorization: Basic JxHAsXeUiHMRkS8Msiu6pWb3PvY20p6am3QvXCY3knXTAntlxTBS3EyEDgly" -H "Content-Type: application/json" -H "Cache-Control: no-cache" 'https://api.endpoint.com/API/v1/system/users/search?groupid=555' > dump.txt
А вот версия, выводимая CURL для каждой платформы:
CentOS (вот где мне это действительно нужно для работы) -
curl 7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.19.1 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2
Protocols: tftp ftp telnet dict ldap ldaps http file https ftps scp sftp
Features: GSS-Negotiate IDN IPv6 Largefile NTLM SSL libz
Suse-
curl 7.19.7 (x86_64-suse-linux-gnu) libcurl/7.19.7 OpenSSL/0.9.8j zlib/1.2.7 libidn/1.10
Protocols: tftp ftp telnet dict ldap ldaps http file https ftps
Features: GSS-Negotiate IDN IPv6 Largefile NTLM SSL libz
OS X-
curl 7.37.1 (x86_64-apple-darwin14.0) libcurl/7.37.1 SecureTransport zlib/1.2.5
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate IPv6 Largefile NTLM NTLM_WB SSL libz
Вот коды ошибок, которые я получаю от Centos:
curl: (56) SSL read: errno -5961
Я не могу найти этот код, на который есть ссылка в документации. https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/SSL_functions/sslerr.html
Я получаю немного другую ошибку от Suse:
curl: (52) SSL read: error:00000000:lib(0):func(0):reason(0), errno 104
Ошибка 104 заставила меня поверить, что сервер останавливает / сбрасывает соединение, но журналы на стороне сервера не показывают, что оно сбрасывается, и OS X может без проблем извлекать данные. Я даже попытался подделать User Agent, чтобы убедиться, что проблема не в этом.
Итак, на данный момент я предполагаю, что пакет SSL SecureTransport делает то, чего не делают OpenSSL и NSS. Вопрос в том, в чем, а если нет, в чем проблема?
Запустите команду curl на компьютере MacOSX, но не перенаправляйте вывод, пусть он будет передаваться в окно оболочки. Посмотрите, не задействована ли какая-либо буферизация, IE, вы получаете вывод с самого начала, по частям, или вы ничего не получаете в течение 5 минут, а затем сразу весь поток данных?
Снова запустите команду curl на машине, на которой время ожидания истекло, и сравните поведение. Если ваш вывод буферизуется каким-либо фоновым процессом на сервере API, вы не можете получить результаты, пока он не завершит свой запрос. Что-то между вашим клиентским приложением, вашей клиентской ОС, серверной ОС, серверным REST api и SSL между ними, вероятно, имеет значение тайм-аута, отличное от нуля, и если этот таймер не видит никаких данных в течение 5 минут, он может закрыть ваше соединение, не объясняя причин. Я вижу, что это часто происходит в службах на основе HTTP. В perl я обычно ставлю $|=1;
в верхней части кода, чтобы отключить буферизацию вывода на стороне сервера.
Также возможно, что стороннее устройство, такое как Cisco ASA, может иметь тайм-аут правил NAT и проблемы с запуском. У меня есть эта проблема с резервными копиями AMANDA, которые пытаются прочитать от клиента на внешней стороне ASA. Если клиенту требуется слишком много времени, чтобы вернуть свои оценки размера через ASA обратно на сервер AMANDA, ASA отбрасывает свое правило динамического NAT и резервное копирование терпит неудачу. Это предложение стоит изучить, если у работающей MacOSX нет брандмауэра между ним и сервером API, а у тех, которые не работают, он есть.
Меня нисколько не удивит, если в MacOSX значение тайм-аута установлено где-то на 0 (ждать вечно), тогда как Linux по умолчанию имеет ограничение в 60 или 90 секунд.