I need to improve the performance of an haproxy 1.5 running as a load balancer in an Ubuntu 14.04 instance. I have an analytics like code on many sites and for every pageview the client asks between 2-5 diferent scrips of ours. The other day we received more than 1k requests per second on the load balancer and it started to run really slow. It reached the active sessions limit 2000 at a rate for 1000 per second. On the configuration we use option http-keep-alive 100 to maintain the connection open for 100 ms until it is closed. How can we improve this? What is the best config for this use case? I may be loosing many details here please ask for them is there is info missing.
EDIT
Here are some details:
I'm running an AWS ubuntu 14.04 server in a c3.xlarge virtual machine. There we use haproxy 1.5 to load balance web traffic between several app instances. (Every app has its own haproxy to load balance between its own app instances - deployed one per core).
The server only has haproxy and no other software installed.
The bottleneck as per haproxy stat page is the front end load balancer as at that moment it had a session rate of 258 and current sessions of 2000 (being 2000 the max), and all the apps had a 96 sessions rate and 0/1 as the current sessions. I would post image but because of my reputation points I can't do that.
This was the configuration at that point in time:
global
maxconn 18000
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
defaults
mode http
retries 2
option redispatch
timeout connect 5s
timeout client 15s
timeout server 15s
timeout http-keep-alive 1
frontend public
log 127.0.0.1 local0 notice
option dontlognull
option httplog
bind *:80
bind *:443 ssl crt /etc/ssl/private/server.pem
default_backend rely_apps
frontend private
bind 127.0.0.1:80
stats enable
stats auth xxx:xxx
stats admin if LOCALHOST
stats uri /haproxy?stats
stats show-legends
stats realm Haproxy\ Statistics
backend rely_apps
option forwardfor
balance roundrobin
option httpchk
server app1 10.0.0.1:80 check
server app2 10.0.0.2:80 check
server app3 10.0.0.3:80 check
The connections were very high, it seems like it was closing them (or closing at a really low rate).
CPU and memory usage was really low.
Now we changed that config for the following one and it's working without problems:
global
maxconn 64000
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
tune.bufsize 16384
tune.maxrewrite 1024
nbproc 4
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
defaults
mode http
retries 2
option redispatch
option forceclose
option http-pretend-keepalive
timeout connect 5s
timeout client 15s
timeout server 15s
timeout http-keep-alive 1s
frontend public
log 127.0.0.1 local0 notice
option dontlognull
option httplog
maxconn 18000
bind *:80
bind *:443 ssl crt /etc/ssl/private/server.pem
default_backend rely_apps
#frontend private
# bind 127.0.0.1:80
stats enable
stats auth xxx:xxx
stats admin if LOCALHOST
stats uri /haproxy?stats
stats show-legends
stats realm Haproxy\ Statistics
backend rely_apps
option forwardfor
balance leastconn
option httpchk
server app1 10.0.0.1:80 check maxconn 100
server app2 10.0.0.2:80 check maxconn 100
server app3 10.0.0.3:80 check maxconn 100
However all connections are being closed on the return (and we have the same rate of sessions and requests).
This is not good also because we have to open a new connection for every client request (and we have 3/4 requests per client).
How can we achieve a good keep-alive (like 100ms I think could work), without hitting the max connections limit?
Thanks.
The number you give are very very low.
Please give more details about your architecture, type of server, third party software running on it (such as iptables), also share your configuration.
Baptiste
Related
We have a server running on port 8080, whenever posting a request to the server it is giving response back.
On the same instance Haproxy is running on 443 (with SSL), when I'm posting the the same request to haproxy (IP:443) it is throwing "502 Bad Gateway" error.
May I know what could be the problem?
Below is the Haproxy config:
global
maxconn 2048
tune.ssl.default-dh-param 2048
daemon
defaults
mode http
option forwardfor
option http-server-close
retries 3
timeout http-request 5000s
timeout queue 3m
timeout connect 5000s
timeout client 3m
timeout server 3m
timeout http-keep-alive 5000s
timeout check 4000s
maxconn 2048
frontend www-https
bind *:443 ssl crt /etc/ssl/haproxy/app-ssl.pem
reqadd X-Forwarded-Proto:\ https
default_backend www-backend
backend www-backend
redirect scheme https if !{ ssl_fc }
server www-1 localhost:8080 check
listen stats
bind *:28080
mode http
stats enable
stats uri /haproxy?stats
Add Global value
tune.maxrewrite 4096 then it worked
Haproxy Config should be as below:
global
maxconn 2048
tune.ssl.default-dh-param 2048
tune.maxrewrite 4096
daemon
defaults
mode http
option forwardfor
option http-server-close
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 2048
frontend www-https
bind *:443 ssl crt /etc/ssl/haproxy/ede-ssl.pem
reqadd X-Forwarded-Proto:\ https
default_backend www-backend
backend www-backend
redirect scheme https if !{ ssl_fc }
server www-1 localhost:8080 check
listen stats
bind *:28080
mode http
stats enable
stats uri /haproxy?stats
Please find the below description:
tune.bufsize
Sets the buffer size to this size (in bytes). Lower values allow more
sessions to coexist in the same amount of RAM, and higher values allow some
applications with very large cookies to work. The default value is 16384 and
can be changed at build time. It is strongly recommended not to change this
from the default value, as very low values will break some services such as
statistics, and values larger than default size will increase memory usage,
possibly causing the system to run out of memory. At least the global maxconn
parameter should be decreased by the same factor as this one is increased.
If HTTP request is larger than (tune.bufsize - tune.maxrewrite), haproxy will
return HTTP 400 (Bad Request) error. Similarly if an HTTP response is larger
than this size, haproxy will return HTTP 502 (Bad Gateway)
We are trying to configure our Socket.io socket servers behind HAProxy and over HAProxy we are using Google Cloud Load Balancer, so that HAProxy is not the single point of failure. As mentioned in this post by https://medium.com/google-cloud/highly-available-websockets-on-google-cloud-c74b35ee20bc#.o6xxj5br8. Also depicted in the picture below.
At the Google cloud load balancer we are using TCP Load balancing with SSL Proxy with Proxy Protocol ON.
The HAProxy is configured to use Cookies so that a client always connects to the same server. However since cookies might not be available on all our clients system, we decided to use load balancing algorithm as source in HAProxy. Here is the HAProxy configuration
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
maxconn 16384
tune.ssl.default-dh-param 2048
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
defaults
mode http
log global
option httplog
option http-server-close
option dontlognull
option redispatch
option contstats
retries 3
backlog 10000
timeout client 25s
timeout connect 5s
timeout server 25s
timeout tunnel 3600s
timeout http-keep-alive 1s
timeout http-request 15s
timeout queue 30s
timeout tarpit 60s
default-server inter 3s rise 2 fall 3
option forwardfor
frontend public
bind *:443 ssl crt /etc/ssl/private/key.pem ca-file /etc/ssl/private/cert.crt accept-proxy
maxconn 50000
default_backend ws
backend ws
timeout check 5000
option tcp-check
option log-health-checks
balance source
cookie QUIZIZZ_WS_COOKIE insert indirect nocache
server ws1 socket-server-1:4000 maxconn 4096 weight 10 check rise 1 fall 3 check cookie ws1 port 4000
server ws2 socket-server-1:4001 maxconn 4096 weight 10 check rise 1 fall 3 check cookie ws2 port 4001
server ws3 socket-server-2:4000 maxconn 4096 weight 10 check rise 1 fall 3 check cookie ws3 port 4000
server ws4 socket-server-2:4001 maxconn 4096 weight 10 check rise 1 fall 3 check cookie ws4 port 4001
This is however giving connection errors on around 5% of our clients as compared to our old single server system. Any suggestions?
Edit: Connection errors means that the client was not able to connect to the socket server and the socket.io client was throwing connection errors.
Thanks in advance.
I have 2 HAProxys that are load balancing user requests with roundrobin algorithm successfully to my 2 WebServers.
When a webserver fails, HAProxy sends the request to the next available server, but for some reason I'm not able to keep the user session, and therefore information isn't displayed properly.
How can I make it so the session is saved during a failover?
Here's my haproxy.cfg:
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
maxconn 2000
user haproxy
group haproxy
daemon
defaults
log global
mode http
option httplog
option dontlognull
retries 3
option redispatch
timeout connect 5000
timeout client 10000
timeout server 1000
listen app 192.168.1.100:80
mode http
stats enable
stats uri /haproxy?stats
stats realm Strictly\ Private
stats auth admin:admin
balance roundrobin
cookie LSW_WEB insert
option httpclose
option forwardfor
option httpchk HEAD / HTTP/1.0
server server1 192.168.1.93:80 cookie LSW_WEB01 check
server server2 192.168.1.94:80 cookie LSW_WEB02 check
This has to do with how you share sessions between your servers not with haproxy itself.
The problem lies in your application or how you are storing sessions.
I am setting up a keepalived HAProxy balancer of http traffic in the frontend of a three appserver-nodes with nginx/php-fpm. So my chain of services would be:
-----> HAProxy -----> nginx -----> php-FPM ----> webapp
Well, the problem is that haproxy can't see my backend servers when is set it to use cookies to ensure session affinity.
here is my haproxy.conf file:
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
user haproxy
group haproxy
daemon
defaults
log global
mode http
option httplog
option dontlognull
contimeout 5000
clitimeout 50000
srvtimeout 50000
frontend http-in
bind *:80
default_backend servers
backend servers
option httpchk OPTIONS /
option forwardfor
option http-server-close
balance roundrobin
cookie PHPSESSID prefix indirect nocache
stats enable
stats refresh 10s
stats hide-version
stats scope .
stats uri /lb?stats
stats auth admin:admin2013
server nodo1 10.10.200.19:80 check cookie nodo1
server nodo2 10.10.200.20:80 check cookie nodo2
server nodo3 10.10.200.21:80 check cookie nodo3
Anyone has any idea why this is happening? I already checked my php.ini file and the session.name variable has the correct value (PHPSESSID in this case).
In the other hand, i'm planning use a redis db as a session storage, i'm thinking that if I choose this, would not be necessary to use session affinity in haproxy, but i'm worry that in this case, the user could been jumping on each server in every request.
Finally I found the error, i had to remove the line:
option httpchk OPTIONS /
this was all the problem, now is working like a charm!
Now I'll continue with the connection of redis to ensure that the session of the user will not been lost in a eventually node crash.
I have a database cluster of 3 nodes using Percona XtraDB. The three nodes are configured on three different systems. I have used HAProxy load balancer to pass requests to these nodes.
Two of the 3 nodes are configured as backup in HAProxy. When I fire a request to the load balancer connection URL, I can see the request go to node A by default. If node A is down and I request a new database connection, I see the request being routed to node B. This is as per the desired design.
However, if a connection request is sent to HAProxy using a Java program (jdbc URL), the request is routed to node A, after serving a few requests if node A goes down, I wish node B/ node C to serve the request. In the current scenario I see "Connection Failed".
Is there any configuration which will ensure that in case of failure of a node, the database connection will not fail and future requests will be routed to the next available node?
My current HAProxy configuration file is as follows:
global
stats socket /var/run/haproxy.sock mode 0600 level admin
log 127.0.0.1 local2 debug
#chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
daemon
defaults
mode tcp
log global
option tcplog
timeout connect 10000 # default 10 second time out if a backend is not found
timeout client 300000
timeout server 300000
maxconn 20000
# For Admin GUI
listen stats
bind :8080
mode http
stats enable
stats uri /stats
listen mysql *:3306
mode tcp
balance roundrobin
option mysql-check user haproxyUser
option log-health-checks
server MySQL-NodeA <ip-address>:3306 check
server MySQL-NodeB <ip-address>:3306 check backup
server MySQL-NodeC <ip-address>:3306 check backup
Mode tcp under listen *:3306 cannot be use. Check before post here using this command:
haproxy -f /etc/haproxy.cfg -V