• HAPROXY简介


    HAProxy 是一款高性能TCP/HTTP 反向代理负载均衡服务器,具有如下功能:

    • 根据静态分配的cookies完成HTTP请求转发

    • 在多个服务器间实现负载均衡,并且根据HTTP cookies 实现会话粘性

    • 主备服务器切换

    • 接受访问特定端口实现服务监控

    • 实现平滑关闭服务,不中断已建立连接的请求响应,拒绝新的请求

    • 在请求或响应HTTP报文中添加,修改,或删除首部信息

    • 根据正则规则阻断请求

    • 提供带有用户认证机制的服务状态报告页面

    HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持或七层处理。HAProxy运行在时下的硬件上,完全可以支持数以万计的 并发连接。并且它的运行模式使得它可以很简单安全的整合进您当前的架构中, 同时可以保护你的web服务器不被暴露到网络上。

    HAProxy 实现了一种事件驱动、单一进程模型,此模型支持非常大的并发连接数。多进程或多线程模型受内存限制 、系统调度器限制以及无处不在的锁限制,很少能处理数千并发连接。事件驱动模型因为在有更好的资源和时间管理的用户端(User-Space) 实现所有这些任务,所以没有这些问题。此模型的弊端是,在多核系统上,这些程序通常扩展性较差。这就是为什么他们必须进行优化以 使每个CPU时间片(Cycle)做更多的工作。

    HAProxy实际工作中,它占用用户空间时间要比内核运行时间少20倍,所以对系统参数调优是十分必要的一项工作。

    另外衡量一个负载均衡服务器主要考量三个指标

    1. session rate

      此项指标非常重要,它决定了一个load balancer 能不能分发所有接受的请求。这项指标通常是由CPU性能决定。测量指标的大小跟传输的每个对象的大小有关,通常用空对象来测试,Session rates 在 100,000 sessions/s 左右,使用 Xeon E5 在 2014测试。
    2. session concurrency

      该指标与前一指标相关联。这一指标与服务器内存和系统可以处理的文件描述符数量有关。 通常每个session占用34KB,即大概3W个session占用1GB内存空间,实际上,socket buffer也会占用内存空间,2W个session socket占用1GB内存。
    3. data forwarding rate

      这一指标与 session rate 相对立,它的衡量单位通常是 Megabytes/s (MB/s), 或者 Gigabits/s (Gbps)。传输较大的对象有利于该指标的提升,因为较大的对象传输可以减少session建立和关闭浪费的时间。而测量session rate 则在传输小对象时有利于指标提升。haproxy 在2014年使用 Xeon E5 测试成绩为40 Gbps。
      

    2、HAProxy程序环境

    本文环境:CentOS7.2 haproxy 1.5 通过yum 安装

    程序环境:
        配置文件:/etc/haproxy/haproxy.cfg
            Unit File: haproxy.service
            主程序:/usr/sbin/haproxy
            
    配置文件:
        global:全局配置段
            进程及安全配置相关的参数
            性能调整相关的参数
            Debug相关的参数
        proxies:代理配置段
            defaults:为frontend, backend以及listen提供默认配置;
            frontend:前端,相当于Nginx中的server{ ... };
            backend:后端,相当于nginx中的upstream { ...  };
            listen:前后端的直接组合;
        **关于前端与后端的关系:一个前端可以指向多个后端;同时一个后端可以被多个调用。

    3、HAProxy配置详解

    3.1 global配置段

    3.1.1 进程相关配置

    • 定义日志系统相关属性

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

    harpoxy 将日志发送到指定的rsyslog服务器,在本地记录也要开启rsyslog服务;
    全局端最多可配置两个log 服务器;
    < address> :日志服务器地址
    [ len ] 指定记录的日志最大长度

    • 定义运行用户,所属组

    1. username

    group groupname

    • 运行方式

    1. 意味着后台守护进程

    3.1.2 参数调优

        maxconn <number>:设定单haproxy进程的最大并发连接数;
        maxconnrate <number>:设定单haproxy进程每秒接受的连接数;
        maxsslconn <number>:设定单haproxy进程的ssl连接最大并发连接数;
        maxsslrate <number>:单haproxy进程的ssl连接的创建速率上限;
        spread-checks <0..50, in percent>:避免对于后端检测同时并发造成
        的问题,设置错开时间比,范围0到50,一般设置2-5较好。
    

    3.1.3 用户列表

    用于对haproxy 状态监控页面的用户认证。至少要定义一个用户列表并且添加一个用户
    密码可以加密或明文。

    Example:

    userlist L1
      group G1 users tiger,scott
      group G2 users xdb,scott
    
      user tiger password $6$k6y3o.eP$JlKqe4(...)xHSwRv6J.C0/D7cV91
      user scott insecure-password elgato
      user xdb insecure-password hello
    
    userlist L2
      group G1
      group G2
    
      user tiger password $6$k6y3o.eP$JlKBx(...)xHSwRv6J.C0/D7cV91 groups G1
      user scott insecure-password elgato groups G1,G2
      user xdb insecure-password hello groups G2

    3.2 proxy配置段

    这部分配置在下列定义区域下使用

            - defaults  < name >
            - frontend < name >
            - backend  < name >
            - listen   < name >

    “defaults” 区域定义了frontend,backend,listen 的默认参数
    “frontend“ 区域描述了接收客户端请求的监听配置
    ”backend“ 区域描述接受请求处理的后端服务器配置
    ”listen“ 区域描述一组前端和后端直接一对一绑定的组配置

    HAProxy 配置的关键字与区域限制特性,即有些关键字在某个区域不可以使用
    下面开始讲解关键字的用法

    3.2.1 常用配置指令

    1. bind [<address>]:<port_range> [, ...] [param*]

    仅在frontend和listen区域使用。定义服务监听端口地址等参数
    [ param* ] 参数根据系统而定,一般不需要指定
    example:

    bind :80     #监听本机所有IP的80端口
    bind *:80    #监听本机所有IP的80端口
    bind 192.168.12.1:8080,10.1.0.12:8090

    2. mode {tcp|http|health}

    tcp:基于layer4实现代理,可代理大多数基于tcp的应用层协议,例如ssh/mysql/pgsql等;
    http:客户端的http请求会被深度解析;
    health:工作为健康状态检查响应模式,当请求到达时仅回应“OK”即断开连接;


    3. balance <algorithm> [ <arguments> ]
       balance url_param <param> [check_post]

    在backend区域定义调度算法
    < algorithm > 如下:

    • roundrobin

      带有权重的轮询调度算法;
      server后面使用weight来定义权重;
      动态算法:支持权重的运行时调整,支持慢启动(缓慢接收大量请求在刚启动时);仅支持最大4095个后端活动主机
    • static-rr
      静态的roundrobin算法;

    不支持权重的运行时调整及慢启动;但后端主机数量无限制;

    • leastconn
      带权重的最少连接分配动态算法;

    适用长连接应用协议,如ssh等

    • first
      第一优先算法;

    如果第一个服务端可接受请求则总是把连接分配给它,直到第一个服务端处于繁忙,分配给下一个,顺序按服务端的数字ID从小到大排列

    • source
      源IP hash 算法;

    该算法保证在后端服务器组没有减少或增加的情况下,能将来自同一客户端IP的请求分配至同一个服务端;
    该算法适合在无法使用cookie插入的TCP模式下使用
    动态算法或静态算法取决于hash-type;

    • uri
      uri hash 算法;
      该算法hash uri 的查询标记的左侧部分,或者指定whole 参数时hash全部uri;
      该算法保证访问同一uri的请求分配至同一服务端,适用于后端为缓存服务器的情况,以提高缓存命中率;
      动态算法或静态算法取决于hash-type;
      另外:该算法支持追加参数[ < arguments > ]:
      (1) whole :hash完整uri 
      (2) len number:hash指定uri的长度
      (3) depth nubmer:hash指定目录深度,每个"/"代表一个深度

    • uri_param

    1. param hash 算法;

    对用户请求的url中的< param >部分中的指定的参数的值(uri中"="部分)作hash计算;
    该算法适用于有用户识别参数的uri ,它保证同一user id 的请求分配至同一服务端;
    若果check_post 标识启用,则在uri中没有找到"?"参数时,对HTTP Post 请求实体查找参数声明;
    动态算法或静态算法取决于hash-type;
    Example:

    balance url_param userid
    balance url_param session_id check_post 64
    • hdr(< name >)
      HTTP 首部字段hash算法;

    指定的http首部将会被取出做hash计算。如果没有值,则降至轮询调度;
    动态算法或静态算法取决于hash-type;


    4. hash_type < method >

    在balance 指令中选定与hash 有关的算法,都会受此影响。
    默认采取的方法为map-based
    < method > 如下:

    • map-based:取模法,hash数据结构是静态数组;
      该hash是静态的,不支持在线调整权重,不支持慢启动;

    该算法调度平滑,后端服务器能够均匀承受负载;
    缺点也是明显的:当服务器的总权重发生变化时,即有服务器上线或下线,都会导致调度结果整体改变。如果想避免此种情况应采用consistent 方法;

    • consistent:一致性哈希,哈希的数据结构是“树”;
      该hash是动态的,支持在线调整权重,支持慢启动

    每一个server 会在"树"中出现多次, 在树中查找hash key,并选择最近的server;
    该方法的优点在于,当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动。所以十分适合缓存服务器
    缺点:该算法不够平滑,很容易导致后端服务器负载不均衡。所以很有必要对服务器的权重以或者服务器ID进行调整;
    为保持均匀负载,应该保证所有服务器ID保持一致


    5. server <name> <address>[:[port]] [param*]
       default-server [param*]

    server用于在backend和listen中定义一个主机;
    default-server 用于设定server的默认参数;

    [param*] 如下:

    • weight < weight >:当前server的权重;

    • id < number > :设定server ID

    • cookie < value >:为当前server指定其cookie值,此值会在收到请求报文时进行检测,其功能在于实现基于cookie会话保持;

    • check:对当前server进行健康状态检测;
      inter < delay >:时间间隔;
      rise < count >:判定为“健康”状态需要检测的次数,默认2;
      fall < count >:判定为“不健康”状态需要检测的次数,默认3;
      addr <ipv4|ipv6>:健康状态检测时使用的地址;
      port < port >:健康状态检测时使用的端口;

      注意:默认为传输层检测,即探测端口是否能响应;需要执行应用层检测,则需要httpchk, smtpchk, mysql-check, pgsql-check, ssl-hello-chk;

    • maxconn <maxconn>:当前server的最大并发连接数;

    • maxqueue <maxqueue>:当前server的等待队列的最大长度;

    • disabled:将主机标记为不可用;

    • redir <prefix>:将发往当前server的所有请求GET和HEAD类的请求均重定向至指定的URL;

    Examples :
    server first  10.1.1.1:1080 id 3 cookie first  check inter 1000 maxconn 10000 maxqueue 2000
    server second 10.1.1.2:1080 id 4 cookie second check inter 1000

    6. option httpchk
       option httpchk <uri>
       option httpchk <method> <uri>
       option httpchk <method> <uri> <version>    

    基于http协议作7层健康状态检测机制,默认是基于tcp层进行检测;
    TCP 模式也可以使用该检测机制
    < method > < uri > < version >:请求报文的超始行;
    method 默认方法为 OPTIONS;返回状态码2XX,3XX意味成功;

    Examples :
    # Relay HTTPS traffic to Apache instance and check service availability
    # using HTTP request "OPTIONS * HTTP/1.1" on port 80.
    backend https_relay
        mode tcp
        option httpchk OPTIONS /index.html HTTP/1.1
    Host: www
        server apache1 192.168.1.1:443 check port 80

    7. http-check expect [!] <match> <pattern>

    定义检测有效期望值;
    ! 表示认定的错误值;< match > 可取值为:

    • status < string >

    • rstatus < regex > 正则方式

    • string < string >

    • rstring < regex >

    Examples :
    # only accept status 200 as valid
    http-check expect status 200
    
    # consider SQL errors as errors
    http-check expect ! string SQL Error
    
    # consider status 5xx only as errors
    http-check expect ! rstatus ^5
    
    # check that we have a correct hexadecimal tag before /html
    http-check expect rstring <!--tag:[0-9a-f]*</html>

    8. cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ] [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain <domain> ]* [ maxidle <idle> ] [ maxlife <life> ]

    启用基于cookie的会话黏性,要结合server指定的cookie参数一起实现;
    常用形式:cookie WEBSRV insert nocache indirect

    Example:
    backend websrvs
    balance     roundrobin
    cookie WEBSRV insert nocache indirect
    server      web1 10.1.0.68:80 check weight 2 maxconn 5000 cookie web1
    server      web2 10.1.0.69:80 check weight 1 maxconn 3000 cookie web2

    9. default_backend <backend>

    当use_backend 的使用规则没有被匹配时,由default_backend 指定默认服务器组;
    关于use_backend 使用后续会在acl 章节中讲解;


    3.2.2 log 相关

    为frontend或backend定义日志记录机制;

    log global  :使用全局定义的日志记录方式
    log <address> [len <length>] <facility> [<level> [<minlevel>]]:自定义
    no log :不记录
    capture request header <name> len <length>
    -->记录请求报文中的指定的首部的值于日志中;len用于指定要记录的信息的长度;
    capture response header <name> len <length>
    -->记录响应报文中的指定的首部的值于日志中;len用于指定要记录的信息的长度;
    示例:
        capture request header Referer len 30

    3.2.3 自定义错误页面

    - errorfile <code> <file>

    < code > 指定HTTP返回的状态码。200, 400, 403, 408, 500, 502, 503, and 504 可使用;
    < file > 指定一个文件代替HTTP响应; 
    Example:errorfile 503 /etc/haproxy/errorfiles/503sorry.http

    - errorloc <code> <url>
    - errorloc302 <code> <url>

    发生错误时由haproxy重定向至指定url,以上两个命令等同,响应状态码为302
    Example:errorloc 503 http://www.mydomain.com/index...

    - errorloc303 <code> <url>

    响应状态码为303,表示以GET方法重新请求页面


    3.2.4 修改请求或响应报文首部

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

    HAProxy把请求报文发往后端主机之前在请求报文添加“X-Forwared-For”首部
    目的为使后端服务器可记录发出请求客户端的IP地址
    [ except < network> ] :选择排除的网络地址
    [ header < name> ] :不使用X-Forwared-For,自定义名称
    [ if-none ]:有时请求原来带有该字段,此时不再更改
    Example:option forwardfor if-none

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

    在HTTP请求或响应首部内容尾部添加值
    Example:rspadd X-Via: HAProxy/1.5

    reqdel  <search> [{if | unless} <cond>]
    reqidel <search> [{if | unless} <cond>]  (不区分大小写)        

    删除HTTP请求中正则匹配的所有首部

    rspdel  <search> [{if | unless} <cond>]
    rspidel <search> [{if | unless} <cond>]  (不区分大小写)

    删除HTTP响应中正则匹配的所有首部。属于安全加强策略,删除一些服务器版本信息,防止针对攻击
    Example:rspidel Server.*


    3.2.5 超时时长设定

    timeout client <timeout>
    

    设定客户端最大非活动时长, 默认单位是ms;最好与timeout server一致

    
    timeout server <timeout>

    设定服务端最大非活动时长, 默认单位是ms;

    
    timeout connect <timeout>

    设定最大与服务端建立连接的时长

    
    timeout http-keep-alive <timeout>

    设定最大等待新请求的空闲时长,默认单位为ms;

    
    timeout client-fin <timeout>

    在客户端侧设定半关闭连接非活动超时

    
    timeout server-fin <timeout>

    在服务端侧设定半关闭连接非活动超时
    Example:

        
    defaults http
    timeout connect 5s
    timeout client 30s
    timeout server 30s
    timeout client-fin 10s
    timeout http-keep-alive 500
    

    4、使用ACLs和获取样本

    Haproxy 能够从请求报文,响应报文,从客户端或者服务端信息,从表,环境信息等等中提取数据。提取这样的数据的动作我们称之为获取样本。进行检索时,这些样本可以用来实现各种目的,比如作为粘滞表的键,最常用的用途是,根据预定义的模式来进行匹配。
    访问控制列表(ACL)提供一个灵活方案进行内容切换,或者在从请求,响应,任何环境状态中提取的数据基础之上做出决策。控制列表的原则很简单:

    • 从数据流,表,环境中提取数据样本

    • 对提取的样本可选地应用格式转换

    • 对一个样本应用一个或多个模式匹配

    • 当模式匹配样本时才执行动作

    执行的动作通常是阻断请求,选择一个后端服务器或者添加一个HTTP首部
    需要提醒的是,获取的样本数据不光可以使用在acl中,也可以使用别处,例如记录log中
    定义ACL的语法为

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

    这样一条语句建立了一个acl 测试;
    这些测试应用在请求或响应中被"标准"< criterion > 部分所指定的内容,而且可以指定[ flags] 进行特性调整,有些< criterion > 支持操作符[operator] 进行运算,同时一些转换格式的关键字可以跟在< criterion >后面,使用" , "隔开。而值[< value >] 要求被
    < criterion > 所支持的数据形式,多个值使用空格分隔。
    < criterion > 通常是指获取样本方法的名称。使用一个获取样本方法,暗含着其输出样本的类型,类型是以下列出的一种:

    • boolean

    • integer (signed or unsigned)

    • IPv4 or IPv6 address

    • string

    • data block

    ACL引擎匹配数据使用的模式类型如下:

    • boolean

    • integer or integer range

    • IP address / network

    • string (exact, substring, suffix, prefix, subdir, domain)

    • regular expression

    • hex block

    ACL flags 可用列表如下:

    • -i : 忽略大小写

    • -f filename : 从文件中载入模式

    • -m method : 指定模式匹配方法

    • -n : 禁止DNS解析

    • -M : -f 载入的文件作为映射文件使用

    • -u : 强制ACL的名称唯一

    • -- : 强制结束flag结束,避免了字符串中含有的- 引起混淆


    其中flag中的 -m 选项可使用的模式匹配方法如下,需要说明的是有些方法已被默认指定无需声明,例如int,ip

    • "found" : 只是用来探测数据流中是否存在指定数据,不进行任何比较

    • "bool" : 检查结果返回布尔值。匹配没有模式,可以匹配布尔值或整数,不匹配0和false,其他值可以匹配

    • "int" : 匹配整数类型数据;可以处理整数和布尔值类型样本,0代表false,1代表true

    • "ip" : 匹配IPv4,IPv6地址类型数据。该模式仅被IP地址兼容,不需要特别指定

    • "bin" : 匹配二进制数据

    • "len" : 匹配样本的长度的整数值

    • "str" : 精确匹配,根据字符串匹配文本

    • "sub" : 子串匹配,匹配文本是否包含子串

    • "reg" : 正则匹配,根据正则表达式列表匹配文本

    • "beg" : 前缀匹配,检查文本是否以指定字符串开头

    • "end" : 后缀匹配,检查文本是否以指定字符串结尾

    • "dir" : 子目录匹配,检查部分文本中以" / "作为分隔符的内容是否含有指定字符串

    • "dom" : 域匹配。检查部分文本中以" . "作为分隔符的内容是否含有指定字符串

    如果获取样本值为整数,数值比较符可使用,
    eq : true if the tested value equals at least one value
    ge : true if the tested value is greater than or equal to at least one value
    gt : true if the tested value is greater than at least one value
    le : true if the tested value is less than or equal to at least one value
    lt : true if the tested value is less than at least one value

    想必前面一堆理论性的论述已经把大家搞的晕头转向,下面结合获取样本方法和访问控制动作指令具体阐述ACL使用方法
    先介绍控制动作指令

    • layer 4 传输层控制指令

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

    对tcp请求控制指令
    < condition > 即为ACL定义的访问控制列表
    < action > 常用值有 "accept", "reject"

    • layer 7 应用层控制指令

    #阻断符合ACL的访问请求
    block { if | unless } <condition> 
    #http请求的控制指令
    http-request { allow | deny}  [ { if | unless } <condition> ]
    • 后端主机调用

    #根据条件来调用指定后端
    use_backend <backend> [{if | unless} <condition>]
    • 由ACL定义的多个< condition > 组成联合条件,逻辑符为

      • and (默认操作符,可省略)

      • or (或者使用 "||")

      • ! (取反)

    4.1 获取内部状态样本

    # 与后端建立会话速率,每秒钟建立的新会话
    be_sess_rate([<backend>]) : integer

    Example :

    # 某后端被请求过于繁忙,则重定向至错误页
        mode http
        acl being_scanned be_sess_rate gt 100
        redirect location /denied.html if being_scanned

    4.2 获取layer 4 样本

    在传输层获取样本,通常是TCP/IP 协议的IP和端口,以及建立连接速率等等。而且此部分样本通常用于"tcp-request connection"指令中的规则之中。

            dst : ip             #目标地址
            dst_port : integer
            src : ip             #源地址
            src_port : integer

    Example:

    #阻断来自非指定IP的访问8080端口的请求
    acl myhost src 10.1.0.200
    acl myport dst_port 8080
    tcp-request connection reject if !myhost myport        

    4.3 获取layer 7 样本

    /1

    path : string

    提取请求url的地址信息,从第一个"/"开始,不包含host,不包含参数
    ACL 衍生,即包含了-m 选项中匹配模式方法 :
    path : exact string match
    path_beg : prefix match
    path_dir : subdir match
    path_dom : domain match
    path_end : suffix match
    path_len : length match
    path_reg : regex match
    path_sub : substring match

    Example:

    #请求资源为图片,则调用图片服务器后端
     acl picture path_end -i .jpg .png .gif
     use_backend server_pic if picture

    /2

    url : string

    提取URL的全部内容,包含host和参数
    ACL 衍生类似,不再列举


    /3

    req.hdr([<name>[,<occ>]]) : string

    提取http请求的指定首部字段值,< occ >可指定出现的位置
    ACL 衍生 :

      hdr([<name>[,<occ>]])     : exact string match
      hdr_beg([<name>[,<occ>]]) : prefix match
      hdr_dir([<name>[,<occ>]]) : subdir match
      hdr_dom([<name>[,<occ>]]) : domain match
      hdr_end([<name>[,<occ>]]) : suffix match
      hdr_len([<name>[,<occ>]]) : length match
      hdr_reg([<name>[,<occ>]]) : regex match
      hdr_sub([<name>[,<occ>]]) : substring match

    Example:

    #阻断火狐浏览器发送的请求
    acl firefox hdr_reg(User-Agent)     -i      .*firefox.*
    block if firefox
    

    /4

    method : integer + string

    提取请求报文中的请求方法
    Example:

    #拒绝GET HEAD 方式之外的HTTP请求
    acl valid_method method GET HEAD
    http-request deny if ! valid_method
    

    4.4 内建ACL

    HAProxy有众多内建的ACLs,这些ACLs可直接调用,例如

    • LOCALHOST 匹配来自本地IP的连接,127.0.0.1/8

    • HTTP_1.1 匹配http版本1.1

    • METH_GET 匹配http请求GET或HEAD方法

    • TRUE

    • FALSE

    Example:

     
    #拒绝GET HEAD 方式之外的HTTP请求
    http-request deny if ! METH_GET
  • 相关阅读:
    力扣第945题 使数组唯一的最小增量
    力扣第365题 水壶问题
    力扣面试题40 最小的k个数
    力扣第409题 最长回文串
    力扣第46题 全排列
    力扣第1160题 拼写单词
    力扣面试题01.06 字符串压缩
    力扣第695题 岛屿的最大面积
    树莓派 鼠标自动消失
    树莓派 VNC 远程桌面 同一个桌面
  • 原文地址:https://www.cnblogs.com/aisa/p/8626168.html
Copyright © 2020-2023  润新知