Распределенные системы. Паттерны проектирования - [9]
трим изоляцию ресурсов. Ваше приложение может состоять из двух компонентов — сервера приложений, взаимодействующего с пользователем, и фонового загрузчика конфигурационных файлов. Очевидно, что в первую очередь требуется минимизи-ровать задержку обработки пользовательских запросов, поэто-му приложение, взаимодействующее с пользователем, должно иметь достаточно ресурсов, чтобы обеспечить максимальную отзывчивость. В то же время загрузчик конфигурационных файлов обычно нетребователен к времени отклика. Если он будет испытывать небольшую задержку в период максималь-ного количества пользовательских запросов, система будет в порядке. Более того, фоновый загрузчик конфигурационных файлов не должен влиять на качество обслуживания конечных пользователей.
Исходя из всех этих причин, необходимо поместить сервис, который непосредственно взаимодействует с пользователем, и фоновый загрузчик в отдельные контейнеры. Так можно бу-дет закрепить за ними разный объем памяти и вычислительных ресурсов, что, к примеру, позволит фоновому загрузчику по возможности «забирать» процессорное время у пользователь-ского сервиса в те периоды, когда он слабо нагружен. Кроме того, раздельное назначение вычислительных ресурсов двум контейнерам позволит сделать так, чтобы фоновый загрузчик завершался раньше пользовательского сервиса в случае их конфликта за ресурсы, вызванного утечкой или избыточным распределением памяти.
Кроме изоляции ресурсов, существует множество причин раз-делять одноузловое приложение на несколько контейнеров. Рас-смотрим масштабирование команды. Есть достаточно оснований верить тому, что идеальное количество человек в команде — от шести до восьми. Чтобы так структурировать команды и при этом создавать системы значительного размера, членам каждой команды необходимо давать небольшой, четко ограниченный 32 Часть I. Одноузловые паттерны проектирования
участок работ, за который они несли бы ответственность. Не-редко отдельные компоненты (при условии, что они правильно выделены) оказываются повторно применяемыми модулями, которыми могут воспользоваться разные команды. Рассмотрим, к примеру, задачу синхронизации локальной фай-ловой системы с удаленным Git-репозиторием исходных тек-стов. Если вы сделаете такой инструмент синхронизации от-дельным контейнером, то сможете использовать его из PHP, HTML, JavaScript, Python и других веб-ориентированных язы-ков и сред. Если же выделить каждую среду в отдельный кон-тейнер, где, скажем, интерпретатор Python и Git-синхронизатор будут неразрывно связаны, то повторное использование такого модуля и, как следствие, существование соответствующей не-большой команды разработчиков, ответственной за этот мо-дуль, станут невозможными.
Наконец, даже если ваше приложение невелико и за все контей-неры ответственна одна команда, имейте в виду, что разделение обязанностей способствует грамотному восприятию, тестиро-ванию, обновлению и развертыванию вашего приложения. Не-большие приложения с четко очерченными границами проще для понимания и менее жестко привязаны к другим системам. Это значит, что, к примеру, вы можете развернуть контейнер с Git-синхронизатором, не разворачивая заново сервер приложений. Благодаря этому сужается круг зависимостей и уменьшается мас-штаб развертывания в целом. Это, в свою очередь, обеспечивает более надежный процесс развертывания и отката на предыдущую версию, что увеличивает скорость и гибкость развертывания. Резюме
Надеюсь, приведенные примеры натолкнули вас на мысль о де-композиции своих приложений на несколько контейнеров, даже если они работают в рамках одного узла. В последующих главах Часть I. Одноузловые паттерны проектирования 33
будут описаны паттерны, которые помогут вам сориентиро-ваться в построении модульных групп контейнеров. В отличие от многоузловых распределенных паттернов эти паттерны под-разумевают тесную связь между всеми контейнерами. В частно-сти, они предполагают, что исполнение контейнеров в паттерне может быть надежно распланировано в рамках одной машины. Они также подразумевают, что все контейнеры в рамках пат-терна могут при необходимости совместно использовать тома или части файловых систем, а также иные ключевые ресурсы, например сетевые пространства имен и общую память. Такая тесно связанная группа в Kubernetes> 1 называется подом (pod) , но сама идея в общем случае применима к разным оркестрато-рам контейнеров, хотя некоторые из них могут поддерживать ее более естественным образом, нежели другие. 2> Паттерн Sidecar Sidecar — это одноузловой паттерн, состоящий из двух контей-неров. Первый из них — контейнер приложения . Он содержит основную логику программы. Без этого контейнера приложения бы не существовало. Вдобавок к контейнеру приложения пред-усмотрен еще «прицепной» (sidecar) контейнер . Роль прицепа — дополнить и улучшить контейнер приложения, часто таким образом, чтобы приложение не знало о его существовании. В простейшей форме контейнер-прицеп можно использовать, чтобы добавить функциональности контейнеру, который было бы сложно улучшить иным способом.