Як замовник хотів blob замість cache

Як замовник хотів blob замість cache

Відразу введу в курс справи, це був легасі проект і завдання було доопрацювання одного ендпоінта, який повинен повертати величезну Json-ніну. За підсумком роботи середня кількість рядків у респонсі була 800.000-2.000.000 рядків і важила вона в районі 30 мб.


На цьому проекті я з'ясував, що Postman вже ламається від 1.000.000 рядків, перестає працювати форматування і починає кульгати пошук. А в цілому весь json нагадував мені один величезний клубок снігу який пустили гори і він все розростався і розростався, тому що коли я прийшов на проект він був всього лише 40.000-80.000 рядків.

Json складався з декількох рівнів і кожен рівень мав деяку кількість подурівнів, схоже на цю картинку, тільки рівнів було в районі 8 і кожен з рівнів міг мати до 80 подурівнів.

Схема json респонсу

І в цілому весь цей JSON оброблявся в районі 4-5 хвилин, після того як на вибірку з БД прикрутили кеш, то подальший запити вже оброблялися набагато швидше 3-10 секунд. Але перший запит все одно оброблявся дуже довго.

Рішення було прийнято моментально потрібно розділити один великий ендпоінт на два поменше. У підсумку вийшло так що перший 4 рівня пішли на один ендпоінт (назвемо його summary), а наступні вже вибиралися за id на другому ендпоінті (назвемо details).

Реалізація першого ендпоінту не склала великої праці, він скоротив наш великий Json до 8.000-20.000 рядків і розміром 100-400Kb. І час запиту також зменшився до 1-3 секунд.

Середній час запиту з увімкненим кешем

Але між двома частинами все одно залишався сильний зв'язок і інформацію на details едпоінті про наступні рівні просто так взяти не вдавалося, нам потрібні були попередні дані з summary. Ми вирішили дізнатися у замовника яке рішення йому краще і як виявилося він мав своє бачення на проблему. Його ідея полягала в тому, щоб зберігати весь респонс на 30мб в blob-storage, а потім в details скачувати цей json і забирати потрібну нам інформацію. Ми були м'яко кажучи в замішанні трохи не розумію для чого взагалі тоді нам потрібен поділ одного великого ендпоінта. Ми обговорили цей момент і остаточно запропонували реалізувати дві моделі поведінки:

  1. Забирати весь json і зберігати його в blob, після в details забирати весь json з blob-а і повертати потрібну нам інформацію.
  2. У blob зберігати інформацію тільки з summary (8-20к рядків), а потім в details забирати цей json і за допомогою нього забирати додаткову інформацію.
  3. Забирати весь json і зберігати його в blob, після в details забирати весь json з blob-а і повертати потрібну нам інформацію.

За підсумком, як і очікувалося перший випадок з тріском провалився. Тільки взяття json-а з blob-storage займало по різному від 50 секунд до 4 хвилин, але тут треба обмовитися що це сильно залежить від самого blob-storage, швидкості інтернету і azure.

А другий спосіб показав себе досить вдало і в кінцевому підсумку середня швидкість була в районі 300-900 мс.

Замовника природно все влаштувало, але у нас все ще було неприємне почуття використання ресурсу не за призначенням. Ми хотіли використати кеш. На проекті, як я вже до цього згадував, був налаштований кеш і ми вирішили заюзати його.

За підсумком результат нас порадував, середній час запиту на details ендпоінт становив 90-300 мс.

В результаті працювала ця справа наступним чином.

  • Користувач звертається до першого ендпоінту summary і отримує загальну інформацію, в цей час blob записує до себе цей ендпоінт.
  • Якщо користувач хоче отримати більш детальну інформацію він звертається до details ендпоінту.
  • Той у свою чергу для початку перевіряє кеш на існування summary респонсу, якщо він його не знаходить, то тоді він полізе в blob-storage і забере його звідти (використовуємо blob як довгострокове сховище), а потім додасть в кеш з терміном життя 15 хвилин.

Таким чином нам вдалося зменшити час очікування з 5 хвилин до 1.5 секунд

Від blob-storage за підсумком ми все одно не могли відмовитися так як нам потрібно було зберігати інформацію про запити і респонси, для подальшого бізнес аналізу.

Для кешу використовувалася стороння бібліотека CacheManager яка працювала за засобом in-memory cache.