Сервис можно опробовать в контейнере, выполнив следующую команду:
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-сервиса достаточно сложен в вычислитель-ном плане, несмотря на то что состояние сервиса не хранится. Для обслуживания запросов может потребоваться обращение к базе данных, выполнение сложной обработки или визуализации данных. В таких условиях отнюдь не помешает добавить в при-ложение прослойку для кэширования. Кэш находится между 90Часть II. Паттерны проектирования обслуживающих систем stateless-приложением и запросом конечного пользователя. Про-стейшая форма кэширования в веб-приложениях — применение кэширующего веб-прокси. Кэширующий прокси представляет собой просто-напросто HTTP-сервер, хранящий в памяти состоя-ние запросов пользователей. Если два пользователя запросят одну и ту же веб-страницу, только один из запросов будет адресован приложению, второй будет обслужен из памяти кэша (рис. 5.4).
Читать дальше