HAProxy之一----HAPproxy配置参数详解

企业服务架构图及负载均衡的要求

场景说明

• 在企业生产环境中,每天会有很多的需求变更,比如增加服务器、新业务上线、url路由修改、域名配置等等,对于前端负载均衡设备来说,容易维护,复杂度低,是首选指标。在企业中,稳定压倒一切,与其搞得很复杂,经常出问题,不如做的简单和稳定。

• 在企业中,90%以上的故障,来源于需求变更。可能是程序bug,也可能是人为故障,也可能是架构设计问题等等。

• 前端负载均衡设备为重中之重,在软件选型上一定充分考虑,能满足业务的前提下,尽可能降低复杂度,提高易维护性

小型架构图

中型架构图

 

 

公有云Web架构

 

私有云web架构

 

什么是负载均衡:

•负载均衡(Load Balance,简称LB)是一种服务或基于硬件设备等实现的高可用反向代理技术,负载均衡将特定的业务(web服务、网络流量等)分担给指定的一个或多个后端特定的服务器或设备,从而提高了公司业务的并发处理能力、保证了业务的高可用性、方便了业务后期的水平动态扩展。

•https://yq.aliyun.com/articles/1803#阿里云SLB介绍

为什么使用负载均衡:

•Web服务器的动态水平扩展
  •对用户无感知

•增加业务并发访问及处理能力
  •解决单服务器瓶颈问题

•节约公网IP地址
  •降低IT支出成本

•隐藏内部服务器IP
  •提高内部服务器安全性

•配置简单
  •固定格式的配置文件

•功能丰富
  •支持四层和七层,支持动态下线主机

•性能较强
  •并发数万甚至数十万

常见有哪些负载均衡:

•软件负载:

•四层:

•LVS(Linux Virtual Server)
•HAProxy(High Availability Proxy)
•Nginx()
•……

•七层:

•HAProxy
•Nginx
•……

•硬件负载:

•F5
•Netscaler
•……

典型应用场景:

•应用场景:

•四层:Redis、Mysql、RabbitMQ、Memcache等

•七层:Nginx、Tomcat、Apache、PHP、图片、动静分离、API等

四层和七层负载均衡的区别

四层:

通过分析IP层及TCP/UDP层的流量实现的基于"IP+端口"的负载均衡。

七层:

可以根据内容,再配合负载均衡算法来选择后端服务器,不但可以根据"ip+端口"方式进行负载分流,还可以根据网站的URL,访问域名,浏览器类别,语言等决定负载均衡的策略。七层负载均衡模式下,负载均衡与客户端及后端的服务器会分别建立一次TCP连接,而在四层负载均衡模式下(DR),仅建立一次TCP连接;七层负载均衡对负载均衡设备的要求更高,处理能力也低于四层负载均衡。

Haproxy介绍

1、简单介绍

•HAProxy: 是法国人Willy Tarreau开发的一个开源软件,是一款应对客户端10000以上的同时连接的高性能的TCP和HTTP负载均衡器。其功能是用来提供基于cookie的持久性,基于内容的交换,过载保护的高级流量管制,自动故障切换,以正则表达式为基础的控制运行时间,基于Web的报表,高级日志记录以帮助排除故障的应用或网络及其他功能。

•LB Cluster:
四层:lvs, nginx(stream),haproxy(mode tcp)
七层:http: nginx(http), haproxy(mode http), httpd...

•官网:
http://www.haproxy.org
https://www.haproxy.com

•文档:https://cbonte.github.io/haproxy-dconv/

 

2、定义

(1)HAProxy是一个使用C语言编写的自由及开放源代码软件,其提供高性能性、负载均衡,以及基于TCP和HTTP的应用程序代理。相较与 Nginx,HAProxy 更专注与反向代理,因此它可以支持更多的选项更精细的控制更多的健康状态检测机制负载均衡算法

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

(3)包括 GitHub、Bitbucket、Stack Overflow、Reddit、Tumblr、Twitter在内众多知名网站,及亚马逊网络服务系统都使用了HAProxy

 

3、HAProxy功能

•HAProxy是TCP / HTTP反向代理服务器,尤其适合于高可用性高并发环境

•可以针对HTTP请求添加cookie,进行路由后端服务器

•可平衡负载至后端服务器,并支持持久连接

•支持基于cookie进行调度

•支持所有主服务器故障切换至备用服务器

•支持专用端口实现监控服务

•支持不影响现有连接情况下停止接受新连接请求

•可以在双向添加,修改或删除HTTP报文首部

•支持基于pattern实现连接请求的访问控制

•通过特定的URI为授权用户提供详细的状态信息

•历史版本更新功能:1.4 1.5 1.6 1.7 1.8 1.9 2.0-dev

•1.8:多线程,HTTP/2缓存……

•1.7:服务器动态配置,多类型证书……

•1.6:DNS解析支持,HTTP连接多路复用……

•1.5:开始支持SSL,IPV6,keepalived……

 

4、Haproxy的特性

① 可靠性与稳定性都非常出色,可与硬件级设备媲美。

② 支持连接拒绝,可以用于防止DDoS攻击

③ 支持长连接、短连接和日志功能,可根据需要灵活配置

④ 路由HTTP请求到后端服务器,基于cookie作会话绑定;同时支持通过获取指的url来检测后端服务器的状态

⑤ HAProxy还拥有功能强大的ACL支持,可灵活配置路由功能,实现动静分离,在架构设计与实现上带来很大方便

⑥ 可支持四层和七层负载均衡,几乎能为所有服务常见的提供负载均衡功能

⑦ 拥有功能强大的后端服务器的状态监控web页面,可以实时了解设备的运行状态,还可实现设备上下线等简单操作。例:cobbler、samba、httpd

⑧ 支持多种负载均衡调度算法,并且也支持session保持

 

5、Haproxy安装方式

(1)Haproxy安装常用两种方式,yum安装和源码包安装

(2)yum 安装:通常是在线安装,好处是安装方式简单,不易出错;常用的安装yum源为epel

(3)源码包安装:是先将 Haproxy 的源码下载下来,在自己的系统里编译生成可执行文件,然后执行,好处是因为是在自己的系统上编译的,更符合自己系统的性能,也就是说在自己的系统上执行 Haproxy服务性能效率更好。

(4)区别:路径和启动方式不同,支持的模块也不同

  yum 安装方式:

[root@centos7~]#yum install haproxy

 源码编译HAProxy:  

 官网下载HAProxy包,并解压包,切换到haproxy包目录下

[root@centos17haproxy-1.8.20]#tar xvf haproxy-1.8.20.tar.gz && cd haproxy-1.8.20

 安装相关依赖包

[root@centos17haproxy-1.8.20]#yum install gcc gcc-c++ glibc glibc-devel pcrepcre-devel openssl openssl-devel systemd-devel net-tools vim iotopbczip unzip zlib-devellrzsztree screen lsof tcpdump wget ntpdate

  开始编译

[root@centos17haproxy-1.8.20]#make ARCH=x86_64 TARGET=linux2628 USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 PREFIX=/usr/local/haproxy

  指定安装路径

[root@centos17haproxy-1.8.20]#make install PREFIX=/usr/local/haproxy

  将可执行程序haproxy复制/usr/sbin/目录下

[root@centos17haproxy-1.8.20]#cp haproxy  /usr/sbin/

 创建haproxy启动脚本 vim  /usr/lib/systemd/system/haproxy.service

[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target

[Service]
ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg   -c -q
ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg   -p /run/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID

[Install]
WantedBy=multi-user.target

 创建启动脚本目录

[root@centos_17haproxy]#mkdir /etc/haproxy

创建haproxy服务启动目录及基本的配置文件

[root@centos_17haproxy]#vim /etc/haproxy/haproxy.cfg 
global
maxconn 100000
chroot /usr/local/haproxy
#stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
user haproxy
group haproxy
daemon
nbproc 2   绑定两个cpu就开启下面两个,绑定四个就开启四个
cpu-map 1 0
cpu-map 2 1
#cpu-map 3 2
#cpu-map 4 3
pidfile /run/haproxy.pid
log 127.0.0.1 local3 info

defaults
option http-keep-alive
option  forwardfor
maxconn 100000
mode http
timeout connect 300000ms
timeout client  300000ms
timeout server  300000ms

listen stats
 mode http
 bind 0.0.0.0:9999
 stats enable
 log global
 stats uri     /haproxy-status
 stats auth    haadmin:q1w2e3r4ys

listen  web_port
 bind 0.0.0.0:80
 mode http
 log global
 server web1  127.0.0.1:8080  check inter 3000 fall 2 rise 5

 创建一个haproxy用户,并设置为系统不能登录的shell类型

[root@centos_17haproxy]#useradd -s /sbin/nologin haproxy

 启动haproxy服务

[root@centos_17haproxy]#systemctl start haproxy

 查看haproxy启动的线程数

[root@centos_17haproxy]#ps -ef |grep haproxy  可以看到此时用户名是nobody启动双线程,并都属于一个父进程
root 13270 1 0 21:59 ? 00:00:00 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
haproxy 13272 13270 0 21:59 ? 00:00:00 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
haproxy 13273 13270 0 21:59 ? 00:00:00 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
root 13278 12621 0 21:59 pts/0 00:00:00 grep --color=auto haproxy

HAProxy组成

程序环境:

主程序:/usr/sbin/haproxy
配置文件:/etc/haproxy/haproxy.cfg
Unit file:/usr/lib/systemd/system/haproxy.service

配置段:

global:全局配置段

进程及安全配置相关的参数
性能调整相关参数
Debug参数

 proxies:代理配置段

defaults:为frontend, backend, listen提供默认配置
frontend:前端,相当于nginx中的server {}
backend:后端,相当于nginx中的upstream {}
listen:同时拥有前端和后端配置

简单的配置示例:在vim /etc/haproxy/haproxy.cfg配置文件中修改

frontend web
bind 192.168.37.17:80  本机haproxy的IP地址
default_backend websrvs

backend websrvs
balance roundrobin
server srv1 172.16.100.6:80  后台服务的IP地址
server srv2 172.16.100.7:80 

  listen用法:

listen web
        bind 192.168.37.17:80
        server web1 192.168.37.27:80

  访问网页:

 Haproxy配置-global

•chroot  #锁定运行目录
•deamon  #以守护进程运行
•#stats socket /var/lib/haproxy/haproxy.sock  mode 600 level admin   #socket文件
•user, group, uid, gid  #运行haproxy的用户身份
•nbproc   #开启的haproxy进程数,与CPU保持一致
•nbthread  #指定每个haproxy进程开启的线程数,默认为每个进程一个线程
•cpu-map 1 0 #绑定haproxy进程至指定CPU
•maxconn    #每个haproxy进程的最大并发连接数
•maxsslconn  #SSL每个haproxy进程ssl最大连接数
•maxconnrate  #每个进程每秒最大连接数
•spread-checks #后端server状态check随机提前或延迟百分比时间,建议2-5(20%-50%)之间,成百上千个后端服务器可加此选项。
•pidfile#指定pid文件路径
•log 127.0.0.1 local3 info #定义全局的syslog服务器;最多可以定义两个

自定义haproxy的log日志

1、在rsyslog.conf配置配置文件中开启log日志功能。

[root@centos_17haproxy]#vim /etc/rsyslog.conf
$ModLoad imudp 开启udp模式存放日志 $UDPServerRun 514 开启端口 local3.* /var/log/haproxy.log 存放haproxy日志路径

 修改完rsyslog配置文件之后重新启动:systemctl restart rsyslog

 2、在haproxyd的global全局配置文件中修改对应的local3

log 127.0.0.1 local3 

配置完之后重新启动haproxy服务:systemctl restart haproxy  

3、验证结果,此时修改后的配置文件中已经生成单独的log日志文件。

[root@centos_17haproxy]#tail /var/log/haproxy.log 
Dec 22 00:03:19 localhost haproxy[15460]: Proxy stats started.
Dec 22 00:03:19 localhost haproxy[15460]: Proxy web_port started.

HAProxy Proxies配置

•defaults [<name>] #默认配置项,针对以下的frontend、backend和lsiten生效,可以多个name
•frontend <name> #前端servername,类似于Nginx的一个虚拟主机server。
•backend <name> #后端服务器组,等于nginx的upstream
•listen <name> #将frontend和backend合并在一起配置

 注:name字段只能使用”-”、”_”、”.”、和”:”,并且严格区分大小写,例如:Web和web是完全不同的两组服务器。

Proxies配置-defaults

defaults 配置参数:

•option redispatch   #当server Id对应的服务器挂掉后,强制定向到其他健康的服务器
•option abortonclose  #当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接
•option http-keep-alive 60  #开启会话保持
•option forwardfor   #开启IP透传
•mode http   #默认工作类型
•timeout connect 60s  #转发客户端请求到后端server的最长连接时间(TCP之前)
•timeout server 600s  #转发客户端请求到后端服务端的超时超时时长(TCP之后)
•timeout client 600s  #与客户端的最长空闲时间
•timeout http-keep-alive 120s  #session 会话保持超时时间,范围内会转发到相同的后端服务器
•#timeout check 5s  #对后端服务器的检测超时时间

Proxies配置-frontend配置参数

•bind:指定HAProxy的监听地址,可以是IPV4或IPV6,可以同时监听多个IP或端口,可同时用于listen字段中
•bind [<address>]:<port_range> [, ...] [param*]
•mode http/tcp #指定负载协议类型
•use_backend backend_name #调用的后端服务器组名称

 bind指令仅能用于frontend和listen区段,用于定义一个或几个监听的套接字。

① <address>:可选选项,其可以为主机名、IPv4地址、IPv6地址或*;省略此选项、将其指定为*或0.0.0.0时,将监听当前系统的所有IPv4地址;

② <port_range>:可以是一个特定的TCP端口,也可是一个端口范围(如5005-5010),代理服务器将通过指定的端口来接收客户端请求;需要注意的是,每组监听的套接字

③ <address:port>在同一个实例上只能使用一次,而且小于1024的端口需要有特定权限的用户才能使用,这可能需要通过uid参数来定义;

④ <interface>:指定物理接口的名称,仅能在Linux系统上使用;其不能使用接口别名,而仅能使用物理接口名称,而且只有管理有权限指定绑定的物理接口;

 示例:

•frontend WEB_PORT
•bind :80,:8080
•bind 192.168.7.102:10080,192.168.7.102:10043
•use_backend backend_name

Proxies配置-backend配置参数

•mode http/tcp #指定负载协议类型
•option #配置选项
•server #定义后端realserver

 注意:option后面加httpchk,smtpchk, mysql-check, pgsql-check,ssl-hello-chk方法,可用于实现更多应用层检测功能。

 示例:

•frontend WEB_PORT
•bind :80,:8080
•bind 192.168.7.102:10080,192.168.7.102:10043
•use_backend backend_name

后端服务器状态监测及相关配置

•check #对指定real进行健康状态检查,默认不开启
•addr IP  #可指定的健康状态监测IP
•port num  #指定的健康状态监测端口
•inter num  #健康状态检查间隔时间,默认2000 ms
•fall num  #后端服务器失效检查次数,默认为3
•rise num  #后端服务器从下线恢复检查次数,默认为2
•weight #默认为1,最大值为256,0表示不参与负载均衡
•backup #将后端服务器标记为备份状态
•disabled #将后端服务器标记为不可用状态
•redirect prefix http://www.magedu.com   #将请求临时重定向至其它URL,只适用于http模式
•maxconn <maxconn>:当前后端server的最大并发连接数
•backlog <backlog>:当server的连接数达到上限后的后援队列长度 

(mode http|tcp|health)设定实例的运行模式或协议。当实现内容交换时,前端和后端必须工作于同一种模式(一般说来都是HTTP模式),否则将无法启动实例。可以放在任何4段中 default frontent backent listen

① tcp:实例运行于纯TCP模式,在客户端和服务器端之间将建立一个全双工的连接,且不会对7层报文做任何类型的检查,通常用于SSL、SSH、SMTP等应用;

② http:实例运行于HTTP模式,7层,客户端请求在转发至后端服务器之前将被深度分析,所有不与RFC格式兼容的请求都会被拒绝;centos实际默认模式

③ health:实例工作于health模式,其对入站请求仅响应"OK"信息并关闭连接,且不会记录任何日志信息;此模式将用于响应外部组件的健康状态检查请求;目前来讲,此模式已经废弃,因为tcp或http模式中的monitor关键字可完成类似功能;可以用于测试

  示例:

listen web
        mode http
        bind 192.168.37.17:80
        server web1 192.168.37.27:80 check weight 3  inter 3s fall 3 rise 5 #check后面命令是对haproxy进行状态检测
        server web2 192.168.37.37:80 check inter 3s fall 3 rise 5 backup
        redirect prefix http://www.magedu.com    临时重定向,只适用于http模式

 frontend/ backend及Proxies配置-listen配置案例

 使用listen替换frontend和backend的配置方式:

#官网业务访问入口======================================
frontend WEB_PORT_80
        bind 192.168.37.17:80
        mode tcp
        use_backend web_prot_http_nodes
backend web_prot_http_nodes
        mode http
        option forwardfor
        server 192.168.37.27:80 check inter 3000 fall 3 rise 5
        server 192.168.37.37:80 check inter 3000 fall 3 rise 5

frontend WEB_PORT_443
        bind 192.168.37.17:443
        mode tcp
        use_backend web_prot_http_nodes
backend web_prot_http_nodes
        mode http
        option forwardfor
        server  192.168.37.27:443 check inter 3000 fall 3 rise 5
        server  192.168.37.37:443 check inter 3000 fall 3 rise 5

#官网业务访问入口=====================================
listen WEB_PORT_80
        bind 192.168.37.17:80
        mode tcp
        option forwardfor
        server web1 192.168.37.17:80 check inter 3000 fall 3 rise 5
        server web2 192.168.37.27:80 check inter 3000 fall 3 rise 5

listen WEB_PORT_443
        bind 192.168.37.17:443
        mode tcp
        option forwardfor
        server web1 192.168.37.27:443 check inter 3000 fall 3 rise 5
        server web2 192.168.37.37:443 check inter 3000 fall 3 rise 5

 

HAProxy 调度算法 

balance:指明对后端服务器的调度算法,配置在listen或backend

静态算法:按照事先定义好的规则轮询公平调度,不关心后端服务器的当前负载、链接数和相应速度等,且无法实时修改权重,只能重启后生效。

•static-rr:基于权重的轮询调度,不支持权重的运行时调整及后端服务器慢启动,其后端主机数量没有限制

•first:根据服务器在列表中的位置,自上而下进行调度,但是其只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务,因此会忽略服务器的权重设置。

 first示例:

#官网业务访问入口=====================================
listen WEB_PORT_80
        bind 192.168.37.17:80
        balance first
        mode tcp
        option forwardfor
        server web1 192.168.37.27:80 check inter 3000 fall 3 rise 5
        server web2 192.168.37.37:80 check inter 3000 fall 3 rise 5

 测试效果,先只会访问第一台服务器,当达到最大连接数,才会访问到第二台服务器。

动态算法:基于后端服务器状态进行调度适当调整,比如优先调度至当前负载较低的服务器,且权重可以在haproxy运行时动态调整无需重启。

roundrobin:基于权重的轮询动态调度算法,支持权重的运行时调整,不等于lvs 的rr,支持慢启动即新加的服务器会逐渐增加转发数,每个后端backend中最多支持4095个server,此为默认调度算法,server 权重设置weight。

leastconn:加权的最少连接的动态,支持权重的运行时调整和慢启动,即当前后端服务器连接最少的优先调度,比较适合长连接的场景使用,比如MySQL等场景,其并不太适用于较短会话的应用层协议。

roundrobin示例:

listen WEB_PORT_80
        bind 192.168.37.17:80
        #balance first
        balance roundrobin  默认是此算法
        mode tcp
        option forwardfor
        server web1 192.168.37.27:80 check inter 3000 fall 3 rise 5
        server web2 192.168.37.37:80 check inter 3000 fall 3 rise 5

hash 算法

source:源地址hash,基于用户源地址hash并将请求转发到后端服务器,默认为静态即取模方式,但是可以通过hash-type支持的选项更改,后续同一个源地址请求将被转发至同一个后端web服务器,比较适用于session保持/缓存业务等场景,用法不多。
•map-based:取模法,基于服务器权重的hash数组取模,该hash是静态的即不支持在线调整权重,不支持慢启动,其对后端服务器调度均衡,缺点是当服务器的总权重发生变化时,即有服务器上线或下线,都会因权重发生变化而导致调度结果整体改变,hash(o)mod  n(其中n代表是有几个权重)。

1、source:源地址hash,基于用户源地址hash并将请求转发到后端服务器,默认为静态即取模方式,但是可以通过hash-type支持的选项更改,后续同一个源地址请求将被转发至同一个后端web服务器,比较适用于session保持/缓存业务等场景。
2、consistent:一致性哈希,该hash是动态的,支持在线调整权重,支持慢启动,优点在于当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动。

listen web_prot_http_nodes
   bind 192.168.7.101:80
  mode http
  balance source
  hash-type consistent
  log global
  option forwardfor
  server 192.168.7.101 192.168.7.101:8080 check inter 3000 fall 3 rise 5
  server 192.168.7.102 192.168.7.102:8080 check inter 3000 fall 3 rise 5

3、uri:基于对用户请求的uri做hash并将请求转发到后端指定服务器,适用于后端缓存服务器

 对URI 的左半部分整个uri 做hash 计算,并除以服务器总权重取模

 左半部分:/<path>;<params>

 整个uri :/<path>;<params>?<query>#<frag>

map-based:取模法
consistent:一致性哈希
http://example.org/absolute/URI/with/absolute/path/to/resource.txt #URI/URL
ftp://example.org/resource.txt #URI/URL
/relative/URI/with/absolute/path/to/resource.txt #URI

uri: uniform resource identifier,统一资源标识符,是一个用于标识某一互联网资源名称的字符串

示例:

listen WEB_PORT_80
        bind 192.168.37.17:80
        #balance first
        #balance source
        #hash-type consistent
        balance uri
        mode http
        option forwardfor
        server web1 192.168.37.27:80 check weight 3  inter 3000 fall 3 rise 5
        server web2 192.168.37.37:80 check inter 3000 fall 3 rise 5

 测试效果,访问指定的uri路径文件:

[root@centos_17~]#curl http://192.168.37.17/app/test1.html
192.168.37.37 RS1

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

假设url= http://www.magedu.com/foo/bar/index.php?k1=v1&k2=v2

则:
host = "www.magedu.com"
url_param= "k1=v1&k2=v2"

listen WEB_PORT_80
        bind 192.168.37.17:80  # haproxy调度器IP地址
        #balance first
        #balance source
        #hash-type consistent
        #balance uri
        balance url_param name  定义name值
        mode http  #不支持tcp模式,会切换至tcp的roundrobin负载模式
        option forwardfor
        server web1 192.168.37.27:80 check inter 3000 fall 3 rise 5  # 后端服务器IP地址
        server web2 192.168.37.37:80 check inter 3000 fall 3 rise 5

测试效果,定义的name=的值就会默认访问一个IP地址,不是name=有可能访问另外一个IP地址。

5、hdr(不常用)

hdr(<name>):针对用户每个http头部(header)请求中的指定信息做hash,此处由<name>指定的http首部将会被取出并做hash计算,然后由服务器总权重相除以后派发至某挑出的服务器,假如无有效的值,则会被轮询调度

•hdr( Cookie、User-Agent、host )

6、rdp-cookie对远程桌面的负载,使用cookie保持会话

•rdp-cookie(<name>)

算法总结:

•roundrobin-------->tcp/http 动态  用的比较多,做四层负载,做过session共享用的最多的调度算法,调度轮询,支持权重分配。

•leastconn----------->tcp/http 动态  用的比较多,做四层负载均衡,用于后端服务器上MySQL/PHP/HTTPS

•static-rr-------------->tcp/http 静态轮询,等于roundrobin,但是不支持权重。

•first-------------------->tcp/http 静态,很少使用

•source---------------->tcp/http    取决于hash_type是否consistent,后端服务器没有seesion共享,但是还要实现会话保持

•Uri---------------------->http       取决于hash_type是否consistent,缓存场景,CDN缓存服务器,七层。

•url_param---------->http          取决于hash_type是否consistent,缓存场景,七层

•hdr--------------------->http      取决于hash_type是否consistent,基于请求头部指定的信息做调度,七层模式。

•rdp-cookie--------->tcp         取决于hash_type是否consistent,windows远程桌面,很少使用,四层。

什么时候用四层,什么时候用七层?

在haproxy对用户的请求报文,响应报文,不做响应处理,只做转发作用时,就用四层,通常情况,使用四层做负载。

在haproxy匹配头部信息,匹配某个字段,在做头部报文处理,需要用七层,七层做负载均衡,会对头部报文处理,会影响转发性能。

四层与七层的区别:  

四层:

•在四层负载设备中,把client发送的报文目标地址(原来是负载均衡设备的IP地址),根据均衡设备设置的选择web服务器的规则选择对应的web服务器IP地址,这样client就可以直接跟此服务器建立TCP连接并发送数据。

 

七层:
•七层负载均衡服务器起了一个代理服务器的作用,服务器建立一次TCP连接要三次握手,而client要访问webserver要先与七层负载设备进行三次握手后建立TCP连接,把要访问的报文信息发送给七层负载均衡;然后七层负载均衡再根据设置的均衡规则选择特定的webserver,然后通过三次握手与此台webserver建立TCP连接,然后webserver把需要的数据发送给七层负载均衡设备,负载均衡设备再把数据发送给client;所以,七层负载均衡设备起到了代理服务器的作用。

 七层IP透传:

(1)分析:后端收到服务的请求是haproxy的,所以日志记录的请求ip也是haproxy的;如我们想要记录真实client 的ip,需加forwardfor 选项;

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

(2)格式

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

[ except <network> ] :请求报请来自此处指定的网络时不予添加此首部,如haproxy 自身所在网络

[ header <name> ] :使用自定义的首部名称,而非默认的"X-Forwarded-For"

[ if-none ] 如果没有首部才添加首部,如果有使用默认值

七层负载:

listen web_prot_http_nodes
  bind 192.168.7.102:80  # haproxy主机的IP地址
  mode http
  option forwardfor  IP地址透传
  server web1 blogs.studylinux.net:80 check inter 3000 fall 3 rise 5 # 调度到后端服务器上

确保nginx的日志格式为json格式:以下是nginx的json日志格式

http { 
   log_format access_json '{"@timestamp":"$time_iso8601",'
        '"host":"$server_addr",'
        '"clientip":"$remote_addr",'
        '"size":$body_bytes_sent,'
        '"responsetime":$request_time,'
        '"upstreamtime":"$upstream_response_time",'
        '"upstreamhost":"$upstream_addr",'
        '"http_host":"$host",'
        '"uri":"$uri",'
        '"domain":"$host",'
        '"xff":"$http_x_forwarded_for",'
        '"referer":"$http_referer",'
        '"tcp_xff":"$proxy_protocol_addr",'
        '"http_user_agent":"$http_user_agent",'
        '"status":"$status"}';
    access_log  /var/log/nginx/access.log  access_json;

查看nginx的访问日志就可以收集到client的IP地址: tail -f  /var/log/nginx/access.log

 四层负载:

listen web_prot_http_nodes
   bind 192.168.7.102:80 # haproxy调度器IP地址
   mode tcp
   server web2 blogs.studylinux.net:80 send-proxy check inter 3000 fall 3 rise 5

Nginx配置:需要在nginx配置文件中加入以下两部分内容,并将nginx的日志格式改为json格式。

listen 80 proxy_protocol; # 加入proxy_protocol选项
'"tcp_xff":"$proxy_protocol_addr",' #TCP获取客户端真实IP日志格式,需要添加两个配置选项。

查看nginx的访问日志就可以收集到client的IP地址: tail -f  /var/log/nginx/access.log

Cookie 配置(生产中可以基于haproxy均衡调度到后端服务器)  

cookie <value>:为指定server设定cookie值,此处指定的值将在请求入站时被检查,第一次为此值挑选的server将在后续的请求中被选中,其目的在于实现持久连接的功能; 

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实现的session 保持:

实现原理:首先以轮询的方式第一次给访问用户分配服务器,并给用户发放cookie值,然后用户再次访问时,就会携带cookie值,调度器会区分cookie值,将用户调度到后端服务器,实现cookie的会话黏性。

listen WEB_PORT_80
        bind 192.168.37.17:80
     balance roundrobin  # 以轮询的方式先对用户发放cookie值。
        mode http
        cookie SERVER-COOKIE  insert  indirect  nocache  #先定义,下边才能使用,insert报文首部,nocache 不缓存cookie,其中SERVER-COKIE名称可以自定义。
        server web1 192.168.37.27:80 cookie web-27 check inter 3000 fall 3 rise 5
        server web2 192.168.37.37:80 cookie web-37 check inter 3000 fall 3 rise 5

用curl命令验证cookie会话保持状态:

[root@mysql2 ~]# curl --cookie "SERVER-COOKIE=web1-27" http://192.168.37.27/index.html
192.168.7.103
[root@mysql2 ~]# curl --cookie "SERVER-COOKIE=web1-37" http://192.168.37.37/index.html

配置HAProxy状态页,监测web页面  

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

示例:

vim  /etc/haproxy/haproxy.cfg

listen stats
        bind :9527
        stats enable
        stats hide-version
        stats uri /haproxy-status
        stats realm HAPorxy\Stats\Page
        stats auth haadmin:123456
        stats auth admin:123456
        stats refresh 30s
        stats admin if TRUE

 打开状态页访问:192.168.37.17:9527/haproxy-status

验证HAProxy状态页

session rate(每秒的连接会话信息):
Errors(错误统计信息):
cur:每秒的当前会话数量
Req:错误请求量
max:每秒新的最大会话数量
conn:错误链接量
limit:每秒新的会话限制量
Resp:错误响应量
sessions(会话信息):
Warnings(警告统计信息):
cur:当前会话量
Retr:重新尝试次数
max:最大会话量
Redis:再次发送次数
limit: 限制会话量
Total:总共会话量
Server(real server信息):
LBTot:选中一台服务器所用的总时间
Status:后端机的状态,包括UP和DOWN
Last:和服务器的持续连接时间
LastChk:持续检查后端服务器的时间
Wght:权重
Bytes(流量统计):
Act:活动链接数量
In:网络的字节输入总量
Bck:备份的服务器数量
Out:网络的字节输出总量
Chk:心跳检测时间
Dwn:后端服务器连接后都是DOWN的数量
Denied(拒绝统计信息):
Dwntme:总的downtime时间
Req:拒绝请求量
Thrtle:server 状态
Resp:拒绝回复量

状态页信息

pid = 3698 (process #2, nbproc = 2, nbthread = 2) #pid为当前pid号,process为当前进程号,nbproc和nbthread为一共多少进程和每个进程多少个线程
uptime = 0d 0h00m08s #启动了多长时间
system limits: memmax = unlimited; ulimit-n = 131124 #系统资源限制:内存/最大打开文件数/
maxsock = 131124; maxconn = 65536; maxpipes = 0 #最大socket连接数/单进程最大连接数/最大管道数maxpipes
current conns = 1; current pipes = 0/0; conn rate = 1/sec #当前连接数/当前管道数/当前连接速率
Running tasks: 1/9; idle = 100 % #运行的任务/当前空闲率
active UP:#在线服务器backup UP:#标记为backup的服务器
active UP, going down:#监测未通过正在进入down过程backup UP, going down:#备份服务器正在进入down过程
active DOWN, going up:#down的服务器正在进入up过程backup DOWN, going up:#备份服务器正在进入up过程
active or backup DOWN:#在线的服务器或者是backup的服务器已经转换成了down状态not checked:#标记为不监测的服务器
active or backup DOWN for maintenance (MAINT) #active或者backup服务器认为下线的
active or backup SOFT STOPPED for maintenance #active或者backup被认为软下线(人为将weight改成0)

修改报文首部  

在请求报文尾部添加指定报文:

reqadd<string> [{if | unless} <cond>]#支持条件判断

在响应报文尾部添加指定报文:

rspadd<string> [{if | unless} <cond>]
示例:rspaddX-Via:\HAPorxy

从请求报文中删除匹配正则表达式的首部

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

从响应报文中删除匹配正则表达式的首部

rspdel<search> [{if | unless} <cond>]
rspidel<search> [{if | unless} <cond>]

示例:rspidel  server.* #从相应报文删除server信息
rspidel   X-Powered-By:.* #从响应报文删除X-Powered-By信息

演示:

listen WEB_PORT_80
        bind 192.168.37.17:80
        mode http
        rspidel Server:.*  删除后端服务器的版本信息
        server web1 192.168.37.27:80 check inter 3000 fall 3 rise 5
        server web2 192.168.37.37:80 check inter 3000 fall 3 rise 5

 

  修改前会显示apache的版本号,不安全。

 访问地址:192.168.37.17

 

  修改后,将会删除对应的Server:.*正则表达式后面的所有字符,隐藏后端服务器的版本号,以防私密泄漏,此时访问时,已经无法看到后端服务器的apache版本号。

  访问地址:192.168.37.17

 

 HAProxy 日志配置

定义haproxy日志文件路径:

1、在default配置项定义:

log 127.0.0.1 local{1-7} info #基于syslog记录日志到指定设备,级别有(err、warning、info、debug)

2、配置rsyslog:vim /etc/rsyslog.conf

$ModLoad imudp
$UDPServerRun 514
local3.* /var/log/haproxy.log

3、配置HAProxy:vim /etc/haproxy/haproxy.cfg,在global字段定义log日志级别

global
log         127.0.0.1 local3
#####################################################
listen web_port
bind 127.0.0.1:80
mode http
log global
option tcplog
server web1 127.0.0.1:8080 check inter 3000 fall 2 rise 5

4、重启rsyslog服务并访问haproxy状态页

自定义记录日志

将特定信息记录在日志中(1.8版本不生效)

capture cookie <name> len <length>       #捕获请求和响应报文中的cookie并记录日志
capture request header <name> len <length>   #捕获请求报文中指定的首部内容和长度并记录日志
capture response header <name> len <length>   #捕获响应报文中指定的内容和长度首部并记录日志

示例:

capture request header Host len 256

capture request header User-Agent len 512

实战演示:

vim /etc/haproxy/haproxy.cfg

#官网业务访问入口=====================================
listen WEB_PORT_80
        bind 192.168.37.7:80
        mode http
        capture request header Host len 512   
     capture request header User-Agent len 512                                                                                                   
        server web1 192.168.37.27:80 check inter 3000 fall 3 rise 5
        server web2 192.168.37.37:80 check inter 3000 fall 3 rise 5

 

网页版查看访问的host主机的IP地址

 经过日志分析,也可以捕获到本机的host的IP地址。

 

HAProxy 压缩功能

•compression    algo #启用http协议中的压缩机制,常用算法有gzip deflate

•compression    type #要压缩的类型

实战演示:

  vim  /etc/haproxy/haproxy.cfg

#官网业务访问入口=====================================
listen WEB_PORT_80
        bind 192.168.37.7:80
        mode http
        capture request header Host len 512
        capture request header User-Agent len 512
        compression algo gzip deflate                                                                                                            
        compression type text/plain text/html text/css text/xml text/javascript application/javascript
        server web1 192.168.37.27:80 check inter 3000 fall 3 rise 5

 访问网页,查看此时支持的gzip和deflate格式的压缩:192.168.37.17

 

Web服务器状态监测 

三种状态监测方式:

•基于四层的传输端口做状态监测

server 172.18.200.103 172.18.200.103:80 check port 9000 addr 172.18.200.104 inter 3s fall 3 rise 5 weight 1

•基于指定URI 做状态监测

•基于指定URI的request请求头部内容做状态监测

option httpchk

•option httpchk <uri>
•option httpchk <method> <uri>
•option httpchk <method> <uri> <version>

示例:

•listen web_prot_http_nodes
•bind 192.168.7.102:80
•mode http
•log global
•option httpchk GET /wp-includes/js/jquery/jquery.js?ver=1.12.4 HTTP/1.0 #基于指定URL
•#option httpchk HEAD /wp-includes/js/jquery/jquery.js?ver=1.12.4 HTTP/1.0\r\nHost:\192.168.7.102 #通过request获取的头部信息进行匹配进行健康检测,节省很多不必要的网络开销,降低磁盘IO。
•server 192.168.7.102 blogs.studylinux.net:80 check inter 3000 fall 3 rise 5
•server 192.168.7.101 192.168.7.101:8080 cookie web1 check inter 3000 fall 3 rise 5

实战演示: 

在后端服务器(192.168.37.37)新建一个monitor_page目录,并在目录下创建一个index.html文件。

[root@centos37html]#mkdir /var/www/html/monitor_page
[root@centos37html]#echo OK >  monitor_page/index.html

vim  /etc/haproxy/haproxy.cfg 

#官网业务访问入口=====================================
listen WEB_PORT_80
        bind 192.168.37.17:80
        mode tcp   改为tcp类型,也会从http服务进行访问。
        rspidel Server:.*
        #option httpchk GET /monitor_page/index.html  HTTP/1.0
        option httpchk HEAD  /monitor_page/index.html  HTTP/1.0\r\nHost:\192.168.37.17 生产用,用HEAD模式,可以节省很多不必要的网络开销,降低磁盘IO,声明是从17的IP地址发起的请求。
        server web1 192.168.37.27:80 check inter 3000 fall 3 rise 5
        server web2 192.168.37.37:80 check inter 3000 fall 3 rise 5

 改为HEAD模式(只获取头部信息,并设置为每五秒监控一次),就不会在后端服务器日志中不会再显示文件大小,节省不必要的网络开销,降低磁盘IO。

在网页上进行状态页检查,此时可以看到后端服务器(192.168.37.27)没有monitor_page此目录,就会显示down机现象。

 

HAProxy中的ACL

1、ACL定义:

访问控制列表,用于实现基于请求报文的首部响应报文的内容其它的环境状态信息来做出转发决策,这大大增强了其配置弹性。其配置法则通常分为两步,首先去定义ACL ,即定义一个测试条件,而后在条件得到满足时执行某特定的动作,如阻止请求或转发至某特定的后端。

acl:对接收到的报文进行匹配和过滤,基于请求报文头部中的源地址、源端口、目标地址、目标端口、请求方法、URL、文件后缀等信息内容进行匹配并执行进一步操作。

•acl <aclname> <criterion> [flags] [operator] [<value>]
•acl 名称条件条件标记位具体操作符操作对象类型
•acl image_service hdr_dom(host) -i img.magedu.com
•ACL名称,可以使用大字母A-Z、小写字母a-z、冒号:、点.、中横线和下划线,并且严格区分大小写,必须Image_site和image_site完全是两个acl。

2、ACL derivatives :

•hdr([<name> [,<occ>]]):完全匹配字符串
•hdr_beg([<name> [,<occ>]]):前缀匹配
•hdr_dir([<name> [,<occ>]]):路径匹配
•hdr_dom([<name> [,<occ>]]):域匹配
•hdr_end([<name> [,<occ>]]):后缀匹配
•hdr_len([<name> [,<occ>]]):长度匹配
•hdr_reg([<name> [,<occ>]]):正则表达式匹配
•hdr_sub([<name> [,<occ>]]):子串匹配

3、<criterion> :匹配条件

(1)dst 目标IP

(2)dst_port 目标PORT

(3)src 源IP

(4)src_port 源PORT

hdr <string>用于测试请求头部首部指定内容

hdr_dom(host) 请求的host名称,如www.magedu.com
hdr_beg(host) 请求的host开头,如www. img. video. download. ftp.
hdr_end(host) 请求的host结尾,如.com .net .cn
path_beg      请求的URL开头,如/static、/images、/img、/css
path_end     请求的URL中资源的结尾,如.gif .png .css .js .jpg .jpeg

 演示:

frontend web
        bind 192.168.37.17:80
        mode http
#      acl www_web_page hdr_dom(host)  -i www.magedu.net
#      acl mobile_web_page hdr_dom(host)  -i mobile.magedu.net 
        acl ip_range_test src 192.168.37.7 192.168.0.0/24   此源IP地址或者IP段访问时,都跳转至后端服务器的192.168.37.27地址上。
        use_backend web2 if ip_range_test
        default_backend     backup_web_host

backend web2
        server web1 192.168.37.27:80 weight 1 check  port 80 inter 3s fall 3 rise 5
        #server web1 192.168.37.37:80 weight 1 check  port 80 inter 3s fall 3 rise 5

 

 在客户端(192.168.37.7)访问haproxy效果,就会一直访问192.168.37.27地址。

 

 当我们知道客户端的IP地址时,也可以进行拒绝客户端的访问,加上block选项。

 

 查看访问效果,此时客户端被拒绝访问。

 

4、<flags>-条件标记

-i 不区分大小写
-m 使用指定的pattern匹配方法
-n 不做DNS解析
-u 禁止acl重名,否则多个同名ACL匹配或关系

5、[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进行匹配
-subdirmatch (-m dir) :查看提取出来的用斜线分隔(“/”)的字符串,如果其中任何一个匹配,则ACL进行匹配
-domain match (-m dom) :查找提取的用点(“.”)分隔字符串,如果其中任何一个匹配,则ACL进行匹配

6、<value>的类型:

-Boolean #布尔值false,true
-integer or integer range #整数或整数范围,比如用于匹配端口范围,1024~32768
-IP address / network #IP地址或IP范围, 192.168.0.1 ,192.168.0.1/24

-string用法:

exact    –精确比较
substring  —子串     
suffix   -后缀比较
prefix   -前缀比较
subdir  -路径,    /wp-includes/js/jquery/jquery.js
domain  -域名,www.magedu.com
-regular expression     #正则表达式
-hex block     #16进制

 实战演示:

frontend web
        bind 192.168.37.17:80
        mode http
        acl www_web_page hdr_dom(host)  -i www.magedu.net     访问www.magedu.net时,跳转至192.168.37.27后端服务器
        acl mobile_web_page hdr_dom(host)  -i mobile.magedu.net  访问mobile.magedu.net时,跳转至192.168.37.37后端服务器

        use_backend pc_web_host if www_web_page
        use_backend mobile_web_host if mobile_web_page
        default_backend     backup_web_host   访问其他域名时,默认跳转至192.168.37.47后端服务器。

backend pc_web_host
        server web1 192.168.37.27:80 weight 1 check  port 80 inter 3s fall 3 rise 5
        #server web1 192.168.37.37:80 weight 1 check  port 80 inter 3s fall 3 rise 5

backend mobile_web_host
        #server web1 192.168.37.27:80 weight 1 check  port 80 inter 3s fall 3 rise 5
        server web1 192.168.37.37:80 weight 1 check  port 80 inter 3s fall 3 rise 5

backend backup_web_host
        server web1 192.168.37.47:80 weight 1 check  port 80 inter 3s fall 3 rise 5

网页访问效果:

 

7、Acl定义与调用
多个acl作为条件时的逻辑关系:

-与:隐式(默认)使用
-或:使用“or” 或“||”表示
-否定:使用“!“ 表示

示例:

if valid_src valid_port    #与关系
if invalid_src || invalid_port  #或
if ! invalid_src    #非

自定义错误页面

支持200, 400, 403, 408, 500, 502, 503, 504.

errorfile 500 /usr/local/haproxy/html/500.html     #自定义错误页面跳转
errorfile 502 /usr/local/haproxy/html/502.html
errorfile 503 /usr/local/haproxy/html/503.html

自定义错误跳转,直接跳转到指定的服务器IP地址上,此IP地址需要是公网IP,并让其客户端能够访问,否则无法跳转。

errorloc 503 http://192.168.37.27/error_page/503.html

实战演一:

直接在HAProxy机器上创建自定义的错误页面。

errorfile 500 /usr/local/haproxy/html/500.html
errorfile 502 /usr/local/haproxy/html/502.html
errorfile 503 /usr/local/haproxy/html/503.html
frontend web
        bind 192.168.37.17:80
        mode http
        acl www_web_page hdr_dom(host)  -i www.magedu.net
        use_backend mobile_web_host if www_web_page
        default_backend     backup_web_host

backend mobile_web_host
        #server web1 192.168.37.27:80 weight 1 check  port 80 inter 3s fall 3 rise 5
        server web1 192.168.37.37:80 weight 1 check  port 80 inter 3s fall 3 rise 5

backend backup_web_host
        server web1 192.168.37.47:80 weight 1 check  port 80 inter 3s fall 3 rise 5

  

  然后创建错误页面目录及文件

[root@centos_17html]#mkdir /usr/local/haproxy/html
[root@centos_17html]#cd /usr/local/haproxy/html/
[root@centos_17html]#echo error 503 >  503.html
[root@centos_17html]#echo error 502 >  502.html
[root@centos_17html]#echo error 500 >  500.html

 访问网页:

 

实战演示二:

自定义错误跳转,直接跳转到指定的服务器URL上,此IP地址需要是公网域名,并让其客户端能够访问,否则无法跳转。

errorloc 503 http://192.168.37.37/error_page/503.html   指定跳转至192.168.37.37的服务器上。

 

 在后端要跳转的服务器上创建一个错误提示:

[root@centos37monitor_page]#mkdir /var/www/html/error_page
[root@centos37monitor_page]#echo Custerm error 503 > /var/www/html/error_page/503.html

 停止掉要访问的后端服务器:systemctl stop httpd

 验证访问效果:

 

 

  

 

 

 

 

  

 

 

 

  

  

 



 

  

 

  

  

 

 

 

  

posted @ 2019-12-28 18:50  一叶知秋~~  阅读(6664)  评论(0编辑  收藏  举报