3-5-3-haproxy-gpc0计数器说明

熊 0 阅读 Linux集群服务

如何理解和使用HAProxy的gpc0计数

global
    log 127.0.0.1   local0
    log 127.0.0.1   local1 notice
    stats socket /var/run/haproxy.stat mode 600 level operator
    maxconn 4096
    user haproxy
    group haproxy
    daemon
​
defaults
    log global
    mode http
    option httplog
    option dontlognull
    retries 3
    option redispatch
    maxconn 2000
    contimeout 5000
    clitimeout 50000
    srvtimeout 50000
 
frontend http
    bind *:2550
    stick-table type ip size 200k expire 10m store gpc0
    # check the source before tracking counters, that will allow it to
    # expire the entry even if there is still activity.
    acl whitelist src 192.168.1.154
    acl source_is_abuser src_get_gpc0(http) gt 0
    use_backend ease-up-y0 if source_is_abuser
    tcp-request connection track-sc1 src if !source_is_abuser
​
    acl is_test1 hdr_sub(host) -i test1.com
    acl is_test2 hdr_sub(host) -i test2.com
    
    use_backend test1 if is_test1
    use_backend test2 if is_test2
​
backend test1
    stick-table type ip size 200k expire 30s store conn_rate(100s),bytes_out_rate(60s)
    acl whitelist src 192.168.1.154
    # values below are specific to the backend
    tcp-request content track-sc2 src
    acl conn_rate_abuse sc2_conn_rate gt 3
    acl data_rate_abuse sc2_bytes_out_rate  gt 20000000
     
    # abuse is marked in the frontend so that it's shared between all sites
    acl mark_as_abuser sc1_inc_gpc0 gt 0
    tcp-request content reject if conn_rate_abuse !whitelist mark_as_abuser
    tcp-request content reject if data_rate_abuse mark_as_abuser
    server local_apache localhost:80
 
backend test2
    stick-table type ip size 200k expire 1m store conn_rate(100s),bytes_out_rate(60s)
    acl whitelist src 192.168.1.154
    # values below are specific to the backend
    tcp-request content track-sc2 src
    acl conn_rate_abuse sc2_conn_rate gt 5
    acl data_rate_abuse sc2_bytes_out_rate gt 20000000
 
    # abuse is marked in the frontend so that it's shared between all sites
    acl mark_as_abuser sc1_inc_gpc0 gt 0
    tcp-request content reject if conn_rate_abuse !whitelist mark_as_abuser
    tcp-request content reject if data_rate_abuse mark_as_abuser
    server local_apache localhost:80
​
backend ease-up-y0
    mode http
    errorfile 503 /etc/haproxy/errors/503rate.http
​

整个配置实现如下目的: 1.根据主机头判断是test1.com还是test2.com , 然后发到对应的backend服务器 2.来自192.168.1.154的访问不受访问速率限制 3.如果100秒之内平均连接速率或者发送的字节数速率超过限制 , 则使用ease-up-y0这个backend处理 , 将持续返回503错误给用户。

下边来解说一下我们关注的限速部分的配置,我将按照逻辑的顺序说明,而不是配置文件中的位置。

  1. 针对backend test1 , 我们定义一个stick-table , key类型是ip地址 , 表项最多200K个 , 表项自动过期时间3分钟 ,存储2个数据 : 100秒内本IP新建connection的速率 , 60秒内本IP向外发送数据大小的比率

    stick-table type ip size 200k expire 3m store conn_rate(100s),bytes_out_rate(60s)

    stick-table中每个IP表项有50bytes大小 , 加上connection rate和bytes out rate各12bytes。所以每个表项占用74bytes内存 , 74*200*1024/1024*1024 ~= 14.11MBytes。所以整个stick-table占用14Mbytes内存。

  2. 将请求的源ip地址作为key , 存入当前stick-table的sc2计数器内(官方的建议是sc0用于frontend , sc1 用于backend)。

    tcp-request content track-sc2 src

    如果100秒内新建连接速率大于3 , 则标记acl conn_rate_abuse 如果60秒内发送数据的数量大于20000000 bytes , 则标记acl data_rate_abuse

    acl conn_rate_abuse sc2_conn_rate gt 3
    acl data_rate_abuse sc2_bytes_out_rate gt 20000000
  3. 接下来这段真正执行这些规则。

    acl mark_as_abuser sc1_inc_gpc0 gt 0
    tcp-request content reject if conn_rate_abuse !whitelist mark_as_abuser
    tcp-request content reject if data_rate_abuse mark_as_abuser

    这段配置比较晦涩难懂,但并不复杂。gpc0是一个通用计数器 , sc1_inc_gpc0是gpc0计数器增量(我们在frontend配置中使用)

     tcp-request content reject if conn_rate_abuse !whitelist mark_as_abuser

    这一行说明 , 无论用户违反了连接速率或者发送byte速率的限制 , 而且用户不在白名单中 , 则frontend中的gpc0计数器的值会增加。sc1_inc_gpc0永远返回真值 ,根据短路求值的原则,如果conn_rate_abuse或data_rate_abuse不为真值 , 则mark_as_abuser规则不会被触发执行。

  4. 上边的gpc0计数器 , 会在frontend中被处理

    stick-table type ip size 200k expire 10m store gpc0
    # check the source before tracking counters, that will allow it to
    # expire the entry even if there is still activity.
    acl whitelist src 192.168.1.154
    acl source_is_abuser src_get_gpc0(http) gt 0
    use_backend ease-up-y0 if source_is_abuser
    tcp-request connection track-sc1 src if !source_is_abuser

    在frontend我们声明了一个stick-table , 用于存储per source ip的通用计数器。如果这个计数器的值被backend增加了(大于0)则使用ease-up-y0这个backend服务器 , 用户会被返回一个503错误页面。 一旦用户触发了规则,则这个source ip将不会再被跟踪 , 也就是说这个source ip会一直被返回503错误。直到这个source ip表项过期 , 本例中是10分钟(expire 10m)。