Все статьи из цикла AWS

В третьей истории расскажу, как я страдал от сетевых проблем в Амазоне. Как абонент Уральский: раньше не было разрывов, а теперь есть разрывы.

У нас в проекте много лямбд, и каждая вызывает другие. При таком раскладе невыгодно передавать результат напрямую. Можно использовать S3 как шину данных. Например, одна лямбда вызывает другую и говорит: положи результат в такой-то бакет и файл. Затем опрашивает файл, пока он не появится.

Это удобно, когда результат огромен: иные лямбды производят CSV-шки по нескольку гигабайт. Не гонять же их напрямую между лямбдами. Но файлы привносят хаос: не всегда очевидно, кто произвел файл и кто его потребители. Если изменить путь, через день придет коллега из другого сервиса и скажет: мы каждый день забираем файл из этой папки, куда он делся? Или наоборот: ты обнаружил, что некий сервис производит удобный файл, в котором все есть. Через месяц он перестал появляться, потому что они переехали на что-то другое. Мы вам ничего не обещали.

Файлы CSV удобно стримить прямо из S3. Послал GET-запрос, получил InputStream. Передал его в парсер и готово: получается ленивая коллекция кортежей. Навесил на нее map/filter, все обработалось как нужно, красота. Не нужно сохранять файл на диск.

То же самое с форматом JSONL, где каждая строка — отдельный объект JSON. Из стрима получаешь Reader, из него ленивый line-seq, и пошел колбасить.

Неожиданно это схема перестала работать с большими файлами. Где-то на середине цикл обрывается с IOException. Чего я только не пробовал: оборачивал стрим в BufferedInputStream с разным размером, засекал время обработки, передавал опции в к S3… ничего не помогло. Запросы в Гугл тоже ничего внятного выдали.

У меня подозрение, что дело в неравномерном чтении. Когда вы читаете файл, Амазон определяет скорость забора байтиков. Поскольку мы читаем и обрабатываем стрим в одном потоке, чтение чередуется с простоем на обработку данных. В больших файлах я нашел записи, которые больше других во много раз. Возможно, что когда обработка доходила до них, ожидание было больше среднего, и Амазон закрывал соединение.

Я пытался повторить это на публичных файлах S3: читал в цикле N байтов и где-то на середине ставил длинный Thread/sleep. Но S3 покорно ждал аж две минуты, и эксперимент провалился.

Словом, я так и не выяснил, почему вылазит IOException, но смог это исправить в два шага.

Первый — файл S3 тупо записывается во временный файл, и дальше с ним работаешь локально. Перенос стрима делается одним методом InputStream.transferTo. Во время переноса ошибки связи не возникают.

Второй — иные агрегаты достигают 3.5 гигабайтов, а у лямбды ограничение на 10 гигабайтов места. Скачал три агрегата — и привет, out of disk space. Поэтому при записи файл кодируется Gzip-ом, а при чтении — декодируется обратно.

Все вместе дало мне функцию, которая:

  • посылает запрос к S3, получает стрим
  • создает временный файл
  • переносит стрим в файл, попутно сжимая Gzip-ом
  • возвращает GzipInputStream из файла

Со стороны кажется, что вызвал get-s3-reader — и байтики потекли, делов-то. А внутри вот какие штучки.

Примечательно, что в одном проекте я сам спровоцировал IOException. Разработчик до меня позаботился о переносе файла S3 во временный файл. Я подумал, что он просто не знает, как обработать данные из сети и убрал запись на диск. Возможно, он что-то знал, но не оставил комментария. А надо было!

Из этой истории следует: никогда не обрабатывайте файл S3 сразу из сети. Сохраните его во временный файл и потом читайте локально — так надежней. Рано или поздно вы схватите IOException, а на расследование будет времени. Чтобы сэкономить диск, оберните файл в Gzip.


На этом я закончу истории про Амазон. У меня есть еще несколько, но они не такие интересные и сводятся к тезису “думал так, а оно эдак”. Ну и обсасывать одну и ту же тему уже не хочется.

Думаю, вы поняли, что в Амазоне хватает странностей. Это не баги, потому что все они описаны в документации. Примерно как в Javascript: никто не знает, почему {} + [] = 0, а [] + {} = [object Object]. Да, в стандарте описано, но кому от этого легче? Выбирая Амазон, закладывайте время и деньги на подобные непонятки.