Core concepts
Stick tables
Stick tables are in-memory storage spaces that run inside the load balancer process. They store data about traffic as it passes through the load balancer.
A stick table tracks data types (also known as counters) that count the occurrences of specific events. You can write ACL expressions that trigger actions based on these data types, such as denying a user’s request when that user’s behavior seems abnormal. There is a limited set of data types that you can use.
Stick table are useful for various purposes, including:
- counting the number of requests a client makes
- counting errors a client has triggered
- counting the number of times a webpage has been accessed
Create a stick table Jump to heading
To create a stick table, you can either:
- add a
stick-table
directive to afrontend
orbackend
section - add a
table
directive to apeers
section
For each stick-table
directive that you add to your configuration, the load balancer provisions a new storage area, which is similar to a table in a relational database where each table holds its own set of records.
Use the stick-table directive Jump to heading
To provision a stick table:
-
Add a
stick-table
line to afrontend
orbackend
. In the following example, we define a stick table that tracks the HTTP request rate of each client that passes through the load balancer:haproxyfrontend wwwbind :80stick-table type ip size 1m expire 10s store http_req_rate(10s)haproxyfrontend wwwbind :80stick-table type ip size 1m expire 10s store http_req_rate(10s)In this example:
- The table’s primary key is of type
ip
, which means that the keys will be IP addresses - The table holds a maximum of 1m records, which is 1048576 records
- A record expires after 10 seconds unless it is accessed during that time
- We store (associate) the
http_req_rate(10s)
counter with each IP address, which calculates the HTTP request rate over the last 10 seconds
You can track more than one counter, as shown below:
haproxyfrontend wwwbind :80stick-table type ip size 1m expire 10s store http_req_rate(10s),conn_rate(10s),bytes_in_rate(10s)haproxyfrontend wwwbind :80stick-table type ip size 1m expire 10s store http_req_rate(10s),conn_rate(10s),bytes_in_rate(10s) - The table’s primary key is of type
-
Invoke
http-request track-sc0
to add a record to the table. It takes a fetch method whose value will be set as the key in the table. In the following example, we use the client’s source IP address, which we get with thesrc
fetch method, as the key. We also include thehttp-request deny
directive to deny any client whose request rate goes above 10:haproxyfrontend wwwbind :80stick-table type ip size 1m expire 10s store http_req_rate(10s)http-request track-sc0 srchttp-request deny if { sc_http_req_rate(0) gt 10 }haproxyfrontend wwwbind :80stick-table type ip size 1m expire 10s store http_req_rate(10s)http-request track-sc0 srchttp-request deny if { sc_http_req_rate(0) gt 10 }When the IP address goes into the table, the associated HTTP request rate counter begins counting that client’s rate of requests. Each time that the same client makes a request, this record and its associated counters update.
The
http-request deny
directive rejects clients with an HTTP request rate greater than 10 within the time period tracked by the counter: 10 seconds.
Use the table directive Jump to heading
Available since
- HAProxy 2.0
- HAProxy Enterprise 2.0r1
- HAProxy ALOHA 11.5
You can also define a stick table in a peers
section via the table
directive. When you operate multiple load balancers in an active-active or active-standby setup, then you’ll use a peers
section to synchronize stick table data between them. Note that active-active clustering requires an enterprise module.
In the following example, we’ve added a stick table definition via the table
line to the peers
section and updated it to have the name sticktable1
. We then reference it on the http-request track-sc0
and http-request deny
lines in the frontend by prefixing it with the peers
section name:
haproxy
peers myclusterpeer loadbalancer1 192.168.1.10:10000peer loadbalancer2 192.168.1.11:10000table sticktable1 type ip size 1m expire 10s store http_req_rate(10s)frontend wwwbind :80http-request track-sc0 src table mycluster/sticktable1http-request deny if { sc_http_req_rate(0,mycluster/sticktable1) gt 10 }
haproxy
peers myclusterpeer loadbalancer1 192.168.1.10:10000peer loadbalancer2 192.168.1.11:10000table sticktable1 type ip size 1m expire 10s store http_req_rate(10s)frontend wwwbind :80http-request track-sc0 src table mycluster/sticktable1http-request deny if { sc_http_req_rate(0,mycluster/sticktable1) gt 10 }
Stick table arguments Jump to heading
In this section, we will describe a stick table’s arguments.
type Jump to heading
Choose any of the following data types as the primary key in the stick table. Set this as the type
argument on the stick table definition.
- ip
- ipv6
- integer
- string len length
- binary len length
For example, you could track the HTTP request rate on a per-backend basis rather than on a per-client basis by setting the table’s type
to string
. Then, change the http-request track-sc0
directive to capture the name of the backend using the be_name
fetch method:
haproxy
frontend wwwbind :80stick-table type string size 1m expire 10s store http_req_rate(10s)use_backend apiservers if { path_beg /api/ }default_backend webserversbackend webserversserver s1 192.168.50.20:80http-request track-sc0 be_name table wwwbackend apiserversserver s1 192.168.50.21:80http-request track-sc0 be_name table www
haproxy
frontend wwwbind :80stick-table type string size 1m expire 10s store http_req_rate(10s)use_backend apiservers if { path_beg /api/ }default_backend webserversbackend webserversserver s1 192.168.50.20:80http-request track-sc0 be_name table wwwbackend apiserversserver s1 192.168.50.21:80http-request track-sc0 be_name table www
size Jump to heading
Set the stick table’s size
argument to one of the following values:
Size | Number of records the table can store |
---|---|
1 | 1 |
1k | 1 x 210 = 1024 |
1m | 1 x 220 = 1048576 |
1g | 1 x 230 = 1073741824 |
Sticky counters Jump to heading
A sticky counter is a variable that temporarily holds the input sample to look up as the primary key in the stick table.
For example, if you want to store a client’s HTTP request rate, you first get their source IP address using the src
fetch method. You then store that value in sticky counter 0 by using http-request track-sc0
:
haproxy
frontend wwwbind :80stick-table type ip size 1m expire 10s store http_req_rate(10s)http-request track-sc0 src
haproxy
frontend wwwbind :80stick-table type ip size 1m expire 10s store http_req_rate(10s)http-request track-sc0 src
An http-request track-sc0
line inserts or updates a record in a stick table. The sc0
part specifies the sticky counter to use. By default, there are three variants of this function, depending on which sticky counter you want to use:
http-request track-sc0
http-request track-sc1
http-request track-sc2
The sticky counter variable sc0
holds the IP address as you create or update the stick table entry. You can track multiple aspects of a request by invoking the other track-sc
directives. Below, we track an entry in the table by the client’s source IP address, the name of the backend, and the Host
header:
haproxy
peers myclusterpeer loadbalancer1 192.168.1.10:10000peer loadbalancer2 192.168.1.11:10000table sticktable1 type ip size 1m expire 10s store http_req_rate(10s)table sticktable2 type string size 1m expire 10s store http_req_rate(10s)table sticktable3 type string size 1m expire 10s store http_req_rate(10s)frontend wwwbind :80# key is source IP addresshttp-request track-sc0 src table mycluster/sticktable1# key is backend namehttp-request track-sc1 be_name table mycluster/sticktable2# key is Host headerhttp-request track-sc2 req.hdr(Host) mycluster/table sticktable3
haproxy
peers myclusterpeer loadbalancer1 192.168.1.10:10000peer loadbalancer2 192.168.1.11:10000table sticktable1 type ip size 1m expire 10s store http_req_rate(10s)table sticktable2 type string size 1m expire 10s store http_req_rate(10s)table sticktable3 type string size 1m expire 10s store http_req_rate(10s)frontend wwwbind :80# key is source IP addresshttp-request track-sc0 src table mycluster/sticktable1# key is backend namehttp-request track-sc1 be_name table mycluster/sticktable2# key is Host headerhttp-request track-sc2 req.hdr(Host) mycluster/table sticktable3
All fetch methods that retrieve a record from a stick table use the ID of the sticky counter that holds the key. For instance, the sc_http_req_rate
fetch takes the sticky counter number as its first argument:
haproxy
http-request deny if { sc_http_req_rate(0,mysticktable) gt 10 }
haproxy
http-request deny if { sc_http_req_rate(0,mysticktable) gt 10 }
General-purpose counters Jump to heading
There are a number of built-in counters that track a predefined aspect of a request, such as http_req_rate([period])
, which tracks HTTP request rate. There are also general-purpose counters, which you can increment manually.
The following stick table registers two general-purpose counters: gpc0
and gpc1
. It uses http-request sc-inc-gpc0(0)
to increment gpc0
and http-request sc-inc-gpc1(0)
to increment gpc1
:
haproxy
frontend wwwbind :80stick-table type ip size 1m expire 10s store gpc0,gpc1http-request track-sc0 srchttp-request sc-inc-gpc0(0) if { req.hdr(Host) example.com }http-request sc-inc-gpc1(0) if { url_param(example) test }
haproxy
frontend wwwbind :80stick-table type ip size 1m expire 10s store gpc0,gpc1http-request track-sc0 srchttp-request sc-inc-gpc0(0) if { req.hdr(Host) example.com }http-request sc-inc-gpc1(0) if { url_param(example) test }
Here, gpc0
increments whenever a request’s Host
header equals example.com
. The gpc1
counter increments whenever the URL parameter example
has the value test
.
Use the gpc0_rate([period])
and gpc1_rate([period])
counters to track the rate at which the gpc0
and gpc1
counters increment during the given time period:
haproxy
frontend wwwbind :80stick-table type ip size 1m expire 10s store gpc0,gpc1,gpc0_rate(10s),gpc1_rate(10s)
haproxy
frontend wwwbind :80stick-table type ip size 1m expire 10s store gpc0,gpc1,gpc0_rate(10s),gpc1_rate(10s)
Synchronize stick tables across peers Jump to heading
A peers
section enables the replication of stick table data between two or more load balancers. This feature implements one-way replication of data. This makes it ideal for an active-standby cluster where the active node pushes data to the standby node. When the data replicates from the active node to the standby node, it overwrites existing data on the standby node. For active-active clustering, enterprise modules exist.
Enable synchronization Jump to heading
To enable synchronization:
-
Add one or more
peer
lines to apeers
section. Each one identifies a load balancer that takes part in the synchronization. One of thepeer
lines must be the local host:haproxypeers mycluster# local host, active nodepeer loadbalancer1 192.168.1.10:10000# standby nodepeer loadbalancer2 192.168.1.11:10000haproxypeers mycluster# local host, active nodepeer loadbalancer1 192.168.1.10:10000# standby nodepeer loadbalancer2 192.168.1.11:10000Ensure the host name specified in the
peer
directive for the local host matches the name of the host as determined by one of the following methods, in order of precedence:- The
-L
argument specified in the command line used to start the load balancer process. - The
localpeer
name specified in theglobal
section of the load balancer configuration. - The host name returned by the
hostname
command. This is the default. The other methods are recommended.
It is strongly recommended you use the exact same
peers
section on all peers and then rely on the-L
orlocalpeer
methods, above, to set the peer host name for each load balancer. This type of configuration makes it easier to maintain a consistent configuration across all peers. - The
-
Add a
peers
attribute to yourstick-table
directive to include that stick table in the synchronization. The attribute references the name of thepeers
section you defined:haproxybackendstick-table type ip size 1m expire 10s store http_req_rate(10s) peers myclusterhaproxybackendstick-table type ip size 1m expire 10s store http_req_rate(10s) peers mycluster
Persist data at reload Jump to heading
A useful side effect of using a peers
section is that the load balancer will persist stick table data after a reload. This is because during a reload the old process connects to the new one and shares all of its stick table entries with it.
To use this feature, define a peers
section with only the local host address:
haproxy
peers myclusterpeer local 127.0.0.1:10000
haproxy
peers myclusterpeer local 127.0.0.1:10000
Without this, stick table data will be lost during a reload.
Add tables to peers section Jump to heading
Available since
- HAProxy 2.0
- HAProxy Enterprise 2.0r1
- HAProxy ALOHA 11.5
You can also add stick table definitions directly to the peers
section, in which case you do not need to use the peers
attribute on the stick table. Then, reference the table as peers-section-name/table-name
.
In the following example, we’ve added a stick table definition via the table
line to the peers
section and updated it to have the name sticktable1
. We then reference it on the http-request track-sc0
and http-request deny
lines in the frontend:
haproxy
peers myclusterpeer loadbalancer1 192.168.1.10:10000peer loadbalancer2 192.168.1.11:10000table sticktable1 type ip size 1m expire 10s store http_req_rate(10s)frontend wwwbind :80http-request track-sc0 src table mycluster/sticktable1http-request deny if { sc_http_req_rate(0,mycluster/sticktable1) gt 10 }
haproxy
peers myclusterpeer loadbalancer1 192.168.1.10:10000peer loadbalancer2 192.168.1.11:10000table sticktable1 type ip size 1m expire 10s store http_req_rate(10s)frontend wwwbind :80http-request track-sc0 src table mycluster/sticktable1http-request deny if { sc_http_req_rate(0,mycluster/sticktable1) gt 10 }
Server syntax Jump to heading
Available since
- HAProxy 2.0
- HAProxy Enterprise 2.0r1
- HAProxy ALOHA 11.5
Instead of writing peer
lines, you can useserver
lines. This allows the same functionality of a server as seen in a backend
section, such as the ability to connect to the remote peer using TLS. You can also use a default-server
line to set defaults for the server lines that follow.
haproxy
peers mycluster# peers will receive sync traffic over the bound port# optional: enable SSLbind :10000 ssl crt /ssl.pem# define defaults for 'server' lines# e.g. 'ssl', peers will send sync traffic using SSLdefault-server ssl# do not set an IP address and port for the local peerserver loadbalancer1server loadbalancer2 192.168.1.11:10000
haproxy
peers mycluster# peers will receive sync traffic over the bound port# optional: enable SSLbind :10000 ssl crt /ssl.pem# define defaults for 'server' lines# e.g. 'ssl', peers will send sync traffic using SSLdefault-server ssl# do not set an IP address and port for the local peerserver loadbalancer1server loadbalancer2 192.168.1.11:10000
See also Jump to heading
Do you have any suggestions on how we can improve the content of this page?