Б Бёрнс - Распределенные системы. Паттерны проектирования
- Название:Распределенные системы. Паттерны проектирования
- Автор:
- Жанр:
- Издательство:Питер
- Год:2019
- ISBN:978-5-4461-0950-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Б Бёрнс - Распределенные системы. Паттерны проектирования краткое содержание
Распределенные системы. Паттерны проектирования - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
window 600
sys 0
Мониторинг работоспособности сервисов
В качестве последнего примера рассмотрим применение паттерна Adapter для мониторинга работоспособности контейнера приложе-ния. Разберем задачу мониторинга работоспособности контейнера типовой СУБД. В данном случае контейнер СУБД предоставляет-ся ее разработчиками, и мне не хотелось бы модифицировать его Глава 4. Адаптеры 73
только для того, чтобы добавить в него проверку работоспособ-ности. Оркестратор контейнеров, конечно, может взять на себя несложную проверку работоспособности, чтобы убедиться, что процесс запущен и принимает подключения по определенному порту. А что, если мы хотим выполнять сложную проверку рабо-
тоспособности, делая, например, запросы к базе данных? Оркестраторы контейнеров наподобие Kubernetes также по-зволяют задавать сценарии оболочки, проверяющие работо-способность контейнера. Имея такую возможность, мы можем написать сложный сценарий оболочки, выполняющий несколь-ко диагностических запросов к базе данных, чтобы определить степень ее работоспособности. Но где хранить такой сценарий и как следить за его версиями?
Нетрудно догадаться, как решить эту проблему, — можно исполь-зовать контейнер-адаптер. База данных работает в контейнере приложения, который имеет общий с контейнером-адаптером сетевой интерфейс. Контейнер-адаптер — простой контейнер, который содержит только сценарий оболочки, оценивающий работоспособность базы данных. Этот сценарий можно настроить в качестве комплексного средства проверки контейнера СУБД, выполняющего любую диагностику, необходимую нашему при-
ложению. Если контейнер приложения когда-либо не пройдет проверку, он будет автоматически перезапущен. Практикум. Комплексный мониторинг работоспособности MySQL
Допустим, вы хотите следить за работоспособностью базы дан-ных MySQL путем периодического выполнения запросов, со-ответствующих рабочей нагрузке вашего приложения. Одним из вариантов будет добавить в контейнер MySQL проверку работоспособности, отвечающую вашим требованиям. В общем случае, однако, это не очень желательное решение, поскольку 74Часть I. Одноузловые паттерны проектирования
оно требует преобразования базового MySQL-образа, а также обновления модифицированного образа по мере выхода новых версий базового образа.
В этом случае использование паттерна Adapter гораздо более привлекательно, нежели добавление проверок работоспособ-ности непосредственно в базовый образ. Вместо того чтобы модифицировать существующий контейнер с MySQL, можно добавить к типовому MySQL-контейнеру контейнер-адаптер, который бы проверял состояние базы данных. Учитывая, что адаптер проверяет работоспособность посредством протокола HTTP, все сводится к определению процесса проверки работо-способности базы данных в терминах интерфейса, предостав-ляемого адаптером.
Исходный текст такого адаптера довольно прост и выглядит на языке Go следующим образом (очевидно, что его можно реали-зовать и на другом языке):
package main
import (
"database/sql"
"flag"
"fmt"
"net/http"
_ "github.com/go-sql-driver/mysql"
)
var (
user = flag.String("user", "", "Имя пользователя базы данных") passwd = flag.String("password", "", "Пароль к базе данных") db = flag.String("database", "", "К какой базе данных необходимо подключиться")
query = flag.String("query", "", "Тестовый запрос") addr = flag.String("address", "localhost:8080", "По какому IP-адресу принимать запросы")
Глава 4. Адаптеры 75
// Пример использования:
// db-check --query="SELECT * from my-cool-table" \ // --user=bdburns \
// --passwd="you wish"
//
func main() {
flag.Parse()
db, err := sql.Open("localhost", fmt.Sprintf("%s:%s@/%s", *user, *passwd, *db))
if err != nil {
fmt.Printf("Ошибка подключения к базе данных: %v", err)
}
// Простой веб-обработчик, выполняющий запрос http.HandleFunc("", func(res http.ResponseWriter, req *http.Request) {
_, err := db.Exec(*query)
if err != nil {
res.WriteHeader(http.StatusInternalServerError)
res.Write([]byte(err.Error()))
return
}
res.WriteHeader(http.StatusOK)
res.Write([]byte("OK"))
return
})
// Запуск сервера
http.ListenAndServe(*addr, nil)
}
Затем мы можем собрать контейнер-адаптер и поместить его в группу, которая будет выглядеть следующим образом: apiVersion: v1
kind: Pod
metadata:
name: adapter-example-health
namespace: default
spec:
containers:
- image: mysql
name: mysql
76Часть I. Одноузловые паттерны проектирования
- image: brendanburns/mysql-adapter
name: adapter
Контейнер mysql остается неизменным, при этом необходимую обратную связь можно получить от контейнера-адаптера. На первый взгляд может показаться, что такой вариант при-менения паттерна Adapter является излишним. Мы, конечно, можем собрать свой собственный образ, который знает, как проверять работоспособность экземпляра mysql . Это верно, но подобный подход игнорирует преимущества, следующие из модульности. Если каждый разработчик будет реализовывать свою собственную модификацию контейнера со встроенной проверкой работоспособности, то потеряется возможность по-вторного (или совместного) его использования. Напротив, если применять паттерны вроде Adapter для разра-ботки модульных решений, состоящих из нескольких контей-неров, то приложение естественным образом декомпозируется на части, которые можно использовать повторно. Адаптер, раз-работанный для проверки работоспособности mysql , может быть совместно/повторно использован многими людьми. Кроме того, разработчики могут применять паттерн Adapter, используя об-щий контейнер для проверки работоспособности, не вдаваясь в детали наблюдения за базами данных mysql . Таким образом, модульность в целом и паттерн Adapter в частности не только способствуют совместному применению кода, но и позволяют воспользоваться знаниями других людей.
Надо отметить, что паттерны проектирования предназначены не только для их непосредственного применения в приложениях, но и для развития сообществ, участники которых могут взаимо-действовать между собой и делиться результатами. Часть II
Паттерны
проектирования обслуживающих систем В предыдущей главе мы рассмотрели паттерны группирования наборов контейнеров, совместно исполняемых на одной ма-шине. Подобные группы представляют собой тесно связанные, симбиотические системы. Они зависят от совместно исполь-зуемых локальных ресурсов: дискового пространства, сетевых интерфейсов, а также от межпроцессного взаимодействия. Та-кие наборы контейнеров являются не только важными паттер-нами, но и строительными блоками для более крупных систем. Требования к надежности, масштабируемости, разделению обязанностей обуславливают то, что реальные системы состоят из множества различных компонентов, развернутых на многих машинах. Компоненты в многоузловых паттернах связаны сла-бее, чем в одноузловых. Хотя эти паттерны и диктуют схему взаимодействия компонентов между собой, само взаимодей-ствие осуществляется через сетевые вызовы. Кроме того, па-раллельно выполняется множество вызовов, координируемых путем нестрогой синхронизации, а не с помощью ограничений реального времени.
Читать дальшеИнтервал:
Закладка: