forked from haproxy/haproxy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
intro.txt
1700 lines (1333 loc) · 88.8 KB
/
intro.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
-----------------------
HAProxy Starter Guide
-----------------------
version 3.1
This document is an introduction to HAProxy for all those who don't know it, as
well as for those who want to re-discover it when they know older versions. Its
primary focus is to provide users with all the elements to decide if HAProxy is
the product they're looking for or not. Advanced users may find here some parts
of solutions to some ideas they had just because they were not aware of a given
new feature. Some sizing information is also provided, the product's lifecycle
is explained, and comparisons with partially overlapping products are provided.
This document doesn't provide any configuration help or hints, but it explains
where to find the relevant documents. The summary below is meant to help you
search sections by name and navigate through the document.
Note to documentation contributors :
This document is formatted with 80 columns per line, with even number of
spaces for indentation and without tabs. Please follow these rules strictly
so that it remains easily printable everywhere. If you add sections, please
update the summary below for easier searching.
Summary
-------
1. Available documentation
2. Quick introduction to load balancing and load balancers
3. Introduction to HAProxy
3.1. What HAProxy is and is not
3.2. How HAProxy works
3.3. Basic features
3.3.1. Proxying
3.3.2. SSL
3.3.3. Monitoring
3.3.4. High availability
3.3.5. Load balancing
3.3.6. Stickiness
3.3.7. Logging
3.3.8. Statistics
3.4. Standard features
3.4.1. Sampling and converting information
3.4.2. Maps
3.4.3. ACLs and conditions
3.4.4. Content switching
3.4.5. Stick-tables
3.4.6. Formatted strings
3.4.7. HTTP rewriting and redirection
3.4.8. Server protection
3.5. Advanced features
3.5.1. Management
3.5.2. System-specific capabilities
3.5.3. Scripting
3.6. Sizing
3.7. How to get HAProxy
4. Companion products and alternatives
4.1. Apache HTTP server
4.2. NGINX
4.3. Varnish
4.4. Alternatives
5. Contacts
1. Available documentation
--------------------------
The complete HAProxy documentation is contained in the following documents.
Please ensure to consult the relevant documentation to save time and to get the
most accurate response to your needs. Also please refrain from sending questions
to the mailing list whose responses are present in these documents.
- intro.txt (this document) : it presents the basics of load balancing,
HAProxy as a product, what it does, what it doesn't do, some known traps to
avoid, some OS-specific limitations, how to get it, how it evolves, how to
ensure you're running with all known fixes, how to update it, complements
and alternatives.
- management.txt : it explains how to start haproxy, how to manage it at
runtime, how to manage it on multiple nodes, and how to proceed with
seamless upgrades.
- configuration.txt : the reference manual details all configuration keywords
and their options. It is used when a configuration change is needed.
- coding-style.txt : this is for developers who want to propose some code to
the project. It explains the style to adopt for the code. It is not very
strict and not all the code base completely respects it, but contributions
which diverge too much from it will be rejected.
- proxy-protocol.txt : this is the de-facto specification of the PROXY
protocol which is implemented by HAProxy and a number of third party
products.
- README : how to build HAProxy from sources
2. Quick introduction to load balancing and load balancers
----------------------------------------------------------
Load balancing consists in aggregating multiple components in order to achieve
a total processing capacity above each component's individual capacity, without
any intervention from the end user and in a scalable way. This results in more
operations being performed simultaneously by the time it takes a component to
perform only one. A single operation however will still be performed on a single
component at a time and will not get faster than without load balancing. It
always requires at least as many operations as available components and an
efficient load balancing mechanism to make use of all components and to fully
benefit from the load balancing. A good example of this is the number of lanes
on a highway which allows as many cars to pass during the same time frame
without increasing their individual speed.
Examples of load balancing :
- Process scheduling in multi-processor systems
- Link load balancing (e.g. EtherChannel, Bonding)
- IP address load balancing (e.g. ECMP, DNS round-robin)
- Server load balancing (via load balancers)
The mechanism or component which performs the load balancing operation is
called a load balancer. In web environments these components are called a
"network load balancer", and more commonly a "load balancer" given that this
activity is by far the best known case of load balancing.
A load balancer may act :
- at the link level : this is called link load balancing, and it consists in
choosing what network link to send a packet to;
- at the network level : this is called network load balancing, and it
consists in choosing what route a series of packets will follow;
- at the server level : this is called server load balancing and it consists
in deciding what server will process a connection or request.
Two distinct technologies exist and address different needs, though with some
overlapping. In each case it is important to keep in mind that load balancing
consists in diverting the traffic from its natural flow and that doing so always
requires a minimum of care to maintain the required level of consistency between
all routing decisions.
The first one acts at the packet level and processes packets more or less
individually. There is a 1-to-1 relation between input and output packets, so
it is possible to follow the traffic on both sides of the load balancer using a
regular network sniffer. This technology can be very cheap and extremely fast.
It is usually implemented in hardware (ASICs) allowing to reach line rate, such
as switches doing ECMP. Usually stateless, it can also be stateful (consider
the session a packet belongs to and called layer4-LB or L4), may support DSR
(direct server return, without passing through the LB again) if the packets
were not modified, but provides almost no content awareness. This technology is
very well suited to network-level load balancing, though it is sometimes used
for very basic server load balancing at high speed.
The second one acts on session contents. It requires that the input streams is
reassembled and processed as a whole. The contents may be modified, and the
output stream is segmented into new packets. For this reason it is generally
performed by proxies and they're often called layer 7 load balancers or L7.
This implies that there are two distinct connections on each side, and that
there is no relation between input and output packets sizes nor counts. Clients
and servers are not required to use the same protocol (for example IPv4 vs
IPv6, clear vs SSL). The operations are always stateful, and the return traffic
must pass through the load balancer. The extra processing comes with a cost so
it's not always possible to achieve line rate, especially with small packets.
On the other hand, it offers wide possibilities and is generally achieved by
pure software, even if embedded into hardware appliances. This technology is
very well suited for server load balancing.
Packet-based load balancers are generally deployed in cut-through mode, so they
are installed on the normal path of the traffic and divert it according to the
configuration. The return traffic doesn't necessarily pass through the load
balancer. Some modifications may be applied to the network destination address
in order to direct the traffic to the proper destination. In this case, it is
mandatory that the return traffic passes through the load balancer. If the
routes doesn't make this possible, the load balancer may also replace the
packets' source address with its own in order to force the return traffic to
pass through it.
Proxy-based load balancers are deployed as a server with their own IP addresses
and ports, without architecture changes. Sometimes this requires to perform some
adaptations to the applications so that clients are properly directed to the
load balancer's IP address and not directly to the server's. Some load balancers
may have to adjust some servers' responses to make this possible (e.g. the HTTP
Location header field used in HTTP redirects). Some proxy-based load balancers
may intercept traffic for an address they don't own, and spoof the client's
address when connecting to the server. This allows them to be deployed as if
they were a regular router or firewall, in a cut-through mode very similar to
the packet based load balancers. This is particularly appreciated for products
which combine both packet mode and proxy mode. In this case DSR is obviously
still not possible and the return traffic still has to be routed back to the
load balancer.
A very scalable layered approach would consist in having a front router which
receives traffic from multiple load balanced links, and uses ECMP to distribute
this traffic to a first layer of multiple stateful packet-based load balancers
(L4). These L4 load balancers in turn pass the traffic to an even larger number
of proxy-based load balancers (L7), which have to parse the contents to decide
what server will ultimately receive the traffic.
The number of components and possible paths for the traffic increases the risk
of failure; in very large environments, it is even normal to permanently have
a few faulty components being fixed or replaced. Load balancing done without
awareness of the whole stack's health significantly degrades availability. For
this reason, any sane load balancer will verify that the components it intends
to deliver the traffic to are still alive and reachable, and it will stop
delivering traffic to faulty ones. This can be achieved using various methods.
The most common one consists in periodically sending probes to ensure the
component is still operational. These probes are called "health checks". They
must be representative of the type of failure to address. For example a ping-
based check will not detect that a web server has crashed and doesn't listen to
a port anymore, while a connection to the port will verify this, and a more
advanced request may even validate that the server still works and that the
database it relies on is still accessible. Health checks often involve a few
retries to cover for occasional measuring errors. The period between checks
must be small enough to ensure the faulty component is not used for too long
after an error occurs.
Other methods consist in sampling the production traffic sent to a destination
to observe if it is processed correctly or not, and to evict the components
which return inappropriate responses. However this requires to sacrifice a part
of the production traffic and this is not always acceptable. A combination of
these two mechanisms provides the best of both worlds, with both of them being
used to detect a fault, and only health checks to detect the end of the fault.
A last method involves centralized reporting : a central monitoring agent
periodically updates all load balancers about all components' state. This gives
a global view of the infrastructure to all components, though sometimes with
less accuracy or responsiveness. It's best suited for environments with many
load balancers and many servers.
Layer 7 load balancers also face another challenge known as stickiness or
persistence. The principle is that they generally have to direct multiple
subsequent requests or connections from a same origin (such as an end user) to
the same target. The best known example is the shopping cart on an online
store. If each click leads to a new connection, the user must always be sent
to the server which holds his shopping cart. Content-awareness makes it easier
to spot some elements in the request to identify the server to deliver it to,
but that's not always enough. For example if the source address is used as a
key to pick a server, it can be decided that a hash-based algorithm will be
used and that a given IP address will always be sent to the same server based
on a divide of the address by the number of available servers. But if one
server fails, the result changes and all users are suddenly sent to a different
server and lose their shopping cart. The solution against this issue consists
in memorizing the chosen target so that each time the same visitor is seen,
he's directed to the same server regardless of the number of available servers.
The information may be stored in the load balancer's memory, in which case it
may have to be replicated to other load balancers if it's not alone, or it may
be stored in the client's memory using various methods provided that the client
is able to present this information back with every request (cookie insertion,
redirection to a sub-domain, etc). This mechanism provides the extra benefit of
not having to rely on unstable or unevenly distributed information (such as the
source IP address). This is in fact the strongest reason to adopt a layer 7
load balancer instead of a layer 4 one.
In order to extract information such as a cookie, a host header field, a URL
or whatever, a load balancer may need to decrypt SSL/TLS traffic and even
possibly to re-encrypt it when passing it to the server. This expensive task
explains why in some high-traffic infrastructures, sometimes there may be a
lot of load balancers.
Since a layer 7 load balancer may perform a number of complex operations on the
traffic (decrypt, parse, modify, match cookies, decide what server to send to,
etc), it can definitely cause some trouble and will very commonly be accused of
being responsible for a lot of trouble that it only revealed. Often it will be
discovered that servers are unstable and periodically go up and down, or for
web servers, that they deliver pages with some hard-coded links forcing the
clients to connect directly to one specific server without passing via the load
balancer, or that they take ages to respond under high load causing timeouts.
That's why logging is an extremely important aspect of layer 7 load balancing.
Once a trouble is reported, it is important to figure if the load balancer took
a wrong decision and if so why so that it doesn't happen anymore.
3. Introduction to HAProxy
--------------------------
HAProxy is written as "HAProxy" to designate the product, and as "haproxy" to
designate the executable program, software package or a process. However, both
are commonly used for both purposes, and are pronounced H-A-Proxy. Very early,
"haproxy" used to stand for "high availability proxy" and the name was written
in two separate words, though by now it means nothing else than "HAProxy".
3.1. What HAProxy is and isn't
------------------------------
HAProxy is :
- a TCP proxy : it can accept a TCP connection from a listening socket,
connect to a server and attach these sockets together allowing traffic to
flow in both directions; IPv4, IPv6 and even UNIX sockets are supported on
either side, so this can provide an easy way to translate addresses between
different families.
- an HTTP reverse-proxy (called a "gateway" in HTTP terminology) : it presents
itself as a server, receives HTTP requests over connections accepted on a
listening TCP socket, and passes the requests from these connections to
servers using different connections. It may use any combination of HTTP/1.x
or HTTP/2 on any side and will even automatically detect the protocol
spoken on each side when ALPN is used over TLS.
- an SSL terminator / initiator / offloader : SSL/TLS may be used on the
connection coming from the client, on the connection going to the server,
or even on both connections. A lot of settings can be applied per name
(SNI), and may be updated at runtime without restarting. Such setups are
extremely scalable and deployments involving tens to hundreds of thousands
of certificates were reported.
- a TCP normalizer : since connections are locally terminated by the operating
system, there is no relation between both sides, so abnormal traffic such as
invalid packets, flag combinations, window advertisements, sequence numbers,
incomplete connections (SYN floods), or so will not be passed to the other
side. This protects fragile TCP stacks from protocol attacks, and also
allows to optimize the connection parameters with the client without having
to modify the servers' TCP stack settings.
- an HTTP normalizer : when configured to process HTTP traffic, only valid
complete requests are passed. This protects against a lot of protocol-based
attacks. Additionally, protocol deviations for which there is a tolerance
in the specification are fixed so that they don't cause problem on the
servers (e.g. multiple-line headers).
- an HTTP fixing tool : it can modify / fix / add / remove / rewrite the URL
or any request or response header. This helps fixing interoperability issues
in complex environments.
- a content-based switch : it can consider any element from the request to
decide what server to pass the request or connection to. Thus it is possible
to handle multiple protocols over a same port (e.g. HTTP, HTTPS, SSH).
- a server load balancer : it can load balance TCP connections and HTTP
requests. In TCP mode, load balancing decisions are taken for the whole
connection. In HTTP mode, decisions are taken per request.
- a traffic regulator : it can apply some rate limiting at various points,
protect the servers against overloading, adjust traffic priorities based on
the contents, and even pass such information to lower layers and outer
network components by marking packets.
- a protection against DDoS and service abuse : it can maintain a wide number
of statistics per IP address, URL, cookie, etc and detect when an abuse is
happening, then take action (slow down the offenders, block them, send them
to outdated contents, etc).
- an observation point for network troubleshooting : due to the precision of
the information reported in logs, it is often used to narrow down some
network-related issues.
- an HTTP compression offloader : it can compress responses which were not
compressed by the server, thus reducing the page load time for clients with
poor connectivity or using high-latency, mobile networks.
- a caching proxy : it may cache responses in RAM so that subsequent requests
for the same object avoid the cost of another network transfer from the
server as long as the object remains present and valid. It will however not
store objects to any persistent storage. Please note that this caching
feature is designed to be maintenance free and focuses solely on saving
haproxy's precious resources and not on save the server's resources. Caches
designed to optimize servers require much more tuning and flexibility. If
you instead need such an advanced cache, please use Varnish Cache, which
integrates perfectly with haproxy, especially when SSL/TLS is needed on any
side.
- a FastCGI gateway : FastCGI can be seen as a different representation of
HTTP, and as such, HAProxy can directly load-balance a farm comprising any
combination of FastCGI application servers without requiring to insert
another level of gateway between them. This results in resource savings and
a reduction of maintenance costs.
HAProxy is not :
- an explicit HTTP proxy, i.e. the proxy that browsers use to reach the
internet. There are excellent open-source software dedicated for this task,
such as Squid. However HAProxy can be installed in front of such a proxy to
provide load balancing and high availability.
- a data scrubber : it will not modify the body of requests nor responses.
- a static web server : during startup, it isolates itself inside a chroot
jail and drops its privileges, so that it will not perform any single file-
system access once started. As such it cannot be turned into a static web
server (dynamic servers are supported through FastCGI however). There are
excellent open-source software for this such as Apache or Nginx, and
HAProxy can be easily installed in front of them to provide load balancing,
high availability and acceleration.
- a packet-based load balancer : it will not see IP packets nor UDP datagrams,
will not perform NAT or even less DSR. These are tasks for lower layers.
Some kernel-based components such as IPVS (Linux Virtual Server) already do
this pretty well and complement perfectly with HAProxy.
3.2. How HAProxy works
----------------------
HAProxy is an event-driven, non-blocking engine combining a very fast I/O layer
with a priority-based, multi-threaded scheduler. As it is designed with a data
forwarding goal in mind, its architecture is optimized to move data as fast as
possible with the least possible operations. It focuses on optimizing the CPU
cache's efficiency by sticking connections to the same CPU as long as possible.
As such it implements a layered model offering bypass mechanisms at each level
ensuring data doesn't reach higher levels unless needed. Most of the processing
is performed in the kernel, and HAProxy does its best to help the kernel do the
work as fast as possible by giving some hints or by avoiding certain operation
when it guesses they could be grouped later. As a result, typical figures show
15% of the processing time spent in HAProxy versus 85% in the kernel in TCP or
HTTP close mode, and about 30% for HAProxy versus 70% for the kernel in HTTP
keep-alive mode.
A single process can run many proxy instances; configurations as large as
300000 distinct proxies in a single process were reported to run fine. A single
core, single CPU setup is far more than enough for more than 99% users, and as
such, users of containers and virtual machines are encouraged to use the
absolute smallest images they can get to save on operational costs and simplify
troubleshooting. However the machine HAProxy runs on must never ever swap, and
its CPU must not be artificially throttled (sub-CPU allocation in hypervisors)
nor be shared with compute-intensive processes which would induce a very high
context-switch latency.
Threading allows to exploit all available processing capacity by using one
thread per CPU core. This is mostly useful for SSL or when data forwarding
rates above 40 Gbps are needed. In such cases it is critically important to
avoid communications between multiple physical CPUs, which can cause strong
bottlenecks in the network stack and in HAProxy itself. While counter-intuitive
to some, the first thing to do when facing some performance issues is often to
reduce the number of CPUs HAProxy runs on.
HAProxy only requires the haproxy executable and a configuration file to run.
For logging it is highly recommended to have a properly configured syslog daemon
and log rotations in place. Logs may also be sent to stdout/stderr, which can be
useful inside containers. The configuration files are parsed before starting,
then HAProxy tries to bind all listening sockets, and refuses to start if
anything fails. Past this point it cannot fail anymore. This means that there
are no runtime failures and that if it accepts to start, it will work until it
is stopped.
Once HAProxy is started, it does exactly 3 things :
- process incoming connections;
- periodically check the servers' status (known as health checks);
- exchange information with other haproxy nodes.
Processing incoming connections is by far the most complex task as it depends
on a lot of configuration possibilities, but it can be summarized as the 9 steps
below :
- accept incoming connections from listening sockets that belong to a
configuration entity known as a "frontend", which references one or multiple
listening addresses;
- apply the frontend-specific processing rules to these connections that may
result in blocking them, modifying some headers, or intercepting them to
execute some internal applets such as the statistics page or the CLI;
- pass these incoming connections to another configuration entity representing
a server farm known as a "backend", which contains the list of servers and
the load balancing strategy for this server farm;
- apply the backend-specific processing rules to these connections;
- decide which server to forward the connection to according to the load
balancing strategy;
- apply the backend-specific processing rules to the response data;
- apply the frontend-specific processing rules to the response data;
- emit a log to report what happened in fine details;
- in HTTP, loop back to the second step to wait for a new request, otherwise
close the connection.
Frontends and backends are sometimes considered as half-proxies, since they only
look at one side of an end-to-end connection; the frontend only cares about the
clients while the backend only cares about the servers. HAProxy also supports
full proxies which are exactly the union of a frontend and a backend. When HTTP
processing is desired, the configuration will generally be split into frontends
and backends as they open a lot of possibilities since any frontend may pass a
connection to any backend. With TCP-only proxies, using frontends and backends
rarely provides a benefit and the configuration can be more readable with full
proxies.
3.3. Basic features
-------------------
This section will enumerate a number of features that HAProxy implements, some
of which are generally expected from any modern load balancer, and some of
which are a direct benefit of HAProxy's architecture. More advanced features
will be detailed in the next section.
3.3.1. Basic features : Proxying
--------------------------------
Proxying is the action of transferring data between a client and a server over
two independent connections. The following basic features are supported by
HAProxy regarding proxying and connection management :
- Provide the server with a clean connection to protect them against any
client-side defect or attack;
- Listen to multiple IP addresses and/or ports, even port ranges;
- Transparent accept : intercept traffic targeting any arbitrary IP address
that doesn't even belong to the local system;
- Server port doesn't need to be related to listening port, and may even be
translated by a fixed offset (useful with ranges);
- Transparent connect : spoof the client's (or any) IP address if needed
when connecting to the server;
- Provide a reliable return IP address to the servers in multi-site LBs;
- Offload the server thanks to buffers and possibly short-lived connections
to reduce their concurrent connection count and their memory footprint;
- Optimize TCP stacks (e.g. SACK), congestion control, and reduce RTT impacts;
- Support different protocol families on both sides (e.g. IPv4/IPv6/Unix);
- Timeout enforcement : HAProxy supports multiple levels of timeouts depending
on the stage the connection is, so that a dead client or server, or an
attacker cannot be granted resources for too long;
- Protocol validation: HTTP, SSL, or payload are inspected and invalid
protocol elements are rejected, unless instructed to accept them anyway;
- Policy enforcement : ensure that only what is allowed may be forwarded;
- Both incoming and outgoing connections may be limited to certain network
namespaces (Linux only), making it easy to build a cross-container,
multi-tenant load balancer;
- PROXY protocol presents the client's IP address to the server even for
non-HTTP traffic. This is an HAProxy extension that was adopted by a number
of third-party products by now, at least these ones at the time of writing :
- client : haproxy, stud, stunnel, exaproxy, ELB, squid
- server : haproxy, stud, postfix, exim, nginx, squid, node.js, varnish
3.3.2. Basic features : SSL
---------------------------
HAProxy's SSL stack is recognized as one of the most featureful according to
Google's engineers (http://istlsfastyet.com/). The most commonly used features
making it quite complete are :
- SNI-based multi-hosting with no limit on sites count and focus on
performance. At least one deployment is known for running 50000 domains
with their respective certificates;
- support for wildcard certificates reduces the need for many certificates ;
- certificate-based client authentication with configurable policies on
failure to present a valid certificate. This allows to present a different
server farm to regenerate the client certificate for example;
- authentication of the backend server ensures the backend server is the real
one and not a man in the middle;
- authentication with the backend server lets the backend server know it's
really the expected haproxy node that is connecting to it;
- TLS NPN and ALPN extensions make it possible to reliably offload SPDY/HTTP2
connections and pass them in clear text to backend servers;
- OCSP stapling further reduces first page load time by delivering inline an
OCSP response when the client requests a Certificate Status Request;
- Dynamic record sizing provides both high performance and low latency, and
significantly reduces page load time by letting the browser start to fetch
new objects while packets are still in flight;
- permanent access to all relevant SSL/TLS layer information for logging,
access control, reporting etc. These elements can be embedded into HTTP
header or even as a PROXY protocol extension so that the offloaded server
gets all the information it would have had if it performed the SSL
termination itself.
- Detect, log and block certain known attacks even on vulnerable SSL libs,
such as the Heartbleed attack affecting certain versions of OpenSSL.
- support for stateless session resumption (RFC 5077 TLS Ticket extension).
TLS tickets can be updated from CLI which provides them means to implement
Perfect Forward Secrecy by frequently rotating the tickets.
3.3.3. Basic features : Monitoring
----------------------------------
HAProxy focuses a lot on availability. As such it cares about servers state,
and about reporting its own state to other network components :
- Servers' state is continuously monitored using per-server parameters. This
ensures the path to the server is operational for regular traffic;
- Health checks support two hysteresis for up and down transitions in order
to protect against state flapping;
- Checks can be sent to a different address/port/protocol : this makes it
easy to check a single service that is considered representative of multiple
ones, for example the HTTPS port for an HTTP+HTTPS server.
- Servers can track other servers and go down simultaneously : this ensures
that servers hosting multiple services can fail atomically and that no one
will be sent to a partially failed server;
- Agents may be deployed on the server to monitor load and health : a server
may be interested in reporting its load, operational status, administrative
status independently from what health checks can see. By running a simple
agent on the server, it's possible to consider the server's view of its own
health in addition to the health checks validating the whole path;
- Various check methods are available : TCP connect, HTTP request, SMTP hello,
SSL hello, LDAP, SQL, Redis, send/expect scripts, all with/without SSL;
- State change is notified in the logs and stats page with the failure reason
(e.g. the HTTP response received at the moment the failure was detected). An
e-mail can also be sent to a configurable address upon such a change ;
- Server state is also reported on the stats interface and can be used to take
routing decisions so that traffic may be sent to different farms depending
on their sizes and/or health (e.g. loss of an inter-DC link);
- HAProxy can use health check requests to pass information to the servers,
such as their names, weight, the number of other servers in the farm etc.
so that servers can adjust their response and decisions based on this
knowledge (e.g. postpone backups to keep more CPU available);
- Servers can use health checks to report more detailed state than just on/off
(e.g. I would like to stop, please stop sending new visitors);
- HAProxy itself can report its state to external components such as routers
or other load balancers, allowing to build very complete multi-path and
multi-layer infrastructures.
3.3.4. Basic features : High availability
-----------------------------------------
Just like any serious load balancer, HAProxy cares a lot about availability to
ensure the best global service continuity :
- Only valid servers are used ; the other ones are automatically evicted from
load balancing farms ; under certain conditions it is still possible to
force to use them though;
- Support for a graceful shutdown so that it is possible to take servers out
of a farm without affecting any connection;
- Backup servers are automatically used when active servers are down and
replace them so that sessions are not lost when possible. This also allows
to build multiple paths to reach the same server (e.g. multiple interfaces);
- Ability to return a global failed status for a farm when too many servers
are down. This, combined with the monitoring capabilities makes it possible
for an upstream component to choose a different LB node for a given service;
- Stateless design makes it easy to build clusters : by design, HAProxy does
its best to ensure the highest service continuity without having to store
information that could be lost in the event of a failure. This ensures that
a takeover is the most seamless possible;
- Integrates well with standard VRRP daemon keepalived : HAProxy easily tells
keepalived about its state and copes very well with floating virtual IP
addresses. Note: only use IP redundancy protocols (VRRP/CARP) over cluster-
based solutions (Heartbeat, ...) as they're the ones offering the fastest,
most seamless, and most reliable switchover.
3.3.5. Basic features : Load balancing
--------------------------------------
HAProxy offers a fairly complete set of load balancing features, most of which
are unfortunately not available in a number of other load balancing products :
- no less than 10 load balancing algorithms are supported, some of which apply
to input data to offer an infinite list of possibilities. The most common
ones are round-robin (for short connections, pick each server in turn),
leastconn (for long connections, pick the least recently used of the servers
with the lowest connection count), source (for SSL farms or terminal server
farms, the server directly depends on the client's source address), URI (for
HTTP caches, the server directly depends on the HTTP URI), hdr (the server
directly depends on the contents of a specific HTTP header field), first
(for short-lived virtual machines, all connections are packed on the
smallest possible subset of servers so that unused ones can be powered
down);
- all algorithms above support per-server weights so that it is possible to
accommodate from different server generations in a farm, or direct a small
fraction of the traffic to specific servers (debug mode, running the next
version of the software, etc);
- dynamic weights are supported for round-robin, leastconn and consistent
hashing ; this allows server weights to be modified on the fly from the CLI
or even by an agent running on the server;
- slow-start is supported whenever a dynamic weight is supported; this allows
a server to progressively take the traffic. This is an important feature
for fragile application servers which require to compile classes at runtime
as well as cold caches which need to fill up before being run at full
throttle;
- hashing can apply to various elements such as client's source address, URL
components, query string element, header field values, POST parameter, RDP
cookie;
- consistent hashing protects server farms against massive redistribution when
adding or removing servers in a farm. That's very important in large cache
farms and it allows slow-start to be used to refill cold caches;
- a number of internal metrics such as the number of connections per server,
per backend, the amount of available connection slots in a backend etc makes
it possible to build very advanced load balancing strategies.
3.3.6. Basic features : Stickiness
----------------------------------
Application load balancing would be useless without stickiness. HAProxy provides
a fairly comprehensive set of possibilities to maintain a visitor on the same
server even across various events such as server addition/removal, down/up
cycles, and some methods are designed to be resistant to the distance between
multiple load balancing nodes in that they don't require any replication :
- stickiness information can be individually matched and learned from
different places if desired. For example a JSESSIONID cookie may be matched
both in a cookie and in the URL. Up to 8 parallel sources can be learned at
the same time and each of them may point to a different stick-table;
- stickiness information can come from anything that can be seen within a
request or response, including source address, TCP payload offset and
length, HTTP query string elements, header field values, cookies, and so
on.
- stick-tables are replicated between all nodes in a multi-master fashion;
- commonly used elements such as SSL-ID or RDP cookies (for TSE farms) are
directly accessible to ease manipulation;
- all sticking rules may be dynamically conditioned by ACLs;
- it is possible to decide not to stick to certain servers, such as backup
servers, so that when the nominal server comes back, it automatically takes
the load back. This is often used in multi-path environments;
- in HTTP it is often preferred not to learn anything and instead manipulate
a cookie dedicated to stickiness. For this, it's possible to detect,
rewrite, insert or prefix such a cookie to let the client remember what
server was assigned;
- the server may decide to change or clean the stickiness cookie on logout,
so that leaving visitors are automatically unbound from the server;
- using ACL-based rules it is also possible to selectively ignore or enforce
stickiness regardless of the server's state; combined with advanced health
checks, that helps admins verify that the server they're installing is up
and running before presenting it to the whole world;
- an innovative mechanism to set a maximum idle time and duration on cookies
ensures that stickiness can be smoothly stopped on devices which are never
closed (smartphones, TVs, home appliances) without having to store them on
persistent storage;
- multiple server entries may share the same stickiness keys so that
stickiness is not lost in multi-path environments when one path goes down;
- soft-stop ensures that only users with stickiness information will continue
to reach the server they've been assigned to but no new users will go there.
3.3.7. Basic features : Logging
-------------------------------
Logging is an extremely important feature for a load balancer, first because a
load balancer is often wrongly accused of causing the problems it reveals, and
second because it is placed at a critical point in an infrastructure where all
normal and abnormal activity needs to be analyzed and correlated with other
components.
HAProxy provides very detailed logs, with millisecond accuracy and the exact
connection accept time that can be searched in firewalls logs (e.g. for NAT
correlation). By default, TCP and HTTP logs are quite detailed and contain
everything needed for troubleshooting, such as source IP address and port,
frontend, backend, server, timers (request receipt duration, queue duration,
connection setup time, response headers time, data transfer time), global
process state, connection counts, queue status, retries count, detailed
stickiness actions and disconnect reasons, header captures with a safe output
encoding. It is then possible to extend or replace this format to include any
sampled data, variables, captures, resulting in very detailed information. For
example it is possible to log the number of cumulative requests or number of
different URLs visited by a client.
The log level may be adjusted per request using standard ACLs, so it is possible
to automatically silent some logs considered as pollution and instead raise
warnings when some abnormal behavior happen for a small part of the traffic
(e.g. too many URLs or HTTP errors for a source address). Administrative logs
are also emitted with their own levels to inform about the loss or recovery of a
server for example.
Each frontend and backend may use multiple independent log outputs, which eases
multi-tenancy. Logs are preferably sent over UDP, maybe JSON-encoded, and are
truncated after a configurable line length in order to guarantee delivery. But
it is also possible to send them to stdout/stderr or any file descriptor, as
well as to a ring buffer that a client can subscribe to in order to retrieve
them.
3.3.8. Basic features : Statistics
----------------------------------
HAProxy provides a web-based statistics reporting interface with authentication,
security levels and scopes. It is thus possible to provide each hosted customer
with his own page showing only his own instances. This page can be located in a
hidden URL part of the regular web site so that no new port needs to be opened.
This page may also report the availability of other HAProxy nodes so that it is
easy to spot if everything works as expected at a glance. The view is synthetic
with a lot of details accessible (such as error causes, last access and last
change duration, etc), which are also accessible as a CSV table that other tools
may import to draw graphs. The page may self-refresh to be used as a monitoring
page on a large display. In administration mode, the page also allows to change
server state to ease maintenance operations.
A Prometheus exporter is also provided so that the statistics can be consumed
in a different format depending on the deployment.
3.4. Standard features
----------------------
In this section, some features that are very commonly used in HAProxy but are
not necessarily present on other load balancers are enumerated.
3.4.1. Standard features : Sampling and converting information
--------------------------------------------------------------
HAProxy supports information sampling using a wide set of "sample fetch
functions". The principle is to extract pieces of information known as samples,
for immediate use. This is used for stickiness, to build conditions, to produce
information in logs or to enrich HTTP headers.
Samples can be fetched from various sources :
- constants : integers, strings, IP addresses, binary blocks;
- the process : date, environment variables, server/frontend/backend/process
state, byte/connection counts/rates, queue length, random generator, ...
- variables : per-session, per-request, per-response variables;
- the client connection : source and destination addresses and ports, and all
related statistics counters;
- the SSL client session : protocol, version, algorithm, cipher, key size,
session ID, all client and server certificate fields, certificate serial,
SNI, ALPN, NPN, client support for certain extensions;
- request and response buffers contents : arbitrary payload at offset/length,
data length, RDP cookie, decoding of SSL hello type, decoding of TLS SNI;
- HTTP (request and response) : method, URI, path, query string arguments,
status code, headers values, positional header value, cookies, captures,
authentication, body elements;
A sample may then pass through a number of operators known as "converters" to
experience some transformation. A converter consumes a sample and produces a
new one, possibly of a completely different type. For example, a converter may
be used to return only the integer length of the input string, or could turn a
string to upper case. Any arbitrary number of converters may be applied in
series to a sample before final use. Among all available sample converters, the
following ones are the most commonly used :
- arithmetic and logic operators : they make it possible to perform advanced
computation on input data, such as computing ratios, percentages or simply
converting from one unit to another one;
- IP address masks are useful when some addresses need to be grouped by larger
networks;
- data representation : URL-decode, base64, hex, JSON strings, hashing;
- string conversion : extract substrings at fixed positions, fixed length,
extract specific fields around certain delimiters, extract certain words,
change case, apply regex-based substitution;
- date conversion : convert to HTTP date format, convert local to UTC and
conversely, add or remove offset;
- lookup an entry in a stick table to find statistics or assigned server;
- map-based key-to-value conversion from a file (mostly used for geolocation).
3.4.2. Standard features : Maps
-------------------------------
Maps are a powerful type of converter consisting in loading a two-columns file
into memory at boot time, then looking up each input sample from the first
column and either returning the corresponding pattern on the second column if
the entry was found, or returning a default value. The output information also
being a sample, it can in turn experience other transformations including other
map lookups. Maps are most commonly used to translate the client's IP address
to an AS number or country code since they support a longest match for network
addresses but they can be used for various other purposes.
Part of their strength comes from being updatable on the fly either from the CLI
or from certain actions using other samples, making them capable of storing and
retrieving information between subsequent accesses. Another strength comes from
the binary tree based indexation which makes them extremely fast even when they
contain hundreds of thousands of entries, making geolocation very cheap and easy
to set up.
3.4.3. Standard features : ACLs and conditions
----------------------------------------------
Most operations in HAProxy can be made conditional. Conditions are built by
combining multiple ACLs using logic operators (AND, OR, NOT). Each ACL is a
series of tests based on the following elements :
- a sample fetch method to retrieve the element to test ;
- an optional series of converters to transform the element ;
- a list of patterns to match against ;
- a matching method to indicate how to compare the patterns with the sample
For example, the sample may be taken from the HTTP "Host" header, it could then
be converted to lower case, then matched against a number of regex patterns
using the regex matching method.
Technically, ACLs are built on the same core as the maps, they share the exact
same internal structure, pattern matching methods and performance. The only real
difference is that instead of returning a sample, they only return "found" or
or "not found". In terms of usage, ACL patterns may be declared inline in the
configuration file and do not require their own file. ACLs may be named for ease
of use or to make configurations understandable. A named ACL may be declared
multiple times and it will evaluate all definitions in turn until one matches.
About 13 different pattern matching methods are provided, among which IP address
mask, integer ranges, substrings, regex. They work like functions, and just like
with any programming language, only what is needed is evaluated, so when a
condition involving an OR is already true, next ones are not evaluated, and
similarly when a condition involving an AND is already false, the rest of the
condition is not evaluated.
There is no practical limit to the number of declared ACLs, and a handful of
commonly used ones are provided. However experience has shown that setups using
a lot of named ACLs are quite hard to troubleshoot and that sometimes using
anonymous ACLs inline is easier as it requires less references out of the scope
being analyzed.
3.4.4. Standard features : Content switching
--------------------------------------------
HAProxy implements a mechanism known as content-based switching. The principle
is that a connection or request arrives on a frontend, then the information
carried with this request or connection are processed, and at this point it is
possible to write ACLs-based conditions making use of these information to
decide what backend will process the request. Thus the traffic is directed to
one backend or another based on the request's contents. The most common example
consists in using the Host header and/or elements from the path (sub-directories
or file-name extensions) to decide whether an HTTP request targets a static
object or the application, and to route static objects traffic to a backend made
of fast and light servers, and all the remaining traffic to a more complex
application server, thus constituting a fine-grained virtual hosting solution.
This is quite convenient to make multiple technologies coexist as a more global
solution.
Another use case of content-switching consists in using different load balancing
algorithms depending on various criteria. A cache may use a URI hash while an
application would use round-robin.
Last but not least, it allows multiple customers to use a small share of a
common resource by enforcing per-backend (thus per-customer connection limits).
Content switching rules scale very well, though their performance may depend on
the number and complexity of the ACLs in use. But it is also possible to write
dynamic content switching rules where a sample value directly turns into a
backend name and without making use of ACLs at all. Such configurations have
been reported to work fine at least with 300000 backends in production.
3.4.5. Standard features : Stick-tables
---------------------------------------
Stick-tables are commonly used to store stickiness information, that is, to keep
a reference to the server a certain visitor was directed to. The key is then the
identifier associated with the visitor (its source address, the SSL ID of the