HAproxy的笔记

一致性算法:
   一致性Hash 是为了解决动态缓存节点映射问题的
      一致性hash的要求:
        平衡性:数据分配要均匀
        单调性:原有的数据只能映射到其所在的缓冲区或者新的缓冲区,而非其他旧缓冲区
        分散性:同样的内容映射到相同的缓冲区,而非相同的内容映射到不同的缓冲区
        负载:降低缓冲的负荷
  旧的Hash映射算法:取模法
     hash(object)%N,object表示数据,N表示节点数量
 
  一致性Hash的实现:环形Hash
         思想:在动态增加/删除节点时,只迁移小部分数据,完成新的映射关系
            将key的Hash值映射到2的32次方的空间中,并将所有缓冲节点也映射到这个空间中,通过顺时针计算把数据分配到对应的节点中
            当增加或删除节点时,只需再次按照顺时针计算把相关的数据迁移到对应的节点即可,保证最低迁移量
            为了解决平衡性,把数据尽量平均分配到各个节点,可以把实际节点映射为多个虚拟节点,使节点比较平均的分布。比如把一个节点的IP地址后增加『#1』 『#2』作为key值做Hash计算后映射到空间中

LB:
  tcp:
     lvs,haproxy,nginx
  application layer:
     http:haproxy,nginx,ats,apache
     mysql:mysql-proxy

  web arch:haproxy
     mode:http,tcp(https,mysql)

HAProxy:
  代理(http):掮客(broker)
     正向代理
     反向代理

     代理作用:
        web缓存(加速),反向代理,内容路由(根据流量及内容类型等将请求转发至特定服务器),转码器
          在代理服务器上添加via首部

    缓存的作用:
       减少冗余内容传输
       节省带宽,缓解网络瓶颈
       降低了对原始服务器的访问压力
       降低了传输延迟

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

            HAProxy借助于OS上几种常见的技术来实现性能的最大化。

            1,单进程、事件驱动模型显著降低了上下文切换的开销及内存占用。

            2,O(1)事件检查器(event checker)允许其在高并发连接中对任何连接的任何事件实现即时探测。

            3,在任何可用的情况下,单缓冲(single buffering)机制能以不复制任何数据的方式完成读写操作,这会节约大量的CPU时钟周期及内存带宽;

            4,借助于Linux 2.6 (>= 2.6.27.19)上的splice()系统调用,HAProxy可以实现零复制转发(Zero-copy forwarding),在Linux 3.5及以上的OS中还可以实现零复制启动(zero-starting);

            5,内存分配器在固定大小的内存池中可实现即时内存分配,这能够显著减少创建一个会话的时长;

            6,树型存储:侧重于使用作者多年前开发的弹性二叉树,实现了以O(log(N))的低开销来保持计时器命令、保持运行队列命令及管理轮询及最少连接队列;

            7,优化的HTTP首部分析:优化的首部分析功能避免了在HTTP首部分析过程中重读任何内存区域;

            8,精心地降低了昂贵的系统调用,大部分工作都在用户空间完成,如时间读取、缓冲聚合及文件描述符的启用和禁用等;

    haproxy:
       frontend
          use_backend
          default_backend
       backend
          balancer
          server
          server
       listen:
          server
       default

配置文件:haproxy.cfg
   全局配置
   代理配置

全局配置:
   global配置中的参数为进程级别的参数,且通常与其运行的os相关
    进程管理及安全相关的参数:
        - chroot <jail dir>:修改haproxy的工作目录至指定的目录并在放弃权限之前执行chroot()操作,可以提升haproxy的安全级别,
        不过需要注意的是要确保指定的目录为空目录且任何用户没有写权限
        - daemon:让haproxy以守护进程的方式工作于后台,其相当于"-D"选项的功能,当然,也可以在命令行中以".db"选项将其禁用.
        - gid <number>:以指定的GID运行haproxy,建议使用专门的用于运行haproxy的GID,以免因权限问题带来风险
        - group <group name>:同gid,不过指定的组名
        - log <address> <facility> [max level[min level]]:定义全局的syslog服务器,最多可以定义两个
        - log-send-hostname [<string>]:在syslog信息的首部添加当前主机名,可以为"string"指定的名称,也可以缺省使用当前主机名
        - nbproc <number>:指定启动的haproxy的进程个数,只能用于守护进程模式的haproxy,默认只启动一个进程,鉴于调试困难等多方面的原因,
        一般只在单进程仅能打开少数文件描述符的场景中才使用多进程模式
        - pidfile:
        - uid:以指定的uid身份运行haproxy
        - ulimit-n:设定每进程所能打开的最大文件描述符数目,默认情况下其会自动进行计算,因此不推荐修改此选项
        - user:同uid,但使用的是用户名
        - stats:
        - node:定义当前节点的名称,用于HA场景中多haproxy进程共享同一个ip地址时

    性能调整相关的参数:
        - maxconn <number>:设定每个haproxy进程所接受的最大并发连接数,其等同于命令行选项"-n";"ulimit-n"自动计算的结果正是参照此参数
        设定的
        - maxpipes <number>:haproxy使用pipe完成基于内核的tcp报文重组,此选项则用于设定每进程所允许的使用的最大pipe个数;每个pipe会打
        开两个文件描述符,因此,"ulimit -n"自动计算时会根据需要调大此值,默认为maxconn/4,其通常会显得过大
        - noepoll:在linux系统上禁用epoll机制
        - nokqueue:在BSD系统上禁用kqueue机制
        - nopoll:禁用poll机制
        - nosepoll:在linux系统禁用启发式epoll机制
        - nosplice:禁止在linux系统套接字上使用内核tcp重组,这回导致更多的recv/send系统调用,不过,在linux2.6.25-28系列的内核上,tcp重组
        功能有bug存在
        - spread-checks <0..50,in percent>:在haproxy后端有众多服务器的场景中,在精确的时间间隔后统一对众服务器进行健康状况检查可能会
        带来意外问题,此选项用于将其检查的时间间隔长度上增加或减少一定的随机时长
        - tune.bufsize <number>:设定buffer的大小,同样的内存条件下,较小的值可以让haproxy有能力接受更多的并发连接,较大的值可以让某些应
        用程序使用较大的cookie信息,默认为16384,其可以在编译时修改,不过强烈建议使用默认值
        - tune.chksize <number>:设定检查缓冲区的大小,单位为字节,更大的值有助于在较大的页面中完成基于字符串或模式的文本查找,但也会占用
        更多的系统资源,不建议修改
        - tune.maxaccept <number>:设定haproxy进程内核调度运行时一次性可以接受的连接的个数,较大的值可以带来较大的吞吐量,默认在单进程模
        式下为100,多进程模式下为8,设定为-1可以禁用此限制,一般不建议修改
        - tune.maxpollevents <number>:设定一次系统调用可以处理的事件最大数,默认值取决于OS,其值小于200时可节约带宽,但会略微增大网络延
        迟,而大于200时会降低延迟,但会稍稍增加网络带宽的占用量
        - tune.maxrewrite <number>:设定为首部重写或追加可预留的缓冲空间,建议使用1024左右的大小,在需要使用更大得空间时,haproxy会自动
        增加其值
        - tune.rcvbuf.client <number>;
        - tune.rcvbuf.server <number>:设定内核套接字中服务器端接收缓冲的大小,单位为字节,强烈推荐使用默认值
        - tune.sndbuf.client <number>:
        - tune.sndbuf.server <number>:

配置:/etc/haproxy/haproxy.cfg
  /usr/sbin/haproxy
  centos6:/etc/rc.d/init.d/haproxy
  centos7:haproxy.service

    配置分为两段:
       global:
          配置参数:log,maxconn,...
       proxies:
         defaults,frontend,backend,listen

       示例:
         frontend main *:80
             default_backend webserver
         backend webserver
             balance roundrobin
             server web1 192.168.137.128 check
             server web2 192.168.137.141 check


HAProxy(2)
   代理参数;
      balance:指定调度算法
         动态:权重可动态调整
         静态:调整权重不会实时生效

         roundrobin:轮询,基于权重进行轮叫,动态算法,每行后端主机最多支持4128个连接
         static-rr:轮询,基于权重进行轮叫,静态算法,和roundrobin类似,不支持动态调整后端服务器权重,每个后端主机支持的数量无上限
         leastconn:最少连接数,动态算法,基于后端主机的负载数量进行调度
         source:将请求的源地址进行hash计算,并由后端主机的权重总数相除后派发至指定的服务器,默认是静态算法,但是可以通过使用hash-type
         修改此特性
              hash-type map-based    静态hash    对于ip的hash取余
              hash-type consistent    动态hash    使用hash环
         uri:对URI的左部分('问题'标记之前的部分)或整个URI进行hash运算,并由后端主机的权重总数相除后派发至指定的服务器,此算法仅应用于
         HTTP后端的场景,其默认为静态算法
               另外:该算法支持追加参数[ < arguments > ]:
                (1) whole :hash完整uri
                (2) len number:hash指定uri的长度
                (3) depth nubmer:hash指定目录深度,每个"/"代表一个深度
              基于uri来进行选择,比如客户访问了http://test.com/a.jpg,那么在此uri缓存失效之前,任何一个客户访问这个路径,一定访问的就是a.jpg
                    len    基于多少个字符的uri
                    depth    基于多少个目录层次的uri
                    例子:http://test.com/a/b/c/d/e/a.jpg
                        len 3    hash的uri是/a/
                        depth 3    hash的uri是/a/b/c/
              hash-type map-based    静态hash    对于ip的hash取余
              hash-type consistent    动态hash    使用hash环
         uri-params:根据uri中的指定参数的值进行调度,把值进行hash计算,并除以总权重,默认是静态算法
              参数指那一部分,先看下url格式,
                <scheme>://<user>:<passwd>@<host>:<port>/<path>;<params>?<query>#<frag>
                <query>表示php程序请求的查询信息
                <frag>表示当前页的片段页,即跳转到当前页的某个部分
                例子:http://test.com/hammers:sale=false/index.html:graphics=ture
                这里的意思就是如果访问的是hammers,则传递参数sale(并赋值false),如果访问的是index.html,则传递参数graphics(并赋值ture)
                     hash-type map-based    静态hash    对于ip的hash取余
                     hash-type consistent    动态hash    使用hash环
         hdr(name):根据请求报文中的指定的header(如user_agent,referer,hostname),默认为静态算法
             hdr(name)-->header基于首部的信息来构建hash表
             hdr(Host)    基于用户请求的主机名进行调度
         rdp-cookie:
         rdp-cookie(name):
         first:第一优先算法
             如果第一个服务端可接受请求则总是把连接分配给它,直到第一个服务端处于繁忙,分配给下一个,顺序按服务端的数字ID从小到大排列

   bind:
      bind [<address>]:<port_range> [,...]
      bind [<address>]:<port_range> [,...] interface <interface>
      此指令仅能用于frontend和listen区段,用于定义一个或几个监听的套接字

   mode:设定实例的运行模式或协议,当实现内容交换时,前端和后端必须工作于同一种模式(一般来说都是http模式),否则无法启动实例
      HAProxy的工作模式,默认为tcp
         tcp,http,health
   log:为每个实例启用时间和流量日志,可用于所有区段,每个实例最多可以指定两个log参数
     log global
     log <address> <facility> [<level> [<minlevel>]]
     global:当前这个实例的log如果和global段中的相同时将使用此格式
   default_backend:默认的backend
     为frontend指明使用的默认backend
   use_backend:
     为frontend指明使用的backend
       实例:
         use_backend dynamic if url_dyn(acl访问控制列表的名称)
   server:
      server <name> <address>[:port] [params]
         params:
            backup:备用服务器,也可以用作sorry server
            check:启动对此server执行健康状态检测,还可以接其他参数
               inter <delay>:检测的时间间隔,单位ms,默认2000
               rise <count>:从离线到正常要经过的次数
               fail <count>:从正常到离线的次数
            cookie <value>:为指定的server设定cookie值,此处指定的值将在请求入站时被检查,第一次为此值挑选的server将在后续的请求中被选中,其目的在于实现持久连接的功能
            maxconn <maxconn>:此服务器能接受的最大并发连接数
            maxqueue <maxqueue>:设定请求队列的最大长度
            observe <mode>:通过观察服务器的通信状况来判定健康状况,默认为禁用,支持的类型为"layer4"和"layer7",layer7用于http代理场景
            redir <Profix>:启用重定向功能,将发往此服务器的GET和HEAD请求均以302状态码响应,需要注意的是,在prefix后面不能使用/,且不能使用
            相对地址,以免造成循环,例如
                server sev1 192.168.137.141:80 redir http://imageserver.fang.com check
            weight: <weight>:权重,默认为1,最大值256,0表示不参与负载均衡

            检查方法:
                option httpchk
                option httpchk <uri>
                option httpchk <method> <uri>
                option httpchk <method> <uri> <version>

    通过cookie对会话进行绑定:
       #---------------------------------------------------------------------
        backend webserver
            balance   roundrobin
            cookie serverid insert nocache indirect
            server web1 192.168.137.128:80 check cookie websrv1
            server web2 192.168.137.141:80 check cookie websrv2
               indirect:
                  如果不配合"indirect"选项,服务端可以看到客户端请求时的所有cookie信息。如果配合"indirect"选项,则haproxy在将请求转发给后端时,将删除自己设置的cookie,使得后端只能看到它自己的cookie,这样对后端来说,整个过程是完全透明的,它不知道前面有负载均衡软件
               preserve:
                  如果insert关键字配合"preserve"关键字,那么当后端设置了cookie时,haproxy将强制保留该cookie,不做任何修改。也就是说,如果将haproxy的cookie名称也设置为PHPSESSID,那么客户端第一次请求时收到的响应报文中将只有一个"Set-Cookie"字段,且这个字段的值是后端服务器设置的,和haproxy无关
               ignore-persist:
                  其实,通过cookie表保持和后端的会话只是默认情况,haproxy允许"即使使用了cookie也不进行会话绑定"的功能。这可以通过ignore-persist指令来实现。当满足该指令的要求时,表示不将该cookie插入到cookie表中,因此无法实现会话保持,即使haproxy设置了cookie也没用。
                   例如:
                      backend dynamic_group
                        acl  url_dynamic   path_end  -i .php
                        ignore-persist if  url_dynamic
                        cookie app_cook insert nocache
                        server app1 192.168.100.60:80 cookie app_server1
                        server app2 192.168.100.61:80 cookie app_server2
                   这表示当请求uri以".php"结尾时,将忽略会话保持功能。这表示,对于php结尾的请求,app_cook这个cookie从头到尾都是摆设
                     当然,上面的设置是不合理的,更合理的应该是这样的
                        acl url_static  path_beg         /static /images /img /css
                        acl url_static  path_end         .gif .png .jpg .css .js
                        ignore-persist  if url_static
                   与ignore-persist相对的是force-persist,但不建议使用该选项,因为它和option redispatch冲突

        要点:
          (1)每个server有自己唯一的cookie标识
          (2)在backend中定义为用户请求调度完成后操纵其cookie
    查看统计信息:
        listen statistics
        bind *:9090
        stats enable
        stats hide-version
        stats scope .
        stats admin:启用管理功能
            stats admin {if |unless} <cond>
              例如:
                 stats admin if LOCALHOST:本地登录有效
                 stats admin if TRUE:经过了认证后

    向日志中记录额外信息:
       capture request header
       capture response header
    
    当mode为http模式时,记录详细的日志信息
     option httplog:
       option httplog [clf]
      启用记录http请求,会话状态和计时器的功能
         clf:使用CLF格式来代替haproxy默认的http格式
    
    option logasap:
      启用或禁用提前将HTTP请求记入日志,不能用于backend区段
        默认情况下,http请求是在请求结束时记录日志,在传输大的对象时计入日志的时间会比较长,logasap会在开始接收请求时开始记录日志

    option forwardfor
       option forwardfor [except <network] [header <name>] [if-none]
         允许在发往服务器的请求首部中插入"x-forward-for"首部
           except:排除地址
           header:可以使用自定义的首部,如"x-client"来替代"x-forward-for"
           if-none:仅在此首部不存在时才将其添加至请求报文中
    option dontlognull:
       启用该项,日志中将不会记录空连接。所谓空连接就是在上游的负载均衡器或者监控系统为了探测该服务是否存活可用时,需要定期的连接或者获取某一固定的组件或页面,或者探测扫描端口是否在监听或开放等动作被称为空连接;官方文档中标注,如果该服务上游没有其他的负载均衡器的话,建议不要使用该参数,因为互联网上的恶意扫描或其他动作就不会被记录下来
    errorfile:定义错误页面,但是404无法返回,因为由后端返回,可用于所有配置段
      errorfile <code> <file>
        code:状态码,400,403,408,500,502,503和504
        file:错误文件

    errorloc302:
    错误页面重定向:
       errorfile:使用haproxy主机本地文件进行响应
       errorloc,errorloc302:使用指定的url进行响应,响应状态码为302,不适用于GET以外的方法
       errorloc303:返回303状态码

    访问控制:
       http_request:
       tcp_request

    添加请求或响应报文首部:
       reqadd:请求报文
       rspadd:响应报文

    timeout http-request:
       定义请求报文的超时时间
    timeout connect:
        队列超时时长
    timeout client:
        客户端超时时间
    timeout http-keep-alive:
        keepalive的超时时间
    timeout check:
        check的超时时间
    option http-server-close 对于某些server端不支持http长连接的情况,利用这个参数可以使用客户端到haproxy是长连接,而haproxy到server端是短连接


ACL:
   语法:
     acl <aclname> <criterion> [flags] [operator] <value> ...
        <aclname>:ACL名称,区分字符大小写,且只能包含大小写字母,数字,-,下划线,点号,冒号(:),haproxy中acl可以重名
        <criterion>:测试标准,即对什么信息发起测试,测试方法可以通过flags指定的标志进行调整,而有些测试标准也可以需要为其在<value>
        之前指定一个操作符[operatior]
        <flags>:目前haproxy的acl支持的标志位有3个
            -i:不区分<value>中模式字符的大小写
            -f:从指定的文件中加载模式
            --:标志位的强制结束标记,在模式中的字符串像标记符时使用
        <value>:acl测试条件支持的值有以下四项
            整数或整数范围:如1024:65535表示从1024到65535,仅支持使用正整数,支持的操作符有五个,eq,ge,gt,le和lt
            字符串:支持使用-i忽略大小写,支持使用\转义
            正则表达式:其机制类同字符串匹配
            ip地址及网络地址
     同一个acl中可以指定多个测试条件,有与,或,非,与是默认的


     be_sess_rate(backend) <integer>:
        用于测试指定的frontend上会话创建的速率,即每秒创建的会话数是否满足指定的条件,常用于在指定的backend上的会话速率过高时将用户
        请求转发至另外的backend,或用于阻止攻击行为,例如
            backend dynamic
               mode http
               acl being_scanned be_sess_rate gt 50
               redirect location /error_pages/denied.html if being_scanned
     fe_sess_rate(frontend) <integer>
        用于测试指定的frontend(或当前frontend)上的会话创建速率是否满足指定的条件,常用于为frontend指定一个合理的会话创建速率的上限
        以防止服务被滥用,例如下面的例子限定入站邮件速率不能大于50封/秒,所有在此指定范围之外的请求邮件将被延时50毫秒
           frontend mail
             bind:25
             mode tcp
             maxconn 500
             acl too_fast fe_sess_rate ge 50
             tcp-request inspect-delay 50ms
             tcp-request content accept if ! too_fast
             tcp-request content accept if WAIT_END

     hdr <string>
       hdr (header) <string>
       用于测试请求报文中的所有首部或指定首部是否满足指定的条件,指定首部时,不区分大小写,且在括号中不能有任何多余的空白字符,测试
       服务器端的响应报文时可以使用shdr(),例如下面的例子用于测试首部connection的值是否为close
          hdr(connection) -i close

     method <string>
       method <string>
       测试http请求报文中使用的方法

     path_beg <string>
       用于测试请求的URL是否以<string>指定的模式开头,下面的例子用于测试URL是否以/static,/images,/JavaScript或/stylesheets头
          acl url_static path_beg -i /static  /images /JavaScript /styleheets

     path_end <string>
       用于测试请求的URL是否以<string>指定的模式结尾,
          acl url_static path_end -i .jpg .gif .png .css .js

     hdr_beg <string>
       用于测试请求报文中的指定首部的开头是否符合<string>
              acl host_static hdr_beg(hsot) -i img. video. download. ftp.


      url_beg
      url_end
      url_reg
      path_reg:正则表达式的匹配



haproxy参数的调优:
        maxconn <number>:设定单haproxy进程的最大并发连接数
        maxconnrate <number>:设定单haproxy进程每秒接受的连接数
        maxsslconn <number>:设定单haproxy进程的ssl连接最大并发连接数
        maxsslrate <number>:单haproxy进程的ssl连接的创建速率上限
        spread-checks <0..50, in percent>:避免对于后端检测同时并发造成的问题,设置错开时间比,范围0到50,一般设置2-5较好
阅读更多
文章标签: haproxy笔记
个人分类: linux
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭