Блог

Як я монолітний проєкт Tip2Go на мікросервіси розділяв

Юрій Мельников

Коли проєкт Tip2Go почав розростатися, довелося терміново змінювати його архітектуру. Оскільки спочатку проєкт задумувався невеликим і був зроблений у форматі моноліту, то розділення його на сервіси виявилося цікавою задачею!

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

Оскільки Tip2Go спочатку задумувався як бот у Telegram з обмеженим функціоналом, я починав його робити як моноліт, що містить у собі весь функціонал. Це дійсно зручно, коли пакуєш усе в Docker і для деплою достатньо виконати одну команду.

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

А це означає, що з проєкту можна легко виокремити потрібні об'єкти і досить швидко перенести їх в інший проєкт, без шкоди для основного. Все ж, принцип єдиної відповідальності (single responsibility), за який відповідає літера S в абревіатурі SOLID, дуже важливий. Адже, якби я в об'єкти додавав зайвий функціонал, то виділити їх в окремий сервіс так просто не вдалося б.

Отже, що ж із себе представляє проєкт після розділення на сервіси?

Балансувальник на вході, за ним 4 сервіси, база даних на окремому сервері без зовнішнього IP, а файли зберігаються в S3.

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

У проєкті назовні дивиться тільки один IP і на ньому сидить балансувальник, який перенаправляє запити на внутрішні сервіси.

Якщо запитано картинку, то запит перенаправляється на сервіс із файлами. Тут я реалізував давню ідею з картинками, точніше з перевіркою їх існування на сервері і повернення заглушки, замість картинки, якщо вона не знайдена.

Якщо користувач хоче зайти в панель управління, то йому потрібно спочатку авторизуватися на основному сервісі і мати відповідну роль у системі. В іншому випадку, користувача просто перенаправить на сторінку основного сервісу.

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

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

Але про це розповім іншим разом.