Проблемы с производительностью при запуске nginx в контейнере докеров

Я использую ApacheBench (ab) для измерения производительности двух nginx в Linux. У них одинаковый файл конфигурации. Единственная разница в том, что один из nginx работает в док-контейнере.

Nginx в хост-системе:

Running: ab -n 50000 -c 1000 http://172.17.0.2:7082/

Concurrency Level:      1000
Time taken for tests:   9.376 seconds
Complete requests:      50000
Failed requests:        0
Total transferred:      8050000 bytes
HTML transferred:       250000 bytes
Requests per second:    5332.94 [#/sec] (mean)
Time per request:       187.514 [ms] (mean)
Time per request:       0.188 [ms] (mean, across all concurrent requests)
Transfer rate:          838.48 [Kbytes/sec] received

Nginx в док-контейнере:

Running: ab -n 50000 -c 1000 http://172.17.0.2:6066/

Concurrency Level:      1000
Time taken for tests:   31.274 seconds
Complete requests:      50000
Failed requests:        0
Total transferred:      8050000 bytes
HTML transferred:       250000 bytes
Requests per second:    1598.76 [#/sec] (mean)
Time per request:       625.484 [ms] (mean)
Time per request:       0.625 [ms] (mean, across all concurrent requests)
Transfer rate:          251.37 [Kbytes/sec] received

Просто интересно, почему у контейнера такая плохая производительность

nginx.conf:

worker_processes  auto;
worker_rlimit_nofile 10240;

events {
    use epoll;
    multi_accept on;
    worker_connections  4096;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  10;

    client_header_timeout 10;
    client_body_timeout 10;

    send_timeout 10;

    tcp_nopush on;
    tcp_nodelay on;

    server {
        listen       80;
        server_name  localhost;
        location / {
            return 200 'hello';
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

person Sveargith    schedule 28.02.2018    source источник


Ответы (2)


Я хотел бы добавить к ответу @Andrian Mouat то, что я только что нашел в документации.

Это написано в справочнике по запуску Docker:

СЕТЬ: ХОСТ

По сравнению с режимом bridge по умолчанию, режим host обеспечивает значительно более высокую производительность сети, поскольку он использует собственный сетевой стек хоста, тогда как мост должен пройти один уровень виртуализации с помощью демона docker.

Рекомендуется запускать контейнеры в этом режиме, когда их сетевая производительность критична, например, балансировщик нагрузки в рабочей среде или высокопроизводительный веб-сервер.


Ниже приведены некоторые тесты с Flame Graphs:

При использовании собственного сетевого стека хоста с --net=host системных вызовов меньше, и это ясно показано на следующих графиках Flame. Подробности:

  • общесистемные захваты за 30 секунд: sudo perf record -F 99 -a -g -- sleep 30
  • ab-тест с другой физической машины: ab -n 50000 -c 1000 http://my-host-ip/ (происходит во время захвата)

Для получения дополнительной информации о Flame Graphs посетите веб-сайт Брендана Грегга: www.brendangregg.com/

Flame Graph при публикации порта -p 80:80:

Полное изображение здесь

Увеличено до nginx части:

docker nginx flame graph увеличен порт публикации



График пламени при использовании --net=host:

Полное изображение здесь

Увеличено до nginx части:

docker nginx flame graph net host увеличен

person tgogos    schedule 14.03.2018

Как у вас работает контейнер? Использует ли он сеть моста Docker по умолчанию? Если это так, попробуйте запустить тесты с помощью --net=host и посмотрите, как выглядят результаты.

person Adrian Mouat    schedule 28.02.2018
comment
Ух ты! Это увеличивает производительность примерно на 50%! Time taken for tests: 16.944 seconds - person Sveargith; 28.02.2018
comment
Да, мостовая сеть действительно проста, чтобы заставить все работать, но это не очень хорошо для эффективности. Там все еще довольно большая разница, было бы интересно выяснить, откуда она взялась. Запись в файлы журнала и кэша также может быть медленнее из-за оверлея fs. - person Adrian Mouat; 28.02.2018
comment
Я пробовал это, но по-прежнему получаю около 60% работы nginx непосредственно на хосте (когда у меня нет параметра --net=host, я получаю только 35%). - person Nikolay Dimitrov; 17.10.2018
comment
Я бы также проверил, используете ли вы одну и ту же библиотеку (glibc и musl) и эффекты файловой системы контейнера (попробуйте использовать тома для любых данных/файлов). - person Adrian Mouat; 18.10.2018
comment
Просто предупреждаю, --net host к сожалению, не работает в Docker для Mac — кажется, поддерживается только в Linux - person davnicwil; 07.07.2019
comment
@davnicwil это не совсем так, просто это не то, что вы могли ожидать. Если вы получите адрес виртуальной машины xhyve внутри Docker для Mac, вы сможете подключиться к контейнеру с помощью --net=host и избежать некоторых сетевых накладных расходов. - person Adrian Mouat; 26.07.2019