Truly Seamless Reloads with HAProxy
haproxy.com
haproxy.com
Surely you don't need to fork: Just parse the new config, create the necessary internal data structures, and let traffic flow into the new ruleset while keeping all the sockets (except for those that are superfluous, and of course let in-flight requests finish). Is it because HAProxy's internals weren't designed to do that and that it would too big of a rewrite?
I always found Varnish's design very cool: It compiles the configuration (which is a DSL called VCL) to C and loads it as a dynamically loaded library. I don't know how it does hot reloads, but I believe it does do them seamlessly.
Bingo. The internals will eventually be rewritten to support things like this (and I think that's what Willy was hinting at towards the end of the article) in time. But it's a big project, and it's a complicated piece of software, and there are a lot of conflicting demands on dev time.
That said: it's a welcoming community, and if you want to help... do it!
"Service upgrades are even more important because, while some products are designed from the ground to support config updates without having to be reloaded, they cannot be upgraded at all without a stop/start sequence. Consequently, admins leave bogus versions of those software components running in production because it is never the right time to do it."
All in all, HAproxy is a brilliant piece of software and Willy is running it in an exemplary way. Kudos!
I know that HAProxy is not an apples to apples comparison with something like apache, but I don't see how something similar would be a huge burden to add.
It's not that surprising to me, especially given that haproxy is 17 years old. Expectations of a load balancer where pretty light when it was invented, so the internals weren't built for hot reload.
Sure, but what about seamless updates?
It reloads just fine, same as all software.
Or if you prefer the pessimistic version: HAProxy, nginx, Apache and Varnish all suck at reloading configurations.
The difference is that HAProxy 1) tests it and 2) have a TCP mode.
To quote the issue: They manage to achieve 1 error per 40 000 connections... only if pinning to specifics CPU (typical in high performance environment to achieve 100% usage of all cores) while doing 10 reloads per second and creating 80k new connections per second.
Do you think any of apache/nginx/varnish, would do better than that in these circumstances? If you do, you are not very realistic ;)
iptables --wait --table nat --append PREROUTING --protocol tcp --dport 80 ! --in-interface docker0 --jump DNAT --to $new_target
Then removing tables for old one: iptables --wait --table nat --delete PREROUTING --protocol tcp --dport 80 ! --in-interface docker0 --jump DNAT --to $old_target
(repeat the same for ip6tables).The same had to be repeated on system start but otherwise it worked flawlessly and had zero-downtime.
And then there is a blog on a new http://www.haproxy.com site.
Is there a comparision of HaProxy, Varnish, Squid, Traffic Server (ATS), Nginx, lighttpd, etc for typical scenario.
It's a far far better website than most so called "modern" websites.
I've used HAProxy on and off throughout a lot of my career. I'm currently using it at my company as a way for services to talk to each other without specifically knowing who is where. I wouldn't call it "microservices" but probably similar: each server has HAProxy on it, and Ansible creates the HAProxy config/hosts file so that, say, a worker server can grab http://lb-api:6666/some/resource. lb-api is a host that routes to 127.0.0.1 and HAProxy runs on port 6666 locally, parses the "lb-api" host, and routes the request to one of the servers in the "api" group. Any time we change any servers, we just run our haproxy playbook and everything just flows.
As always, HAProxy is one of the few pieces of our infrastructure that "just works" day after day.
I highly recommend this tool. Yelp has used it in production for years to manage a fairly large PaaS (hundreds of services, thousands of containers, constant churn); it's proven quite flexible and resilient.
Synapse is available on github [0], and we've open sourced our automation used to create a highly available service router using Synapse as well [1][2].
[0] https://github.com/airbnb/synapse [1] https://github.com/Yelp/synapse-tools/tree/master/src/synaps... [2] http://paasta.readthedocs.io/en/latest/yelpsoa_configs.html#...
what's the alternative to reloading on config change? automatic detection and reload on file change? personally I prefer the explicit action
This simply means you can have hitless reloads - change your configuration, reload HAProxy, and you will drop zero incoming connections during the reload time. Other methods previously existed to do this without having to first drain traffic, but they were both unwieldy and still tended to have a performance impact.
The new technique is for the old process to use a Unix socket to seamlessly transfer ownership of the listening sockets to the new process. At no point are the listening sockets closed, so no connections are rejected.
It's still a (potentially) new haproxy binary starting up and parsing the (potentially) changed haproxy config because the user requested a graceful restart.
Here's a thread showing a config that does that, and some of the limitations. http://discourse.haproxy.org/t/trouble-with-dns-resolvers-st...
It can do DNS resolution at runtime, additionally you can override bunch of options as to how DNS resolution behaves in terms of TTL, Failures etc
Absolutely awesome.
old_pids=$(ps -A -opid,args | grep haproxy | egrep -v -e 'grep|reload-haproxy' | awk '{print $1}' | tr '\n' ' ')
Can we do this without grep, egrep and awk?
Would this work? old_pids=$(exec ps -A -opid,args |sed -n '/sed/d;/reload-haproxy/d;/haproxy/{s/ .*//;p};'|tr '\n' ' ') old_pids=$(pgrep '^haproxy')I see this usage often where it seems like
grep pattern1 | grep -v pattern2
can be replaced by sed -n '/pattern1/d;/pattern2/p'
or at least sed '/pattern1/!d' | sed '/pattern2/d'
or sed -n 's/pattern1pattern2//g;/pattern2/p'
But I must be missing something obvious.For example look at the "grep -v" usage here:
https://github.com/thomwiggers/qhasm/raw/master/qhasm-arm
Is there something wrong with using
sed '/^op:livefloat80:/d'
Moreover, in the last line, why not use sed 's/\$/#/g'
instead of tr '$' '#'
Apologies if I am missing the obvious. grep [h]aproxyIf you still want grep, without it matching itself, an old trick is egrep '[h]aproxy' or similar.
Egrep, as opposed to pgrep, is more widely installed on non Linux systems like osx.
ps -A -opid,comm | awk '($2 == "haproxy") {printf "%d ",$1}'
However, "pidof haproxy" would work too.You put your finger on it right there - it's quite different. For example can nginx tunnel an RDP session for example? No of course not - nginx is a web server (proxy) etc. They have overlapping use cases but there are quite a few bits outside the intersection of their capabilities. Even now I am mentally writing a haproxy.conf to serve web content. The static bit is easy but I'll stick to using nginx or apache for what they are good at.
Obviously I wouldn't dream of letting IIS accept external inbound connections unless mediated via HAProxy ...
[1] https://www.nginx.com/resources/admin-guide/tcp-load-balanci...
And, frankly - HAProxy is pretty darn flexible around HTTP too. It's not really an apples-to-apples comparison.
For some odd reason Products -> Compare versions didn't work for me (Chrome on Linux) so I can't tell what plus brings to the show.
*Prerequisites*
Latest NGINX Open Source built with the --with-stream
configuration flag, or latest NGINX Plus (no extra build
steps required)The free nginx is lagging farrrrr behind in terms of features.
*Prerequisites*
Latest NGINX Open Source built with the --with-stream
configuration flag, or latest NGINX Plus (no extra build
steps required)If you mean something else then HAproxy also supports "graceful restarts several times per second with no issues". But the article is not talking about that.
EDIT: added link.
[0] https://serverfault.com/questions/523417/reloading-new-nginx...
The link you give talks about persistent HTTP connections paired with a broken http client.
I did however find instructions how to properly restart Nginx without dropping connections: https://www.digitalocean.com/community/tutorials/how-to-upgr... Apparently it can be done (and could even be automated), but the procedure looks very generic to me (not nginx-specific). Is this what you did?