OkHttp буферизует ~800kb перед загрузкой данных, несмотря на flush()
Я пытаюсь опубликовать процесс загрузки изображений, загружая их, используя okhttp в качестве моего клиента и mimecraft, чтобы упаковать файл из нескольких частей.
Я добавил журналы, чтобы записать байтовый счет, когда данные записываются в сокет (кусками по 4 Кб, если я могу правильно сказать), а затем загружаются.
Проблема в том, что, хотя я вызываю flush для выходного потока каждый раз, когда записывается кусок данных, кажется, что ничего не загружается, пока ~800kb не будет записано в выходной поток. Как только он достигает этой точки, кажется, что он загружает ~100 КБ, и приложение затем записывает еще 100 КБ в выходной поток (например, его освободившееся пространство и может записать немного больше) и продолжает работу.
В результате (более 1,2 МБ файла) первые 800 КБ записываются / регистрируются практически мгновенно, а затем начинают загрузку (отслеживается через сетевое программное обеспечение charles), а затем начинают чтение / запись / загрузку 100 КБ в течение следующего несколько секунд, а затем, как только я записал последние байты в выходной поток, приложение сообщает, что записано 100% загрузки. Это правда, хотя, поскольку сетевой клиент все еще загружает последние 800 КБ, которые все еще находятся в сетевом буфере, и он сидит там еще 5-10 секунд, загружая это, затем завершает запрос.
Кто-нибудь имел такой опыт, или знает, это распространенная проблема в охттп?
ура
РЕДАКТИРОВАТЬ: если я загружаю файл размером менее 800 КБ, я протестировал около 250 КБ и 500 КБ, и все они записываются на 100% в поток сразу перед загрузкой, но изображение размером 3 МБ все равно будет загружать 800 КБ, а затем отметится примерно в 100 КБ. и цикл записи сидит там, записывая еще 100 КБ каждый раз, когда некоторые загружаются.
3 ответа
Поскольку ответ от @nmr сказал, что это потому, что буфер отправки слишком высок, как объяснено в билете об ошибке здесь: https://github.com/square/okhttp/issues/1078
Итак, я создал фабрику сокетов, которая позволяет вам переопределять размер буфера отправки.
https://gist.github.com/slightfoot/00a26683ea68856ceb50e26c7d8a47d0
По умолчанию для буфера отправки сокета установлено высокое значение, и сброс не выполняется. Я безуспешно пытался найти способ синхронизации сокета Java, по умолчанию Socket OutputStream игнорирует сбрасывания.
https://github.com/square/okhttp/issues/1078
Ужасная рубка установки размера буфера отправки здесь: https://github.com/ACMEAtronOmatic/okhttp/tree/topic/hack-to-fix-socket-sendbuffer-size
Попробуйте позвонить setFixedLengthStreamingMode(content length)
или же setChunkedStreamingMode(0)
прежде чем открыть поток вывода.