Как я могу обработать большое тело http ответа от запроса Друида в Go - PullRequest
0 голосов
/ 14 января 2020

Я сейчас запрашиваю Друида и возвращаю большой набор данных обратно (примерно 4-5 ГБ). Я хотел бы обработать этот ответ и декодировать JSON в список структур. У меня это работает нормально, когда я изменяю запрос, чтобы вернуть меньший набор данных, но как только ответ становится слишком большим, я получаю ошибку unexpected EOF.

Я попытался прочитать все тело ответа

bytes, err := ioutil.ReadAll(resp.Body)

Непосредственное декодирование тела ответа

var object []NewObject
err = json.NewDecoder(resp.Body).Decode(&object)

Создание буфера и запись в файл

f, err := os.OpenFile("/tmp/test.txt", os.O_APPEND|os.O_WRONLY, 0600)
defer f.Close()
const oneMB = 1024 * 1024
bytesRead := 0
respBuf := make([]byte, oneMB)

// Read the response body
for {
    n, err := resp.Body.Read(respBuf)
    bytesRead += n

    if err == io.EOF {
        break
   }

    if err != nil {
        fmt.Println("Error reading HTTP response: ", err.Error())
        break
    }

    if _, err = f.Write(respBuf); err != nil {
        panic(err)
    }

}

Все это закончилось тем, что я получил ошибку unexpected EOF. Я использую модуль net/http по умолчанию и encoding/json, которые, по-видимому, должны нормально работать. Могу ли я попробовать что-нибудь еще?

1 Ответ

0 голосов
/ 15 января 2020

Я понял проблему. Похоже, что у Друида есть жесткий тайм-аут запроса (эта ссылка объясняет больше об этих настройках конфигурации). Что интересно, он появляется, если вы хотите получить ответ как объект, и он слишком велик, он просто обрезает середину байтового потока, но если вы хотите получить результат в виде массива и он слишком велик, он отправит байты в fini * 1005. * текущий элемент, а затем отправьте закрывающий ], поэтому, когда вы анализируете результат, кажется, что все прошло (без ошибок), хотя вы могли быть отрезаны в среднем потоке.

...