Upload
tanya-denisyuk
View
7.269
Download
4
Embed Size (px)
Citation preview
load balancing и оптимальная загрузка кластера
Андрей Свелов[email protected]
● Пишу на Python с 1999 года● Python Code Developer● Соавтор asyncio, aiohttp и ещё дюжины
библиотек● Работаю в DataRobot
Простейшая схема развертывания
Browser Server
Проблемы:
1. Статика
Проблемы:
1. Статика2. Безопасность
Reverse proxy
Browser Application Server
Reverse proxyaka NGINX, HAProxy etc
Конфигурация NGINX:http {
server {
location /static {
root /www/static;
}
location / {
proxy_pass http://127.0.0.7:8080;
}
}
}
Балансировка на несколько app servers:
Browser Reverse proxy
Конфигурация NGINX:server {
upstream backend {
server http://127.0.0.7:8080;
server http://127.0.0.7:8081;
}
location / {
proxy_pass http://backend;
}
}
Round Robin:
Reverse proxy
1
2
3
Ситуация:
1. В DataRobot делаем предсказания на обученых моделях2. Предсказание занимает в 20-600 милисекунд в среднем.3. Модель может "весить" гигабайт(ы).4. Загрузка модели в память требует в 10-30 раз больше времени.Хочу чтобы запрос шел на сервер с уже загруженной моделью.
Каждому узлу -- по своей модели:
Node 1
Reverse proxy Node 2
Model 1
Model 2
Model 3
Model 4
Особенность:
url = "/v1/<project_id>/<model_id>/predict"
Удобный hash key
URL Hash как решение:
upstream = servers[hash(url) % len(servers)]
Конфигурация NGINX:server {
upstream backend {
hash $request_uri; server http://127.0.0.7:8080;
server http://127.0.0.7:8081;
}
location / {
proxy_pass http://backend;
}
}
URL Hash как плохое решение:
upstream = servers[hash(url) % len(servers)]
Если один сервер умирает -- вся система требует перебалансировки.
Пропадание узла:4 сервера, 12 объектов 3 сервера, 12 объектов
Consistent hash:
Consistent hash 2:
Конфигурация NGINX:server {
upstream backend {
consistent_hash $request_uri; server http://127.0.0.7:8080;
server http://127.0.0.7:8081;
}
location / {
proxy_pass http://backend;
}
}
Sticky sessions:
HTTP cookie based upstream selection
Всё это классно, но нам не годится:
● Нужен лучший контроль над выбором upstream
● Велосипедим сами
Самодельный контроллер
NGINX
Controller
Node 1
Node 2
Конфигурация NGINX:server {
location / {
set $upstream "<placeholder>";
rewrite_by_lua '
ctrl = require("controller")
ngx.var.upstream = ctrl.get(ngx.var.uri,
"unix://tmp/ctrl.sock")
';
proxy_pass http://$upstream;
}
}
LUA:function get(uri, sock_path)
local sock = ngx.socket.connect(sock_path)
local buf = pack("<HB", string.len(uri)+1, 1)
sock:send({buf, uri})
local resp_len_buf = sock:receive(3)
local resp_len, resp_code = unpack("<HB", resp_len_buf)
local upstream = sock:receive(resp_len - 1)
sock:setkeepalive()
return upstream
end
Контроллер:
● asyncio UNIX/TCP сервер● данные -- в REDIS slave
Управление:
● REST сервер -- конфигурирование● Sentinel -- наблюдение
Результат:
● Емкость кластера х4● Утилизация серверов х3 (75%)
Ищем сотрудников в Минский офис
http://datarobot.com● Python backend● JavaScript frontend● DevOps● Data Science
Вопросы?
Андрей Светлов[email protected]