记录日常工作关于系统运维,虚拟化云计算,数据库,网络安全等各方面问题。

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

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

场景说明

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

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

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

小型架构图

中型架构图

 

 

公有云Web架构

 

私有云web架构

 

什么是负载均衡:

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

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

为什么使用负载均衡:

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

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

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

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

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

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

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

常见有哪些负载均衡:

•软件负载:

•四层:

1
2
3
4
•LVS(Linux Virtual Server)
•HAProxy(High Availability Proxy)
•Nginx()
•……

•七层:

1
2
3
•HAProxy
•Nginx
•……

•硬件负载:

1
2
3
•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 安装方式:

1
[root@centos7~]#yum install haproxy

 源码编译HAProxy:  

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

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

 安装相关依赖包

1
[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

  开始编译

1
[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

  指定安装路径

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
[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

 创建启动脚本目录

1
[root@centos_17haproxy]#mkdir /etc/haproxy

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[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类型

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

 启动haproxy服务

1
[root@centos_17haproxy]#systemctl start haproxy

 查看haproxy启动的线程数

1
2
3
4
5
[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组成

程序环境:

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

配置段:

global:全局配置段

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

 proxies:代理配置段

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

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

1
2
3
4
5
6
7
8
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用法:

1
2
3
listen web
        bind 192.168.37.17:80
        server web1 192.168.37.27:80

  访问网页:

 Haproxy配置-global

1
2
3
4
5
6
7
8
9
10
11
12
13
•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日志功能。

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

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

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

1
log 127.0.0.1 local3

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

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

1
2
3
[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配置

1
2
3
4
•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 配置参数:

1
2
3
4
5
6
7
8
9
10
•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配置参数

1
2
3
4
•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系统上使用;其不能使用接口别名,而仅能使用物理接口名称,而且只有管理有权限指定绑定的物理接口;

 示例:

1
2
3
4
•frontend WEB_PORT
•bind :80,:8080
•bind 192.168.7.102:10080,192.168.7.102:10043
•use_backend backend_name

Proxies配置-backend配置参数

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

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

 示例:

1
2
3
4
•frontend WEB_PORT
•bind :80,:8080
•bind 192.168.7.102:10080,192.168.7.102:10043
•use_backend backend_name

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

1
2
3
4
5
6
7
8
9
10
11
12
•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关键字可完成类似功能;可以用于测试

  示例:

1
2
3
4
5
6
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的配置方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#官网业务访问入口======================================
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示例:

1
2
3
4
5
6
7
8
#官网业务访问入口=====================================
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示例:

1
2
3
4
5
6
7
8
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是动态的,支持在线调整权重,支持慢启动,优点在于当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动。

1
2
3
4
5
6
7
8
9
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>

1
2
3
4
5
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,统一资源标识符,是一个用于标识某一互联网资源名称的字符串

示例:

1
2
3
4
5
6
7
8
9
10
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路径文件: