• HAProxy


    一、HAProxy简介

    HAProxy是一个使用C语言编写的自由及开放源代码软件,其提供高可用性、负载均衡,以及基于TCP和HTTP的应用程序代理。

    功能:

    • 根据静态分配的cookie路由HTTP请求
    • 在通过使用HTTP cookie确保服务器持久性的同时,在多个服务器之间传播负载
    • 在主服务器发生故障时切换到备份服务器
    • 接受专用于服务监控的特殊端口的连接
    • 停止接受连接而不破坏现有连接
    • 在两个方向上添加,修改和删除HTTP标头
    • 阻止匹配特定模式的请求
    • 从应用程序拦截的URI向已通过身份验证的用户报告详细状态

    # yum install haproxy -y
    

    主程序:/usr/sbin/haproxy

    配置文件:/etc/haproxy/haproxy.cfg

    启动服务:# systemctl start haproxy.service

    简单配置示例:实现调度功能

    frontend web  #前端,相当于nginx, server {}
        bind *:80  #监听于80端口
        default_backend websrvs  #指定后端
    backend websrvs  #后端,相当于nginx, upstream {}
    	balance roundrobin  #调度算法,轮调
    	server srv1 192.168.0.9:80 check  #后端server,并做健康检查
    	server srv2 192.168.0.10:80 check
    

    二、全局(global)配置段参数

    1、日志记录

    定义全局的syslog服务器;最多可以定义两个

    log <address> [len <length>] <facility> [max level [min level]]
    
    [root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
    log         127.0.0.1 local2
    [root@haproxy ~]# systemctl restart haproxy
    [root@haproxy ~]# vim /etc/rsyslog.conf
    #### MODULES ####
    $ModLoad imudp
    $UDPServerRun 514
    #### RULES ####
    # Save haproxy log to haproxy.log
    local2.*      /var/log/haproxy.log
    [root@haproxy ~]# systemctl restart rsyslog
    

    2、性能调整相关参数

    nbproc <number>:要启动的haproxy的进程数量

    maxconn <number>:设定每个haproxy进程所能接受的最大并发连接数

    总体的并发连接数:nbproc * maxconn

    ulimit-n <number>:每个haproxy进程可打开的最大文件数

    maxconnrate <number>:每个进程每秒种所能创建的最大连接数量

    maxsessrate <number>:每个进程每秒所能创建的最大会话数量

    maxsslconn <number>:设定每个haproxy进程所能接受的ssl的最大并发连接数

    默认配置:

    global
        log         127.0.0.1 local2
        chroot      /var/lib/haproxy  #虚根
        pidfile     /var/run/haproxy.pid
        maxconn     4000  #每个haproxy进程最大并发连接数,默认4000
        user        haproxy  #以haproxy的身份运行
        group       haproxy
        daemon
        stats socket /var/lib/haproxy/stats  #打开本机socket文件实现本地通信
    

    三、代理配置段

    - defaults <name>  #默认配置段
    - frontend <name>  #前端配置段
    - backend  <name>  #后端配置段
    - listen   <name>
    

    name:所有代理名称必须由大写和小写字母,数字,'-','_','.'组成。

    • default_backend <backend> 设定默认的backend,用于frontend中;

    • default-server [param*] 为backend中的各server设定默认选项;

    1、bind

    在前端定义一个或多个侦听地址或端口

    bind [<address>]:<port_range> [,...] [param*]
    
    bind *:80,*:443
    bind 192.168.0.8:80,192.168.0.8:8080
    bind /var/run/ssl-frontend.sock user root mode 600 accept-proxy
    

    2、balance

    后端服务器组内的服务器调度算法

    balance <algorithm> [ <arguments> ]
    balance url_param <param> [check_post]
    
    • roundrobin:轮调,动态算法:支持权重的运行时调整,支持慢启动;每个后端中最多支持4095个server

    • static-rr:静态轮调,静态算法:不支持权重的运行时调整及慢启动;后端主机数量无上限

    • leastconn:最少连接数,推荐使用在具有较长会话的场景中,例如MySQL、LDAP等

    • first:根据服务器在列表中的位置,自上而下进行调度;前面服务器的连接数达到上限,新请求才会分配给下一台服务

    • source:源地址hash

    • uri:对URI的左半部分做hash计算,并由服务器总权重相除以后派发至某挑出的服务器

    <scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
    	左半部分:/<path>;<params>
    	整个uri:/<path>;<params>?<query>#<frag>
    
    • url_param

    对用户请求的uri的<params>部分中的参数的值作hash计算,并由服务器总权重相除以后派发至某挑出的服务器;通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个Backend Server

    • hdr(<name>)

    对于每个http请求,此处由<name>指定的http首部将会被取出做hash计算; 并由服务器总权重相除以后派发至某挑出的服务器;没有有效值的会被轮询调度

    • rdp-cookie(<name>)

    3、hash-type

    hash-type <method> <function> <modifier>
    
    • map-based:除权取余法,哈希数据结构是静态的数组
    • consistent:一致性哈希,哈希数据结构是一个

    4、server

    定义后端主机的各服务器及其选项

    server <name> <address>[:[port]] [param*]
    
    • name:服务器在haproxy上的内部名称
    • address:服务器地址,支持使用主机名
    • port:端口映射;省略时,表示同bind中绑定的端口
    • param*:参数
      • maxconn <maxconn>:当前server的最大并发连接数

      • backlog <backlog>:当前server的连接数达到上限后的后援队列长度

      • backup:设定当前server为备用服务器

      • disabled:标记为不可用

      • check:对当前server做健康状态检测

        • addr :检测时使用的IP地址
        • port :针对此端口进行检测
        • inter <delay>:连续两次检测之间的时间间隔,默认为2000ms
        • rise <count>:连续多少次检测结果为“成功”才标记服务器为可用;默认为2
        • fall <count>:连续多少次检测结果为“失败”才标记服务器为不可用;默认为3
      • cookie <value>:为当前server指定其cookie值,用于实现基于cookie的会话黏性

      • on-error <mode>:后端服务故障时的行动策略

        • fastinter:强迫快速
        • fail-check:快速失败,快速测试;有故障则离线,没有问题上线,默认策略
        • sudden-death:模拟一个致命的失败健康检查,另一个失败的检查将标记服务器关闭,强制fastinter
        • mark-down:立即标记服务器并强制执行fastinter
      • redir <prefix>:将发往此server的所有GET和HEAD类的请求重定向至指定的URL

      • weight <weight>:权重,默认为1

    5、option httpchk

    定义基于http协议的7层健康状态检测机制

    option httpchk
    option httpchk <uri>
    option httpchk <method> <uri>
    option httpchk <method> <uri> <version>
    
    http-check expect [!] <match> <pattern>
    

    用于定义应用层检测方法:

    • httpchk:检测httpd服务的健康状态
    option httpchk GET /test.html
    

    6、maxconn

    为指定的frontend定义其最大并发连接数;默认为2000

    7、mode

    mode { tcp|http|health } :定义haproxy的工作模式
    
    • tcp:基于layer4实现代理;可代理mysql, pgsql, ssh, ssl等协议;
    • http:仅当代理的协议为http时使用;
    • health:工作为健康状态检查的响应模式,当连接请求到达时回应“OK”后即断开连接;

    8、cookie

    cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ]  [ postonly ] [ preserve ] [ httponly ] [ secure ]  [ domain <domain> ]* [ maxidle <idle> ] [ maxlife <life> ]
    
    • name:修改或插入的cookie的名称,以便带来持久性
    • rewirte:重写
    • insert:插入
    • prefix:前缀

    基于cookie的调度配置示例:

    frontend web
        bind *:80
        default_backend websrvs
    backend websrvs
        balance roundrobin
        cookie WEBSRV insert nocache indirect
        server srv1 192.168.0.9:80 check inter 1000 rise 1 fall 2 maxconn 2000
     cookie web1
        server srv2 192.168.0.10:80 check maxconn 1500 cookie web2
    

    9、option forwardfor

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

    在由haproxy发往后端主机的请求报文中添加“X-Forwarded-For”首部,其值前端客户端的地址;用于向后端主发送真实的客户端IP

    • [ except <network> ]:请求报请来自此处指定的网络时不予添加此首部
    • [ header <name> ]:使用自定义的首部名称,而非“X-Forwarded-For”

    10、errorfile 和 errorloc

    errorfile <code> <file>
    errorloc <code> <url>
    errorloc302 <code> <url>
    
    • code:HTTP状态代码。 目前HAProxy能够支持的代码:200, 400, 403, 408, 500, 502, 503, and 504
    • file:指定包含完整HTTP响应的文件
    errorfile 400 /etc/haproxy/errorfiles/400badreq.http
    errorfile 408 /dev/null  #解决方法Chrome预连接错误
    errorfile 403 /etc/haproxy/errorfiles/403forbid.http
    errorfile 503 /etc/haproxy/errorfiles/503sorry.http
    

    11、修改报文头部

    reqadd  <string> [{if | unless} <cond>] 在HTTP请求的末尾添加标头
    rspadd  <string> [{if | unless} <cond>] 在HTTP响应的末尾添加标头
    reqdel  <search> [{if | unless} <cond>] 删除与HTTP请求中的正则表达式匹配的所有标头
    reqidel <search> [{if | unless} <cond>]  (ignore case)
    rspdel  <search> [{if | unless} <cond>] 删除与HTTP响应中的正则表达式匹配的所有标头
    rspidel <search> [{if | unless} <cond>]  (ignore case)
    
    rspidel  Server.*  #删除响应报文中的Server字段信息
    

    12、连接超时时长

    timeout client <timeout>  面向客户端侧的超时时间,默认单位是毫秒
    timeout server <timeout>  面向服务器侧的超时时间
    timeout http-keep-alive <timeout>  持久连接的持久时长
    timeout http-request <timeout>  等待客户端传完的请求报文的超时时长
    timeout connect <timeout>  向后端服务器发起连接请求时的超时时长
    timeout client-fin <timeout>  设置客户端一侧的半关闭连接超时时长
    timeout server-fin <timeout>  设置服务器一侧的半关闭连接超时时长
    

    13、访问控制

    满足条件时拒绝请求:

    block { if | unless } <condition>
    

    示例:当源地址为172.16.200.2,则拒绝请求,并返回错误页

    acl invalid_src src 172.16.200.2
    block if invalid_src
    errorfile 403 /var/www/error.html
    

    根据http请求包控制:

    http-request { allow | deny } [ { if | unless } <condition> ]
    

    根据tcp连接控制:

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

    示例:拒绝192.168.0.7的ssh访问

    acl invalid_src src 192.168.0.7
    tcp-request connection reject if invalid_src
    

    14、use_backend

    当符合指定的条件时使用特定的backend,可以实现条件式调度

    use_backend <backend> [{if | unless} <condition>]
    

    六、统计接口

    • stats enable:启用统计页;基于默认的参数启用stats page
    stats uri   : /haproxy?stats
    stats realm : "HAProxy Statistics"
    stats auth  : no authentication
    stats scope : no restriction
    
    • stats auth <user>:<passwd>:认证时的账号和密码,可使用多次
    • stats realm <realm>:认证时的realm
    • stats uri <prefix>:自定义stats page uri
    • stats refresh <delay>:设定自动刷新时间间隔
    • stats admin { if | unless } <cond>:启用stats page中的管理功能

    配置参数示例:

    listen stats
        bind :8080
        stats realm "HAProxy Stats Page"
        stats auth admin:adminpass
        stats admin if TRUE
    

    访问:http://192.168.0.8:8080/haproxy?stats进入管理页

    七、ACL

    访问控制列表的使用提供了一种灵活的解决方案来执行内容切换,并且通常基于从请求,响应或任何环境状态中提取的内容来做出决策

    acl <aclname> <criterion> [flags] [operator] [<value>] ...
    
    • aclname:ACL名称必须由大写和小写字母,数字,' - '(短划线),'_'(下划线),'.' 组成。ACL名称区分大小写
    • value:值
    boolean 布尔型
    integer or integer range 整数或整数范围
    IP address / network IP或网络地址
    string (exact精确匹配, substring子串匹配, suffix前缀匹配, prefix后缀匹配, subdir子路径匹配, domain子域名匹配) 字符串匹配
    regular expression 正则表示式匹配
    hex block 16进制的块匹配
    
    • flags:标志
    -i : 忽略字符大小写
    -m : 特定的模式
    -n : 禁止DNS解析
    -u : 要求acl使用唯一的名称
    
    • operator:操作符
    匹配整数值:eq、ge、gt、le、lt
    匹配字符串:
    	exact match 精确匹配
    	substring match 子串匹配
    	prefix match 前缀匹配
    	suffix match 后缀匹配
    	subdir match 子路径匹配
    	domain match 子域名匹配
    
    • acl作为条件时的逻辑关系:
    if invalid_src invalid_port  或关系
    if invalid_src || invalid_port  与关系
    if ! invalid_src invalid_port  非invalid_src
    
    • criterion:判断标准
    dst : 目标ip
    dst_port : 目标端口
    src : 源ip
    src_port : 源端口
    
    检查url的路径
    path     : 精确匹配
    path_beg : 前缀匹配
    path_dir : 子串匹配
    path_dom : 子域名匹配
    path_end : 路径后缀匹配
    path_len : 路径长度匹配
    path_reg : 路径的正则表达式模式匹配
    path_sub : 路径的子字串匹配
    
    检查整个url
    url     : 精确匹配
    url_beg : 前缀匹配
    url_dir : 子串匹配
    url_dom : 子域名匹配
    url_end : 后缀匹配
    url_len : 长度匹配
    url_reg : 正则表达式匹配
    url_sub : 子字串匹配
    
    请求报文的指定头部检查 req.hdr([<name>[,<occ>]]) : string
    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
    

    示例:阻止curl访问

    frontend web *:80
        acl bad_curl hdr_sub(User-Agent) -i curl
        block if bad_curl
        default_backend appsrvs
    

    示例:实现动静分离

    frontend web *:80
        acl url_static path_beg -i /static /images /javascript /stylesheets
        acl url_static path_end -i .jpg .gif .png .css .js .html .txt .htm
        use_backend staticsrvs if url_static
        default_backend appsrvs
    backend staticsrvs
        balance roundrobin
        server stcsrv1 192.168.0.9:80 check
    backend appsrvs
        balance roundrobin
        server app1 192.168.0.10:80 check
        server app2 192.168.0.11:80 check
    

    八、配置HAProxy支持https协议

    1)准备ca证书

    [root@haproxy ~]# cd /etc/pki/tls/certs/
    [root@haproxy certs]# vim Makefile
    %.key:
        umask 77 ; 
        /usr/bin/openssl genrsa $(KEYLEN) > $@  #将-aes128删除,避免私钥加密
    [root@haproxy certs]# make haproxy.crt
    Country Name (2 letter code) [XX]:CN
    State or Province Name (full name) []:bj
    Locality Name (eg, city) [Default City]:bj
    Organization Name (eg, company) [Default Company Ltd]:dongfei.com
    Organizational Unit Name (eg, section) []:opt
    Common Name (eg, your name or your server's hostname) []:www.dongfei.com
    [root@haproxy certs]# cp haproxy.* /etc/haproxy/
    [root@haproxy ~]# cd /etc/haproxy/
    [root@haproxy haproxy]# cat haproxy.crt haproxy.key > haproxy.pem
    

    2)配置HAProxy

    frontend web *:80
        bind *:443 ssl crt /etc/haproxy/haproxy.pem
        redirect scheme https if !{ ssl_fc }  #将80端口跳转到443
        acl url_static path_beg -i /static /images /javascript /stylesheets
        acl url_static path_end -i .jpg .gif .png .css .js .html .txt .htm
        use_backend staticsrvs if url_static
        default_backend appsrvs
    backend staticsrvs
        balance roundrobin
        server stcsrv1 192.168.0.9:80 check
    backend appsrvs
        balance roundrobin
        server app1 192.168.0.10:80 check
        server app2 192.168.0.11:80 check
    

    九、常用功能的实现

    1)压缩

    frontend web *:80
        default_backend appsrvs
        compression algo gzip
        compression type text/html text/plain
    backend appsrvs
        balance roundrobin
        server app1 192.168.0.10:80 check
        server app2 192.168.0.11:80 check
    

    2)stats page

    listen stats
        bind :8080
        stats realm "HAProxy Stats Page"
        stats auth admin:adminpass  #认证用户:密码
        stats admin if TRUE
    访问:http://192.168.0.8:8080/haproxy?stats进入状态管理页
    

    3)自定义错误页

    [root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
    frontend web *:80
            default_backend appsrvs
            acl bad_guy src 192.168.0.7
            block if bad_guy
            errorfile 403 /etc/haproxy/errorfiles/403forbid.http
    backend appsrvs
            balance roundrobin
            server app1 192.168.0.10:80 check
            server app2 192.168.0.11:80 check
    [root@haproxy ~]# mkdir /etc/haproxy/errorfiles/ -p
    [root@haproxy ~]# echo 'forbid' >/etc/haproxy/errorfiles/403forbid.http
    [root@haproxy ~]# systemctl restart haproxy
    [root@client ~]# curl http://192.168.0.8/
    forbid
    

    4)访问控制

    listen stats
        bind :8080
        stats realm "HAProxy Stats Page"
        stats auth admin:adminpass
        stats admin if TRUE
        acl admin_client src 192.168.0.254
        block unless admin_client  #只允许192.168.0.254访问状态管理页
    

    5)日志功能

    调度器中配置
    [root@haproxy ~]# vim /etc/haproxy/haproxy.cfg 
    backend appsrvs
        balance roundrobin
        option forwardfor
        server app1 192.168.0.10:80 check
        server app2 192.168.0.11:80 check
    [root@haproxy haproxy]# systemctl restart haproxy.service
    
    后端服务器配置(Apache)
    [root@web2 ~]# vim /etc/httpd/conf/httpd.conf
    LogFormat "%{X-Forwarded-For}i %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent
    }i"" combined  #改变日志记录方式
    [root@web2 ~]# systemctl restart httpd
    [root@web2 ~]# tail -f /var/log/httpd/access_log
    

    6)基于cookie的session粘滞

    [root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
    frontend web *:80
        mode http
        default_backend appsrvs
    backend appsrvs
        balance roundrobin
        option forwardfor
        cookie WEBSRV insert nocache indirect
        server app1 192.168.0.10:80 check inter 1000 rise 1 fall 2 maxconn 2000 cookie websrv1
        server app2 192.168.0.11:80 check maxconn 1500 cookie websrv2
    [root@client ~]# curl -b "WEBSRV=websrv1" http://192.168.0.8/
    web1
    [root@client ~]# curl -b "WEBSRV=websrv2" http://192.168.0.8/ 
    web2
    

    7)后端主机的健康状态检测

    backend appsrvs
        balance roundrobin
        option httpchk GET /test.html
        server app1 192.168.0.10:80 check 
        server app2 192.168.0.11:80 check
    

    8)请求和响应报文首部的操纵:替换响应报文的Server字段信息

    [root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
    frontend web *:80
        mode http
        rspidel ^Server:.*
        rspadd Server: Apache or Nginx
        default_backend appsrvs
    [root@client ~]# curl -I http://192.168.0.8/
    Server: Apache or Nginx  #掩人耳目
    

    感谢阅读!

  • 相关阅读:
    首次远程安装 GlassFish 后以远程 Web 方式访问其后台管理系统出现错误的解决方法(修订)
    在 Mac OS X 环境中从源代码编译安装 FFmpeg
    编译 Android 版本的 Opus 音频编解码库的方法
    在 NetBeans 中开发一般 Java 应用程序时配置 Allatori 进行代码混淆
    使用 IntelliJ IDEA 开发一般 Java 应用程序时配置 Allatori 进行代码混淆
    使用 IntelliJ IDEA 开发 Android 应用程序时配置 Allatori 进行代码混淆
    基于现有图像数据创建自定义像素格式的 BufferedImage
    AppCode 中开发 Mac OS X 应用程序或共享库的经验小结
    MinGW 创建的程序或 DLL 脱离 libgcc-xx-xx.dll 和 libstdc++-x.dll 运行库的方法
    MinGW 使用和创建 DLL 应注意的问题
  • 原文地址:https://www.cnblogs.com/L-dongf/p/9292677.html
Copyright © 2020-2023  润新知