Назад | Перейти на главную страницу

Балансировка нагрузки Nginx - плохая конфигурация или плохое поведение?

В настоящее время я использую Nginx в качестве балансировщика нагрузки, чтобы сбалансировать сетевой трафик между 3 узлами, на которых работает API NodeJS.

Экземпляр Nginx работает на node1, и каждый запрос выполняется на node1. У меня есть обзор запросов около 700 тыс. За 2 часа, и nginx настроен для переключения их циклическим образом между node1, node2 и node3. Здесь conf.d/deva.conf:

upstream deva_api {
    server 10.8.0.30:5555 fail_timeout=5s max_fails=3;
    server 10.8.0.40:5555 fail_timeout=5s max_fails=3;
    server localhost:5555;
    keepalive 300;
}

server {

        listen 8000;

        location /log_pages {

                proxy_redirect off;
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

                proxy_http_version 1.1;
                proxy_set_header Connection "";

                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Allow-Methods' 'GET, POST, PATCH, PUT, DELETE, OPTIONS';
                add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Origin,X-Auth-Token';
                add_header 'Access-Control-Allow-Credentials' 'true';

                if ($request_method = OPTIONS ) {
                        return 200;
                }

                proxy_pass http://deva_api;
                proxy_set_header Connection "Keep-Alive";
                proxy_set_header Proxy-Connection "Keep-Alive";

                auth_basic "Restricted";                                #For Basic Auth
                auth_basic_user_file /etc/nginx/.htpasswd;  #For Basic Auth
        }
}

и здесь nginx.conf конфигурация:

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

worker_rlimit_nofile 65535;
events {
        worker_connections 65535;
        use epoll;
        multi_accept on;
}

http {

        ##
        # Basic Settings
        ##

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 120;
        send_timeout 120;
        types_hash_max_size 2048;
        server_tokens off;

        client_max_body_size 100m;
        client_body_buffer_size  5m;
        client_header_buffer_size 5m;
        large_client_header_buffers 4 1m;

        open_file_cache max=200000 inactive=20s;
        open_file_cache_valid 30s;
        open_file_cache_min_uses 2;
        open_file_cache_errors on;

        reset_timedout_connection on;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # SSL Settings
        ##

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        ##
        # Gzip Settings
        ##

        gzip on;
        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}

Проблема в том, что с этой конфигурацией я получаю сотни ошибок в error.log, например:

upstream prematurely closed connection while reading response header from upstream

но только на node2 и node3. Я уже пробовал следующие тесты:

  1. увеличить количество параллельных API в каждом узле (на самом деле я использую PM2 как балансировщик внутри узла)
  2. удалите один узел, чтобы упростить работу nginx
  3. применил веса к nginx

Ничто не улучшает результат. В этих тестах я заметил, что ошибки были только на 2 удаленных узлах (node2 и node3), поэтому я попытался удалить их из уравнения. В результате я больше не получаю подобных ошибок, но у меня стали появляться две разные ошибки:

recv() failed (104: Connection reset by peer) while reading response header from upstream

и

writev() failed (32: Broken pipe) while sending request to upstream

Кажется, проблема была связана с отсутствием API на node1, API, вероятно, не могут ответить на весь входящий трафик до тайм-аута клиента (это было, я думаю). Сказал, что я увеличил количество параллельных API на node1, и результат был лучше, чем у предыдущих, но я продолжаю получать последние 2 ошибки, и я больше не могу увеличивать количество одновременных API на node1.

Итак, вопрос в том, почему я не могу использовать nginx в качестве балансировщика нагрузки со всеми моими узлами? Я делаю ошибки в конфигурации nginx? Есть ли другие проблемы, которых я не заметил?

РЕДАКТИРОВАТЬ: Я провожу несколько сетевых тестов между 3 узлами. Узлы общаются друг с другом через Openvpn:

ПИНГ:

node1->node2
PING 10.8.0.40 (10.8.0.40) 56(84) bytes of data.
64 bytes from 10.8.0.40: icmp_seq=1 ttl=64 time=2.85 ms
64 bytes from 10.8.0.40: icmp_seq=2 ttl=64 time=1.85 ms
64 bytes from 10.8.0.40: icmp_seq=3 ttl=64 time=3.17 ms
64 bytes from 10.8.0.40: icmp_seq=4 ttl=64 time=3.21 ms
64 bytes from 10.8.0.40: icmp_seq=5 ttl=64 time=2.68 ms

node1->node2
PING 10.8.0.30 (10.8.0.30) 56(84) bytes of data.
64 bytes from 10.8.0.30: icmp_seq=1 ttl=64 time=2.16 ms
64 bytes from 10.8.0.30: icmp_seq=2 ttl=64 time=3.08 ms
64 bytes from 10.8.0.30: icmp_seq=3 ttl=64 time=10.9 ms
64 bytes from 10.8.0.30: icmp_seq=4 ttl=64 time=3.11 ms
64 bytes from 10.8.0.30: icmp_seq=5 ttl=64 time=3.25 ms

node2->node1
PING 10.8.0.12 (10.8.0.12) 56(84) bytes of data.
64 bytes from 10.8.0.12: icmp_seq=1 ttl=64 time=2.30 ms
64 bytes from 10.8.0.12: icmp_seq=2 ttl=64 time=8.30 ms
64 bytes from 10.8.0.12: icmp_seq=3 ttl=64 time=2.37 ms
64 bytes from 10.8.0.12: icmp_seq=4 ttl=64 time=2.42 ms
64 bytes from 10.8.0.12: icmp_seq=5 ttl=64 time=3.37 ms

node2->node3
PING 10.8.0.40 (10.8.0.40) 56(84) bytes of data.
64 bytes from 10.8.0.40: icmp_seq=1 ttl=64 time=2.86 ms
64 bytes from 10.8.0.40: icmp_seq=2 ttl=64 time=4.01 ms
64 bytes from 10.8.0.40: icmp_seq=3 ttl=64 time=5.37 ms
64 bytes from 10.8.0.40: icmp_seq=4 ttl=64 time=2.78 ms
64 bytes from 10.8.0.40: icmp_seq=5 ttl=64 time=2.87 ms

node3->node1
PING 10.8.0.12 (10.8.0.12) 56(84) bytes of data.
64 bytes from 10.8.0.12: icmp_seq=1 ttl=64 time=8.24 ms
64 bytes from 10.8.0.12: icmp_seq=2 ttl=64 time=2.72 ms
64 bytes from 10.8.0.12: icmp_seq=3 ttl=64 time=2.63 ms
64 bytes from 10.8.0.12: icmp_seq=4 ttl=64 time=2.91 ms
64 bytes from 10.8.0.12: icmp_seq=5 ttl=64 time=3.14 ms

node3->node2
PING 10.8.0.30 (10.8.0.30) 56(84) bytes of data.
64 bytes from 10.8.0.30: icmp_seq=1 ttl=64 time=2.73 ms
64 bytes from 10.8.0.30: icmp_seq=2 ttl=64 time=2.38 ms
64 bytes from 10.8.0.30: icmp_seq=3 ttl=64 time=3.22 ms
64 bytes from 10.8.0.30: icmp_seq=4 ttl=64 time=2.76 ms
64 bytes from 10.8.0.30: icmp_seq=5 ttl=64 time=2.97 ms

Проверка пропускной способности через IPerf:

node1 -> node2
[ ID] Interval       Transfer     Bandwidth
[  4]  0.0-10.0 sec   229 MBytes   192 Mbits/sec

node2->node1
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec   182 MBytes   152 Mbits/sec

node3->node1
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec   160 MBytes   134 Mbits/sec

node3->node2
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec   260 MBytes   218 Mbits/sec

node2->node3
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec   241 MBytes   202 Mbits/sec

node1->node3
[ ID] Interval       Transfer     Bandwidth
[  4]  0.0-10.0 sec   187 MBytes   156 Mbits/sec

Кажется, что в туннеле OpenVPN есть узкое место, потому что тот же тест через eth составляет около 1 Гбит. Сказал, что я следил за этим руководством community.openvpn.net но я получил только удвоенную пропускную способность, измеренную ранее.

Я хотел бы оставить OpenVPN включенным, поэтому есть ли какие-либо другие настройки, которые нужно сделать, чтобы увеличить пропускную способность сети или какие-либо другие изменения в конфигурации nginx, чтобы он работал должным образом?

Проблемы были вызваны медлительностью сети OpenVPN. Маршрутизируя запросы в Интернете после добавления аутентификации на каждом отдельном сервере, мы сократили количество ошибок до 1-2 в день и, вероятно, теперь вызваны некоторыми другими проблемами.