haproxy配置文件与常用指令

haproxy配置文件与常用指令

配置要点

配置时要考虑的问题

  1. haproxy选择哪种http事务模型
    1. 静态web的适合长连接
    2. 动态app的适合短连接
  2. haproxy的对外最大连接数设置
    1. 综合考虑,各个后端节点并发之和,以及各个节点的可排队队列数
  3. haproxy的各类超时时间设置
    1. 连接超时
    2. 请求超时
    3. 传输超时
    4. 超时重试
  4. haproxy连接重用的选择
    1. 是否为了提供效率,对连接进行重用,牺牲部分安全性;
  5. haproxy调度算法的选择
  6. 是否开启多进程,多实例
    1. haproxy一般单实例即可;
  7. 是否设置cookie和stick table
    1. 调度的粘性上,选择设置cookie,或stick table
  8. haproxy的状态页,建议开启,设置合理权限
  9. 客户端ip透传,建议开启,X-Forwarded-For

1、事务模型

​ 后端是静态web时,响应速度一般较快,建立连接的时间占比大,频繁建立释放连接浪费资源,因此采用keep-alive模型

​ 后端是动态应用服务器时,响应速度一般较慢,建立连接时间占比不大,反而空闲连接浪费资源,因此采用server-close模型

2、并发设置

​ haproxy的对外提供的最大并发连接数,应该小于等于后端所有节点的并发连接之和,

​ 在考虑了每个后端节点都设置了等待队列的情况下,haproxy对外总的最大并发也要考虑到每个节点的等待队列大小

3、超时时间

​ haproxy连接两端,对外的客户端,对内的服务端,两端都有不同的超时时间,如:和后端建立连接的超时时间、健康探测时超时时间,客户端长连接超时时间等,都需要根据实际情况合理设置

4、连接重用

​ 和后端节点的空闲tcp连接,是否设置重用,需要平衡安全性,效率,综合考虑进行设置

5、调度算法的选择

​ 根据后端节点的角色,处理能力等进行设置,静态web一般使用加权轮询,动态应用服务及mysql等长连接的应用一般用最小连接,

调度算法优先级低于cookie,在设置了cookie请求下,相关请求会根据cookie进行调度,只有新的不相关请求进来,或长连接失效时,会利用调度算法重新选择调度

6、是否多进程

​ haproxy单进程,事件驱动,一般不需要开启多进程

7、cookie和stick table

​ 都是为了解决会话绑定问题,将同一客户端的相关连的请求调度到同一个后端节点上,以便每次请求都能找到会话信息;当后端节点利用共享会话服务器的情况下,haproxy也就无须设置此2项

配置文件详解

配置文件结构

  • global:设置haproxy进程相关属性;
  • default:设置可以被fronted,backend,listend继承的配置,
  • listen:等效于一组fronted+backend配置
  • fronted:对外开放端口,并发数等
  • backend:后端节点信息,健康检测,调度算法,cookie 设置等

global配置段示例

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

默认配置文件

[root@host2 ~]# vim /etc/haproxy/haproxy.cfg 
# 全局配置段,配置进程属性相关信息
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
    # to have these messages end up in /var/log/haproxy.log you will
    # need to:
    #
    # 1) configure syslog to accept network log events.  This is done
    #    by adding the '-r' option to the SYSLOGD_OPTIONS in
    #    /etc/sysconfig/syslog
    #
    # 2) configure local2 events to go to the /var/log/haproxy.log
    #   file. A line like the following can be added to
    #   /etc/sysconfig/syslog
    #
    #    local2.*                       /var/log/haproxy.log
    #
    log         127.0.0.1 local2
    # 日志记录到本机local2设置,需要在/etc/rsyslog.conf中配置local2对应的文件路径,如/var/log/haproxy

    chroot      /var/lib/haproxy
    # 限制haproxy的活动目录
    pidfile     /var/run/haproxy.pid
    # pid文件路径
    maxconn     4000
    # 前端对外的最大并发,默认4000较小
    user        haproxy
    group       haproxy
    daemon
    # 进行以daemon方式运行,用户和组为haproxy

    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats
    # 开启管理socket

# 默认配置段,会被listen和backend段继承的配置;

#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000
# 模式默认http代理
# 日志采用全局日志;
# 不记录空日志
# http事务模型是server-close
# 透传客户端ip,除了本机地址;
# cookie模式下,应被调度到的某节点down掉,重新选择节点调度;
# 重试次数3
# 各类超时时间;
# 最大并发连接数;

# 定义个前端;分别将动静请求转发给2个后端服务器组;
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend  main
        bind  *:5000
    acl url_static       path_beg       -i /static /images /javascript /stylesheets
    acl url_static       path_end       -i .jpg .gif .png .css .js

    use_backend static          if url_static
    default_backend             app


# 定义了2个后端服务器组,和调度算法,启用健康检测;
#---------------------------------------------------------------------
# static backend for serving up images, stylesheets and such
#---------------------------------------------------------------------
backend static
    balance     roundrobin
    server      static 127.0.0.1:4331 check

#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend app
    balance     roundrobin
    server  app1 127.0.0.1:5001 check
    server  app2 127.0.0.1:5002 check
    server  app3 127.0.0.1:5003 check
    server  app4 127.0.0.1:5004 check

示例配置

1、配置haproxy,注意:haproxy配置文件,中文注释会报错!

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
# 增大了并发数到20000
# spread-checks 后端节点多时,精确的每过几秒集中检测一下,会压力较大,因此采用在精确时间点的前后2%的时间端内进行检测;官网建议2%-5%

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
# 对外开放一个80的http服务,
# 截取请求报文的host和referer头部字段
# 定义4个同名的acl,匹配静态资源的请求,之间是或关系;满足一个即可
# 根据acl定义,被匹配到是静态资源的转发给静态服务器组,其余的交给动态服务器组;

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
# 定义静态服务器组;采用长连接,连接重用用safe级别,检测页面是/index.html,依靠200状态码判断是否健康
定义了2个后端节点,每个节点最大连接5000,连续探测1次正常就可以重新标记为正常;

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
# 定义后端组,设置cookie,cookie的变量名是appsrv,insert是在原有响应报文头部插入模式,此外还有prefix追加在头部,rewrite覆盖改写等2种模式;
# 调度算法轮询, http事务模式是server-close,探测页面/index.php,判断依据是200的状态码,
# 定义2个后端节点,每个节点最大并发3000,每个节点的标识符即cookie对应的值分别是appsrv1 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
# listen是等效fronted和backend结合的写法
# 启用状态页,隐藏版本号,定义uri和提示符,用户名和密码,端口在8081

2、准备2个后端节点

yum install -y httpd php php-fpm
systemctl start httpd;systemctl enable httpd
systemctl start php-fpm
# 安装httpd,php,php-fpm


vim /var/www/html/index.php
[root@host4 ~]# cat /var/www/html/index.php 
<h1>response from webapp 192.168.80.103</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>";
?>

[root@host3 ~]# cat /var/www/html/index.php 
<h1>response from webapp 192.168.80.102</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文件,2个节点会生成不同的session值

3、直接访问后端节点时,检查cookie

image-20200916153651900

4、重启haproxy配置生效,通过haproxy访问时

​ 可以看到多出一个appsrv字段,值是被调度到的appsrv1,第一个节点的标识符,通过这个cookie字段,客户端的后续请求,携带此cookie,haproxy就可以根据它一直将其调度到第一个节点;

​ cookie与session简单理解:当客户端第一次请求服务时,服务端会为其生成一个sessionid,sessionid的值各不相同,这个sessionid关联了这个客户端的各种信息,如登陆状态,用户权限等,sessionid和其值保存在服务端,多个客户端的session共同存储在服务端端,相当于服务端的一个用户信息检索数据表;假设某客户端生成的sessionid值是xxx,那么服务器发回客户端时,就会发送一个键值对,sessionid=xxx,作为客户端的cookie;客户端收到后会存储在本地,再次请求时都会携带该cookie,服务端收到请求后根据sessionid=xxx就可以检索到其对应的状态信息,不同用户的sessionid不同,从而达到了区分客户端,并能记录每个客户端不同状态信息的效果;cookie就是一堆k-v类型的键值对,sessionid只是其中一种;

image-20200916154138022

配置文件指令

https://cbonte.github.io/haproxy-dconv/1.7/configuration.html#4.1

官网文档上:各个指令的语法和配置示例,

balance

​ 共9种调度算法:

  • roundrobin 加权轮询,可动态修改权重
  • static-rr 静态加权轮询,运行时不可修改权重
  • leastconn
  • source 源地址hash
  • uri 适用缓存服务器
  • url_param 基于用户id进行hash,然后调度
  • hdr(name) 基于指定的请求头部调度,一般采用hdr(host)基于主机头调度
  • rdp-cookie
  • rdp-cookie(name)

hash-type

  • consistent:一致性hash
  • map-based

bind

​ fronted段,绑定到哪个端口;

mode

  • tcp
  • http

log

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

capture request/response header

常用的捕获头部字段示例:

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

maxconn

use_backend

default_backend

其他

  1. server
  2. default-server
  3. option httpchk
  4. stats
  5. option forwardfor
  6. errorfile 错误页面相关
  7. cookie 和option redispatch
  8. reqadd和 rspadd
  9. 超时时间相关
  10. http过滤,http-request:https://cbonte.github.io/haproxy-dconv/1.7/configuration.html#4-http-request
  11. tcp过滤 tcp-request tcp-response

acl

https://cbonte.github.io/haproxy-dconv/1.7/configuration.html#7

acl常用于,匹配区分uri,如区分动态和静态请求,然后用use_backend指令,转发给不同的后端组;

acl语法:

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

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

四层常用检查项

src <ip>
src_port <port or port_ranges>
dst <ip>
dst_port <port or port_ranges>

七层常用检查项

hdr(Host) www.b.com
hdr_reg(host) *\.b\.com
path_beg
path_end
path_reg
url_beg
url

acl实现动静分离示例

acl acl_static path_beg /static /image
acl acl_static path_end .gif .png
acl acl_dynamic path_end .php .jsp
acl acl_b hdr(host) -i www.b.com

use_backend static_group if acl_static
use_backend dynamic_group if acl_dynamic
use_backend b_group if acl_b

定义了三种acl,动态请求、静态请求、请求主机头是www.b.com的,分别将其转发到3个主机组,
之后,定义三个主机组即可
updatedupdated2020-10-222020-10-22
加载评论