haproxy

目录

haproxy介绍

haproxy的基本配置信息

[global 配置参数说明](#global 配置参数说明)

proxies配置

haproxy的算法

会话保持实现方式

高级功能及配置

基于cookie的会话保持

HAProxy状态页

IP透传

四层IP透传

七层IP透传

ACL

ACL示例-域名匹配

ACL示例-基于源IP或子网调度访问

ACL示例-基于源地址的访问控制

ACL示例-匹配浏览器类型

ACL示例-基于文件后缀名实现动静分离

ACL-匹配访问路径实现动静分离

[自定义HAProxy 错误界面](#自定义HAProxy 错误界面)

基于自定义的错误页面文件

基于http重定向错误页面

[HAProxy https 实现](#HAProxy https 实现)


haproxy介绍

HAProxy是法国开发者 威利塔罗(Willy Tarreau) 在2000年使用C语言开发的一个开源软件 是一款具备高并发(万级以上)、高性能的TCP和HTTP负载均衡器 支持基于cookie的持久性,自动故障切换,支持正则表达式及web状态统计

四层负载和七层负载的区别

四层和七层的区别 所谓的四到七层负载均衡,就是在对后台的服务器进行负载均衡时,依据四层的信息或七层的信息来决 定怎么样转发流量

四层的负载均衡,就是通过发布三层的IP地址(VIP),然后加四层的端口号,来决定哪些流量需要做负 载均衡,对需要处理的流量进行NAT处理,转发至后台服务器,并记录下这个TCP或者UDP的流量是由哪 台服务器处理的,后续这个连接的所有流量都同样转发到同一台服务器处理

七层的负载均衡,就是在四层的基础上(没有四层是绝对不可能有七层的),再考虑应用层的特征,比 如同一个Web服务器的负载均衡,除了根据VIP加80端口辨别是否需要处理的流量,还可根据七层的 URL、浏览器类别、语言来决定是否要进行负载均衡。

1.分层位置:四层负载均衡在传输层及以下,七层负载均衡在应用层及以下

2.性能 :四层负载均衡架构无需解析报文消息内容,在网络吞吐量与处理能力上较高:七层可支持解析应用 层报文消息内容,识别URL、Cookie、HTTP header等信息。

3.原理 :四层负载均衡是基于ip+port;七层是基于虚拟的URL或主机IP等。

4.功能类比:四层负载均衡类似于路由器;七层类似于代理服务器。

5.安全性:四层负载均衡无法识别DDoS攻击;七层可防御SYN Cookie/Flood攻击

haproxy的基本配置信息

HAProxy 的配置文件haproxy.cfg由两大部分组成,分别是:

global:全局配置段

  • 进程及安全配置相关的参数
  • 性能调整相关参数
  • Debug参数

proxies:代理配置段

  • defaults:为frontend, backend, listen提供默认配置
  • frontend:前端,相当于nginx中的server {}
  • backend:后端,相当于nginx中的upstream {}
  • listen:同时拥有前端和后端配置,配置简单,生产推荐使用

global 配置参数说明

127.0.0.1 local2

定义 syslog 服务器地址和设施代码,需确保 syslog 服务已启用 UDP 协议支持。最多支持配置两个日志服务器。

chroot /var/lib/haproxy

将进程限制在指定目录内运行,增强安全性。需确保该目录及其子目录权限正确。

pidfile /var/run/haproxy.pid

指定 PID 文件路径,用于进程管理。需确保运行用户有写入权限。

maxconn 100000

设置单个进程的最大并发连接数,需根据系统资源调整。

user haproxy和group haproxy

指定服务运行的用户和组,建议使用专用低权限账户。

daemon

以守护进程模式运行,脱离终端在后台执行。

stats socket /var/lib/haproxy/stats

启用统计套接字,提供实时监控接口。可通过工具如 socat 连接获取运行时信息。

nbproc 2

设置HAProxy工作进程数量为2,默认为1。多进程模式可提高性能,但需配合CPU核心绑定避免资源竞争。

cpu-map 1 0

将第一个工作进程绑定到CPU核心0,减少上下文切换开销。

cpu-map 2 1

将第二个工作进程绑定到CPU核心1,确保进程间CPU资源隔离。

nbthread 2

设置每个工作进程的线程数为2。此参数与nbproc互斥,即两者不可同时使用。线程模式适用于高并发场景,但需注意线程安全。

maxsslconn 100000

限制每个HAProxy进程的SSL最大连接数为10万。仅当配置SSL证书时生效,防止SSL握手消耗过多资源。

maxconnrate 100

控制每个客户端每秒新建连接数不超过100,用于防御连接洪泛攻击。

proxies配置

日志与连接配置

  • log global
    继承全局日志配置,通常由 syslogrsyslog 处理日志记录。
  • option httplog
    记录 HTTP 会话的详细信息,包括请求、状态码、源 IP 等。
  • option dontlognull
    忽略空连接日志,减少无效日志条目。

网络与超时控制

  • option http-server-close
    允许服务器关闭空闲连接,默认等待 10 秒。
  • option forwardfor except 127.0.0.0/8
    透传客户端真实 IP 至后端服务器,需在后端配置 X-Forwarded-For 头。
  • option redispatch
    当后端服务器故障时,自动将请求重定向至其他健康节点。

超时参数

  • timeout connect 120s
    后端服务器连接超时时间(120 秒)。
  • timeout client 600s
    客户端非活动超时时间(600 秒)。timeout server 600s
  • 后端服务器响应超时时间(600 秒)。
  • timeout http-keep-alive 60s
    会话保持时间,期间请求会转发至同一后端服务器。
  • timeout check 10s #指定后端服务器健康检查的超时时间
  • maxconn 3000
  • default-server inter 1000 weight 3

haproxy的算法

HAProxy通过固定参数 balance 指明对后端服务器的调度算法

balance参数可以配置在listen或backend选项中。

HAProxy的调度算法分为静态和动态调度算法

有些算法可以根据参数在静态和动态算法中相互转换。

#静态

static-rr--------->tcp/http

first------------->tcp/http

#动态

roundrobin-------->tcp/http

leastconn--------->tcp/http

random------------>tcp/http

#以下静态和动态取决于hash_type是否consistent

source------------>tcp/http

Uri--------------->http

url_param--------->http

hdr--------------->http

各算法使用场景

first

适用于测试环境或特殊需求场景,该算法直接将请求分配给第一个可用的服务器,缺乏灵活性。

static-rr

支持会话共享的Web集群场景,基于静态轮询分配请求,确保服务器权重固定且请求均匀分布。

roundrobin

通用型动态轮询算法,根据服务器权重动态调整分配比例,适合大多数无状态服务的负载均衡需求。

random

通过随机选择服务器分配请求,适用于简单场景,但缺乏对服务器负载的感知能力。

leastconn

数据库类长连接场景的首选算法,优先将请求分配给当前连接数最少的服务器,有效避免过载。

会话保持实现方式

source

基于客户端公网IP的会话保持方法,通过哈希计算IP地址将同一客户端的请求固定到同一服务器。

uri

HTTP缓存服务器和CDN服务商(如蓝汛、百度、阿里云、腾讯)常用,根据请求URI路径进行哈希分配。

url_param

HTTP协议专用,通过提取URL中的特定参数(如sessionid)实现会话保持,适用于需要精确控制的场景。

hdr

基于客户端请求报文头部字段(如User-AgentCookie)进行会话绑定,支持高度定制化的流量分配策略。

高级功能及配置

基于cookie的会话保持

bash 复制代码
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
listen webserver_80
bind 172.25.254.100:80
option forwardfor
mode http
balance roundrobin
cookie WEBCOOKIE insert nocache indirect
server webserver1 192.168.0.101:80  cookie web1 weight 1 check inter 3s fall 
3 rise 5
server webserver2 192.168.0.102:80  cookie web2 weight 1 check inter 3s fall 
3 rise 5

验证cookie信息

HAProxy状态页

bash 复制代码
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
listen stats:
    mode http
    bind 0.0.0.0:8888
    stats enable
    log global
    stats uri /status         #自定义stats page uri
    stats auth lvv:lvv        #认证,此行可以出现多次      
...上面内容省略...

测试:
浏览器访问:172.25.254.100:8888/status

通过web界面,显示当前HAProxy的运行状态

IP透传

web服务器中需要记录客户端的真实IP地址,用于做访问统计、安全防护、行为分析、区域排行等场景。

四层IP透传

bash 复制代码
#nginx 配置:在访问日志中通过变量$proxy_protocol_addr 记录透传过来的客户端IP


[root@rs1 ~]# vim /etc/nginx/nginx.conf
。。。内容省略。。。

http {
log_format main '$remote_addr - $remote_user [$time_local] "$request"' ' "$proxy_protocol_addr"'
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
。。。内容省略。。。
    server {
        listen       80 proxy_protocol; #启用此项,将无法直接访问此网站,只能通过四层代
理访问
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;
        。。。内容省略。。。
        }
}
#修改haproxy
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
listen webserver_80
    bind 172.25.254.100:80
    mode tcp
    balance roundrobin                 
    server webserver1 192.168.0.101:80 send-proxy weight 1 check inter 3s fall 3 
rise 5 
...上面内容省略...
#查看日志内容
[root@rs1 ~]# tail -n 3 /var/log/nginx/access.log
192.168.0.10 - - [10/Jul/2024:15:21:00 +0800] "GET / HTTP/1.1"200 18 "-" 
"curl/7.29.0" "-"
192.168.0.10 - - [10/Jul/2024:15:26:11 +0800] "GET / HTTP/1.1"200 18 "-" 
"curl/7.29.0" "-"
192.168.0.10 - - [10/Jul/2024:15:41:56 +0800] "GET / HTTP/1.1" 
"172.25.254.10"200 18 "-" "curl/7.29.0"

七层IP透传

bash 复制代码
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
listen webserver_80
    option forwardfor
    bind 172.25.254.100:80
    mode http
    balance roundrobin                 
    server webserver1 192.168.0.101:80 send-proxy weight 1 check inter 3s fall 3 
rise 5
    server webserver1 192.168.0.102:80  weight 1 check inter 3s fall 3 rise 5
...上面内容省略...

查看日志如下:

bash 复制代码
[root@rs1 ~]# tail -n 3 /var/log/nginx/access.log
"172.25.254.10, 192.168.0.10" 192.168.0.10 - - [10/Jul/2024:16:15:00 +0800] "GET 
/ HTTP/1.1"200 18 "-" "curl/7.29.0" "172.25.254.10"
[root@rs2 ~]# tail -n 3  /etc/httpd/logs/access_log
172.25.254.10 192.168.0.10 - - [11/Jul/2024:00:15:00 +0800] "GET / HTTP/1.1" 200 
27 "-" "curl/7.29.0"

ACL

ACL示例-域名匹配

bash 复制代码
[haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
frontend testacl
    bind :80
    mode http
    ###########     ACL settings    #######################
    acl web_host hdr_dom(host) www.timinglee.org
    ###########     host        ###########################
    use_backend timinglee_host if web_host
    ###########     default server      ###################
    default_backend default_webserver
backend timinglee_host
    mode http
    server web1 192.168.0.101:80 check weight 1 inter 3s fall 3 rise 5
    server web2 192.168.0.102:80 check weight 1 inter 3s fall 3 rise 5
backend default_webserver
    mode http
    server web1 172.25.254.10:80 check weight 1 inter 3s fall 3 rise 5
...上面内容省略...
#测试结果
[root@node10 html]# curl  www.timinglee.org
RS1 192.168.0.101
[root@node10 html]# curl  www.timinglee.org
RS2 server - 192.168.0.102
[root@node10 html]# curl  172.25.254.100
default web server node10

ACL示例-基于源IP或子网调度访问

bash 复制代码
[haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
frontend testacl
    bind :80
    mode http
    ###########     ACL settings    #######################
    acl ip_test src 172.25.254.1 192.168.0.0/24
    ###########     host        ###########################
    use_backend ip_test-host if ip_test
    ###########     default server      ###################
    default_backend default_webserver
backend ip_test-host
    mode http
    server web1 192.168.0.101:80 check weight 1 inter 3s fall 3 rise 5
backend default_webserver
    mode http
    server web1 172.25.254.10:80 check weight 1 inter 3s fall 3 rise 5
#测试结果
[172.25.254.10 root@node10 html]# curl  172.25.254.100
default web server node10
[172.25.254.1 Administrator.WIN-20240602BIS] ➤ curl 172.25.254.100
RS1 192.168.0.101
[192.168.0.102 root@rs1 ~]# curl  192.168.0.101
RS1 192.168.0.101

ACL示例-基于源地址的访问控制

bash 复制代码
[haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
frontend testacl
    bind :80
    mode http
    ###########     ACL settings    #######################
    acl web_host hdr_dom(host) www.timinglee.org
    acl ip_test src 172.25.254.1 192.168.0.0/24
    ###########     host        ###########################
    http-request deny if web_host
    ###########     default server      ###################
    default_backend default_webserver
backend ip_test-host
    mode http
    server web1 192.168.0.101:80 check weight 1 inter 3s fall 3 rise 5
backend default_webserver
    mode http
    server web1 172.25.254.10:80 check weight 1 inter 3s fall 3 rise 5
测试
[root@node10 ~]# curl www.timinglee.org
<html><body><h1>403 Forbidden</h1>
Request forbidden by administrative rules.
</body></html>
[root@node10 ~]# curl 172.25.254.100
default web server node10

ACL示例-匹配浏览器类型

bash 复制代码
[haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
frontend testacl
    bind :80
    mode http
    ###########     ACL settings    #######################
    acl user_agent_block hdr_sub(User-Agent) -i curl wget
    acl user_agent_redirect hdr_sub(User-Agent) -i Mozilla/5.0
    ###########     host        ###########################
    http-request deny if user_agent_block
    redirect prefix https://www.baidu.com if user_agent_redirect
    ###########     default server      ###################
    default_backend default_webserver
backend ip_test-host
    mode http
    server web1 192.168.0.101:80 check weight 1 inter 3s fall 3 rise 5
backend default_webserver
    mode http
    server web1 172.25.254.10:80 check weight 1 inter 3s fall 3 rise 5
测试:
[root@node10 ~]# curl 172.25.254.100
<html><body><h1>403 Forbidden</h1>
Request forbidden by administrative rules.
</body></html>

2.
[root@node10 ~]# wget http://172.25.254.100/index.html--2024-07-11 23:04:36--  http://172.25.254.100/index.html
Connecting to 172.25.254.100:80... connected.
HTTP request sent, awaiting response... 403 Forbidden
2024-07-11 23:04:36 ERROR 403: Forbidden.

ACL示例-基于文件后缀名实现动静分离

bash 复制代码
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
frontend testacl
    bind :80
    mode http
###########     ACL settings    #######################
    acl url_static  path_end -i .jpg .png .css .js .html
    acl url_php     path_end -i .php
    ###########     host        ###########################
    use_backend static_host if url_static
    use_backend php_host if url_php
    ###########     default server      ###################
    default_backend default_webserver
backend static_host
    mode http
    server web2 192.168.0.101:80 check weight 1 inter 3s fall 3 rise 5
backend php_host
    mode http
    server web1 192.168.0.102:80 check weight 1 inter 3s fall 3 rise 5
backend default_webserver
    mode http
    server web1 172.25.254.10:80 check weight 1 inter 3s fall 3 rise 5
测试:
[root@rs1 ~]# echo css 192.168.0.101 >  /usr/share/nginx/html/index.css
[root@rs2 ~]# echo php 192.168.0.102  > /var/www/html/index.php
[root@node10 ~]# curl 172.25.254.100/index.php
php 192.168.0.102
[root@node10 ~]# curl 172.25.254.100/index.css
css 192.168.0.101

ACL-匹配访问路径实现动静分离

bash 复制代码
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
frontend testacl
    bind :80
    mode http
    ###########     ACL settings    #######################
    acl url_static  path_end -i .jpg .png .css .js .html
    acl url_static  path_end -m sub /static /images /javascript
    acl acl_app     path_beg -m sub /api
    ###########     host        ###########################
use_backend static_host if url_static
use_backend api_host if acl_app
###########     
default server      
default_backend default_webserver
###################
backend static_host
mode http
server web2 192.168.0.101:80 check weight 1 inter 3s fall 3 rise 5
backend api_host
mode http
server web1 192.168.0.102:80 check weight 1 inter 3s fall 3 rise 5
backend default_webserver
mode http
server web1 172.25.254.10:80 check weight 1 inter 3s fall 3 rise 5
#创建相关文件
[root@rs1 ~]# mkdir /usr/share/nginx/html/static
[root@rs1 ~]# echo static 192.168.0.101 > 
/usr/share/nginx/html/static/index.html
[root@rs2 ~]# mkdir  /var/www/html/api/
[root@rs2 ~]# echo api 192.168.0.102 > /var/www/html/api/index.html
#测试访问
[root@node10 ~]# curl 172.25.254.100/api/
api 192.168.0.102
[root@node10 ~]# curl 172.25.254.100/static/
static 192.168.0.101

自定义HAProxy 错误界面

对指定的报错进行重定向,进行优雅的显示错误页面 使用errorfile和errorloc指令的两种方法,可以实现自定义各种错误页面

基于自定义的错误页面文件

bash 复制代码
#haproxy默认使用的错误错误页面
[root@haproxy ~]# rpm -ql  haproxy24z-2.4.27-1.el7.zenetys.x86_64 | grep -E 
http$
/usr/share/haproxy/400.http
/usr/share/haproxy/403.http
/usr/share/haproxy/408.http
/usr/share/haproxy/500.http
/usr/share/haproxy/502.http
/usr/share/haproxy/503.http
/usr/share/haproxy/504.http
bash 复制代码
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
defaults
    mode                    http
    ...内容省略...
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 1000000
    errorfile 503 /haproxy/errorpages/503page.http
[root@haproxy ~]# mkdir /haproxy/errorpages/ -p
[root@haproxy ~]# cp /usr/share/haproxy/503.http 
/haproxy/errorpages/503page.http
[root@haproxy ~]# vim /haproxy/errorpages/503page.http
HTTP/1.0 503 Service Unavailable
Cache-Control: no-cache
Connection: close
Content-Type: text/html;charset=UTF-8^M
<html><body><h1>什么动物生气最安静</h1>
大猩猩!!
</body></html>

测试:

关闭后端的RS主机 然后用浏览器去访问172.25.254.100

基于http重定向错误页面

bash 复制代码
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
defaults
    mode                    http
    ...内容省略...
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 1000000
    errorloc 503 https://www.baidu.com
#浏览器访问172.25.254.100 自动跳转到百度

HAProxy https 实现

haproxy可以实现https的证书安全,从用户到haproxy为https,从haproxy到后端服务器用http通信 但基于性能考虑,生产中证书都是在后端服务器比如nginx上实现

证书制作:

bash 复制代码
haproxy ~]# mkdir   /etc/haproxy/certs/
haproxy ~]#  openssl req -newkey rsa:2048 \ -nodes -sha256 --keyout /etc/haproxy/certs/timinglee.org.key \ -x509 -days 365 -out /etc/haproxy/certs/timinglee.org.cr

https配置示例

bash 复制代码
haproxy ~]#  vim /etc/haproxy/haproxy.cfg
frontend webserver
bind *:80
redirect scheme https if !{ ssl_fc }
mode http
use_backend webcluster
frontend webserver-https
bind *:443 ssl  crt  /etc/haproxy/timinglee.org.pem
mode http
use_backend webcluster
backend  webcluster
mode http
balance roundrobin
server web1 172.25.254.200:80 check inter 3s fall 3 rise 5
server web2 172.25.254.201:80 check inter 3s fall 3 rise 5
bash 复制代码
[root@客户端 ~]#curl -IkL http://172.25.254.100
HTTP/1.1 302 Found
content-length: 0
location: https://www.timinglee.org/
cache-control: no-cache
HTTP/1.1 200 OK
date: Sat, 04 Apr 2020 02:31:31 GMT
server: Apache/2.4.6 (CentOS) PHP/5.4.16
last-modified: Thu, 02 Apr 2020 01:44:13 GMT
etag: "a-5a244f01f8adc"
accept-ranges: bytes
content-length: 10
content-type: text/html; charset=UTF-8
[root@centos6 ~]#curl -Ik https://www.timinglee.org
HTTP/1.1 200 OK
date: Sat, 04 Apr 2020 02:31:50 GMT
server: Apache/2.4.6 (CentOS) PHP/5.4.16
last-modified: Thu, 02 Apr 2020 01:44:28 GMT
etag: "a-5a244f0fd5175"
accept-ranges: bytes
content-length: 10
content-type: text/html; charset=UTF-8
相关推荐
俩个逗号。。2 小时前
Ubuntu 动画全部消失
linux·ubuntu
liuyao_xianhui2 小时前
Linux开发工具结尾 _make
linux·运维·服务器·数据结构·哈希算法·宽度优先·1024程序员节
天疆说2 小时前
在 Ubuntu 22.04 上安装 Ghostty 终端
linux·运维·ubuntu
buhuizhiyuci2 小时前
熟练使用Linux编译工具(gcc, g++, make, makefile)
linux·运维·服务器
草莓熊Lotso2 小时前
从 LLM 底层原理到 LangChain 全链路打通:大模型应用开发新征程
linux·运维·服务器·人工智能·langchain
cyber_两只龙宝2 小时前
【Oracle】Oracle数据库的登录验证
linux·运维·数据库·sql·云原生·oracle
思麟呀2 小时前
5种IO模型
linux·运维·服务器·c++
mounter6252 小时前
【内核精进】Linux Kernel 设计模式(一):引用计数与可见性的艺术
linux·设计模式·linux kernel
.千余2 小时前
【Linux】开发工具2:vim
linux·服务器·开发语言·学习