Краткое резюме
Я использую HTTP-сервер в качестве службы на Docker Swarm. Я тестирую время запроса, когда curl запускает его в цикле. Если я использую какой-либо прокси, направляющий трафик на сервис, я получаю случайные задержки в 1 секунду. Если я использую порт, опубликованный на рое HTTP-сервером - все в порядке. Если я запускаю тот же сервис без роя (с docker run
) и использую тот же прокси-сервер - время тоже в порядке.
Вы получили такой эффект? У кого-нибудь есть советы как от него избавиться?
Подробное описание и сценарии
Это простой docker-compose файл службы HTTP, который я использую:
version: '3.5'
services:
app:
image: nginx:latest
networks:
- proxy
ports:
- 48091:80
deploy:
placement:
constraints:
- node.hostname == some-node-name
labels:
- "traefik.docker.network=proxy"
- "traefik.port=80"
- "traefik.frontend.rule=Host:some.test.url.com"
networks:
proxy:
external: true
По умолчанию Nginx используется в качестве основного прокси-сервера вне роя, направляя запросы тестового домена к прокси-серверу Traefik, работающему в качестве сервиса внутри роя, и перенаправляет запросы в тестовый HTTP-сервис. Разумеется, опубликованный порт 48091 в этом сценарии не используется.
Я тестирую время запросов с помощью curl из локальной сети, используя простой скрипт:
#!/bin/
for i in {1..1000}; do
curl -g -so /dev/null -w '%{time_total}\n' http://some.test.url.com
done
Обычное общее время запроса, записанное curl, составляет около 0,006 мс, но время от времени оно прибавляет 1 секунду. Иногда все 1000 запросов выполняются без этой задержки, но при следующем запуске «длинные» времена составляют 2% или 6%. Иногда задержки бывают единичными, но обычно служба блокируется на некоторое время, и я получаю много длинных запросов подряд.
Моей первой мыслью было, что это вызвано Traefik, поэтому я опубликовал порт 48091 на рое и направил запросы от основного Nginx прямо на него, полностью минуя Traefik. Результат был точно таким же - много длинных запросов.
Следующий тест был запущен непосредственно на Traefik - без первого Nginx. Без изменений - все еще сломано.
Но
Служба тестирования без какого-либо прокси-сервера - кажется, что просто направление запросов curl на порт 48091 на узле роя работает нормально. Я запустил несколько сотен тысяч запросов, и ни один из них не был заблокирован.
Кроме того, если я запустил службу HTTP без роя - используя docker run -p 48091:80 nginx:latest
на той же машине, что использовалась ранее, и протестировал с передним Nginx - все тоже в порядке.
Подводя итог
Проблема возникает, если я запускаю службу в рое и использую любой прокси перед ним. Если он работает без роя, или я использую непосредственно опубликованный порт - все работает хорошо.
Буду признателен за любую помощь в этом вопросе, поскольку мы планируем запустить большой сайт, и это похоже на шоу-стопор. Переключиться на Kubernetes перед запуском сейчас нереально: (
Редактировать
Я настроил скрипт тестирования, чтобы получить точную информацию о таймингах из curl:
#!/bin/bash
URL="http://some.test.url.com"
OUT="%{time_total} | lookup: %{time_namelookup} | connect: %{time_connect} | appconnect: %{time_appconnect} | pretransfer: %{time_pretransfer} | redirect: %{time_redirect} | starttransfer: %{time_starttransfer}\n"
for i in {1..10000}; do
curl -g -so /dev/null -w "$OUT" $URL
done
Теперь результат тестового запуска с Nginx-> Swarm (только длинные запросы) выглядит так:
1.027 | lookup: 0.004 | connect: 0.005 | appconnect: 0.000 | pretransfer: 0.005 | redirect: 0.000 | starttransfer: 1.027
1.028 | lookup: 0.004 | connect: 0.005 | appconnect: 0.000 | pretransfer: 0.005 | redirect: 0.000 | starttransfer: 1.027
1.047 | lookup: 0.004 | connect: 0.005 | appconnect: 0.000 | pretransfer: 0.005 | redirect: 0.000 | starttransfer: 1.047
1.046 | lookup: 0.004 | connect: 0.005 | appconnect: 0.000 | pretransfer: 0.005 | redirect: 0.000 | starttransfer: 1.046
1.049 | lookup: 0.004 | connect: 0.005 | appconnect: 0.000 | pretransfer: 0.005 | redirect: 0.000 | starttransfer: 1.049
1.010 | lookup: 0.004 | connect: 0.005 | appconnect: 0.000 | pretransfer: 0.005 | redirect: 0.000 | starttransfer: 1.009
1.009 | lookup: 0.004 | connect: 0.005 | appconnect: 0.000 | pretransfer: 0.005 | redirect: 0.000 | starttransfer: 1.009
1.009 | lookup: 0.004 | connect: 0.005 | appconnect: 0.000 | pretransfer: 0.005 | redirect: 0.000 | starttransfer: 1.008
Так что задержка всегда на «starttransfer». Если я правильно понимаю это: https://blog.cloudflare.com/a-question-of-timing/ это означает, что существует некоторая проблема с передачей GET-запроса между Nginx и сервисом в Swarm.