Чому розщеплення вашої бази кодів занадто рано може тихо знищити швидкість вашої команди - і що робити замість цього.
Чому розщеплення вашої бази кодів занадто рано може тихо знищити швидкість вашої команди - і що робити замість цього.
В рамках стартапу,your survival depends on how quickly you can iterate, ship features, and deliver value to end-usersЦе місце, де фундаментальна архітектура вашого стартапу відіграє велику роль; Крім того, такі речі, як ваш технологічний штаб і вибір мови програмування, безпосередньо впливають на швидкість вашої команди.
Я мав цей досвід, коли працював над проектами зеленого поля для стартапів на ранній стадії, де були прийняті сумнівні рішення з точки зору програмної архітектури, що призвело до напівзавершених послуг таБрудні, надмірно інженеровані та зламані локальні налаштуванняІdemoralized teamsякі борються за збереження непотрібної складності.
Перш ніж зануритися в конкретні пастки, ось що ви насправді підписуєтеся, коли вводите мікрослужби передчасно:
Microservices Early On: What You’re Paying For
Pain Point |
Real-World Manifestation |
Developer Cost |
---|---|---|
Deployment Complexity |
Orchestrating 5+ services for a single feature |
Hours lost per release |
Local Dev Fragility |
Docker sprawl, broken scripts, platform-specific hacks |
Slow onboarding, frequent breakage |
CI/CD Duplication |
Multiple pipelines with duplicated logic |
Extra toil per service |
Cross-Service Coupling |
"Decoupled" services tightly linked by shared state |
Slower changes, coordination tax |
Observability Overhead |
Distributed tracing, logging, monitoring |
Weeks to instrument properly |
Test Suite Fragmentation |
Tests scattered across services |
Brittle tests, low confidence |
Складність розгортання
Організація 5+ сервісів для однієї функції
Hours lost per release
Місцева дефрагментація
Розширення Docker, зламані скрипти, хаки, специфічні для платформи
Slow onboarding, frequent breakage
CI/CD дублювання
Ряд трубопроводів з подвійною логікою
Extra toil per service
Кроссервіс Coupling
"Відключені" послуги тісно пов'язані спільним станом
Slower changes, coordination tax
Спостереження над головою
Розподілений відстеження, логінг, моніторинг
Weeks to instrument properly
Тест Suite Фрагментація
Тести розкидані по сервісах
Brittle tests, low confidence
Давайте розпакуємо, чому мікрослужби часто відступають на ранніх термінах, де вони дійсно допомагають, і як структурувати системи вашого стартапу для швидкості та виживання.
Моноліти – не ворог
Якщо ви будуєте деякий продукт SaaS, навіть простий обробник баз даних SQL в кінцевому підсумку може принести багато внутрішньої складності в тому, як працює логіка вашого бізнесу; Крім того, ви можете отримати різні інтеграції та фонові завдання, які дозволяють трансформувати один набір даних в інший.
З часом, іноді з непотрібними функціями, неминуче, що ваше додаток може розгубитися.Monoliths, even when messy, keep your team focused on what matters most:
- Залишатися живим
- Доставка клієнтської цінності
Найбільша перевага монолітів полягає в їх простоті розгортання.Зазвичай такі проекти будуються навколо існуючих рамок — це може бути Django для Python,АСП.НЕТдля C#, Nest.js для додатків Node.js і т. д. Коли ви дотримуєтеся монолітної архітектури, ви отримуєте найбільшу перевагу над фантастичними мікросервісами - широку підтримку спільноти з відкритим кодом та керівників проектів, які в першу чергу розробили ці рамки для роботи як один процес, монолітна програма.
На одному стартапі з нерухомості, де я очолював команду фронту, і іноді консультувався з командою backend щодо виборів технологій, у нас була цікава еволюція програми на базі Laravel.
З часом він перетворився на багатофункціональний пакет, який обробляв сотні гігабайтів документів і інтегрувався з десятками сторонніх сервісів.
Команда сильно спиралася на найкращі практики, рекомендовані спільнотою Laravel. Ця дисципліна виплатилася, ми змогли значно розширити можливості додатка, все одно задовольняючи потреби та очікування бізнесу.
Цікаво, що нам ніколи не потрібно було роз'єднувати систему в мікросервіси або приймати більш складні шаблони інфраструктури. Ми уникнули багато випадкової складності таким чином. Простота архітектури дала нам важелі.«Великий моноліт»Це пояснює, чому простота на ранніх термінах є суперсилою.
Люди часто вказують на те, що складно зробити моноліти масштабованими, але це погана модуляризаціяВнутрішнійМоноліт, який може викликати такі проблеми.
Takeaway: A well-structured monolith keeps your team focused on shipping, not firefighting.
Але чи не є мікропослуги «кращою практикою»?
Багато інженерів досягають мікросервісів рано, думаючи, що вони «правильним шляхом». і, звичайно, в масштабі, вони можуть допомогти.
Мікропослуги виплачуються тільки тоді, коли у вас є реальні обмеження масштабування, великі команди або самостійно розвиваються домени. до того? Ви платите ціну, не отримуючи переваги: дублювання інфра, крихкі локальні налаштування та повільна ітерація.SegmentЗрештоюЗворотний поділ мікропослугЗ цієї причини — занадто багато витрат, недостатньої вартості.
Takeaway: Microservices are a scaling tool — not a starting template.
Де мікропослуги йдуть не так (особливо на початку)
В одній команді на ранніх етапах, яку я порадив, рішення розділити послуги створило більшу координацію PM-інженерії, ніж технічний приріст. Архітектура сформувала не тільки код, але і те, як ми планували, оцінювали і відправляли.
Ось найбільш поширені антимоделі, які виникають на ранніх термінах.
Границі довільної служби
Теоретично, ви часто бачите пропозиції щодо розділення ваших додатків за доменів бізнес-логіки - сервіс користувачів, сервіс продуктів, сервіс замовлень і так далі.Це часто позичається від концепцій Дизайн на основі домену або Чиста архітектура - які мають сенс в масштабі, але на ранніх етапах продуктів вони можуть осіфікувати структуру передчасно, перш ніж сам продукт буде стабільним або підтвердженим.
- Спільні бази даних
- Cross-Service закликає до простих робочих процесів
- Спілкування маскується як «розлучення»
В одному проекті я спостерігав, як команда розділяє користувача, аутентифікацію та авторизацію на окремі сервіси, що призвело до складності розгортання та труднощів у координації послуг для будь-якої операції API, яку вони будували.
Насправді, ділова логіка безпосередньо не вказує на межі служби.Передчасне відділення може зробити систему більш крихкою і часто ускладнює швидке введення змін.
Замість цього, ізолюйте пляшки хірургічно - на основі реального масштабування болю, а не теоретичної елегантності.
Коли я навчав команди на ранніх етапах, ми іноді використовували внутрішні прапори або розгортки для імітації майбутніх поділів послуг - без безпосереднього оперативного навантаження.
Takeaway: Don’t split by theory — split by actual bottlenecks.
Репозиторій та інфраструктура Sprawl
При роботі над додатком, як правило, важливий наступний набір речей:
- Код стилю послідовності (лінтинг)
- Тестування інфраструктури, включаючи тестування інтеграції
- Конфігурація місцевого середовища
- Документація
- Конфігурація CI/CD
Якщо ваш проект структурований як монорепо, ви можете спростити своє життя, маючи центральну конфігурацію CI/CD (при роботі з GitHub Actions або GitLab CI).
Перемикання контексту між сховищами та інструментами збільшує час розробки кожної функції, яка відправляється.
Зменшення проблем за допомогою монорепо та єдиної мови програмування
Для ранніх проектів найважливіша річ - зберігати свій код в монорепо. Це гарантує, що є одна версія коду, яка існує на prod, і це набагато простіше координувати огляд коду і співпрацювати для менших команд.
Для проектів Node.js, я настійно рекомендую використовувати інструмент monorepo, якnx
абоturborepo
В обох:
- Спрощення конфігурації CI/CD між підпроектами
- Підтримка графічного кешування на основі залежності
- Нехай внутрішні сервіси розглядаються як бібліотеки TypeScript (через імпорт ES6)
Ці інструменти заощаджують час, витрачений на написання клейкого коду або переосмислення оркестрації.
- Дерева комплексної залежності можуть швидко рости
- Тюнінг продуктивності CI не є тривіальним
- Вам може знадобитися більш швидке інструментування (наприклад, бунт), щоб тримати час будівництва вниз
Наступна стаття: Tooling likenx
абоturborepo
дає маленьким командам швидкість монорепо - якщо ви готові інвестувати, щоб зберегти їх в чистоті.
Коли розвиваєтьсяgo
на основі мікропослуг, хороша ідея на початку розробки полягає в тому, щоб використовувати один go
робочий простір зreplace
Директиви вgo.mod
Зрештою, по мірі масштабування програмного забезпечення, можна без зусиль розділити go
Модулі зберігаються в окремих сховищах.
Takeaway: A monorepo with shared infra buys you time, consistency, and sanity.
Розбитий локальний дев = Розбита швидкість
If it takes three hours, a custom shell script, and a Docker marathon just to run your app locally, you've already lost velocity.
Ранні проекти часто страждають від:
- Відсутність документації
- застарілі залежності
- ОС-специфічні хаки (привіт, налаштування тільки для Linux)
На моєму досвіді, коли я отримував проекти від попередніх команд розробників, вони часто розроблялися для однієї операційної системи. Деякі розробники віддавали перевагу будівництву на macOS і ніколи не турбувалися про підтримку своїх скриптів на Windows. У моїх попередніх командах я мав інженерів, які працювали на машинах Windows, і часто це вимагало переписування скриптів на шпалах або повного розуміння та зворотного інженерії процесу створення місцевого середовища. З часом, ми стандартизували налаштування навколишнього середовища на всіх ОС розробників, щоб зменшити тертя на борту - невелика інвестиція, яка заощадила години на нового інженера.
В іншому проекті сольний розробник створив крихку установку мікросервісу, що робочий процес запуску контейнерів Docker монтується на локальну файлову систему.
Але включення нового розробника на передній панелі зі старим ноутбуком Windows перетворилося на кошмар. Вони повинні були розгорнути десять контейнерів, щоб переглянути інтерфейс користувача. Все зламалося - обсяги, мережа, сумісність контейнерів - і установка дуже погано задокументована.
Ми в кінцевому підсумку зламали Node.js проксі, який імітував конфігурацію nginx/Docker без контейнерів.
Takeaway: If your app only runs on one OS, your team’s productivity is one laptop away from disaster.
Tip:В ідеалі, метою дляgit clone <repo> && make up
Якщо це неможливо, то підтримка оновленого файлу README з інструкціями для Windows/macOS/Linux є обов'язковим. Сьогодні, є деякі мови програмування та ланцюжки інструментів, які не працюють добре на Windows (наприклад, OCaml), але сучасний широко популярний стек працює добре на кожній широко використовуваній операційній системі; обмежуючи ваш локальний налаштування до однієї операційної системи, це часто симптом недостатньої інвестиції в DX.
Технологічна невідповідність
Крім архітектури, ваш технологічний стек також формує, як стають болючими мікрослужби - не кожна мова сяє в мікрослужбі.
- Node.js і Python: відмінно підходять для швидкої ітерації, але керування артефактами, версіями залежності та послідовністю часу роботи у різних сервісах стає болючим.
- Go: складає статичні бінарні копії, швидкі часи будівництва та низька оперативність. Більш природно підходить, коли дійсно потрібно розділення.
Якщо ви шукаєте продуктивність, можливо, шукаєте JVM і його екосистему, а також можливість розгортати артефакти в масштабі і запускати їх в архітектурах, заснованих на мікросервісах.
Це досить часто для команд, щоб зрозуміти, що є великі проблеми з їх вибором технології, які не були очевидними спочатку, і вони повинні були заплатити ціну відновлення заднього кінця в іншій мові програмування (наприклад,Ці хлопцібули змушені зробити щось про спадкоємну базу кодів Python 2 і переїхали в Go).
Але навпаки, якщо вам дійсно потрібно, ви можете перетнути кілька мов програмування з такими протоколами, якgRPCЯкщо ви хочете збагатити свій набір функцій функціональністю машинного навчання або роботами, заснованими на ETL, ви б просто окремо побудували свою ML-інфраструктуру в Python, завдяки своїй багатій екосистемі доменних бібліотек, які, природно, бракують будь-якій іншій мові програмування. Але такі рішення повинні бути прийняті, коли є достатньо рахунків, щоб виправдати це підприємство; інакше невелика команда буде вічно притягнута до нескінченної складності мостування декількох стеків програмного забезпечення разом.
Takeaway: Match the tech to your constraints, not your ambition.
Прихована складність: комунікація та моніторинг
Мікропослуги вводять невидиму мережу потреб:
- Служба відкриття
- API версії
- Ретриси, кругові перемикачі, падіння
- Розподілений трек
- Централізоване відстеження та попередження
У моноліті, помилка може бути простим стеком стеку. У розподіленій системі, це "чому сервіс A виходить з ладу, коли розгортання B затримується на C на 30 секунд?" Вам доведеться ретельно інвестувати в свій стек спостережності. Щоб зробити це "правильно", це вимагає інструментування ваших додатків певними способами, наприклад, інтегрування OpenTelemetry для підтримки відстеження, або покладаючись на інструменти вашого постачальника хмарочосів, як AWS XRay, якщо ви йдете з системою без складних серверів.actuallyфункціонування у виробництві.
Звичайно, частина інструментації спостережності потрібна для виконання на монолітних додатках, але це набагато простіше, ніж робити це з точки зору кількості послуг послідовно.
Tip:Розумійте, щоdistributed systems Вони не вільні.Вони є зобов'язанням для цілком нового класу інженерних викликів.
Вони не вільні.Коли мікропослугидоЗробіть сенс
доНезважаючи на згадані труднощі з мікросервісами, бувають випадки, коли роз'єднання на рівні сервісу насправді є дуже корисним.
- Ізоляція робочого навантаження: загальним прикладом цього є найкраща практика AWS щодо використання сповіщень про події S3 — коли зображення завантажується на S3, запускається процес зміни зображення / OCR і т. Д. Чому це корисно: ми можемо роз'єднати незрозумілі бібліотеки обробки даних у самоізольовану послугу і зробити API зосередженим виключно на обробці зображень і генеруванні виходу з завантажених даних.
- Дивергентна необхідність масштабування: — Уявіть, що ви будуєте продукт AI. Одна частина системи (веб-API), яка запускає робочі навантаження ML і показує минулі результати, не є інтенсивною ресурсом, вона легка, тому що вона взаємодіє переважно з базою даних. Навпаки, модель ML, що працює на GPU, насправді важка для запуску і вимагає спеціальних машин з підтримкою GPU з додатковою конфігурацією.
- Різні вимоги до часу запуску: — Припустимо, що у вас є деяка спадкова частина коду, написаного на C++. У вас є 2 варіанти — магічно перетворити його на вашу основну мову програмування або знайти способи інтеграції з кодовою базою. Залежно від складності цієї спадкоємної програми, вам доведеться писати клейкий код, впроваджуючи додаткові мережеві / протоколи для встановлення взаємодії з цією послугою, але в підсумку — вам, ймовірно, доведеться розділити це додаток як окрему послугу через несумісності часу запуску.
Великі інженерні організації стикалися з подібними проблемами. наприклад, інженерна команда UberДокументували перехід до доменно-орієнтованої мікросервісної архітектури— не з теоретичної чистоти, а у відповідь на реальну складність між командами та масштабуванням кордонів. Їх пост є хорошим прикладом того, як мікрослужби можуть працювати, коли у вас є організаційна зрілість і оперативне навантаження, щоб підтримати їх.
На одному з проектів, який також буває нерухомим, у нас був код з попередньої команди, яка виконувала аналітичні робочі навантаження на базі Python, які завантажували дані в MS-SQL db, ми виявили, що було б марно будувати на ньому додаток Django.
Takeaway: Use microservices when workloads diverge — not just because they sound clean.
Практичні рекомендації для стартапів
Якщо ви відправляєте свій перший продукт, ось книжка, яку я рекомендую:
- Почніть монолітично. Виберіть загальну рамку і зосередьтеся на виконанні функцій. Всі відомі рамки більш ніж достатньо хороші, щоб побудувати деякий API або веб-сайт і обслуговувати користувачів. Не слідуйте за хипом, дотримуйтеся нудного способу робити речі; ви можете подякувати собі пізніше.
- Не турбуйтеся про поділ коду на декілька сховищ. Я працював з засновниками, які хотіли розділити репо, щоб зменшити ризик копіювання IP-адресами підрядниками — це важлива стурбованість. Але на практиці це додало більше тертя, ніж безпеки: повільніші будівлі, фрагментований CI/CD, і погана видимість по всій команді. Маргінальний IP-захист не вартий операційної тяги, особливо коли правильні контролю доступу всередині монорепо було легше управляти.
- Зробіть макіяж роботи. Якщо це займе більше, будьте дуже конкретні на кроки, записуйте відео / Loom, і додати скріншоти. Якщо ваш код буде запускатися стажером або молодшим розробником, вони, ймовірно, потраплять в дорожній бар'єр, і ви будете витрачати час, пояснюючи, як виправити проблему.
- Навіть якщо це простий HTML, який ви могли б просто scp на сервер вручну, ви могли б автоматизувати це і покладатися на управління джерелом з CI / CD, щоб зробити це. Коли налаштування належним чином автоматизовано, ви просто забуваєте про вашу інфраструктуру безперервної інтеграції і зосередитися на функціях. Я бачив, що багато команд і засновників, коли працюють з аутсорсованими командами, часто є дешевими на CI / CD, і це призводить до того, що команда деморалізується і дратується ручними процесами розгортання.
- Розщеплення хірургічним шляхом. Розщеплення тільки тоді, коли це чітко вирішує болючий проміжок пляшки. В іншому випадку інвестуйте в модульність і тести всередині моноліту - це швидше і простіше підтримувати.
І перш за все:optimize for developer velocity.
Velocity is your startup’s oxygen.Передчасні мікросервіси витокують цей кисень повільно - до одного дня ви не можете дихати.
Takeaway: Start simple, stay pragmatic, and split only when you must.
Якщо ви йдете з мікросервісним підходом
У мене були проекти на основі мікропослуг, створені раніше, ніж вони повинні були бути виконані, і ось наступні рекомендації, які я міг би дати з цього приводу:
- Оцініть свій технічний стек, який підтримує вашу архітектуру на базі мікропослуг. Інвестуйте в інструменти досвіду розробників. Коли у вас є відділення на основі послуг, тепер потрібно подумати про автоматизацію вашого стеку мікропослуг, автоматизацію конфігурації як у місцевих, так і у виробничих середовищах. У деяких проектах мені довелося побудувати окремий CLI, який виконує адміністративні завдання на монорепозиторії. Один проект, який я мав, містив 15-20 розгортань мікропослуг, і для місцевого середовища, мені довелося створити кліп-інструмент для генерування файлів docker-compose.yml динамічно до бездоганного однокомандного старту для звичайного розробника.
- Зосередьтеся на надійних протоколах зв'язку навколо сервісного зв'язку. Якщо це асинхронні повідомлення, переконайтеся, що ваші схеми повідомлень є послідовними та стандартизованими. Якщо це REST, зосередьтеся на документації OpenAPI. Клієнти зв'язку між службами повинні впроваджувати багато речей, які не виходять з-під коробки: ретриї з експоненціальними зворотними перервами, час від часу. Типовий голий gRPC-клієнт вимагає, щоб ви вручну обчислювали ці додаткові речі, щоб переконатися, що ви не страждаєте від тимчасових помилок.
- Переконайтеся, що ваш пристрій, тестування інтеграції та налаштування тестування від кінця до кінця стабільні і масштабуються з кількістю розділень рівня служби, які ви вводите в свою кодову базу.
- На менших проектах, які використовують робочі навантаження на основі мікропослуг, ви, ймовірно, за замовчуванням використовуєте спільну бібліотеку з спільними помічниками для інструменталізації вашої спостережуваності, коду зв'язку послідовним чином. Важливе враження тут - тримайте свою спільну бібліотеку якомога меншою. Будь-які великі зміни змушують перебудувати всі залежні послуги - навіть якщо вони не пов'язані.
- Додайте структуровані журнали JSON і створюйте різні ідентифікатори кореляції для дебуджування речей після розгортання вашого додатка. Навіть базові помічники, які виводять багату інформацію про логінг (до того часу, поки ви не інструментували свою програму з відповідними засобами логінг / відстеження), часто заощаджують час, дізнаючись про неприємні потоки користувачів.
Підсумовуючи: якщо ви все ще йдете на мікропослуги, ви повинні заздалегідь зрозуміти податки, які ви будете платити з точки зору додаткового часу розробки та технічного обслуговування, щоб зробити налаштування працездатним для кожного інженера у вашій команді.
Takeaway: If you embrace complexity, invest fully in making it manageable.
Висновок
Premature microservices are a tax you can’t afford. Stay simple. Stay alive.Розщеплення тільки тоді, коли біль робить його очевидним.
Survive first. Scale later. Choose the simplest system that works — and earn every layer of complexity you add.
Зв'язані ресурси
- Моноліт перший — Мартін Фоулер
- Величний моноліт — DHH / Basecamp
- Прощання з мікросервісами: від 100 проблемних дітей до 1 суперзірки
- Деконструювати моноліт — Shopify Eng.
- Доменно-орієнтована мікросервісна архітектура — Uber Eng.
- Go + Services = One Goliath Project — Канська академія