HAProxy vs. Nginx for load balancing (2016)
thehftguy.com
thehftguy.com
I had some doubts about Nginx' direction and feature development, but most really great features (like stream proxy with SNI support) make their way into the open source release. Built in monitoring sucks though. There are options for better monitoring your requests with Prometheus.
This project implements prometheus metrics using Lua scripting inside Nginx:
https://github.com/knyar/nginx-lua-prometheus
This project is indended as a sidecar service to nginx and receives access logs and timings using syslog protocol (Nginx has a native syslog over UDP capabilities) so no scripting inside Nginx is necessary:
https://github.com/markuslindenberg/nginx_request_exporter
(I'm the author of this exporter)
Is there any difference in what data is able to be exported?
Performance wise I assume the external exporter has less impact on Nginx' operation because it doesn't keep shared state or run code inside Nginx at all (see https://github.com/knyar/nginx-lua-prometheus#caveats), all Ngnix does is push out log records over syslog/UDP. If the exporter should overload that doesn't concern Nginx at all, what happens is that observations get dropped.
Also note that Willy Tarreau has been a Linux kernel guy for eons and does a lot of upstream kernel patches, some of which haproxy benefit from. Most recent example: https://github.com/torvalds/linux/commit/3979ad7e82dfe3fb94a...
Willy also was the long term maintainer of the 2.4 Linux kernel (yes... 2.4), and does a lot of maintenance with the long term 2.6 release. So many embedded companies rely on his trees for their devices it isn't even funny.
Disclaimer: I am on the Amplify team at NGINX.
https://www.nginx.com/products/nginx-amplify/
It looks like you have some really good experience in tooling around metric collection surrounding NGINX.
Edit: For reference, here are all the metrics we can collect...and I believe it to be a fairly complete list of notable metrics pertaining to NGINX performance:
https://amplify.nginx.com/docs/guide-metrics-and-metadata.ht...
Is there a self hosted version?
Currently, we are working on the NGINX Controller which will have an embedded Amplify within it to drive it's telemetry needs (and will be available in addition):
https://www.nginx.com/products/nginx-controller/
If you are interested in an on-prem version I would love if you could give it a try. If it's something you think you would find useful in an on-prem scenario then please leave us feedback in Intercom!
The more people that ask for it the more likely our product owners will prioritize it :)
Traefik: reverse proxy built in Go with dynamic backends and modern integrations, good replacement for most situations. https://traefik.io/
Envoy: fast C++ L3/L7 proxy with some great features, http/2 support both ways, websockets, grpc, advanced health checking and load balancing, lots of metrics and integrations, my default recommendation now. https://envoyproxy.github.io/ + good comparison page: https://envoyproxy.github.io/envoy/intro/comparison.html
You supposed pick the right tools for a project not a project for the tools.
Nginx has been the best routing and traffic serving system for a while now, but it's showing its age. In addition to hiding metrics, HTTP 2 support is difficult, there's no clear path to grpc, and (as mentioned in tfa) there is no way to get stats out of it.
Envoy (envoyproxy.github.io) seems like the next thing. Nginx won because of the predominant patterns at the time, and it's still totally fine for serving lots of HTTP traffic. The problem is that if you're thinking microservices or rely on metrics to do your job or have elastic infrastructure, Envoy's feature set is the only real way to handle traffic routing in that world.
Disclaimer: I work for turbinelabs.io, and we're moving from nginx to Envoy to take advantage of a lot of these features to power our product. We've put a lot of effort into that decision, and believe it's the right one.
(You can do this in nginx, too, and it's similarly annoying. This is a big part of what we do at Turbine Labs -- a UI with a slider between blue and green, and a place to host all those stats, so you don't have to manage it!)
Put the green servers in one cluster, the blue servers in another cluster. Then use the route configuration to switch between the two.
https://envoyproxy.github.io/envoy/configuration/http_conn_m...
The transition has been good! There's certainly a lot more complexity to implement with the Envoy APIs, but that's because there's a lot of power. Working with Matt Klein and the rest of the community has been really positive. We're excited about all the other patterns that unlocks, like circuit breaking and tracing. Those sorts of features are on the wrong side of the cost/benefit equation for most companies, but if you get them for free because you deployed Envoy as ingress and service mesh, they're great to have.
https://envoyproxy.github.io/envoy/intro/arch_overview/dynam...
Still, we use nginx to terminate https at work, and it's doing a very fine job at that - much better than pound, which we used before. If it weren't for Varnish directly behind it, however, it would very often be supremely difficult to debug what's actually going on between our HTTP backends and UAs if the need arises.
Other efforts I'd seen at automated testing of nginx config relied on testing in a VM, but of necessity used different listen addresses etc. They looked complex to set up and weren't even testing the config as shipped...that's what I was aiming for.
Since then we've moved away from that config, and I'm in a different role...keep meaning to see if we can open source that code. However, nginx being such a moving target, with lua config and such, I was never sure if it would find an audience.
And even with all that effort, it didn't give us enough information. You'd try a request on some config and scratch your head to figure out why it didn't end up being processed in the right place. Run it in the simulator though, and you'd find the exact line that had rewritten your request so it didn't reach the line of config you thought was going to kick in...
Probably the best approach would have been to patch nginx itself to add the logging we wanted, and have it handle all of those external addresses differently. The challenge there would have been getting the same depth of traceability with nginx doing things like converting rewrite rules to bytecode. But, you could probably get 80% of the way there and avoid bugs from our system not accurately re-implementing their algorithms.
The difference is that HAProxy has a monitoring page to see what is configured and where connections are going. Nginx is a black box unless you pay them ~ $2000 for the pro edition.
Monitoring is feature #1 of a load balancer.
A scooter can transport cargo. A truck can transport cargo effectively.
Note that I'm not implying these figures are true of either HAProxy or nginx, just pointing out that the OP is probably correct that the number one feature of a load balancer is its ability to load balance. Good monitoring makes it easier to use, though.
The truth is that most load balancing solutions are capable of handling _a lot_ of traffic, way way more than the majority of the people need. So performance is not a huge concern, typically.
However, if you are at the level where it does actually matter and want to use nginx, chances are, you'll have no problem paying for the premium version.
HAProxy has a status page to see how many requests are processed and going where. nginx doesn't.
Monitoring is essential to any infrastructure, regardless of its scale.
This is a bad analogy, because 'flying blind' in a plane means you can't use it effectively. Being able to see out of a plane isn't a 'bonus'; it can't be used without this feature. Whereas plenty of people can and do use a load-balancer without heavy monitoring. (not to mention that there are strong moves towards self-driving transportation at the moment)
The analogy also doesn't work because a loadbalancer that can handle 1000 units is going to have far fewer problems that are in need of diagnosis than one whose limit is 100 units; when the traffic level is between 100 and 1000. When the traffic is at 100, then yes, you're going to want monitoring on the 100-unit LB, because you're trying to squeeze extra performance out of it. Whereas the 1000-unit one isn't even sweating at that point.
we loadbalance nginx clusters with haproxy and we use filebeat & metricbeat to feed logs to an ELK stack.
That monitoring page is useless to us now and your logging & monitoring should be centralized to one place anyway.
For those who are on AWS, Network Load Balancer is also competitive with LVS.
ipvsadm -L will get you metrics in a human-readable format, /proc/net/ip_vs* has stats for monitoring systems to parse.
But, I can't imagine going back to it from haproxy. Haproxy allows so many other things including nice status page, agent and service checks, SSL termination, great monitoring (we use Influxdb/telegraf/grafana and Icinga2), and really advanced routing of requests (SNI, path, pretty much anything in the requests).
Also it is entirely free and open source. Yes you are reading it correctly: Within your edge environment you are able to get pretty much all the features of a $2500+ per instance NGINGX Plus deployment with equal performance for nothing but a little investment in time (unless you need/want commercial support, ofcourse).
Cap Gemini UK apparently is using it within projects [1], GitLab is using it within their infrastructure [2] and Reevoo is using it aswell [3].
Katacoda [4] and Play-with-Docker [5] both have sandbox environments available which allow you to play with it.
[1] https://hackernoon.com/kubernetes-ingress-controllers-and-tr...
[2] https://about.gitlab.com/2017/07/11/dockerizing-review-apps/
[3] https://www.youtube.com/watch?v=aFtpIShV60I
[4] https://www.katacoda.com/courses/traefik/deploy-load-balance...
[5] http://training.play-with-docker.com/traefik-load-balancing
Conclusions don’t have to be in the title
I'm getting $2500 for a single license at the lowest level of support. They don't specify USD, so possibly I'm getting AUD because of my location, but usually a global vendor will specify if they're giving prices in non-USD.
Per server, no less. Enterprise pricing, but sucks for SMBs.
Well haproxy is still great and one of the best load balancers out there. But it's still sad that it misses h2 on the frontend. (Well backend would be cool, but there aren't that many load balancers that can do that anyway). I'm pretty sure haproxy 1.8 will at least give experimental support! which would be awesome.
" - TLS NPN and ALPN extensions make it possible to reliably offload SPDY/HTTP2 connections and pass them in clear text to backend servers"
The vts module has been updated in recent months to support more granular reporting of request times, but it's had everything we need for a while.
It exposes metrics either as an html page or a json api.
So with vts I can finally replace last instance of haproxy which serves as a core LB between all services (because it has stats).
Plenty of people, myself included, use nginx as a load balancer and it’s absolutely fine. I’m sure there are lots of use cases where HAProxy would be a better choice, but there are also many use cases where nginx is at least as good a choice.
It allows for SSL protected custom domains for a user of a SaaS app in a really easy to do way.
We use it at Shopblocks extensively, and I've written a (brief) outline of roughly how we do it.
which is why haproxy is perfect as the ingress for your web application. Especially if you are using something like kubernetes that will use an overlay network.
unfortunately, the momentum in kubernetes is to leverage nginx as an ingress.
Moreso than the GCP loadbalancing or the relatively new AWS transit loadbalancers?
However, in the limited work happening on lb increases, it's nginx rather than haproxy.
There are many different groups, Nginx in fact has their own ingress controller [1] separate from K8S nginx ingress controller. HAProxy is older and harder to deal with for L7 ingress routing as compared to Nginx.
The Istio project (using Envoy) [2] is gaining speed quickly though to become a much better ingress and internal proxy.
If I'm load balancing http or terminating https I'm not going to use HAproxy. HAproxy is very powerful but overkill.
* I have a perception of nginx being slimmer than HAproxy and more focused on http/https than HAproxy
* Related to the aforementioned point; I have a perception of HAproxy being able to handle many OSI layers compared to nginx which only handles one.
Oddly enough, I have the exact opposite perception. HAProxy doesn't even support logging to files because that would "block" the event loop, so it delegates to syslog. That seems fairly slim to me. The entire project is written with no compromises to support extreme numbers of connections efficiently. Nginx can do this as well, but has to be tuned a lot more to get to the same place, and I'm convinced if both were properly tuned and put in the same environment, HAProxy would come out ahead.
That said, if you're at a place where you already need/use Nginx, it might not make sense to use HAProxy if you can re-use your existing Nginx instances. However if you're in the market for a load balancer and Nginx isn't being used already, definitely check out HAProxy. It's pretty simple to configure.
EDIT: Another point for HAProxy: Recently, the job system we run (beanstalkd) was slowing to a crawl. I needed to find out where the slowdown was. The easiest way was to route the worker connections through HAProxy and enable logging and the HTTP stats page. I was able to determine the problem was in beanstalkd itself, not our workers (or a network issue). Sure there are a number of debugging proxies out there, but HAProxy was already installed and the logs it emits are the perfect balance of information so you can pick things apart without being overwhelmed. It really helped. Nginx wouldn't have been as useful, and would have taken a much longer time to configure.
Ditto, especially if you consider the OpenResty "variant" of Nginx.
Also, I realize Nginx does a good job of being a load balancer / reverse proxy, but to me it will always be a "web server" first. HAProxy on the other hand is built and optimized specifically to be a "load balancer / reverse proxy" first.
If you haven't check it out, I really like Hugo's work. Security first, good looking code.
https://github.com/hsleisink/hiawatha/blob/master/src/rproxy...
On the other hand, I like configuring a haproxy way, way more than configuring a nginx server. It's easier, and more concise to read.
And the official image does not provide for rsyslogd. I want an official image to at least support logging out of the box without having to resort to docker-compose or even weirder setups.
nginx has issues with formatting numbers/string and undefined values, which makes it harder to extract meaningful data from log. haproxy is easier to deal with.
Docker abstract away the logging facilities and the filesystem. It's a general issue with Docker, not the software. See the 4th answer in your issue for a solution.
No it does not, it expects stdout and stderr to be used and stores its output in a logfile to be replayed with "docker logs" command.
First solution in issue: mount /dev/log. Does not work when your host system is OS X or Windows, as you don't have access to the VM that Docker internally uses on non-linuxes. Also, on Linux it pollutes the syslog instead of docker log.
Second (the one that refers to a gmane post from 2010) is essentially the same as #1.
Third, rsyslog on host (or in a docker image): does not use docker log facility, and docker link is weird.
Fourth, use the alpine image which has a syslogd: works, maybe, but is subject to changes in the Dockerfile (e.g. when the inner path of haproxy changes). Also I don't touch Alpine images because I can't use the standard Debian/Ubuntu tooling in case there are network/firewall issues that can best be debugged from inside the container by docker exec -it haproxy bash.
There are many way to write logs, to files, to syslog, to unix socket, to stdout, to UDP sockets. Docker screws with most of them.
Not neccessarily the network, if you're using --net=host.
Docker does not screw with writing logs to files, to stdout or via UDP networking. When it comes to unix sockets or syslog, depends if the target is inside the container (which works fine AFAIK) or outside (e.g. due to bind-mounting /dev/log or such), but I have not tried the latter.
Weird.