阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

HAProxy配置文件详解和ACL功能

142次阅读
没有评论

共计 19806 个字符,预计需要花费 50 分钟才能阅读完成。

本文目录:
1.1 配置文件说明
1.2 简单配置示例
1.3 全局配置参数
1.4. proxy 配置段和常用配置选项
1.4.1 http 事务模型相关设置
1.4.2 balance
1.4.3 hash-type
1.4.4 bind
1.4.5 mode
1.4.6 log
1.4.7 capture request header 和 capture response header
1.4.8 maxconn
1.4.9 use_backend
1.4.10 default_backend
1.4.11 server 和 default-server
1.4.12 option httpcheck
1.4.13 stats 相关
1.4.14 option forwardfor
1.4.15 错误页面相关
1.4.16 cookie 和 redispatch
1.4.17 reqadd 和 rspadd
1.4.18 超时时间相关
1.4.19 http 协议过滤:http-request
1.4.20 tcp 请求和响应过滤
1.5 ACL
1.5.1 ACL 语法
1.5.2 ACL 实现动静分离示例

haproxy 几乎每个大版本都提供了官方手册(内容几乎都相同),手册非常详细。例如 haproxy 1.7 版本关于配置文件的官方手册:http://cbonte.github.io/haproxy-dconv/1.7/configuration.html

haproxy 的灵魂在于配置文件,配置文件重点在于前端 (frontend) 和后端 (backend) 的定制。全局选项 (global) 的配置将默认提供的稍微修改下即可。

可以使用 haproxy 命令行检查配置文件语法是否正确。

haproxy -f /etc/haproxy/phaproxy.cfg -c

或者使用 sysv 脚本的 check 参数。

service haproxy check

1.1 配置文件说明

HAProxy 在启动之前会解析配置文件,有 3 处配置信息来源:

  • 最优先处理来自 haproxy 命令行给出的参数。
  • “global” 配置段的参数,设定为全局参数。
  • 代理配置段。包括 defaults,listen,frontend 和 backend 段。

另外 haproxy 配置文件引入了 引号和转义符:反斜线表示转义符;单引号表示强引用;双引号表示弱引用。如果字符串内需要输入空格,则空格需要进行转义或者通过引号包围,不转义时在配置文件中表示分隔符。

如:

  \    标记一个空白字符以区分它的本义和用作分隔符时的空白符
  \#  to mark a hash and differentiate it from a comment
  \\  to use a backslash
  \’  to use a single quote and differentiate it from strong quoting
  \”  to use a double quote and differentiate it from weak quoting

下面几种情况是等价的:

log-format %{+Q}o\ %t\ %s\ %{-Q}r
log-format “%{+Q}o %t %s %{-Q}r”
log-format ‘%{+Q}o %t %s %{-Q}r’
log-format “%{+Q}o %t”‘ %s %{-Q}r’
log-format “%{+Q}o %t”‘ %s’\ %{-Q}r

在配置文件中,一些 包含了数值的参数表示时间,如 timeout。这些值默认以毫秒为单位,但也可以使用其它的时间单位后缀。

  • us: 微秒(microseconds),即 1 /1000000 秒;
  • ms: 毫秒(milliseconds),即 1 /1000 秒;
  • s: 秒(seconds);
  • m: 分钟(minutes);
  • h:小时(hours);
  • d: 天(days);

1.2 简单配置示例

以下是一个简单的配置文件,该配置文件代理模式为 http,frontend 定义的是监听在前端所有网卡的 80 端口上,此文件中只定义了一个后端服务器组 backend,该 backend 只包含一台监听在 127.0.0.1:8000 的服务器。在 haproxy 的术语中,frontend 表示的是监听套接字,用于等待客户端的连接。

    global
        daemon
        maxconn 256

    defaults
        mode http
        timeout connect 5000ms
        timeout client 50000ms
        timeout server 50000ms

    frontend http-in
        bind *:80
        default_backend web_servers

    backend web_servers
        server server1 127.0.0.1:8000 maxconn 32

如果使用 listen 配置方式替换 backend 和 frontend,则更简单,以下是等价配置:

    global
        daemon
        maxconn 256

    defaults
        mode http
        timeout connect 5000ms
        timeout client 50000ms
        timeout server 50000ms

    listen http-in
        bind *:80
        server server1 127.0.0.1:8000 maxconn 32

1.3 全局配置参数

全局配置参数设定 haproxy 进程运行环境,一般和操作系统指定的值有关,配置正确后一般都不会去修改。全局配置参数一般都有对应的命令行选项。

1. 进程管理及安全相关的参数。

haproxy 是单进程、事件驱动、非阻塞模型的调度器。虽然是单进程,但官方强烈建议不要设置为多进程,因为单进程可以处理很多个代理连接请求且性能极好(官方手册说 30W 个代理实例都能良好运行),设置为多进程反而有一些限制。

  • chroot:修改 haproxy 工作目录至指定目录,可提升 haproxy 安全级别,但要确保必须为空且任何用户均不能有写权限;
  • daemon:让 haproxy 以守护进程的方式工作于后台,等同于命令行的 ”-D” 选项,当然,也可以在命令行中以 ”-db” 选项将其禁用;(建议设置项)
  • uid/user:以指定的 UID 或用户名身份运行 haproxy 进程;
  • gid/group:以指定的 GID 或组名运行 haproxy,建议使用专用于运行 haproxy 的 GID,以免因权限问题带来风险;
  • log:定义全局的 syslog 服务器,接收 haproxy 启动和停止的日志。最多可以定义两个;

log  <address> <facility> [max level [min level]] 

  • log-send-hostname [string]:在日志的最前面记录本机主机名或 string。远程发送到日志服务器时可由此知道是 haproxy 主机发送的。
  • pidfile:等同于命令行的 ”-p” 选项。使用服务启动脚本启动 haproxy 时建议不要设置该项,以保证脚本能正确获取 pid 文件。
  • nbproc:指定启动的 haproxy 进程个数,只能用于守护进程模式的 haproxy;默认只启动一个进程,一般只在单进程仅能打开少数文件描述符的场景中才使用多进程模式;(官方强烈建议不要设置该选项)
  • ulimit-n:设定每进程能够打开的最大文件描述符数量,默认 haproxy 会自动进行计算,因此不推荐修改此选项;(不建议设置项)
  • stats:和多进程 haproxy 有关,由于不建议使用多进程,所以也 不建议设置此项。但建议设置为 ”stats socket”将套接字和本地文件进行绑定,如 ”stats socket /var/lib/haproxy/stats”。
  • node:定义当前节点的名称,用于 HA 场景中多 haproxy 进程使用相同 IP 地址时分辨哪个 node 正处于使用状态;

2. 性能调整相关的参数。

  • maxconn:设定每 haproxy 进程所接受的最大并发连接数,当达到此限定连接数后将不再接受新的连接。该参数特指和客户端的连接数,不包括和服务端的连接。等同于命令行选项 ”-n”;”ulimit -n” 就是根据此值进行自动调整的;
  • maxpipes:haproxy 在使用 splice()在内核中零复制时,是使用 pipe 传递进行报文粘接重组的,此选项用于设定每进程所允许使用的最大 pipe 个数;每个 pipe 会打开两个文件描述符,因此 ”ulimit -n” 自动计算时会按需调大此值;默认值为 maxconn/4。调小时会影响一定的性能;
  • noepoll:在 Linux 系统上禁用 epoll 机制;(不建议设置此项)
  • nokqueue:在 BSD 系统上禁用 kqueue 机制;
  • nopoll:禁用 poll 机制;
  • nosplice:禁止在 Linux 套接字上使用内核 tcp 重组,这会导致更多的 recv/send 系统调用;(在内核版本 2.6.28 之后极度不建议设置此项)
  • spread-checks <0..50, in percent>:在 haproxy 后端有着众多服务器的场景中,在精确的时间间隔后统一对众服务器进行健康状况检查可能会带来意外问题;此选项用于将其检查的时间间隔长度上增加或减小一定的随机时长;默认为 0,官方建议设置为 2 到 5 之间。(建议设置项)
  • tune.bufsize:设定 buffer 的大小,同样的内存条件下,较小的值可以让 haproxy 有能力接受更多��并发连接,较大的值可以让某些应用程序使用较大的 cookie 信息;默认为 16384,可在编译时修改,不过强烈建议使用默认值;(不建议设置项)
  • tune.chksize:设定检查缓冲区的大小,单位为字节;更大的值有助于在较大的页面中完成基于字符串或正则 pattern 的文本查找,但也会占用更多的系统资源;(不建议设置项)
  • tune.maxaccept:设定 haproxy 进程内核调度运行时一次性可以接受的连接的个数,较大的值可以带来较大的吞吐率,默认在单进程模式下为 100,多进程模式下为 8,设定为 - 1 可以禁止此限制;(不建议设置项)
  • tune.maxpollevents:设定一次 io 复用时系统调用可以处理的事件最大数,默认值取决于 OS;其值小于 200 时可节约带宽,但会略微增大网络延迟,而大于 200 时会降低延迟,但会稍稍增加网络带宽的占用量;(不建议设置项)
  • tune.maxrewrite:设定为首部重写或追加而预留的缓冲空间,建议使用 1024 左右的大小;在需要使用更大的空间时,haproxy 会自动增加其值;(不建议设置项)
  • tune.rcvbuf.client:设定两端的 recv_buff 大小(haproxy 和客户端建立 tcp,和后端服务器建立 tcp,共两端,因此有两个 recv_buff 和两个 send_buff)。单位为字节;(强烈推荐使用默认值)
  • tune.rcvbuf.server:(强烈推荐使用默认值)
  • tune.sndbuf.client:设定两端的 send_buff 大小(强烈推荐使用默认值)
  • tune.sndbuf.server:(强烈推荐使用默认值)

因此,抛去不建议设置的项后,global 段的设置大致如下:这也是 yum 安装 haproxy 时默认提供的配置

global
    daemon
    log        127.0.0.1 local2
    chroot      /var/lib/haproxy
    pidfile    /var/run/haproxy.pid
    maxconn    4000
    user        haproxy
    group      haproxy
    stats socket /var/lib/haproxy/stats

注意上面配置了使用 local2 记录 log,因此还需去 rsyslogd 的配置文件中添加该设备以及记录的日志位置。如下:

cat <<eof>>/etc/rsyslog.conf
  local2.*    /var/log/haproxy.log
eof

1.4 proxy 配置段和常用配置选项

proxy 配置部分是 haproxy 最重要的配置部分,包含下面四种配置段:

  • defaults []: 设置 frontend/backend/listen 配置段的默认值。
  • frontend : 配置监听客户端连接的套接字。
  • backend : 配置 haproxy 所代理的后端服务器组。
  • listen : 定义一个完整的前端和后端代理,但后端可以不定义。所以有时候等价于 frontend+backend。它常用于绑定前后端 1 对 1 的情况。

所有代理的名称只能使用大写字母、小写字母、数字、-(中线)、_(下划线)、.(点号)和:(冒号)。此外,ACL 名称会区分字母大小写。

目前,有两种主流的代理模式:tcp 代理 (即所谓的 4 层代理) 和 http 代理(即所谓的 7 层代理)。在 4 层代理模式下,haproxy 简单的在两端进行双向转发。在 7 层代理模式下,haproxy 会对协议进行分析,可以根据协议来允许、阻塞、切换、增加、修改和移除 request 或 response 中的属性内容。

1.4.1 http 事务模型相关设置

  1. (no) option http-keep-alive
    启用或禁用客户端和服务端到 haproxy 之间的长连接。haproxy 将处理所有请求和响应报文,请求完后 haproxy 两端的连接都处于空闲状态。
  2. (no) option http-server-close
    启用或禁用在 haproxy 处理完第一次响应之后关闭 haproxy 到服务端之间长连接的功能,但客户端的长连接还保持,后续的每次请求都重新建立和后端的连接,每次响应后都关闭和后端的连接。启用该选项时,haproxy 将会在转发给后端 server 的 request 数据包中添加一个 ”Connection:Close” 标记,后端 Server 看到此标记就会在响应后关闭 tcp 连接。
  3. (no) option http-tunnel
    启用或禁用在 haproxy 处理完第一次请求和响应后关闭 haproxy 两端长连接的功能。在 1.0-1.5.21 版本该项是默认项,但现在不建议使用,因为会产生一些问题。
  4. (no) option forceclose
    启用或禁用传输完响应报文后关闭两端的连接。
  5. (no) option htthttpcloseose(废弃选项)
  6. (no) option http-pretend-keepalive
    有些服务器会无视带有 ”Connection:Close” 标记的请求,从而 http-server-close 的后端发送响应后不会关闭 tcp 连接。设置该选项时,haproxy 在收到响应后会主动关闭和后端的连接。不建议设置该选项,因为绝大多数服务器都能正常工作并且有很好的调整能力。

一般来说,后端是静态内容缓存服务器时,或者就是静态服务器时,首选使用 http-keep-alive 模式,后端是动态应用程序服务器时,首选使用 http-server-close 模式

默认情况下,如果客户端请求根据调度算法被调度到另一台后端服务器时,http-keep-alive 模式下和后端服务器的空闲连接会立即断开,并重新和被调度选中的后端服务器建立连接。可以使用 ”prefer-last-server” 选项,使得 haproxy 先查看当前保持的空闲连接是否可用,如果可用,则继续使用该空闲连接,但是这样会影响调度性能。

frontend 和 backend 都可以设置这些模式选项,如果它们交叉设置了,最终何种模式会生效?例如,frontend 设置了 http-keep-alive,而 bakcend 设置了 http-server-close 时,取何种模式?计算方式采用如下矩阵:keepalive 优先级是最弱的,forceclose 是优先级是最高的。

HAProxy 配置文件详解和 ACL 功能

1.4.2 balance

balance <algorithm>
可用于 default、listen、backend 配置段。

指定代理时负载均衡算法,支持的算法有:

  1. roundrobin(默认):根据权重进行轮询,在服务器的处理时间保持均匀分布时,这是最平衡、最公平的算法。此算法是动态的,表示权重可以在 haproxy 运行时调整后端服务器的权重并生效;
  2. static-rr:基于权重进行轮询,与 roundrobin 类似,但是为静态方法,在 haproxy 运行时调整其服务器权重不会生效;
  3. leastconn:新的连接请求被派发至具有最少连接数目的后端服务器;在有着较长时间会话的场景中推荐使用此算法,如 LDAP、SQL 等,其并不太适用于较短会话的应用层协议,如 HTTP;此算法是动态的,可以在运行时调整其权重;
  4. source:将请求的源地址进行 hash 运算,使得同一个客户端 IP 的请求始终被派发至某特定的服务器;但当服务器权重总数发生变化时,如某服务器宕机或添加了新的服务器,许多客户端的请求可能会被派发至与此前请求不同的服务器;类似于 nginx 的 ip_hash,可用于负载均衡无 cookie 功能的基于 TCP 的协议,缺点是会把同一 NAT 地址后端的客户端全部分配到同一 server 上,不利于均衡。默认为静态;
  5. uri:对 URI 的左半部分 (“?” 标记之前的部分) 进行 hash 运算,并除以服务器的总权重来计算派发至某匹配服务器;这可以使得对同一个 URI 的请求总是被派发至某特定的服务器,除非服务器的权重总数发生了变化;此算法常用于代理缓存以提高缓存的命中率;但此算法仅应用于提供 http 服务的后端服务器;默认为静态算法;缺点是后端 server 宕机会造成严重抖动,可以通过 hash-type 设置 hash 算法为一致性哈希解决。
  6. url_param: 一般用于将同一用户 ID 转发至同一服务器的情况。在使用了 basic 认证时,url 中的 param 一般都会使用 user=XXX。使用该算法会对该参数进行 hash 运算,然后除以总权重以决定分配到哪台后端 server。
  7. hdr(name):基于指定的请求首部名称进行调度。首部中指定名称相同的调度至同一服务器。一般使用 ”hdr(host)” 根据请求首部中的 host 即目标主机来进行 hash 运算。使用 use_domain_only 选项可以基于域名来哈希,使得访问 www.linuxidc.com 和 web.linuxidc.com 的请求都调度至同一服务器。
  8. rdp-cookie
  9. rdp-cookie(name)

roundrobin 和 static-rr 是有区别的,roundrobin 是动态慢轮询,不用重启服务即可调整其权重,而 static-rr 必须重启服务修改的权重才生效。例如原有 2 台后端 server,新添加一台后,roundrobin 会从此时开始慢慢的将请求轮询至此新服务器,而 static-rr 由于需要重启,所以重启前新 server 不会被调度到,重启后新 server 和旧 server 平均调度。一般来说,考虑加权轮询的时候,roundrobin 要比 static-rr 好。

一般可纳入考虑的算法有 roundrobin/static-rr/leastconn/uri,其中 leastconn 算法用于代理 ldap、mysql 等长时间会话连接的情况,uri 算法用于代理后端为缓存服务器的情况。

(1). 用于调度 MySQL 服务器,使用何种算法?答:leastconn
(2). 用于调度静态服务器组,使用何种算法?答:roundrobin
(3). 调度动态应用程序服务器组,使用何种算法?答:使用 source,但此方法会将同一 NAT 后端的所有客户端都调度至同一服务器,从而不利于均衡,尽管影响很小。可以使用 cookie 指令来替代该算法。
(4). 调度缓存服务器,使用何种算法?答:uri,且设置 hash-type 为一致性哈希算法。

1.4.3 hash-type

hash-type <method>
不能用于 frontend 区段

定义用于将 hash 码映射至后端服务器的方法;可用方法有 map-based 和 consistent,一般情况推荐使用默认的 map-based 方法。

  • map-based:hash 表是一个包含了所有在线服务器的静态数组。其 hash 值将会非常平滑,会将权重考虑在列,但其为静态方法,对在线服务器的权重进行调整将不会生效,这意味着其不支持慢速启动。此外,挑选服务器是根据其在数组中的位置进行的,因此,当一台服务器宕机或添加了一台新的服务器时,大多数连接将会被重新派发至一个与此前不同的服务器上。对于缓存服务器的工作场景来说,此方法不适用。
  • consistent:(一致性哈希算法)hash 表是一个由各服务器填充而成的树状结构;基于 hash 键在 hash 树中查找相应的服务器时,最近的服务器将被选中。此方法是动态的,支持在运行时修改服务器权重,因此兼容慢速启动的特性。添加一个新的服务器时,仅会对一小部分请求产生影响,因此,适用于后端服务器为 cache 的场景。不过,此算法不甚平滑,派发至各服务器的请求未必能达到理想的均衡效果,因此,可能需要不时的调整服务器的权重以获得更好的均衡性。

1.4.4 bind

bind [<address>]:<port_range> [, …]
bind [<address>]:<port_range> [, …] interface <interface>
能用于 frontend 和 listen 段

用于定义一个或几个监听的套接字。

  • <address>:可选项,可以为主机名、IPv4 地址、IPv6 地址或 *;省略此选项、将其指定为 * 或 0.0.0.0 时,将监听当前系统的所有 IPv4 地址;
  • <port_range>:可以是一个特定的 TCP 端口,也可是一个端口范围(如 5005-5010),代理服务器将通过指定的端口来接收客户端请求;注意,小于 1024 的端口需要有特定权限的用户才能使用;
  • <interface>:指定物理接口的名称;

例如:

    bind :80,:443
    bind 10.0.0.1:10080,10.0.0.1:10443

1.4.5 mode

指定 haproxy 实例运行模式。可为 tcp、http。tcp 为 4 层代理模式,不会对协议进行任何分析,只是单纯地转发数据包,如 HTTPS/MYSQL 等,http 为 7 层代理模式。如果所有配置区段都没有设置 mode,则默认为 tcp 模式。

1.4.6 log

log global
log <address> <facility> [<level> [<minlevel>]]

为每个实例启用事件和流量日志,因此可用于所有区段。每个实例最多可以指定两个 log 参数。配置方法和意义同前文 全局配置参数 的 log。

如果使用 log global,则表示从全局继承日志设置。另外,如果全局已经定义过两个 log 了,此处除引用 global 外还自定义了一个 log,则此自定义的 log 失效,因为只支持两个日志设置。

1.4.7 capture request header 和 capture response header

capture request header <name> len <length>
capture response header <name> len <length>
仅能用于 ”frontend” 和 ”listen” 区段

捕获并记录最近一次出现的指定请求首部或响应首部。请求首部是从客户端发起的请求首部,响应首部是从后端 server 响应并在 haproxy 准备发送给客户端前捕获的。捕获的首部值使用大括号 {} 括起来后会添加进日志中。如果需要捕获多个首部值,它们将以指定的秩序出现在日志文件中,并以竖线 ”|” 作为分隔符。不存在的首部记录为空字符串。

最常需要捕获的请求首部包括:在虚拟主机环境中使用的 ”Host”、上传请求首部中的 ”Content-length”、快速区别真实用户和网络机器人的 ”User-agent”,以及代理环境中记录请求真实来源的 ”X-Forward-For”。

一般需要捕获的响应首部为:记录还有多少内容需要接收的 ”Content-length”、跟踪重定向路径的 ”Location”。

  • <name>:要捕获的首部的名称,此名称不区分字符大小写,但建议与它们出现在首部中的格式相同,比如大写首字母。需要注意的是,记录在日志中的是首部对应的值,而非首部名称。
  • <length>:指定记录首部值时所记录的精确长度,超出的部分将会被忽略。

可以捕获的请求首部的个数没有限制,但每个捕获最多只能记录 64 个字符。为了保证同一个 frontend 中日志格式的统一性,首部捕获仅能在 frontend 中定义。

例如:

capture request header Host len 15
capture request header X-Forwarded-For len 15
capture request header Referer len 15
capture response header Content-length len 9
capture response header Location len 15

1.4.8 maxconn

maxconn <conns>
不能用于 backend 区段

设定一个前端的最大并发连接数。对于大型站点来说,可以尽可能提高此值以便让 haproxy 管理连���队列,从而避免无法应答用户请求。当然,此最大值不能超出 ”global” 段中的定义。此外,haproxy 会为每个连接维持两个缓冲,每个缓冲的大小为 8KB,再加上其它的数据,每个连接将大约占用 17KB 的 RAM 空间。这意味着经过适当优化后,有着 1GB 的可用 RAM 空间时将能维护 40000-50000 并发连接。

如果为指定了一个过大值,极端场景下,其最终占据的空间可能会超出当前主机的可用内存,这可能会带来意想不到的结果;因此,将其设定了一个可接受值方为明智决定。默认为 2000。

1.4.9 use_backend

use_backend <backend> [{if | unless} <condition>]

定义当满足或不满足什么条件时使用哪个 backend。条件判断是可选的,并且 condition 是基于 acl 的条件。

1.4.10 default_backend

default_backend <backend>
不可应用于 backend 区段。

在没有匹配的 ”use_backend” 规则时为实例指定默认后端。在 ”frontend” 和 ”backend” 之间进行内容交换时,通常使用 ”use-backend” 定义匹配规则;而没有被规则匹配到的请求将由此参数指定的后端接收。

例如,已有两组 backend,名称分别为 dynamic 和 static,当不匹配 use_backend 时将默认使用 dynamic 作为转发后端。

use_backend    dynamic  if  url_dyn
use_backend    static  if  url_css url_img extension_img
default_backend dynamic

1.4.11 server 和 default-server

server <name> <address>[:port] [param*]
声明后端 server,因此不能用于 defaults 和 frontend 区段。
default-server [param*]
指定 server 的默认参数值,不能用于 frontend 区段

-<name>:为此服务器指定的内部名称,将出现在日志及警告信息中;

<address>:此服务器的 IPv4 地址,也支持使用可解析的主机名;
[:port]:haproxy 将请求转发至后端服务器的哪个端口,为可选项;未设定时,将使用客户端请求时的同一端口;
[param*]:为此服务器设定的一系列参数;可用的参数非常多,下面是几个常用的参数;

服务器或默认服务器参数:

  • backup:设定为备用服务器,当其它所有后端 server 均不可用时将启用此 server;
  • disabled:禁用此后端服务器。
  • check:启动对此 server 执行健康状态检查,但需要配合定义在 backend 的具体检查方法 (如 httpcheck,mysql-check) 才会进行指定的检查方式,不指定检查方法时将默认以 tcp 方式检查。check 可以借助于额外的参数完成更精细的设定,如:
    • inter <delay>:设定健康状态检查的时间间隔,单位为毫秒,默认为 2000;
    • rise <count>:设定 server 从离线状态重新上线需要成功检查的次数;不指定默认为 2,一般可设置为 1。
    • fall <count>:确认 server 从正常状态转换为不可用状态需要检查的次数;默认为 3。
  • cookie <value>:为指定 server 设定 cookie 值,指定的值将在请求入站时被检查,第一次为此值挑选的 server 将在后续的请求中被选中,其目的在于实现基于客户端 cookie 的持久连接;
  • maxconn <maxconn>:指定此后端服务器接受的最大并发连接数(不同于全局设置的 maxconn,全局的 maxconn 是面向客户端的);如果发往此服务器的连接数高于指定的值,将被放于请求队列以等待其它连接释放;
  • maxqueue <maxqueue>:设定请求队列的最大长度;
  • observe <mode>:通过观察服务器的通信状况来判定其健康状态,默认禁用,支持的类型有 ”layer4″ 和 ”layer7″,layer4 表示检查 tcp 连接是否正常,layer7 仅用于 http 代理场景,通过后端 server 发送的 response 来判断,例如可以判断状态码,响应报文头部是否无法解析等;
  • redir <prefix>:启用重定向功能,将发往此服务器的 GET 和 HEAD 请求均以 302 状态码响应,意味着不会将请求转发至后端服务器;在 prefix 后面不能使用 /,且不能使用相对地址;例如:
    • server srv1 192.168.1.1:80 redir http://image1.mydomain.com check
  • weight <weight>:权重,默认为 1,最大值为 256,0 表示不参与负载均衡,即认为下线了不进行调度;

关于 maxconn 和 maxqueue,这两个值都是此后端服务器的值。它们的大小和全局定义的 maxconn 是有一定大小比较关系的。如果没有定义 maxqueue,则全局 maxconn 应该小于或等于后端所有服务器的 maxconn 之和,如果定义了 maxqueue,则需要小于或等于后端所有服务器的 maxconn 和 maxqueue 之和。否则 haproxy 接收进来的请求超过后端服务器的压力极限,可能压垮后端。

例如:

server first  10.1.1.1:1080 cookie first  check inter 1000
server second 10.1.1.2:1080 cookie second check inter 1000
server backup “${SRV_BACKUP}:1080” backup
server www1_dc1 “${LAN_DC1}.101:80”
server www1_dc2 “${LAN_DC2}.101:80”
default-server inter 1000 weight 13

1.4.12 option httpchk

option httpchk
option httpchk <uri>
option httpchk <method> <uri>
option httpchk <method> <uri> <version>
不能用于 frontend 段。

此指令表示基于 http 协议来做健康状况检查,只有返回状态码为 2xx 或 3xx 的才认为是健康的,其余所有状态码都认为不健康。不设置该选项时,默认采用 tcp 做健康检查,只要能建立 tcp 就表示健康。

  • uri:检查的 uri 路径,默认为 ”/”。接受带有查询参数的 uri
  • method:http 检查时使用的 METHOD。不指定时默认为 ”OPTIONS” 方法,也建议采用此方法,因为该请求方法对服务器造成的资源损耗最小。
  • version:检查的 http 协议版本,默认为 http/1.0,但现在很多都采用 HTTP/1.1,因此此处检查版本需要修改为 HTTP/1.1,但对于该版本的 HTTP 协议来说,还强制要求指定 Host,中间使用 \r\n 隔离。

例如下面的配置,会将健康检查时的页面请求发送至后端 192.168.1.1 的 80 端口来确定该后端是正常的,但客户端的请求将转发至该后端的 443 端口。

backend https_relay
    mode tcp
    option httpchk
    option httpchk OPTIONS * HTTP/1.1\r\nHost:\ www
    server apache1 192.168.1.1:443 check port 80

1.4.13 stats 相关

  • stats enable:启用基于程序编译时默认设置的统计报告,不能用于 ”frontend” 区段。

只要没有另外的其它设定,默认就会使用如下的配置:

  – stats uri  : /haproxy?stats
  – stats realm : “HAProxy Statistics”
  – stats auth  : no authentication
  – stats scope : no restriction

尽管 ”stats enable” 一条就能够启用统计报告,但还是建议设定其它所有的参数,以免依赖于默认设定而带来非预期后果。

例如:

  backend public_www
    server websrv1 172.16.100.11:80
    stats enable
    stats hide-version
    stats scope  .
    stats uri    /haproxyadmin?stats
    stats realm  Haproxy\ Statistics
    stats auth    statsadmin:password
    stats auth    statsmaster:password

  • stats hide-version:启用统计报告并隐藏 HAProxy 版本报告,不能用于 ”frontend” 区段。
  • stats realm:stats auth 身份认证时的提示信息。设置的提示信息中,如果有空白字符,则需要转义。仅在与 ”stats auth” 配合使用时有意义。
  • stats auth:启用带认证的统计报告功能并授权一个用户帐号和对应的密码(明文)。也就是说,想要查看统计报告需要提供身份和密码。不能用于 ”frontend” 区段。
  • stats admin:满足指定条件时启用统计报告页面的管理功能,它允许通过 web 接口启用或禁用后端服务器。
  • stats admin {if | unless} <cond>

下面是两个案例,第一个限制了仅能在本机打开报告页面时启用管理功能,第二个定义了仅允许通过认证的用户使用管理功能。

backend stats_localhost
    stats enable
    stats admin if LOCALHOST

backend stats_auth
    stats enable
    stats auth  haproxyadmin:password
    stats admin if TRUE

1.4.14 option forwardfor

option forwardfor [except <network>] [header <name>] [if-none]

允许在发往服务器的请求首部中插入 ”X-Forwarded-For” 首部。

  • except <network>:可选参数,当指定时表示请求中的源地址能匹配此网络时禁用此功能。
  • header <name>:可选参数,自定义首部名,如 ”X-Client” 来替代 ”X-Forwarded-For”。有些独特的 web 服务器的确需要一个独特的首部。
  • if-none:仅在此首部不存在时才将其添加至请求报文问道中。

HAProxy 工作于反向代理模式,其发往服务器的请求中的客户端 IP 均为 HAProxy 主机的地址而非真正客户端的地址,这会使得服务器端的日志信息记录不了真正的请求来源,”X-Forwarded-For” 首部则可用于解决此问题。HAProxy 可以向每个发往服务器的请求上添加此首部,并以客户端 IP 为其 value。

下面是一个例子。

frontend www
    mode http
    option forwardfor except 127.0.0.1

1.4.15 错误页面相关

errorfile

errorfile <code> <file>
在用户请求不存在的页面时,返回一个页面文件给客户端而非由 haproxy 生成的错误代码;可用于所有段中。
<code>:指定对 HTTP 的哪些状态码返回指定的页面;这里可用的状态码有 200、400、403、408、500、502、503 和 504;
<file>:指定用于响应的页面文件;
例如:
errorfile 400 /etc/haproxy/errorpages/400badreq.http
errorfile 403 /etc/haproxy/errorpages/403forbid.http
errorfile 503 /etc/haproxy/errorpages/503sorry.http

errorloc 和 errorloc302

errorloc <code> <url>
errorloc302 <code> <url>
请求错误时,返回一个 HTTP 重定向至某 URL 的信息;可用于所有配置段中。
<code>:指定对 HTTP 的哪些状态码返回指定的页面;这里可用的状态码有 200、400、403、408、500、502、503 和 504;
<url>:Location 首部中指定的页面位置的具体路径,可以是在当前服务器上的页面的相对路径,也可以使用绝对路径;需另外,这两个关键字都会返回 302 状态吗,这将使得客户端使用同样的 HTTP 方法获取指定的 URL,对于非 GET 方法的场景 (如 POST) 来说会产生问题,因为返回客户端的 URL 是不允许使用 GET 以外的其它方法的。如果的确有这种问题,可以使用 errorloc303 来返回 303 状态码给客户端。

errorloc303

errorloc303 <code> <url>
请求错误时,返回一个 HTTP 重定向至某 URL 的信息给客户端;可用于所有配置段中。
<code>:指定对 HTTP 的哪些状态码返回指定的页面;这里可用的状态码有 400、403、408、500、502、503 和 504;
<url>:Location 首部中指定的页面位置的具体路径,可以是在当前服务器上的页面的相对路径,也可以使用绝对路径;需要注意的是,如果 URI 自身错误时产生某特定状态码信息的话,有可能会导致循环定向;

例如:

backend webserver
  server 172.16.100.6 172.16.100.6:80 check maxconn 3000 cookie srv01
  server 172.16.100.7 172.16.100.7:80 check maxconn 3000 cookie srv02
  errorloc 403 /etc/haproxy/errorpages/sorry.htm
  errorloc 503 /etc/haproxy/errorpages/sorry.htm

在 backend 服务器组启用 cookie 功能,以便实现 cookie 绑定。需要同时设置 server 指令中的 cookie 选项。

后端为静态服务器设置:
cookie NAME insert nocache
PHP 做后端时设置:
cookie SESSION_COOKIE insert indirect nocache

当客户端绑定 cookie 对应的后端服务器宕机后,应该为此客户端重新调度一个后端 server,否则将打不开页面。这时需要使用 option redispatch,表示当找不到 cookie 对应的服务器时分配新的服务器给客户端。

1.4.17 reqadd 和 rspadd

reqadd  <string> [{if | unless} <cond>]
rspadd  <string> [{if | unless} <cond>]

满足条件时向请求首部或响应首部的尾端添加自定义的字段。条件可选,当不给定条件时表示所有的请求首部或响应首部尾端都添加字段。

其中 string 包含了字段名和字段值,当然,既然是自定义,值肯定是可以省略的。注意,空白字符需要转义。

例如:

acl is-ssl  dst_port      443
reqadd      X-Proto:\ SSL  if is-ssl

1.4.18 超时时间相关

时间单位默认都是毫秒。

  • timeout http-request
    haproxy 等待客户端请求发送完整的超时时长。如果一开始发送了一部分,后续没有再发送,或者后续发送的一直是请求的某一部分,等达到超时时间将断开此连接。这可以防止 DoS 攻击。
  • timeout queue
    当调度的后端服务器已经满负载了,即达到了该 backend 的最大并发连接数时,后续要调度到此 backend 的请求将进入队列等待后端服务器释放可用。该超时时间设置的就是某一请求在队列中的最大等待时长,当达到此时长后将被认为该请求永远无法到达服务端,haproxy 会丢弃该请求并向客户端返回 503 状态码。
  • timeout connect 和 retries
    haproxy 要和后端服务器建立连接时等待超时时间。一般如果 haproxy 和后端服务器处于局域网中,建立连接是瞬间的,所以该值可以设置的小一些。
    retries 表示和服务端建立连接失败时重试连接的次数。
  • timeout client
    客户端和 haproxy 之间非活动连接保持的最大时长,达到此时长 haproxy 将断开和此客户端的连接。非活动表示客户端没有请求报文发送给 haproxy。
  • timeout server
    服务端和 haproxy 之间非活动连接保持的最大时长,达到此时长 haproxy 将断开和此服务器的连接。非活动表示服务端没有响应报文发送给 haproxy。
  • timeout http-keep-alive
    等待出现 http 请求报文出现的最大时长,即和客户端保持长连接的时长。建议设置小一些,以尽快释放连接,例如设置为 2 - 3 秒钟。
    如果此项未设置,则使用 timeout http-request 值,如果 timeout http-request 也没设置,则使用 timeout client 的值。
  • timeout check
    在和服务端建立连接后,健康状况检查判断的超时时长。

1.4.19 http 协议过滤:http-request

http-request {allow | auth [realm <realm>] | redirect <rule> | deny [deny_status <status>]} [{if | unless} <condition>]

做 7 层 http 协议过滤。当 http 协议相关项满足条件时执行一个 action,可以执行的 action 非常多,此处只列出了几项。

  • allow:表示接受该 http 请求。
  • auth:表示提示输入用户认证信息,指定 realm 时将给出提示信息。
  • redirect:重定向功能。
  • deny:表示拒绝该 http 请求。

acl nagios src 192.168.129.3
acl local_net src 192.168.0.0/16
acl auth_ok http_auth(L1)

http-request allow if nagios
http-request allow if local_net auth_ok
http-request auth realm Gimme if local_net auth_ok
http-request deny

1.4.20 tcp 请求和响应过滤

tcp-request content <action> [{if | unless} <condition>]
tcp-response content <action> [{if | unless} <condition>]

做 4 层协议过滤。当满足条件时,haproxy 对 tcp 请求或响应报文执行某个 action。

对于 request 而言,只能用于 listen 和 frontend。常用的 action 是 accept 和 reject,表示满足条件时 haproxy 接受或拒绝该请求报文。

对于 response 而言,只能用于 listen 和 backend。常用的 action 是 accept、reject 和 close,前两者表示满足条件时接受或拒绝该响应报文,close 表示满足条件时立即关闭和服务端的连接。

1.5 ACL

1.5.1 ACL 语法

acl <aclname> <criterion> [flags] [operator] [<value>] …

aclname:指定 acl 的名称,在引用时区分大小写。可随意指定,且多个 acl 指令可以指定同一个 aclname,这表示 ” 或 ” 的逻辑关系。
flags:可选项,表示标识位。一般会用到的标识位只有 ”-i”,表示不区分大小写。
operator:可选项,某些操作符,有 ”eq”、”ge”、”gt”、”le”、”lt”,表示数学上的等于、大于、小于。
<criterion>:指定检查标准,即检查方法。见下文给出的常用 4 层标准和 7 层标准
value:根据 criterion 的不同,值的类型不同。

(1).4 层常用检查标准,官方手册:https://cbonte.github.io/haproxy-dconv/1.7/configuration.html#7.3.3

src <ip_addr>
src_port <PORT or PORT_ranges>
dst <ip_addr>
dst_port <PORT or PORT_ranges>

其中 src、src_port、dst 和 dst_port 就是检查标准 creiterion,其后的值就是 value。

例如:

acl accept_clients src 192.168.100.0/24
acl reject_clients src 172.16.0.0/16
tcp-request content accept if accept_clients
tcp-request content reject if reject_clients
tcp-request content reject  # 此项表明不匹配前两项的默认都拒绝

(2).7 层常用检查标准,官方手册:https://cbonte.github.io/haproxy-dconv/1.9/configuration.html#7.3.6

hdr(HEADER):检查首部字段的值是否为指定的值,如 hdr(Connection) -i close 表示首部字段 Connection 的值是否为不区分大小写的 close。hdr(Host) -i www.linuxidc.com 表示首部字段 Host 的值是否为 www.linuxidc.com,即请求的主机是否是指定的值。

  • hdr_reg(HEADER):检查首部字段是否匹配指定的模式。如 hdr_reg(Host) -i .*\.linuxidc\.com。
  • http_first_req:当正处理的请求是第一个请求时返回 true。
  • method:请求的方法为指定的方法时返回方法对应的数值,也就表示 true。例如 ”method GET”。
    • acl valid_method method GET
    • http-request deny if ! valid_method
  • path:匹配 uri 的 path 部分,一般用来匹配精确的文件资源。例如 path -i /a.png。
  • path_beg:匹配 path 的前缀部分。
  • path_end:匹配 path 的后缀部分。
  • path_reg:使用正则表达式来匹配 path。
  • url:对整个 url 进行匹配。
  • url_beg:对 url 的前缀进行匹配。

还有很多很多检查方法,更多的查询官方手册,太多了。一般 4 层的检查标准和 7 层对路径 path 和首部 hdr 的标准就够了。

多个条件使用 ”AND”、”OR”、”!” 操作符表示逻辑与、逻辑或和取反,不写时默认的操作符是 ”AND”。

1.5.2 ACL 实现动静分离示例

acl url_static path_beg /static /images /img /css /viedo /download  # 定义静态检查标准
acl url_static path_end .gif .png .jpg .css .js .bmp                # 定义静态检查标准
acl host_www  path /index.html                                    # 为主页专门定制 acl
acl url_dynamic path_end .php .php5                                # 定义动态检查标准
acl host_www    hdr_beg(Host) -i www.linuxidc.com                  # 定位到主页
use_backend static  if url_static
use_backend dynamic if url_dynamic
use_backend www if host_www

正文完
星哥说事-微信公众号
post-qrcode
 
星锅
版权声明:本站原创文章,由 星锅 2022-01-21发表,共计19806字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中