Есть пользователь, у них часть запросов на копирование из Uploadcare в S3 (/files/remote_copy/) отваливвется по таймауту. Удалось выяснить, что их клиент не закрывал соединение, и они настроили закрытие сокета через 5 секунд, что помогло снизить кол-во проблемных запросов с 250/день до 4-8/день, но проблема все-же сохраняется. Они пробовали увеличить keep-alive до 6 секунд, но без успеха.
! Causing: javax.net.ssl.SSLException: Connection reset
! at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:127)
! at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:326)
! at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:269)
! at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:264)
! at java.base/sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1576)
! at java.base/sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:974)
! at org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:137)
! at org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:153)
! at org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:280)
! at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:138)
! at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:56)
! at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259)
! at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:163)
! at org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:157)
! at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:273)
! at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
! at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:272)
! at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
! at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
! at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
! at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
! at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
! at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
! at com.uploadcare.api.RequestHelper.executeQuery(RequestHelper.java:159)
! ... 73 common frames omitted
! Suppressed: java.net.SocketException: Broken pipe (Write failed)
! at java.base/java.net.SocketOutputStream.socketWrite0(Native Method)
! at java.base/java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:110)
! at java.base/java.net.SocketOutputStream.write(SocketOutputStream.java:150)
! at java.base/sun.security.ssl.SSLSocketOutputRecord.encodeAlert(SSLSocketOutputRecord.java:81)
! at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:357)
! ... 95 common frames omitted
! Causing: com.uploadcare.exceptions.UploadcareNetworkException: Network failure!
! at com.uploadcare.api.RequestHelper.executeQuery(RequestHelper.java:169)
! at com.uploadcare.api.Client.copyFileRemoteStorage(Client.java:651)
Гипотеза от нашего девопса:
Моя гипотеза, что в клиенте на Java плохая конфигурация пула HTTP соединений: инициализируется пул, устанавливается соединение, производится запрос и обмен данными, соединение возвращается в пул до следующего запроса, через 630 секунд AWS ELB закрывает соединение, на клиенте соединение забирается из пула, отправляется запрос, всё сваливается с исключением из-за закрытого соединения. Введением таймаута в 6 секунд устранили эту ситуацию, но приобрели проблему раннего закрытия соединения. Нужен более глубокий анализ библиотеки.
Сейчас предложу клиенту увеличить таймаут до 30 секунд, чтобы он был эквивалентен нашему таймауту на бэкенде. Пока они наблюдают, изучу, может ли потенциально время обработки запроса на копирование упираться в наш таймаут — статистические выбросы в 15-20 секунд выглядят подозрительными.
Продолжение от нашего девопса:
Выяснил, операция копирования для клиента синхронная, таймаут 600 секунд. Если предложенное выше увеличение таймаута до 30 секунд существенно улучшит ситуацию (при условии, что больших файлов, на которые требуется более 30 секунд у клиента немного), нужно будет следующим этапом увеличить таймаут до 600 секунд, пока мейнтейнеры библиотеки Java не дадут свои рекомендации на сей счёт.
Технический бэкграунд для истории: запрос к API /files/remote_copy/ внутренне переадресуется к robots через accel redirect, где синхронно для клиента и выполняется копирование. Время копирования зависит от размера файла. Таймаут определяется таймаутом ELB и для api, и для robots.
Пользователю пока предложили увеличить лимит до 30 и понаблюдать.