Theory of Constraints by Eliyahu Goldratt
Теория ограничений Эльяху Голдрата – это достаточно простая теория о системах с более-менее четкими границами. Итак, мы можем представить себе систему как "черный ящик", у которого есть некий вход (или несколько входов) и некий выход (или несколько выходов). На входе система получает нечто, необходимое для ее работы. Например, электроэнергию и металлическую болванку. На выход система выдает некий продукт своей жизнедеятельности. Например, выточенную деталь. Производительностью системы есть ее пропускная способность. Если система способна потребить 10 болванок в час, она не способна выдать в час более 10 болванок.
Системы серийного производства достаточно просты, и границы в них достаточно четко обозначены. Эти системы обычно состоят из нескольких подсистем, объединенных в некоторую структуру, где выход одной подсистемы подключен ко входу другой. Так, например, в одном цеху производят фарш, в другом – замешивают тесто. Затем фарш и тесто подаются на входы третьей подсистемы, которая производит пельмени. Выход из третьей системы подключен к цеху заморозки полуфабрикатов и т. д.
Из примера такой простой модели становится очевидно, что пропускная способность каждой следующей системы зависит от производительности предыдущей. Давайте оптимизировать!
Если мы просто возьмем и начнем увеличивать производительность всех подсистем, мы существенно увеличим эксплуатационные и получим значительные капитальные расходы. Это потребует инвестиций, и в итоге нужно будет отдать очень много денег. Именно здесь начинается ToC.
Дело в том, что производительность всей системы будет обусловлена производительностью наименее производительной подсистемы (пропускной способностью «бутылочного горлышка»). Все подсистемы, что находятся перед «бутылочным горлышком», будут требовать складов (что увеличивает расходы), либо будут использоваться не на полную (что увеличивает амортизационную составляющую стоимости выхода). В любом случае, наши расходы больше, чем могли бы быть при сохранении того же качества выхода. Таких примеров было полно в СССР с постоянно растущим ВВП (показателем, который вообще ничего не значит). Это происходило благодаря, в частности, пропаганде («Пятилетку за три года!») и приводило к тому, что в СССР были огромные, дорогостоящие склады ржавеющих, никому не нужных деталей.
Согласно ToC, оптимизация должна происходить не произвольным образом, но за счет выявления «бутылочных горлышек» и их расширения. В идеале пропускная способность выходов каждой подсистемы должна соответствовать пропускной способности соответствующих входов принимающих подсистем. В таком случае мы будем максимально эффективно утилизировать подсистемы и минимизируем склады («закопанные в землю» неработающие деньги) и брак/потери.
ToC в архитектуре ПО
ПО состоящее из различных строительных блоков-подсистем подобно предприятию. Например, мы способны принять по сети 1Гб данных в секунду, но обработать способны только 100Мб в секунду. Это означает, что производительность всей нашей системы – 100Мб в секунду. Юнит обработки данных – это наше «бутылочное горлышко», которое следует расширить.
Вертикальное масштабирование
Самое простое, что мы можем сделать для повышения пропускной способности системы, – это изучить внутреннее устройства юнита – «бутылочного горлышка» – и оптимизировать его производительность. Мне иногда удавалось добиться 300X и даже >3000X оптимизации, но такое происходит достаточно редко. На что можно рассчитывать, чтобы не разочароваться, – это 1.05X-3X оптимизация.
Горизонтальное масштабирование
Горизонтальное масштабирование заключается в репликации «бутылочного горлышка». В случае, когда потенциально система может обрабатывать 1Гб данных в секунду, а «бутылочное горлышко» – только 100Мб, мы можем создать 9-11 реплик «бутылочного горлышка», что совокупно будут пропускать ~1Гб данных.
Где здесь микросервисы?
Их нет! Микросервис – это избыточное усложнение, требующее разработки отдельного домена и значительного усложнения процессов и экосистемы, в которой живет непосредственно ваша система. В случае с вертикальной масштабируемостью все совсем просто, а в случае с горизонтальной предыдущая подсистема должна передавать свой выход на вход интерфейса, который скрывает балансировщик нагрузки, разбрасывающий свой вход на входы реплик «бутылочного горлышка».
Итог
Микросервисы – это очень сложно, а потому выбор микросервисной архитектуры должен иметь больше оснований, чем простая дань моде или проблемы с масштабируемостью.