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

Шрифт
Интервал

Сервис можно опробовать в контейнере, выполнив следующую  команду:

docker run -p 8080:8080 brendanburns/dictionary-server Она запустит простой словарный сервер на локальном компью-тере. Например, чтобы узнать толкование слова dog, необходимо  перейти по адресу  http://localhost:8080/dog .

86 Часть II. Паттерны проектирования обслуживающих систем В  журнале  контейнера  видно,  что  он  начинает  обслуживание  сразу  после  запуска,  но  сообщает  о  готовности только  после  того, как загрузит из сети словарь размером примерно 8 Мбайт. Чтобы  развернуть  сервис  в  Kubernetes,  необходимо  создать  конфигурационный файл развертывания:

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

name: dictionary-server

spec:

replicas: 3

template:

metadata:

labels:

app: dictionary-server

spec:

containers:

- name: server

image: brendanburns/dictionary-server

ports:

- containerPort: 8080

readinessProbe:

httpGet:

path: /ready

port: 8080

initialDelaySeconds: 5

periodSeconds: 5

Чтобы создать на его основе реплицированный stateless-сервис,  выполним следующую команду:

kubectl create -f dictionary-deploy.yaml

Теперь, когда у вас запущено несколько копий сервиса, нужен  балансировщик нагрузки, который будет распределять запросы  пользователей между ними. Балансировщик нагрузки не только  равномерно распределяет нагрузку между экземплярами серви-са,  но  и  предоставляет  уровень  абстракции  для  потребителей  Глава 5. Реплицированные сервисы с распределением нагрузки 87 реплицированного сервиса.  Балансировщик  нагрузки  также  предоставляет  общее  разрешимое  сетевое  имя,  независимое  от  того,  какой  из  экземпляров  сервиса  фактически  обслужит  запрос.

Балансировщик  нагрузки  в  Kubernetes  можно  создать  с  помо-щью объекта  Service :

kind: Service

apiVersion: v1

metadata:

name: dictionary-server-service

spec:

selector:

app: dictionary-server

ports:

- protocol: TCP

port: 8080

targetPort: 8080

Сформировав конфигурационный файл, можно запустить сер-вис-словарь следующей командой:

kubectl create -f dictionary-service.yaml

Сервисы с закреплением сессий В  предыдущих  примерах  реализации  паттерна  реплициро-ванного  stateless-сервиса все  пользовательские запросы  на-правлялись  всем  экземплярам  сервиса.  Хотя  такое  решение  гарантирует  равномерное  распределение  нагрузки  и  отказо-устойчивость, оно не всегда является предпочтительным. Часто  лучше обеспечить направление запросов конкретного пользо-вателя экземпляру сервиса, запущенному на определенной ма-шине. Иногда это обусловлено кэшированием пользователь-ских данных в памяти: если запросы этого пользователя будут  попадать на одну и ту же машину, то повысится коэффициент  88 Часть II. Паттерны проектирования обслуживающих систем попадания. Это также может быть обусловлено долгосрочной  природой  взаимодействия  пользователя  с  системой,  когда  часть состояния хранится между запросами. Вне зависимости  от  причины  можно  адаптировать  паттерн  реплицированного  stateless-сервиса к использованию в сервисах с закреплением  сессий, гарантирующих, что все запросы конкретного пользо-вателя будут адресованы одному и тому же экземпляру сервиса  (рис. 5.3).

Рис. 5.3. Сервис с закреплением сессий, в котором все запросы конкретного пользователя адресуются одному и тому же экземпляру сервиса Вообще  говоря,  закрепление  сессий  реализуется  путем  хеши-рования  IP-адресов  клиента  и  сервера  и  использования  этого  соответствия  для  определения  того,  какой  экземпляр  сервиса  какой запрос будет обслуживать. Пока IP-адреса клиента и сер-вера  остаются  неизменными,  все  запросы  этого  клиента  будут 

адресованы одному и тому же экземпляру сервиса. Закрепление  сессий  часто  реализуется  на  базе  консистентной хеш-функции .  Преимущества  консистентной  хеш-функции  становятся  очевидны  при  масштабировании  сервиса  в  боль-Глава 5. Реплицированные сервисы с распределением нагрузки 89

чтительнее использовать закрепление на уровне приложе-шую  или  меньшую  сторону.  Очевидно,  что  если  количество  копий  сервиса  меняется,  то  может  поменяться  и  соответствие  между конкретным пользователем и конкретным экземпляром  сервиса. Консистентные хеш-функции минимизируют количе-ство пользователей, у которых поменяется сопоставленный им  экземпляр сервиса.

Сервисы с репликацией на уровне приложения

Во  всех  предыдущих  примерах  репликация  и  распределение  нагрузки происходят на сетевом уровне сервиса. Распределение  нагрузки не зависит от конкретного протокола взаимодействия  узлов, находящегося в стеке над TCP/IP. Однако многие прило-жения общаются по протоколу HTTP, и, зная протокол общения  узлов,  можно  расширить  паттерн  реплицированного  stateless-сервиса дополнительной функциональностью. Добавляем кэширующую прослойку Иногда код stateless-сервиса достаточно сложен в вычислитель-ном плане, несмотря на то что состояние сервиса не хранится. Для  обслуживания  запросов  может  потребоваться  обращение  к базе данных, выполнение сложной обработки или визуализации  данных.  В  таких  условиях  отнюдь  не  помешает  добавить  в  при-ложение  прослойку  для  кэширования.  Кэш  находится  между