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

Высокая загрузка ЦП HAProxy - проблема с конфигурацией?

Недавно у нас был всплеск трафика, который, хотя и был умеренным по размеру, привел к тому, что haproxy перегружал одно из ядер ЦП (и сервер перестал отвечать). Я предполагаю, что я делаю что-то неэффективно с конфигурацией, и поэтому хотел бы спросить всех экспертов по haproxy, не будут ли они так любезны, чтобы критиковать мой файл конфигурации ниже (в основном с точки зрения производительности).

Конфигурация предназначена для распределения между группой серверов http-приложений, группой серверов, которые обрабатывают соединения с веб-сокетами (с несколькими отдельными процессами на разных портах), и статическим файловым веб-сервером. Он работает хорошо, судя по производительности. (Некоторые детали отредактированы.)

Мы будем очень признательны за любые рекомендации, которые вы могли бы предложить!

HAProxy v1.4.8

#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
        global
                daemon
                maxconn         100000
                log             127.0.0.1 local0 notice
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
        defaults
                log                     global
                mode                    http
                option                  httplog
                option                  httpclose               #http://serverfault.com/a/104782/52811
                timeout connect         5000ms
                timeout client          50000ms
                timeout server          5h                      #long timeouts to stop WS drops - when v1.5 is stable, use 'timeout tunnel';
#---------------------------------------------------------------------
# FRONTEND
#---------------------------------------------------------------------
        frontend public
                bind *:80
                maxconn         100000
                reqidel ^X-Forwarded-For:.*                     #Remove any x-forwarded-for headers
                option forwardfor                               #Set the forwarded for header (needs option httpclose)

                default_backend app
                redirect prefix http://xxxxxxxxxxxxxxxxx code 301 if { hdr(host) -i www.xxxxxxxxxxxxxxxxxxx }
                timeout client  5h                              #long timeouts to stop WS drops - when v1.5 is stable, use 'timeout tunnel';

        # ACLs
        ##########
        acl static_request hdr_beg(host) -i i.
        acl static_request hdr_beg(host) -i static.
        acl static_request path_beg /favicon.ico /robots.txt
        acl test_request hdr_beg(host) -i test.
        acl ws_request hdr_beg(host) -i ws
        # ws11
        acl ws11x1_request hdr_beg(host) -i ws11x1
        acl ws11x2_request hdr_beg(host) -i ws11x2
        acl ws11x3_request hdr_beg(host) -i ws11x3
        acl ws11x4_request hdr_beg(host) -i ws11x4
        acl ws11x5_request hdr_beg(host) -i ws11x5
        acl ws11x6_request hdr_beg(host) -i ws11x6
        # ws12
        acl ws12x1_request hdr_beg(host) -i ws12x1
        acl ws12x2_request hdr_beg(host) -i ws12x2
        acl ws12x3_request hdr_beg(host) -i ws12x3
        acl ws12x4_request hdr_beg(host) -i ws12x4
        acl ws12x5_request hdr_beg(host) -i ws12x5
        acl ws12x6_request hdr_beg(host) -i ws12x6

        # Which backend....
        ###################
        use_backend static   if static_request
        #ws11
        use_backend ws11x1 if ws11x1_request
        use_backend ws11x2 if ws11x2_request
        use_backend ws11x3 if ws11x3_request
        use_backend ws11x4 if ws11x4_request
        use_backend ws11x5 if ws11x5_request
        use_backend ws11x6 if ws11x6_request
        #ws12
        use_backend ws12x1 if ws12x1_request
        use_backend ws12x2 if ws12x2_request
        use_backend ws12x3 if ws12x3_request
        use_backend ws12x4 if ws12x4_request
        use_backend ws12x5 if ws12x5_request
        use_backend ws12x6 if ws12x6_request
#---------------------------------------------------------------------
# BACKEND - APP
#---------------------------------------------------------------------
        backend app
                timeout server          50000ms #To counter the WS default
                mode http
                balance roundrobin
                option httpchk HEAD /upchk.txt
                server app1 app1:8000             maxconn 100000 check
                server app2 app2:8000             maxconn 100000 check
                server app3 app3:8000             maxconn 100000 check
                server app4 app4:8000             maxconn 100000 check
#---------------------------------------------------------------------
# BACKENDs - WS
#---------------------------------------------------------------------
#Server ws11
        backend ws11x1
                server ws11 ws11:8001 maxconn 100000
        backend ws11x2
                server ws11 ws11:8002 maxconn 100000
        backend ws11x3
                server ws11 ws11:8003 maxconn 100000
        backend ws11x4
                server ws11 ws11:8004 maxconn 100000
        backend ws11x5
                server ws11 ws11:8005 maxconn 100000
        backend ws11x6
                server ws11 ws11:8006 maxconn 100000
#Server ws12
        backend ws12x1
                server ws12 ws12:8001 maxconn 100000
        backend ws12x2
                server ws12 ws12:8002 maxconn 100000
        backend ws12x3
                server ws12 ws12:8003 maxconn 100000
        backend ws12x4
                server ws12 ws12:8004 maxconn 100000
        backend ws12x5
                server ws12 ws12:8005 maxconn 100000
        backend ws12x6
                server ws12 ws12:8006 maxconn 100000
#---------------------------------------------------------------------
# BACKEND - STATIC
#---------------------------------------------------------------------
        backend static
                server static1 static1:80   maxconn 40000

100 000 подключений - это много ... Вы так сильно напираете? Если да ... возможно, разделение внешнего интерфейса так, чтобы он привязывался к одному IP-адресу для статического контента и одному IP-адресу для содержимого приложения, а затем запускал варианты static и app как отдельные процессы haproxy (при условии, что у вас есть второе ядро ​​/ процессор на сервере) ...

Если ничего другого, это сузит использование до приложения или статических потоков ...


Если я правильно помню свой сетевой класс 101 ... HaProxy не должен ударить 100,000 связи с ws12:8001 или любой другой backend host: port из-за ограничения порта ~ 65536, который ближе к 28232 в большинстве систем (cat /proc/sys/net/ipv4/ip_local_port_range). Возможно, вы исчерпываете локальные порты, что, в свою очередь, может привести к зависанию процессора, когда он ожидает освобождения портов.

Возможно, уменьшение максимального количества подключений к каждому бэкэнду до 28000 решит проблему? Или изменить диапазон локальных портов на более широкий?

Взгляните на настройку nbproc и посмотрите, помогает ли это, используя более одного ядра. Для большинства аппаратных балансировщиков нагрузки объем трафика, который вы можете обработать, ограничен вашим процессором / памятью балансировщика нагрузки.

1.5) Increasing the overall processing power
--------------------------------------------
On multi-processor systems, it may seem to be a shame to use only one processor,
eventhough the load needed to saturate a recent processor is far above common
usage. Anyway, for very specific needs, the proxy can start several processes
between which the operating system will spread the incoming connections. The
number of processes is controlled by the 'nbproc' parameter in the 'global'
section. It defaults to 1, and obviously works only in 'daemon' mode. One
typical usage of this parameter has been to workaround the default per-process
file-descriptor limit that Solaris imposes to user processes.

Example :
---------

    global
        daemon
        quiet
        nbproc  2

Вне настройки haproxy это поможет немного настроить сеть.

Одна конкретная вещь, которая может помочь, - это убедиться, что ваши сетевые интерфейсы не привязаны к одному процессору (при условии, что вы используете несколько интерфейсов). Если вы используете haproxy в Linux, вы можете проверить баланс следующим образом:

egrep CPU\|eth /proc/interrupts

Например, это показывает, что прерывания для eth0 и eth1 обрабатываются разными процессорами:

$ egrep CPU\|eth /proc/interrupts
      CPU0        CPU1        CPU2    CPU3
103:  3515635238  0           0       0          IR-PCI-MSI-edge  eth0
104:  0           1976927064  0       0          IR-PCI-MSI-edge  eth1

Принимая во внимание, что это показывает, что они обрабатываются одним и тем же процессором:

$ egrep CPU\|eth /proc/interrupts
      CPU0        CPU1  CPU2  CPU3
272:  1526254507  0     0     0     Dynamic-irq  eth0
273:  4877925     0     0     0     Dynamic-irq  eth1

Вы захотите включить привязку smp для этих интерфейсов. В приведенном выше примере вы можете сделать следующее:

echo 010 > /proc/irq/272/smp_affinity
echo 010 > /proc/irq/273/smp_affinity

Я предлагаю активировать «Многопоточный режим», поместив параметр nbthread в глобальный раздел. От мужчины:

Этот параметр доступен только при встроенной поддержке потоков. Он создает потоки для каждого созданного процесса. Это означает, что если HAProxy запущен на переднем плане, он создает потоки только для первого процесса.

Мы активировали «Многопоточный режим», и наш сайт стал работать на x15 быстрее. Вы можете узнать больше о многопроцессорном и многопоточном варианте здесь: https://www.haproxy.com/blog/multithreading-in-haproxy/