When implementing HAProxy as a load balancer, there are scenarios where you need to route traffic based on URI patterns rather than just distributing requests across a server farm. This is particularly useful when certain endpoints require specialized handling or when you're gradually migrating services.
To route requests with URI '/special' to a dedicated server while maintaining the existing round-robin distribution for other requests, we'll use ACL (Access Control List) rules in HAProxy. Here's how to modify the configuration:
listen webfarm 10.254.23.225:80
mode http
balance roundrobin
cookie SERVERID insert
option httpclose
option forwardfor
option httpchk HEAD /check.txt HTTP/1.0
# Define ACL for special URI
acl is_special_path path_beg /special
# Use dedicated server for special path
use_backend special_backend if is_special_path
# Original server definitions
server webA 10.254.23.4:80 cookie A check
server webB 10.248.23.128:80 cookie B check
backend special_backend
mode http
option httpclose
option forwardfor
server webSpecial 10.254.23.200:80 check
For more complex routing scenarios, consider these additional examples:
# Multiple path patterns
acl is_api_path path_beg /api /rest /graphql
use_backend api_backend if is_api_path
# Regular expression matching
acl is_legacy_path path_reg ^/legacy/.*$
use_backend legacy_backend if is_legacy_path
# Host-based routing combined with path
acl is_special_host hdr(host) -i special.example.com
use_backend special_backend if is_special_host || is_special_path
When implementing URI-based routing:
- Place more specific rules before generic ones
- Use simple string matches (path_beg) before regex when possible
- Monitor ACL hit ratios to optimize rule ordering
- Consider using maps for large numbers of routing rules
Here's a full configuration demonstrating various routing techniques:
frontend http_in
bind *:80
mode http
# Define ACLs
acl is_static path_beg /static /images /css /js
acl is_api path_beg /api /v1 /v2
acl is_admin path_beg /admin
acl is_special path_beg /special
# Routing logic
use_backend static_servers if is_static
use_backend api_servers if is_api
use_backend admin_servers if is_admin
use_backend special_server if is_special
default_backend web_servers
backend static_servers
server static1 10.0.0.10:80 check
server static2 10.0.0.11:80 check
backend api_servers
server api1 10.0.0.20:80 check
server api2 10.0.0.21:80 check
backend admin_servers
server admin1 10.0.0.30:80 check
backend special_server
server special1 10.0.0.40:80 check
backend web_servers
balance roundrobin
server web1 10.0.0.50:80 check
server web2 10.0.0.51:80 check
When working with HAProxy as a load balancer, there are cases where you need to route specific URI paths to designated backend servers while maintaining general traffic distribution for other paths. This is particularly useful when:
- Certain paths require special processing
- You need to offload specific functionality to dedicated servers
- Implementing canary releases for specific routes
Here's a typical HAProxy configuration that we'll enhance:
listen webfarm 10.254.23.225:80
mode http
balance roundrobin
cookie SERVERID insert
option httpclose
option forwardfor
option httpchk HEAD /check.txt HTTP/1.0
server webA 10.254.23.4:80 cookie A check
server webB 10.248.23.128:80 cookie B check
To route /special
path to a third server while maintaining existing routing:
frontend http_in
bind 10.254.23.225:80
mode http
# Route /special to dedicated server
acl is_special path_beg /special
use_backend special_backend if is_special
# Default traffic goes to webfarm
default_backend webfarm
backend webfarm
balance roundrobin
cookie SERVERID insert
option httpclose
option forwardfor
option httpchk HEAD /check.txt HTTP/1.0
server webA 10.254.23.4:80 cookie A check
server webB 10.248.23.128:80 cookie B check
backend special_backend
server webSpecial 10.254.23.50:80 check
For more complex routing needs:
# Multiple path-based routing
acl api_path path_beg /api/
acl admin_path path_beg /admin/
acl static_path path_beg /static/
use_backend api_servers if api_path
use_backend admin_servers if admin_path
use_backend static_servers if static_path
HAProxy provides several path matching methods:
path_beg
: Match beginning of pathpath_end
: Match end of pathpath
: Exact path matchpath_sub
: Substring match anywhere in path
When implementing path-based routing:
- Order ACLs from most specific to least specific
- Place frequently matched paths earlier
- Consider using
req.uri
for more complex matching - Monitor performance impact with
show sess
command
Here's a production-ready configuration snippet:
frontend main
bind *:80
mode http
# Health check endpoint
acl health path /health
monitor-uri /health
# Special paths routing
acl static path_beg /static/
acl api path_beg /api/
acl admin path_beg /admin/
use_backend static_servers if static
use_backend api_servers if api
use_backend admin_servers if admin
default_backend web_servers
backend web_servers
balance leastconn
cookie SERVERID insert
server web1 192.168.1.10:80 cookie s1 check
server web2 192.168.1.11:80 cookie s2 check
backend static_servers
server static1 192.168.1.20:80 check
backend api_servers
server api1 192.168.1.30:8080 check
server api2 192.168.1.31:8080 check
backend admin_servers
server admin1 192.168.1.40:80 check