33.0 haproxy

[root@varnish ~ ]#yum info haproxy
Loaded plugins: fastestmirror, langpacks
Loading mirror speeds from cached hostfile
Installed Packages
Name        : haproxy
Arch        : x86_64
Version     : 1.5.18               #base  repository
Release     : 7.el7
Size        : 2.6 M
Repo        : installed
From repo   : base
Summary     : TCP/HTTP proxy and load balancer for high availability environments
URL         : http://www.haproxy.org/
License     : GPLv2+
Description : HAProxy is a TCP/HTTP reverse proxy which is particularly suited for high
            : availability environments. Indeed, it can:
            :  - route HTTP requests depending on statically assigned cookies
            :  - spread load among several servers while assuring server persistence
            :    through the use of HTTP cookies
            :  - switch to backup servers in the event a main server fails
            :  - accept connections to special ports dedicated to service monitoring
            :  - stop accepting connections without breaking existing ones
            :  - add, modify, and delete HTTP headers in both directions
            :  - block requests matching particular patterns
            :  - report detailed status to authenticated users from a URI
            :    intercepted by the application

haproxy

默认http
  支持http反向代理
   支持动态程序的反向代理
  支持基于数据的反向代理(一般数据库不用haproxy,数据库有读写分离技术)
HAProxy是TCP / HTTP反向代理服务器,尤其适合于高可用性环境
   可以针对HTTP请求添加cookie,进行路由后端服务器
   可平衡负载至后端服务器,并支持持久连接
   支持基于cookie进行调度
   支持所有主服务器故障切换至备用服务器
   支持专用端口实现监控服务
   支持不影响现有连接情况下停止接受新连接请求
   可以在双向添加,修改或删除HTTP报文首部
   支持基于pattern实现连接请求的访问控制
   通过特定的URI为授权用户提供详细的状态信息
haproxy的调度算法(1.5版本)
balance参数

balance <algorithm> [ <arguments> ]
balance url_param <param> [check_post]
Define the load balancing algorithm to be used in a backend.

<algorithm> is the algorithm used to select a server when doing load
        balancing. This only applies when no persistence information
        is available, or when a connection is redispatched to another
        server. <algorithm> may be one of the following :

算法

balance

roundrobin 
static-rr
leastconn
first
source
uri 
url_param
hdr(<name>)hdr(user-agent)
rdp-cookie
rdp-cookie(<name>)

hash-type:哈希算法

hash-type <method> <function> <modifier>
    methodmap-based:除权取余法,哈希数据结构是静态数组  
      consistent:一致性哈希,哈希数据结构是一棵树  
    function : 哈希函数,取值:sdbm,djb2,wt6  
    modifier: 取值avalanche时,将修改哈希值,而非直接使用 
default_backend <backend>
无use_backend 匹配时,使用默认的backend,用于frontend中 
default-server [param*]
  为backend中的各server设定默认选项 

配置段

代理配置段:
   - defaults
   - frontend
   - backend
   - listen
Frontend段:指定接收客户端连接侦听套接字设置
ackend段:指定将连接请求转发至后端服务器的相关设置
Listen段:指定完整的前后端设置
proxy 名称:使用字母 数字 - _ . : 并区分字符大小写

性能调整

性能调整:
  maxconn :设置每个haproxy进程所能接受的最大并发连接数
  maxconnrate :设置每个进程每秒种所能建立的最大连接数量 #传输层
  maxsessrate :设置每个进程每秒种所能建立的最大会话数量 #会话层
  maxsslconn : 每进程支持SSL的最大连接数量
  spread-checks <0..50, in percent> 健康检测延迟时长百分比,建议2-5之间

日志

日志系统

log:
  log global
  log <address> [len <length>] <facility> [<level> [<minlevel>]]
    length 日志行的长度,默认1024 
  no log 
  注意:
     默认发往本机的日志服务器 
    (1) local2.*      /var/log/local2.log 
    (2) $ModLoad      imudp  
    $UDPServerRun 514
  log-format <string>:
  参考文档实现combined格式的记录 

日志管理

将特定信息记录在日志中
     capture cookie <name> len <length>  
捕获请求和响应报文中的 cookie并记录日志 
     capture request header <name> len <length>
      捕获请求报文中指定的首部并记录日志 
      示例:
      capture request header X-Forwarded-For len 15 
capture response header <name> len <length>
      捕获响应报文中指定的首部并记录日志 
      示例:
      capture response header Content-length len 9 
      capture response header Location len 15 
[root@cos7 ~ ]#vim /etc/haproxy/haproxy.cfg 
frontend web               #多对多
        bind *:80
        default_backend websrvs
backend websrvs
        balance roundrobin
        server srv1 192.168.31.17:80 check
        server srv2 192.168.31.27:80 check

或者用如下
listen http          
      bind 192.168.31.7:80      #一对一

frontend web
        bind *:80
        default_backend websrvs
backend websrvs
        default-server inter 1000 weight 10
        balance roundrobin
        server srv1 192.168.31.17:80 check weight 2
        server srv2 192.168.31.27:80 check maxconn 5000 backlog 100
        server backupsrv 192.168.31.7:8080 check   #sorry server
[root@cos6 ~ ]#for i in {1..100};do curl 192.168.31.7;sleep .5;done
<h1>rs2</h1>
<h1>rs2</h1>
<h1>rs2</h1>
<h1>rs2</h1>
<h1>rs2</h1>
<h1>rs1</h1>
<h1>rs2</h1>

把rs1和rs2服务都停了,则会显示自定义的道歉页面

  server srv1 192.168.31.17:80 check disabled  #可以用来灰度发布
  server srv1 192.168.31.17:80 check redir http://www.baidu.com
  curl -L 192.168.31.7
  如果调度到192.168.1.17,则会把http://www.baidu.com网址返回给客户端,让客户端去访问此网址
  check选项实现后台服务器(upstream)健康性检测
  backlog 后援队列,即等待连接的客户端数量

健康状态检测

 check:对当前server做健康状态检测,只用于四层检测
  注意:httpchk,“smtpchk”, “mysql-check”, “pgsql-check” and “ssl-hello-chk” 用于定义应用层检测方法
        addr :检测时使用的IP地址 
        port :针对此端口进行检测
        inter <delay>:检测之间的时间间隔,默认为2000ms  
        rise <count>:连续多少次检测结果为“成功”才标记为可用;默认为2  
        fall <count>:连续多少次检测结果为“失败”才标记为不可用;默认为3 
 disabled:标记为不可用
 redir <prefix>:将发往此server的所有GET和HEAD类的请求重定向至指定的URL 

cookie配置

实现session会话绑定

cookie <value>:为当前server指定cookie值,实现基于cookie的会话黏性
  cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ] 
  [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain <domain> ]* 
  [ maxidle <idle> ] [ maxlife <life> ]
  <name>:cookie名称,用于实现持久连接
        rewrite:重写 
        insert:插入 
        prefix:前缀
        nocache:当client和hapoxy之间有缓存时,不缓存cookie 

cookie配置示例

基于cookie的session sticky的实现
  backend websrvs
        cookie WEBSRV insert nocache
        server srv1 172.16.0.6:80 weight 2 check rise 1 fall 2 maxconn 3000 cookie srv1
        server srv2 172.16.0.7:80 weight 1 check rise 1 fall 2 maxconn 3000 cookie srv2 

curl -b WEBSRV cookie=srv1 192.168.31.17

统计接口启用相关的参数

stats enable
      启用统计页;基于默认的参数启用stats page 
stats hide-version 隐藏版本
stats refresh <delay>
      设定自动刷新时间间隔 
stats uri <prefix>
      自定义stats page uri,默认值:/haproxy?stats 
stats realm <realm>
      认证时的realm,示例:stats realm : HAProxy\ Statistics 
stats auth <user>:<passwd>
      认证时的账号和密码,可使用多次,默认:no authentication 
stats admin { if | unless } <cond>   #staus admin true
      启用stats page中的管理功能

配置示例

listen stats
      bind :9527 
      stats enable
      stats hide-version 
      stats uri /hastats
      stats realm HAPorxy\ Stats\ Page 
      stats auth admin1:password1 
      stats auth admin1:password2 
      stats refresh 3s 
      stats admin if TRUE 

示例

vim /etc/haproxy/haproxy.cfg
listen haproxy
        bind 192.168.31.7:9527   #我做实验用的是80端口
        stats enable
        stats hide-version
        stats refresh 30
        stats uri /dhy-ha
        stats realm : HAproxy\Statistics
        stats auth dhy:dhy1
        stats admin if TRUE  
frontend web
        bind 192.168.31.7:80
        default_backend websrvs

backend  websrvs
        cookie WEBSRV insert nocache
        server srv1 192.168.31.17:80 check cookie dhy17 maxconn 5000
        server srv2 192.168.31.27:80 check cookie dhy27 maxconn 5000


这里写图片描述
这里写图片描述

工作模式

maxconn :为指定的frontend定义其最大并发连接数;默认为3000
mode { tcp|http|health }
  定义haproxy的工作模式
  tcp:基于layer4实现代理;可代理mysql, pgsql, ssh, ssl等协议,https时使用此模式,默认模式
  http:仅当代理协议为http时使用,CentOS中haproxy实际的默认模式
  health:工作为健康状态检查的响应模式,当连接请求到达时回应“OK”后即断开连接,较少使用

tcp是伪代理,真正的代理是tcp转发,此处是应用层模拟的传输层;后端服务器日志你看到的是代理服务器在访问后端服务器

TCP模式示例

示例:
      listen ssh
      bind :22022 
      balance leastconn 
      mode tcp
      server sshsrv1 192.168.31.17:22 check 
      server sshsrv2 192.168.31.27 check 

健康状态检测

对后端服务器做http协议健康状态检测:通常用于backend
      option httpchk 默认向后端服务器发请求:OPTIONS / HTTP/1.0 
      option httpchk <uri>
      option httpchk <method> <uri>
      option httpchk <method> <uri> <version>               #开始行
            定义基于http协议的7层健康状态检测机制 
      http-check expect [!] <match> <pattern>
            http协议健康状态检测响应内容或指定响应码 
————————————————————
https://cbonte.github.io/haproxy-dconv/1.5/configuration.html#4-option%20httpchk
backend websrvs
#option httpchk GET / HTTP/1.1\r\nhost:   #实验未能成功,添加官网如下成功
option httpchk OPTIONS * HTTP/1.1\r\nhost:
http-check expect status 200
server srv1 192.168.31.17:80 check

curl 192.168.31.17 503 服务不可用
curl 192.168.31.17  正常访问

forwardfor配置

option forwardfor [ except <network> ] [ header <name> ] [ if-none ]
      在由haproxy发往后端主机的请求报文中添加“X-Forwarded-For”首部,其值为前端客户端的地址;用于向后端主发送真实的客户端IP     #在日志中添加X-Forwarded-For
            [ except <network> ]:请求报请来自此处指定的网络时不予添加此首部, 如haproxy自身所在网络
            [ header <name> ]:使用自定义的首部名称,而非“X-Forwarded-For ”  
            [ if-none ] 如果没有首部才添加首部,如果有使用默认值 

为指定的MIME类型启用压缩传输功能
      compression algo <algorithm> ...:启用http协议的压缩机制,指明压缩 算法gzip, deflate
      compression type <mime type> ...:指明压缩的MIMI类型 

示例

[root@cos7 ~ ]#vim /etc/haproxy/haproxy.cfg 
option forwardfor       except 127.0.0.0/8  #默认头部是X-Forwarded-For
[root@cos17 ~ ]#vim /etc/httpd/conf/httpd.conf 
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{X-Forwarded-For}i\"" combined

#自定义头部
option forwardfor       except 127.0.0.0/8 header dhytest
[root@cos17 ~ ]#vim /etc/httpd/conf/httpd.conf 
\"%{dhytest}i\"
[root@cos17 ~ ]#tail -f /var/log/httpd/accss_log

错误页配置

后端服务器宕机,代理服务器错误页面
[proxy-4.1版](https://cbonte.github.io/haproxy-dconv/1.5/configuration.html#4-errorfile)
errorfile <code> <file> 自定义错误页
      <code>:HTTP status code.
            支持200, 400, 403, 408, 500, 502, 503, 504. 
      <file>:错误页文件路径
示例:
      errorfile 400 /etc/haproxy/errorfiles/400badreq.http 
      errorfile 408 /dev/null # workaround Chrome pre-connect bug 
      errorfile 403 /etc/haproxy/errorfiles/403forbid.http 
      errorfile 503 /etc/haproxy/errorfiles/503sorry.http
errorloc <code> <url>
      相当于errorloc302 <code> <url>,利用302重定向至指URL
      示例:errorloc 503 http://www.dhy.com/error_pages/503.html   #加到backend后端

修改报文首部

在请求报文尾部添加指定首部
      reqadd <string> [{if | unless} <cond>] 
在响应报文尾部添加指定首部
      rspadd <string> [{if | unless} <cond>] 
      示例:rspadd X-Via:\ HAPorxy
从请求报文中删除匹配正则表达式的首部 
      reqdel <search> [{if | unless} <cond>]  
      reqidel <search> [{if | unless} <cond>] 不分大小写 
从响应报文中删除匹配正则表达式的首部
      rspdel <search> [{if | unless} <cond>] 
      rspidel <search> [{if | unless} <cond>] 不分大小写 ignore
      示例: rspidel server.* 

示例

[root@cos7 ~ ]#vim /etc/haproxy/haproxy.cfg
listen ssh
        bind :22222
        balance leastconn
        mode tcp
        server sshsrv1 192.168.31.17:22 check
        server sshsrv2 192.168.31.27:22 check

listen haproxy
        bind 192.168.31.7:9527
        stats enable
        stats hide-version
        stats refresh 30
        stats uri /dhy-ha
        stats realm : haproxy:dhy
        stats auth dhy:dhy1
        stats admin if TRUE

frontend web
        bind 192.168.31.7:80
        default_backend websrvs
        rspidel server.*
        rspadd server:\ dhy-nginx
        reqadd dhyheader:\ requestheader-dhy
        errorfile 503 /etc/haproxy/errorfiles/503.html
backend  websrvs
        cookie WEBSRV insert nocache
        server srv1 192.168.31.17:80 check cookie dhy17 maxconn 5000
        server srv2 192.168.31.27:80 check cookie dhy27 maxconn 5000
[root@cos7 ~ ]#systemctl reload haproxy

[root@cos17 ~ ]#vim /etc/httpd/conf/httpd.conf
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\"  \"%{dhyheader}i\"" combined

[root@cos6 ~ ]#curl -I 192.168.31.7
HTTP/1.1 200 OK
Date: Fri, 14 Sep 2018 09:14:29 GMT
Last-Modified: Fri, 14 Sep 2018 07:44:58 GMT
ETag: "10-575d0000e1342"
Accept-Ranges: bytes
Content-Length: 16
Content-Type: text/html; charset=UTF-8
server: dhy-nginx                         #"国产"nginx
Set-Cookie: WEBSRV=dhy17; path=/
Cache-control: private

[root@cos6 ~ ]#for i in {1..100};do curl 192.168.31.7;sleep 0.5;done
<h1>rs2-27</h1>
<h1>rs1-17</h1>
<h1>rs2-27</h1>
<h1>rs1-17</h1>

[root@cos17 ~ ]#tail -f /var/log/httpd/access_log
192.168.31.7 - - [14/Sep/2018:17:30:43 +0800] "GET / HTTP/1.1" 200 16 "-"  "requestheader-dhy"
192.168.31.7 - - [14/Sep/2018:17:30:44 +0800] "GET / HTTP/1.1" 200 16 "-"  "requestheader-dhy"

图3
这里写图片描述

[root@cos7 ~ ]#mkdri -p /etc/haproxy/errorfiles/
[root@cos7 ~ ]#echo "503 error" > /etc/haproxy/errorfiles/503.html
[root@cos17 ~ ]#systemctl stop httpd
[root@cos27 ~ ]#systemctl stop httpd
[root@cos6 ~ ]#for i in {1..100};do curl 192.168.31.7;sleep 0.5;done
503 error
503 error
503 error

acl:access control list

ACL

acl:访问控制列表(ACL)的使用提供了一个灵活的解决方案来执行内容交换,并且通常基于从请求中提取的内容、响应或任何环境状态进行决策          #类似dns的智能dns
acl <aclname> <criterion> [flags] [operator] [<value>] ...
      <aclname>:ACL名称,可使用字母 数字 : . - _ ,区分字符大小写 
      <criterion>: 比较的标准和条件 

     <value>的类型:
      - boolean
      - integer or integer range 
      - IP address / network
      - string (exact, substring, suffix, prefix, subdir, domain) 
      - regular expression
      - hex block 

     <flags>
      -i 不区分大小写
      -m 使用指定的pattern匹配方法 
      -n 不做DNS解析
      -u 强制每个ACL必须唯一ID,否则多个同名ACL或关系 
      -- 强制flag结束. 当字符串和某个flag相似时使用 
    [operator]
      匹配整数值:eq、ge、gt、le、lt 
      匹配字符串:
        - exact match (-m str) :字符串必须完全匹配模式
        - substring match (-m sub) :在提取的字符串中查找模式,如果其中任何一个被发现,ACL将匹配
        - prefix match (-m beg) :在提取的字符串首部中查找模式,如果其中任何一个被发现,ACL将匹配
        - suffix match (-m end) :将模式与提取字符串的尾部进行比较,如果其中任何一个匹配,则ACL进行匹配
        - subdir match (-m dir) :查看提取出来的用斜线分隔(“/”)的字符串,如果其中任何一个匹配,则ACL进行匹配
        - domain match (-m dom) :查找提取的用点(“.”)分隔字符串,如果其中任何一个匹配,则ACL进行匹配 

ACL 逻辑

acl作为条件时的逻辑关系:  
- 与:隐式(默认)使用
- 或:使用“or ” 或 “||”表示 
- 否定:使用“!“ 表示
示例:if invalid_src invalid_port 与关系  
      if invalid_src || invalid_port 或  
      if ! invalid_src 非 
<criterion> :各种条件
      dst       目标IP 
      dst_port  目标PORT 
      src       源IP 
      src_port  源PORT
      示例:acl invalid_src src 192.168.31.1
[root@cos7 ~ ]#vim /etc/haproxy/haproxy.cfg 
listen haproxy
        bind 192.168.31.7:9527
        acl valid_src src 192.168.31.1
        stats enable
        stats hide-version
        stats refresh 30
        stats uri /dhy-ha
        stats realm : haproxy:dhy
        stats auth dhy:dhy1
        stats admin if ! valid_src

图4
这里写图片描述

[root@cos7 ~ ]#vim /etc/haproxy/haproxy.cfg 
frontedn web
      bind 192.168.31.7:80
      block if METH_HEAD

      acl image_acl path_end .jpg .png    #图片服务器
      default_backedn websrvs
      use_backend appsrvs if image_acl    #图片服务器
backend websrvs
      srvser srv1 192.168.31.17:80 check
backend appsrvs
      srvser srv2 192.168.31.27:80 check   #图片服务器

支持https协议

配置HAProxy支持https协议:  
支持ssl会话;
      bind *:443 ssl crt /PATH/TO/SOME_PEM_FILE 
      crt 后证书文件为PEM格式,且同时包含证书和所有私钥  
            cat demo.crt demo.key > demo.pem
把80端口的请求重向定443
      bind *:80
      redirect scheme https if !{ ssl_fc }   
向后端传递用户请求的协议和端口(frontend或backend)
      http-request set-header X-Forwarded-Port %[dst_port] 
      http-request add-header X-Forwared-Proto https if { ssl_fc } 

frontend web
      bind 172.18.0.7:80
      bind 172.18.0.7:443 ssl crt /etc/haproxy/a.pem
mod tcp
-----------------------
cd /etc/pki/tls/certs/
make a.pem
cat a.pem #包含了证书和私钥,如果是自己手动创建的则,cat a.crt a.key > a.pem
Privacy Enhanced Mail 私有,加强,邮件

猜你喜欢

转载自blog.csdn.net/csdn_immortal/article/details/82708129
今日推荐