Б Бёрнс - Распределенные системы. Паттерны проектирования
- Название:Распределенные системы. Паттерны проектирования
- Автор:
- Жанр:
- Издательство:Питер
- Год:2019
- ISBN:978-5-4461-0950-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Б Бёрнс - Распределенные системы. Паттерны проектирования краткое содержание
Распределенные системы. Паттерны проектирования - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Конечно, стоит учесть, что недоступность сервиса может быть вызвана и другими причинами. При развертывании ПО на загрузку и установку новой версии приложения требуется не-Глава 9. Выбор владельца 155
которое время. Старая и новая версии синглтона не могут ра-ботать одновременно, поэтому на время обновления придется отключить старую версию приложения, а при большом размере образа процесс может занять несколько минут. Следовательно, при ежедневном развертывании, на которое требуется 2 мину-
ты, доступность сервиса будет на уровне двух девяток (99 %), а при ежечасном — ниже 90 %. Развертывание, конечно, можно ускорить путем предварительной загрузки образа на обновля-емую машину. Это уменьшит время развертывания очередной версии до нескольких секунд, но привнесет дополнительную сложность, которой мы избегали изначально. Несмотря на это, существует ряд приложений (например, фо-новая асинхронная обработка), в которых такой компромисс между уровнем доступности и простотой приложения допустим. Один из ключевых аспектов проектирования распределенной системы — следить, чтобы распределенность не слишком ее усложняла. Но есть и ситуации, когда высокая доступность (че-тыре девятки и больше) является критической характеристикой приложения. В таких системах необходимо иметь несколько экземпляров сервиса, среди которых только один является владельцем. Проектирование такого рода систем описывается в последующих разделах.
Основы процесса выбора владельца Представим себе сервис Foo в трех экземплярах: Foo-1, Foo-2 и Foo-3. Допустим, есть также некоторый объект Bar, которым одновременно может владеть только один экземпляр сервиса. Этот экземпляр часто называется владельцем . Соответственно, процесс, описывающий то, как выбрать начального владельца и в случае отказа текущего — очередного владельца, называется выбором владельца .
156Часть II. Паттерны проектирования обслуживающих систем Есть два способа реализовать выбор владельца. Первый — создать распределенный алгоритм согласования вроде Paxos или RAFT. Сложность этих алгоритмов выводит их за рамки книги и делает их дальнейшее рассмотрение нецелесообраз-ным. Реализация какого-нибудь из них сравнима с реали-зацией блокировок с помощью ассемблерных инструкций сравнения и обмена. Из нее выйдет хорошая задачка для уни-верситетского курса информатики, но на практике так делать не стоит.
К счастью, есть ряд распределенных хранилищ типа «ключ — значение», в которых эти алгоритмы уже реализованы. В общем и целом эти системы предоставляют реплицированные, на-дежные хранилища, а также примитивы, необходимые для по-строения сложных механизмов выбора и блокировки. К таким хранилищам относятся, к примеру, etcd, ZooKeeper и consul. К базовым примитивам, предоставляемым подобными система-ми, относится операция сравнения с заменой для конкретного ключа. Если вы ранее не сталкивались с операцией сравнения с заменой, то знайте: она представляет собой атомарную опера-цию следующего вида:
var lock = sync.Mutex{}
var store = map[string]string{}
func compareAndSwap(key, nextValue, currentValue string) (bool, error) {
lock.Lock()
defer lock.Unlock()
if _, found := store[key]; !found {
if len(currentValue) == 0 {
store[key] = nextValue
return true, nil
}
return false, fmt.Errorf("Для ключа %s ожидалось значение %s, но было обнаружено пустое значение", key, currentValue) Глава 9. Выбор владельца 157
if store[key] == currentValue {
store[key] = nextValue
return true, nil
}
return false, nil
}
Операция сравнения с заменой атомарно записывает новое значение ключа, если его текущее значение совпадает с ожи-даемым. В противном случае она возвращает false . Если зна-чения не существует, а currentValue не равно null , она воз-вращает ошибку.
Вдобавок к операции сравнения с заменой хранилища типа «ключ — значение» позволяют устанавливать для ключа срок действия (TTL, time-to-live). Как только он истекает, значение ключа обнуляется.
Этих двух функций достаточно, чтобы реализовать множество примитивов синхронизации.
Практикум. Развертывание etcd Etcd ( https://coreos.com/etcd/docs/latest/ ) — распределенный сервис блокировок, разработанный в рамках проекта CoreOS. Он до-вольно устойчив и хорошо себя зарекомендовал в различных проектах, в том числе в Kubernetes.
Развертывание etcd существенно упростилось благодаря двум проектам с открытым исходным кодом:
helm ( https://helm.sh/ ) — менеджеру пакетов Kubernetes, под-держиваемому Microsoft Azure;
оператору etcd ( https://coreos.com/blog/introducing-the-etcd-operator.html), разработанному в рамках проекта CoreOS.
158Часть II. Паттерны проектирования обслуживающих систем приложений. Оператор отвечает за создание, масштаби-
рование и поддержку функционирования приложения. Пользователи настраивают приложение, задавая его жела-емое состояние с помощью API. К примеру, оператор etcd отвечает за сервис etcd. Операторы — относительно новая задумка, но они представляют собой важное направление
Чтобы развернуть оператор etcd в CoreOS, воспользуемся ме-неджером пакетов helm. Helm — менеджер пакетов, являющий-ся частью Kubernetes и разработанный Deis. Microsoft Azure поглотила Deis в 2017 году, и Microsoft с тех пор продолжает поддерживать open-source-разработку данного проекта. Если вы впервые используете helm, вам понадобится установить его согласно инструкции по адресу https://github.com/kubernetes/ helm/releases .
После запуска helm в своей среде вы можете установить опера-тор etcd следующим образом:
# Инициализация helm
helm init
# Установка оператора etcd
helm install stable/etcd-operator
После установки оператор etcd создает собственный класс Kubernetes-ресурсов, представляющих собой etcd-кластеры. Оператор запущен, но кластеры etcd еще не созданы. Для соз-дания etcd-кластера необходимо составить следующую декла-ративную конфигурацию:
apiVersion: "etcd.coreos.com/v1beta1"
kind: "Cluster"
Глава 9. Выбор владельца 159
metadata:
# Имя может быть любым
name: "my-etcd-cluster"
spec:
# size может принимать значения 1, 3 и 5
size: 3
# Устанавливаемая версия etcd
version: "3.1.0"
Сохраните данную конфигурацию в файл etcd-cluster.yaml и создайте кластер с помощью такой команды: kubectl create -f etcd-cluster.yaml
После создания кластера оператор etcd автоматически создаст pod-группы с копиями кластера. Копии кластера можно уви-деть, выполнив команду:
kubectl get pods
После запуска всех трех копий адреса точек доступа к ним мож-но получить с помощью такой команды:
export ETCD_ENDPOINTS=kubectl get endpoints example-etcd-cluster "-o=jsonpath={.subsets[*].addresses[*].ip}:2379," Теперь в кластер можно что-нибудь записать следующей коман-дой:
kubectl exec my-etcd-cluster-0000 -- sh -c "ETCD_API=3 etcdctl --endpoints=${ETCD_ENDPOINTS} set foo bar"
Реализация блокировок
Простейшая форма синхронизации — взаимоисключающая блокировка, также известная как мьютекс (mutual exclusion, mutex). С блокировками знаком каждый, кто хоть раз зани-мался созданием параллельных программ для одной машины. Для распределенных систем работают те же принципы. Распре-деленные блокировки используют не память и ассемблерные 160Часть II. Паттерны проектирования обслуживающих систем инструкции, а рассмотренные ранее функции распределенных хранилищ типа «ключ — значение».
Читать дальшеИнтервал:
Закладка: