I am currently trying to migrate a somewhat over-complicated and over-provisioned setup to something simpler and more efficient. The application servers lots of small HTTP requests (often 204 or 3xx), and gets requests from all sorts of oddly behaving clients or over-aggressive pre-connecting user agents. (Thanks for the help in the client timeout thread!)

The servers are:
 * AMD Opteron 4184, 6 cores, 2.8 Ghz
 * 2x gigabit Intel 82576 with the igb driver
 * centos 6 (2.6.32-358.23.2.el6.x86_64)

Running 1.4.24 with all traffic currently coming from the outside on eth0 and going to the backend servers on eth1.

The setup that I thought would work well is:
 * core 0: all network interrupts
 * core 1: haproxy
 * core 2-5: httpd for ssl termination

After some adventures in interrupt tunning so that core 0 would not be killed by > 100k/s we got this to satisfy roughly 20k req/s. At this point hatop would report the Queue was growing without bond and maxconn would fill up. The cause looks simple enough, core 1 was consistently 0.00% idle at that load http://pastebin.com/kuT5uCtP.

My first question is if the roughly 1:3 usr/sys ratio is "normal" for a well functioning haproxy serving tiny http objects? See sample config attached. While I don't have an empirical basis for comparison on this older hardware, 20k req/s also "seemed" low.

Because it's what we had used in the old setup I also tried setting nbproc=6 with no IRQ pinning (tests showed IRQs on one core was beneficial with no nbproc). This was able to handle close to *twice* as many req/s. This was a surprising result because almost every thread mentioning nbproc suggests not using it and I expected at best marginal gains. Either way I'd prefer to avoid nbproc for stats and all of the typical reason.

Finally assuming the single process performance can not be further improved I was considering the following setup:
 * core 0: eht0 interrupts
 * core 1: haproxy bound to eth0
 * core 2: eth1 interrupts
 * core 3: haproxy bound to eth1
 * core 4-5: ssl terminator

But I could not find too many examples of similar setups and was unsure if it was a viable long term configuration.
global
    log         127.0.0.1     local4 info
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    daemon
    stats socket /var/run/haproxy.socket mode 766
    maxconn              65530


defaults
    mode                 http
    log                  global
    option               dontlog-normal
    option               dontlognull # uncomment for details
    option               httplog
    option               httpclose
    option               contstats
    timeout client       7s
    timeout server       4s
    timeout connect      4s
    timeout http-request 7s
    maxconn              65530

listen stats
    bind *:81
    stats enable
    stats uri /ha-stats

frontend foo_in
    bind *:80
    mode http
    default_backend foo_nodes
    log global
    option forwardfor except 127.0.0.1

backend foo_nodes
    balance roundrobin
    option tcp-smart-connect
    option httpchk HEAD /live-lb HTTP/1.0
    server s0 xx.xx.xx.xx:8080 maxconn 4096 maxqueue 1024 check inter 1s fall 5 
rise 2
    server s1 xx.xx.xx.xx:8080 maxconn 4096 maxqueue 1024 check inter 1s fall 5 
rise 2
    server s2 xx.xx.xx.xx:8080 maxconn 4096 maxqueue 1024 check inter 1s fall 5 
rise 2
    server s3 xx.xx.xx.xx:8080 maxconn 4096 maxqueue 1024 check inter 1s fall 5 
rise 2
    server s4 xx.xx.xx.xx:8080 maxconn 4096 maxqueue 1024 check inter 1s fall 5 
rise 2
    server s5 xx.xx.xx.xx:8080 maxconn 4096 maxqueue 1024 check inter 1s fall 5 
rise 2
 haproxy -vv
HA-Proxy version 1.4.24 2013/06/17
Copyright 2000-2013 Willy Tarreau <[email protected]>

Build options :
  TARGET  = linux2628
  CPU     = generic
  CC      = gcc
  CFLAGS  = -m64 -march=x86-64 -O2 -g -fno-strict-aliasing
  OPTIONS = USE_LINUX_SPLICE=1 USE_LINUX_TPROXY=1 USE_STATIC_PCRE=1

Default settings :
  maxconn = 2000, bufsize = 16384, maxrewrite = 8192, maxpollevents = 200

Encrypted password support via crypt(3): yes

Available polling systems :
     sepoll : pref=400,  test result OK
      epoll : pref=300,  test result OK
       poll : pref=200,  test result OK
     select : pref=150,  test result OK
Total: 4 (4 usable), will use sepoll.

Reply via email to