Распределенные системы. Паттерны проектирования - страница 22

стр.

спечить сбор показателей из разных систем, Prometheus рассчи-тывает,  что  у  каждого  контейнера  предусмотрен  определенный  программный интерфейс для сбора показателей. Это позволяет  Prometheus  следить  за  самыми  разными  приложениями  через  единообразный интерфейс.

Однако многие приложения, такие как хранилище «ключ — зна-чение»  Redis,  предоставляют  показатели  в  формате,  не  совме-стимом  с  Prometheus.  Следовательно,  паттерн  Adapter  весьма  полезен для адаптирования существующих сервисов вроде Redis  к интерфейсу сбора показателей Prometheus. 68 Часть I. Одноузловые паттерны проектирования

Рассмотрим  спецификацию  простой  группы  контейнеров  для  сервиса Redis:

apiVersion: v1

kind: Pod

metadata:

name: adapter-example

namespace: default

spec:

containers:

- image: redis

name: redis

На данный момент Prometheus не может наблюдать за состояни-ем  такого  контейнера,  поскольку  тот  не  предоставляет  нужного  интерфейса.  Однако  если  мы  просто  добавим  контейнер-адап-тер  (в  данном  случае  открытый  инструмент  экспорта  в  формат  Prometheus),  то  сможем  модифицировать  эту  группу  так,  чтобы  она  предоставляла  необходимый  интерфейс,  соответствующий  ожиданиям Prometheus.

apiVersion: v1

kind: Pod

metadata:

name: adapter-example

namespace: default

spec:

containers:

- image: redis

name: redis

# Предоставляем адаптер, реализующий интерфейс Prometheus - image: oliver006/redis_exporter

name: adapter

Этот пример иллюстрирует не только ценность паттерна Adapter  в плане обеспечения унифицированного интерфейса, но и полез-ность контейнерных паттернов в целом как средства обеспечения  модульности  и  повторного  использования  контейнеров.  При-мер  демонстрирует,  как  совместить  существующий  контейнер  с  Redis  и  адаптер  в  формат  Prometheus.  Совокупным  эффектом  Глава 4. Адаптеры 69

от их стыковки станет Redis-сервер с возможностью мониторинга  при  минимуме  усилий  с  нашей  стороны.  В  отсутствие  паттерна  Adapter развертывание такой же функциональности потребовало  бы гораздо больше наших собственных усилий, привело бы к ме-нее управляемому результату, поскольку любое обновление Redis  или адаптера требует дополнительных трудозатрат на обновление. Ведение журналов

Как  и  в  случае  с  мониторингом,  системы  очень  неоднородно  журналируют  данные.  Системы  могут  разделять  журналы  на  различные  уровни,  например  debug,  info,  warning  и  error,  каж-дый  из  которых  записывается  в  отдельный  файл.  Некоторые  просто выводят информацию в потоки  stdout  или  stderr . Это  особенно критично в случае контейнеризованных приложений,  когда обычно ожидается, что контейнеры выводят информацию  в  поток  stdout ,  так  как  именно  его  содержимое  доступно  при  выполнении команд  docker  logs  или  kubectl  logs . Усложняет ситуацию и то, что журналируемая информация в об-щем случае имеет структурированные элементы, например дату  и время записи, но эти сведения сильно различаются для разных  реализаций библиотек журналирования (например, для встроен-ного в Java средства журналирования и пакета  glog  в Go). Записывая и читая журналы своей распределенной системы, вы,  конечно же, не особо заботитесь о различиях между форматами.  Вы  хотите  убедиться,  что,  несмотря  на  различную  структуру  данных, каждая запись имеет соответствующую метку времени. К счастью, как и в случае мониторинга, паттерн Adapter помогает  предоставить  модульную,  повторно  используемую  архитекту-ру  для  ведения  журналов.  Контейнер  приложения  может  вести  журнал  в  файле,  а  контейнер-адаптер будет  перенаправлять  его  содержимое  в  поток  stdout .  Разные  контейнеры  приложения 

70 Часть I. Одноузловые паттерны проектирования

могут  вести  журналы  в  разных  форматах,  а  контейнер-адаптер  может  преобразовывать  эти  данные  в  общее  структурированное  представление, которым сможет воспользоваться агрегатор жур-налов. Адаптер и в данном случае на основе неоднородной среды  приложений создает однородную среду общих интерфейсов.