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

HAProxy配置示例和需要考虑的问题

186次阅读
没有评论

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

本文目录:
1. 配置 haproxy 需要考虑的事情
2. 配置 haproxy 提供反向代理功能

haproxy 是一个非常优秀的负载均衡工具,它的特性非常丰富,功能也非常非常强大,要想好好使用它,将它的功能和性能挖掘出来,多多阅读官方手册是必不可少的。

本文提供一个简单的配置示例,后面将分别开文章详细解释它的配置文件、cookie 会话保持、stick table 的功能、haproxy 主主模型的复制(replication)、抵御攻击等等。

1. 配置 haproxy 需要考虑的事情

尽管 haproxy 大多数配置选项都可以采用默认配置,但有些选项,特别是关于实际需求、连接数和超时时间相关的选项必须独立配置。

大致总结了下以下几点需要考虑的问题:

  1. haproxy 支持 5 种 http 事务模型。一般只会选择其中两种:
    • (1). 当后端为静态 web 或静态缓存服务器时,使用 http-keep-alive 模型,由于响应速度快,频繁建立 tcp 连接的代价比较大;
    • (2). 当后端为动态应用程序服务器或者静态但传输的资源对象体积较大时,使用 http-server-close 模型,因为响应速度相对较慢,占用空闲连接的资源比建立 tcp 连接的代价更大。
  2. haproxy 反向代理的调度算法优先级是低于 cookie 的,因此当一个连接已经保持了会话,调度算法对该连接就无效。只有新的连接请求或者长连接已经失效时,才会使用调度算法进行调度。在调度算法的选择上,如果不考虑服务器性能差距的话:
    • (1). 如果后端会话时间比较长(mysql),建议使用leastconn,因为调度过程中,后端释放连接时动荡不大,比较稳定。
    • (2). 如果后端是静态 web,建议使用 roundrobin 算法。
    • (3). 如果后端需要保持会话信息,但又不使用 cookie 时,可以使用源地址 hash 算法 source,保证将同一客户端引导到同一后端服务器上。如果使用 cookie,则可以使用roundrobinleastconn算法。源地址 hash 算法,一般只在没有办法的时候但又要调度到同一后端服务器时,才作为最后手段。
    • (4). 如果配置了 session 共享,则对于 haproxy 来说,动态资源的请求是 ” 无状态 ” 的,可以使用 roundrobin 算法或leastconn
    • (5). 如果后端是缓存服务器,为了保证命中率,建议使用 uri 算法,同时将 hash-type 设置为 consistent 方法(一致性 hash),保证后端缓存服务器 down 掉后对客户端的影响足够小。
  3. haproxy 是单进程、事件驱动模型的软件,单进程下工作效率已经非常好,不建议开启的多进程 / 多实例。
  4. maxconn指令控制最大并发连接数,可以在多处设置,设置位置不同,代表意义不同:
    • (1). 设置在 global 段或 frontend/listen/defaults 段的 maxconn 代表的是和客户端 (即 frontend) 的最大连接并发数;其中 global 段的值是硬限制,frontend/listen/defaults 段的 maxconn 值不能超过 global 段的值。
    • (2). 设置在 server 指令中时,代表的是 haproxy 和某台后端服务器维持的最大并发连接数。
    • (3). 前端的最大并发数 (即 global 段的maxconn) 可以根据内存来估算,haproxy 为每个连接维持两个缓存区,每个大致 16K 左右,加上一些额外数据,共约 33-34K 左右,因此理论上 1G 的空闲内存能维持 2W-2.5W 个纯 HTTP 的并发连接 (只是理论上),如果代理的是 https,则允许的最大并发数量要小的多。 前端 maxconn 默认值为 2000,非常有必要将其增加几倍。一般代理纯 http 服务时,如果后端能处理及时,这里设置 20000 以上都不会有什么问题。以上只是大致估算代理能力,实际设置时必须根据后端处理能力以及 haproxy 自身能力设置前端maxconn,否则将前端接进来后端也无法立即处理。
    • (4). 后端所有服务器的 maxconn 值之和应接近前端的 maxconn 值,计算两者差距时,还需要考虑后端的等待队列长度 maxqueue。其中和静态 web 服务器的maxconn 可以设置大一些。
  5. 开启 haproxy 和后端的 连接重用 功能。当某客户端的请求到来后,haproxy 和后端某服务器建立一个 TCP 连接,并将请求调度到该服务器上,该客户端后续的请求也会通过该 TCP 连接转发给后端 (假设没有采用关闭后端连接的 http 事务模型)。但在响应后和该客户端的下一个请求到来前,这个连接是空闲的。和后端建立的 TCP 连接只是为了调度转发,保证持有合适 cookie 的客户端请求能调度到同一后端,完全可以为其它客户端的请求调度也使用这个 TCP 连接,保证 TCP 连接资源不浪费。可以使用http-reuse strategy_name 指令设置连接重用的策略,而默认策略禁用连接重用。
    • (1).never:这是默认设置。表示禁用连接重用,因为老版本的 haproxy 认为来源不同的请求不应该共享同一个后端连接。
    • (2).safe:这是建议使用的策略。” 安全 ” 策略下,haproxy 为客户端的每个第一个请求都单独建立一个和后端的 TCP 连接,但是后续的请求则会重用和该后端的空闲 TCP 连接。这样的转发不仅提高了资源使用率,还保持了 keep-alive 的功能。因此,safe策略配合 http-keep-alive 事务模式比 http-server-close 事务模式更高效,无论后端是静态、缓存还是动态应用服务器。
    • (3).aggressive:一种激进的策略,该策略的 haproxy 会重用空闲 TCP 连接来转发大多数客户端的第一次请求。之所以是大多数而不是所有,是因为 haproxy 会挑选那些已经被重用过至少一次的连接 (即从建立开始转发过至少两次,不管源是否是同一客户端) 进行重用,因为 haproxy 认为只有这样的连接才具有重用能力。
    • (4).always:它将总是为第一个请求重用空闲连接。当后端是缓存服务器时,这种策略比 safe 策略的性能要高许多,因为这样的请求行为都是一样的,且可以共享同一连接来获取资源。不过不建议使用这种策略,因为大多数情况下,它和 aggressive 的性能是一样的,但是却带来了很多风险。

      因此,为了性能的提升,将它设置为 safeaggressive吧,同时再将 http 事务模型设置为http-keep-alive
  6. 对于 haproxy 是否开启 cookie 以及 stick table 相关功能的设置必须严加考虑,它直接影响调度算法的选择和负载均衡的性能。不过如果后端应用程序服务器共享了 session,haproxy 可以不用设置会话粘性相关的选项。
  7. haproxy 的默认配置文件中关于超时时间的设置应该修改,不少项设置都很不合理。
  8. 建议开启 haproxy 的 X-Forwarded-For 选项,使得后端服务器能够记录客户端的真实源 IP 地址。
  9. 建议开启 haproxy 的状态页面,并设置访问权限。

为了实现 Haproxy 完善的功能,上面几个问题是远远不够的,但可以在边使用 haproxy 过程中边增加功能使其不断完美。

2. 配置 haproxy 提供反向代理功能

假如要实现这样的环境:haproxy 反向代理 4 个 nginx 节点,nginx1 和 nginx2 结合 php 提供动态 web 服务,nginx3 和 nginx4 提供静态 web 服务。如下图:

HAProxy 配置示例和需要考虑的问题

由于默认配置文件中和超时时间相关的设置比较不合理,所以建议修改这些时间。另外还有些建议开启或关闭的的项也尽量开启或关闭。

默认配置如下:

global
    log        127.0.0.1 local2      # 需要设置 /etc/rsyslog.conf 加上 local2 设备的日志记录级别和日志路径
    chroot      /var/lib/haproxy
    pidfile    /var/run/haproxy.pid
    maxconn    4000                  # 这是前段对外的最大连接数。代理 http 时,1G 空闲内存承载 20000 以上没大问题
    user        haproxy
    group      haproxy
    daemon
    stats socket /var/lib/haproxy/stats  # 开启动态查看、管理 haproxy 的状态文件
                                        # 另外建议设置 spread-checks 全局项,且百分比建议为 2 - 5 之间
defaults
    mode                    http        # 7 层 http 代理,另有 4 层 tcp 代理
    log                    global
    option                  httplog      # 在日志中记录 http 请求、session 信息等
    option                  dontlognull  # 不要在日志中记录空连接
    option http-server-close            # 后端为动态应用程序建议使用 http-server-close,后端为静态建议使用 http-keep-alive
    option forwardfor      except 127.0.0.0/8  # haproxy 将在发往后端的请求中加上 ”X-Forwarded-For” 首部字段
    option                  redispatch  # 当某后端 down 掉使得 haproxy 无法转发携带 cookie 的请求到该后端时,将其转发到别的后端上
    timeout http-request    10s    # 此为等待客户端发送完整请求的最大时长,应该设置较短些防止洪水攻击,如设置为 2 - 3 秒
                                    # haproxy 总是要求一次请求或响应全部发送完成后才会处理、转发,
    timeout queue          1m      # 请求在队列中的最大时长,1 分钟太长了。设置为 10 秒都有点长,10 秒请求不到资源客户端会失去耐心
    timeout connect        10s    # haproxy 和服务端建立连接的最大时长,设置为 1 秒就足够了。局域网内建立连接一般都是瞬间的
    timeout client          1m      # 和客户端保持空闲连接的超时时长,在高并发下可稍微短一点,可设置为 10 秒以尽快释放连接
    timeout server          1m      # 和服务端保持空闲连接的超时时长,局域网内建立连接很快,所以尽量设置短一些,特别是并发时,如设置为 1 - 3 秒
    timeout http-keep-alive 10s    # 和客户端保持长连接的最大时长。优先级高于 timeout http-request 高于 timeout client
    timeout check          10s    # 和后端服务器成功建立连接后到最终完成检查的时长(不包括建立连接的时间,只是读取到检查结果的时长),
                                    # 可设置短一点,如 1 - 2 秒
    maxconn                3000    # 默认和前段的最大连接数,但不能超过 global 中的 maxconn 硬限制数

所以修改后建议配置为如下:

global
    log        127.0.0.1 local2
    chroot      /var/lib/haproxy
    pidfile    /var/run/haproxy.pid
    maxconn    20000
    user        haproxy
    group      haproxy
    daemon
    stats socket /var/lib/haproxy/stats
    spread-checks 2
defaults
    mode                    http
    log                    global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor      except 127.0.0.0/8
    option                  redispatch
    timeout http-request    2s
    timeout queue          3s
    timeout connect        1s
    timeout client          10s
    timeout server          2s
    timeout http-keep-alive 10s
    timeout check          2s
    maxconn                18000

frontend http-in
    bind            *:80
    mode            http
    log              global
    capture request  header Host len 20
    capture request  header Referer len 60
    acl url_static  path_beg  -i /static /images /stylesheets
    acl url_static  path_end  -i .jpg .jpeg .gif .png .ico .bmp .css .js
    acl url_static  path_end  -i .html .htm .shtml .shtm .pdf .mp3 .mp4 .rm .rmvb .txt
    acl url_static  path_end  -i .zip .rar .gz .tgz .bz2 .tgz

    use_backend      static_group  if url_static
    default_backend  dynamic_group

backend static_group
    balance            roundrobin
    option            http-keep-alive
    http-reuse        safe
    option httpchk    GET /index.html
    http-check expect  status 200
    server staticsrv1  192.168.100.62:80 check rise 1 maxconn 5000
    server staticsrv2  192.168.100.63:80 check rise 1 maxconn 5000

backend dynamic_group
    cookie appsrv insert nocache
    balance roundrobin
    option http-server-close
    option httpchk    GET /index.php
    http-check expect  status 200
    server appsrv1 192.168.100.60:80  check rise 1 maxconn 3000 cookie appsrv1
    server appsrv2 192.168.100.61:80  check rise 1 maxconn 3000 cookie appsrv2

listen report_stats
        bind *:8081
        stats enable
        stats hide-version
        stats uri    /hastats
        stats realm  “pls enter your name”
        stats auth  admin:admin
        stats admin  if TRUE

上面的配置中:

  • (1). 静态请求将分配给 static_group 并进行 roundrobin 调度,同时通过获取 index.html 来做健康状况检查,此外还设置了 haproxy 和后端连接重用的功能。
  • (2). 动态请求将分配给 dynamic_group 并进行 roundrobin 调度,但是向响应报文中插入了一个 cookie,保证被调度过的服务端和客户端能保持会话。此外还设置了通过获取 index.php 来做健康状况检查。

最后配置 nginx 和 php+php-fpm。

yum -y install nginx php php-fpm

为了区分,分别为 nginx1/nginx2 的 index.php、nginx3/nginx4 的 index.html 文件中加入响应的主机来源提示,并在 php 文件中设置 cookie 项。其中 index.php 的内容参考如下:

<h1>response from webapp 192.168.100.60</h1>
<?php
    session_start();
    echo “Server IP: “.”<font color=red>”.$_SERVER[‘SERVER_ADDR’].”</font>”.”<br>”;
    echo “Server Name: “.”<font color=red>”.$_SERVER[‘SERVER_NAME’].”</font>”.”<br>”;
    echo “SESSIONNAME: “.”<font color=red>”.session_name().”</font>”.”<br>”;
    echo “SESSIONID: “.”<font color=red>”.session_id().”</font>”.”<br>”;
?>

测试。其中 php 页面返回内容大致如此:

HAProxy 配置示例和需要考虑的问题

构建高可用集群 Keepalived+Haproxy 负载均衡  https://www.linuxidc.com/Linux/2016-12/138917.htm
HAproxy 的基本配置(负载均衡 + 日志独立 + 动静分离 + 读写分离)https://www.linuxidc.com/Linux/2017-03/141614.htm
CentOS 7 下 Keepalived + HAProxy 搭建配置详解  https://www.linuxidc.com/Linux/2017-03/141593.htm
HAproxy 实现反向代理和负载均衡  https://www.linuxidc.com/Linux/2016-12/138749.htm
HAProxy+Keepalived 实现高可用负载均衡 https://www.linuxidc.com/Linux/2016-06/132225.htm
使用 HAProxy 配置 HTTP 负载均衡器 https://www.linuxidc.com/Linux/2015-01/112487.htm
Ubuntu 16.04 下安装 HAProxy 1.5.11 做 tcp 负载均衡 https://www.linuxidc.com/Linux/2016-06/132689.htm
CentOS 7.2 部署 Haproxy 1.7.2  https://www.linuxidc.com/Linux/2017-10/147553.htm

HAproxy 的详细介绍:请点这里
HAproxy 的下载地址:请点这里

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