отдавайте предпочтение хореографическому, а не оркестровому принципу и безмолвным промежуточным программным средствам с интеллектуальными конечными точками.
Нужно всегда стремиться к тому, чтобы микросервисы могли развертываться и развертывались самостоятельно. Даже когда требуются изменения, нарушающие общий режим работы, нужно добиваться совместного существования конечных точек разных версий, позволяя потребителям со временем внести изменения. Тем самым мы сможем оптимизировать скорость выпуска новых свойств, а также повысить автономность работы команд, владеющих этими микросервисами, снимая с них обязанность постоянного согласования развертываний своих сервисов. Если используется интеграция на основе RPC, избегайте при создании заглушек тесной связанности между клиентом и сервером вроде той, что поддерживается технологией Java RMI.
Принимая модель «по одному сервису на каждом хосте», вы уменьшаете число побочных эффектов, которые могут при развертывании одного сервиса влиять на другой, не связанный с ним сервис. Чтобы отделить развертывание от выпуска, сократив тем самым риск неудачного выпуска, присмотритесь к использованию технологий сине-зеленого развертывания или канареечного выпуска. Чтобы отловить изменения, нарушающие работу системы, еще до того, как они на нее смогут повлиять, воспользуйтесь контрактами на основе запросов потребителей.
Запомните, что возможность внесения изменений в отдельно взятый сервис и его выпуска для работы в производственном режиме без необходимости развертывания других сервисов с приостановкой работы системы должна стать нормой, а не исключением. Ваши потребители должны сами решать, когда им нужно обновляться, а вам следует к этому приспособиться.
Архитектура микросервисов может быть более устойчивой, чем монолитная система, но только если мы разбираемся в ситуации и имеем план на случай сбоев в части нашей системы. Если возможность и неизбежность сбоев вызова нижестоящего сервиса в расчет не принимаются, наша система может испытать катастрофический каскадный сбой и мы останемся с системой, еще более хрупкой, чем прежняя.
При использовании сетевых вызовов не уподобляйте удаленные вызовы локальным, так как из-за этого будут скрываться разные виды отказов. Поэтому убедитесь, что при использовании клиентских библиотек не происходит чрезмерного применения удаленных вызовов.
Не нужно постоянно думать о том, что система должна быть устойчивой к сбоям, и при этом всегда и всюду ожидать сбоев. Обеспечьте соответствующую настройку лимитов времени. Разберитесь, когда и как для ограничения выхода из строя компонентов использовать перегородки и предохранители. Разберитесь в том, какое влияние окажет на клиента неправильная работа всего одной из частей системы. Узнайте, какими окажутся последствия разделения сети и будет ли правильно требовать в этой ситуации принести в жертву доступность или согласованность данных.
При оценке правильности функционирования системы мы не можем полагаться на наблюдение за поведением одного-единственного экземпляра сервиса или состоянием одной машины. Нам требуется более широкое представление о происходящем. Чтобы убедиться в правильном поведении системы, нужно использовать семантический мониторинг путем внедрения в вашу систему искусственных транзакций с целью имитации поведения реального пользователя. Следует объединить свои журналы и объединить статистические данные, чтобы при обнаружении проблемы можно было докопаться до ее источника. А когда дело дойдет до воспроизведения неприятных моментов в поведении системы или наблюдения за тем, как в вашей системе происходит взаимодействие компонентов в производственном режиме работы, используйте идентификаторы взаимосвязанности, позволяющие проводить трассировку вызовов внутри системы.
Этот вопрос мне задавали довольно часто. Первая часть совета будет такой: чем хуже вы разбираетесь в заданной области, тем сложнее вам будет правильно определить ограниченные контексты для сервисов. Как уже говорилось, неправильное определение границ сервисов может привести к необходимости внесения множества изменений в совместную работу сервисов, что является весьма затратным делом. Поэтому, если вы взялись за монолитную систему, область применения которой вам непонятна, сначала уделите время изучению того, чем эта система занимается, а затем, прежде чем разбивать ее на сервисы, присмотритесь к определению четких границ модулей.
Разработка с чистого листа также дается весьма непросто. И дело даже не в том, что область, вероятно, также будет новой, а в том, что разбить на части что-либо уже существующее гораздо проще, чем что-то, чего у вас еще нет! Итак, повторю: присмотритесь сначала к созданию монолитной системы, а ее разбиением займитесь, как только добьетесь от нее стабильной работы.
Сложности, с которыми вы столкнетесь при работе с микросервисами, при масштабировании существенно усугубятся. Если в основном все делается вручную, то при наличии одного-двух сервисов у вас все может получиться, ну а если сервисов будет пять или десять? Если придерживаться старых положений по мониторингу, где просто изучается статистика загруженности центрального процессора и памяти, этого может хватить только для работы с весьма небольшим количеством сервисов, но чем шире используется совместная работа сервисов, тем обременительнее станет процесс. Вас это начнет беспокоить по мере добавления сервисов, и я надеюсь, что приведенные в книге советы помогут вам заметить возникновение ряда подобных проблем и подскажут их конкретные решения. Ранее я упоминал о том, что компании REA и Gilt потратили время на создание инструментария и инструкций по управлению микросервисами еще до появления возможности их использования в большом количестве. Эти истории только подтвердили для меня важность постепенного расширения, чтобы разобраться в потребностях организации и возможностях внесения изменений, которые помогут вам внедрить микросервисы надлежащим образом.
Архитектуры микросервисов предоставляют вам более широкий выбор и возможность принятия большего количества решений. Принимать решение в этой области приходится намного чаще, чем в области монолитных систем. Абсолютно все решения правильными не бывают, это я заявляю со всей ответственностью. Следовательно, каков должен быть наш выбор, зная, что мы что-то поймем неправильно? Я бы посоветовал найти способы принятия каждого решения в самых скромных масштабах. Тогда, если оно окажется неверным, это повлияет лишь на небольшую часть вашей системы. Научитесь следовать концепции развивающейся архитектуры, при которой ваша система будет способна гибко подстраиваться под ситуацию и изменяться по мере обнаружения новых обстоятельств. Не замышляйте грандиозной перезаписи кода, лучше вместо этого сохраняйте гибкость системы путем серии изменений, вносимых в вашу систему в течение длительного времени.
Надеюсь, что теперь я поделился с вами достаточным объемом информации и опыта, чтобы помочь принять решение о том, насколько микросервисы подходят лично вам. Если вы поймете, что они вам нужны, то я надеюсь, что вы воспримете работу с ними как длительное путешествие, а не как стремление добраться до пункта назначения. Действуйте по нарастающей. Разбивайте свою систему на части, обучаясь в процессе работы. И вы привыкнете к этому: во многих отношениях тренировка во внесении постоянных изменений и в развитии ваших систем является гораздо более важным уроком, чем любой другой, преподнесенный мною в данной книге. Изменения неизбежны. Воспримите это как должное.