Рис. 3.2. Обобщенная схема шардированного сервисаПри развертывании шардированного сервиса возникает вопрос о том, как интегрировать его с программным обеспечением клиентского или промежуточного уровня. Очевидно, должен существовать модуль, который бы переадресовывал конкрет-ный запрос конкретному шарду. Часто такой шардированный клиент тяжело интегрировать в систему, компоненты которой рассчитывают на подключение к единому хранилищу данных. К тому же шардированные сервисы препятствуют совместному использованию конфигурации средой разработки (где храни-лище состоит, как правило, из одного шарда) и средой эксплуа-тации (где хранилище часто состоит из множества шардов). Один из вариантов — включить всю логику шардирования в сам шардированный сервис. При таком подходе шардированный сервис должен также иметь балансировщик нагрузки с незави-симой обработкой транзакций, адресующий трафик нужному шарду. Этот балансировщик нагрузки будет, по сути, распре-Глава 3. Паттерн Ambassador 53
деленной реализацией паттерна Ambassador в виде сервиса. Клиентская реализация паттерна Ambassador становится не нужна, но за счет этого усложняется развертывание шардиро-ванного сервиса. Другой вариант — интегрировать одноузловую реализацию паттерна Ambassador на стороне клиента, чтобы она перенаправляла трафик нужному шарду.
Развертывание клиента несколько усложняется, зато упроща-ется развертывание шардированного сервиса. Как и в случае с любыми компромиссами, особенности вашего конкретного приложения будут определять то, какой из двух подходов ока-
жется наиболее осмысленным. В первую очередь нужно разо-браться, каким образом разграничиваются обязанности в вашей команде, во вторую — установить, разрабатываете вы новый код либо развертываете уже существующие решения. Каждый из подходов верен по-своему. В следующем разделе описывается, как использовать одноузловой паттерн Ambassador для шардирования на стороне клиента.
При адаптировании существующего приложения к шардирован-ному хранилищу мы создаем контейнер-посол, который содер-жит всю необходимую логику для переадресации запросов соот-ветствующим шардам хранилища. Таким образом, программное обеспечение клиентского или промежуточного уровней под-ключается к сервису, который выглядит как единое хранилище, работающее на локальной машине. Но этот сервис на самом деле является шардирующим прокси-контейнером , реализующим паттерн Ambassador. Он принимает запросы от приложения, переадресует их соответствующему шарду хранилища и затем возвращает результат приложению.
Главный результат применения паттерна Ambassador к шар-дированным сервисам — разделение обязанностей между кон-тейнером приложения и шардирующим прокси. Контейнер 54Часть I. Одноузловые паттерны проектирования
приложения знает, что ему надо взаимодействовать с сервисом хранения, находящимся на локальном компьютере, а шарди-рующий прокси содержит только тот код, который отвечает за корректное шардирование запросов.
Как и любую хорошую реализацию одноузлового паттерна, контейнер-посол можно повторно использовать в различных приложениях. Или, как вы увидите в следующем практикуме, в качестве посла может выступать готовый сервис с открытым исходным кодом, что позволит ускорить разработку распреде-ленной системы в целом.
Практикум. Шардируем Redis-хранилище Redis — высокопроизводительное хранилище типа «ключ — значение», которое можно использовать в качестве кэша или более постоянного места хранения данных. В этом примере мы задействуем его в качестве кэша. Начнем с развертывания шардированного Redis на кластер Kubernetes. Для этого об-ратимся к API StatefulSet , поскольку он дает каждому шарду уникальные DNS-имена, которыми мы воспользуемся при на-стройке прокси.
StatefulSet для Redis будет выглядеть следующим образом: apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: sharded-redis
spec:
serviceName: "redis"
replicas: 3
template:
metadata:
labels:
app: redis
spec:
Глава 3. Паттерн Ambassador 55
terminationGracePeriodSeconds: 10
containers:
- name: redis
image: redis
ports:
- containerPort: 6379
name: redis
Сохраните этот код в файле redis-shards.yaml , который можно развернуть командой kubectl create -f redis-shards.yaml . Она создаст три контейнера с запущенным Redis. Их можно увидеть, выполнив команду kubectl get pods . Результат будет таким: sharded-redis-[0,1,2]
Читать дальше