高并发Haproxy压力测试与优化之道
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高并发Haproxy压力测试与优化之道相关的知识,希望对你有一定的参考价值。
- 压力测试--压测及调优 HAProxy 实现 200 万并发 SSL 连接的过程
先观察上面截图,可以看到两个关键信息:
? 这台机器已经建立了 2.3 万个 TCP 连接
? 使用内存大约在 22G。
测试目标
我们要测试的组件是 HAProxy 1.6 版。生产环境是在 4 核 30 G 的机器上运行该软件,当前所有的连接都是非 SSL 的。
测试目标有两方面:
- 当将整个负载从非 SSL 连接转移到 SSL 连接时,CPU 使用率增加的百分比。CPU 的使用率肯定会增加,这是由于 5 次握手的加长和数据包加密的开销所带来。
- 其次,希望能够测试单个 HAProxy 每秒请求数和最大并发连接数的上限
组件和配置
? 使用多台客户端机器来执行 HAProxy 压力测试。
? 有各种配置的 HAProxy 1.6 的机器
? 4核,30G
? 16核,30G
? 16核,64G
? 相关后端服务器,用于支持所有并发访问。
HTTP 和 MQTT
我们的整个基础设施支持两种协议:
? HTTP
? MQTT
在我们的技术栈中,没有使用 HTTP 2.0,因此在 HTTP 上没有长连的功能。所以在生产环境中,单个 HAProxy 机器(上行 + 下行)的最大数量的 TCP 连接在(2 * 150k)左右。虽然并发连接数量相当低,但每秒请求的数量却相当高。
另一方面,MQTT 是一种不同的通信方式。它提供高质量的服务参数和持久的连接性。因此,可以在 MQTT 通道上使用双向长连通信。对于支持 MQTT(底层 TCP)连接的 HAProxy,在高峰时段会看到每台机器上大约有 600 - 700k 个 TCP 连接。
我们希望进行负载测试,这将为我们提供基于 HTTP 和 MQTT 连接的精确结果。
有很多工具可以帮助我们轻松地测试 HTTP 服务器,并且提供了高级功能,如结果汇总,将文本转换为图形等。然而,针对 MQTT,我们找不到任何压力测试工具。我们确实有一个自己开发的工具,但是它不够稳定,不足以支持这种负载。
所以我们决定使用客户端测试 HTTP 负载,并在 MQTT 服务器使用相同配置。
初始化设置
考虑到相关内容对于进行类似的压力测试或调优的人来说有帮助,本文提供了很多相关细节,篇幅稍微有些长。
? 我们采用了一台 16 核 30G 机器来运行 HAProxy,考虑到 HAProxy 的 SSL 产生的 CPU 巨大开销,因此没有直接使用目前生产环境。
? 对于服务器端,我们使用了一个简单的 NodeJs 服务器,它在接收到 ping 请求时用 pong 进行回复。
? 对于客户端,我们最终使用 Apache Bench。使用 ab 的原因是因为它是一个大家熟悉和稳定的负载测试工具,它也提供了很好的测试结果汇总,这正是我们所需要的。
ab 工具提供了许多有用的参数用于我们的负载测试,如:
? -c,指定访问服务器的并发请求数。
? -n,顾名思义,指定当前负载运行的请求总数。
? -p,包含 POST 请求的正文(要测试的内容)。
如果仔细观察这些参数,您会发现通过调整所有这三个参数可以进行很多排列组合。示例 ab 请求将看起来像这样
ab -S -p post_smaller.txt -T application/json -q -n 100000 -c 3000 http://test.haproxy.in:80/ping
我们感兴趣的数字是:
? 99% 的返回请求的响应延迟时间。
? Time per request:每个请求的时间
? No. of failed requests:失败请求数。
? Requests per second: 每秒请求量
ab 的最大问题是它不提供控制每秒发起请求量,因此我们不得不调整 -c 并发级别以获得所需的每秒钟请求数,并导致很多后文提到的问题和错误。
实现haproxy301域名跳转:
1、redirect prefix http://oldboy.blog.51.com code 301 if www.9888.cn #当访问www.9888.cn时跳转至http://oldboy.blog.51.com
实现haproxy基于URL地址目录做7层跳转
比如根据目录进行过滤转发:
1、acl oldboy_java path_beg /java/
2、acl oldboy_php path_beg /php/
3、use_backend webserver if oldboy_java #如果是java就找webserver这个池
4、use_backend webserver if oldboy_php
实现haproxy基于扩展名做7层跳转:
1、acl oldboy_pic path_end .gif .png .jpg .css .js
2、use_backend nginxpools if olboy_static or oldboy_pic
实现haproxy基于user_agent做7层跳转
1、acl iphone_users hdr_sub(user-agent) -i iphone
2、redirect prefix http://www.51cto.com if iphone users
3、acl android_users hdr_sub(user-agent) -i android
4、redirect prefix http://www.baidu.com if android_users
实现haproxy基于ip和端口过滤
1、acl valid_ip src 192.168.1.0/24
2、block if !valid_ip #如果不符合valid_ip的规则就block拒绝掉
让haproxy错误页面优雅的显示
errorfile 403 /tec/haproxy/errorfiles/403forbild.html
基于HTTP的直接IP URL方式的健康检查:
1.>第一种HEAD配置方法option httpchk HEAD /check.html HTTP/1.0 这种检测方式就相当于通过curl -i http://127.0.0.1/check.html 或者 wget http://127.0.0.1/check.html访问地址。 **check.html文件必须在网站根目录下创建 健康检查的频率、时间等参数: maxconn 控制节点的并发连接的 weight 12 权重,权重越大,请求越多
2.>第二种GET配置方式
GET后端server的web页面
option httpchk GET /index.html HTTP/1.0
backup 和allbackups参数:
server web1 10.10.100.66:80 check inter 2000 fall 3 weight 30
server web2 10.10.100.67:80 check inter 2000 fall 3 weight 30
server web3 10.10.100.68:80 check inter 2000 fall 3 weight 30 backup当web1和web2服务停止后,web3再提供服务,这样可以达到高可用的目的
option allbackups
server web1 10.10.100.66:80 check inter 2000 fall 3 weight 30
server web2 10.10.100.67:80 check inter 2000 fall 3 weight 30
server web3 10.10.100.68:80 check inter 2000 fall 3 weight 30 backup
server web4 10.10.100.69:80 check inter 2000 fall 3 weight 30 backup加上 option allbackups后,当web1和web2挂掉后,web3和web4都启动起来提供服务,不加allbackups则只有一台提供服务.
haproxy下的RS无法记录客户端真实ip的问题
在haproxy配置文件里加入如下参数:
listen www
option forwardfor 提示:参数最好放在listen www里面 然后在nginx日志格式中加"$http_x_forwarded_for"
关于haproxy日志输出的问题:
CentoS6.5下HAProxy日志配置详解:
syslog这个服务,在Centos5.x中的目录为:/etc/init.d/syslog
而到了Centos6.x中变成了:/etc/init.d/rsyslog
在配置前,我们先来了解下日志的level: local0~local7 16~23保留为本地使用
emerg 0 系统不可用
alert 1 必须马上采取行动的事件
crit 2 关键的事件
err 3 错误事件
warning 4 警告事件
notice 5 普通但重要的事件
info 6 有用的信息
debug 7 调试信息
vim haproxy.conf(在default处添加如下信息)
########################################
defaults
log global
option httplog
log 127.0.0.1 local3
########################################
vim /etc/rsyslog.conf(添加如下内容)
local3.* /var/log/haproxy.log
vim /etc/sysconfig/rsyslog
把SYSLOGD_OPTIONS="-m 0"
改成 SYSLOGD_OPTIONS="-r -m 0"
相关解释说明:
-r: 打开接受外来日志消息的功能,其监控514 UDP端口;
-x: 关闭自动解析对方日志服务器的FQDN信息,这能避免DNS不完整所带来的麻烦;
-m: 修改syslog的内部mark消息写入间隔时间(0为关闭),例如240为每隔240分钟写入一次"--MARK--"信息;
-h: 默认情况下,syslog不会发送从远端接受过来的消息到其他主机,而使用该选项,则把该开关打开,所有接受到的信息都可根据syslog.conf中定义的@主机转发过去.
配置完毕后关闭sellinux然后重启rsyslog和haproxy 即可.
/etc/init.d/rsyslog restart
haproxy实现负载均衡的方式:
haproxy + heartbeat
haproxy + keepalive
haproxy 的配置文件由两部分组成:全局设定和对代理的设定,共分为五段:global,defaults,frontend,backend,listen
1.global: (全局配置主要用于设定义全局参数,属于进程级的配置,通常和操作系统配置有关)
2.default : (配置默认参数,这些参数可以被用到frontend,backend,Listen组件)
在此部分中设置的参数值,默认会自动引用到下面的frontend、backend、listen部分中,因引,某些参数属于公用的配置,只需要在defaults部分添加一次即可。而如果frontend、backend、listen部分也配置了与defaults部分一样的参数,Defaults部分参数对应的值自动被覆盖。
3.frontend:( 接收请求的前端虚拟节点,Frontend可以更加规则直接指定具体使用后端的backend)
frontend是在haproxy 1.3版本以后才引入的一个组件,同时引入的还有backend组件。通过引入这些组件,在很大程度上简化了haproxy配置文件的复杂性。forntend可以根据ACL规则直接指定要使用的后端backend
4.backend : (后端服务集群的配置,真实服务器,一个Backend对应一个或者多个实体服务器)
在HAProxy1.3版本之前,HAProxy的所有配置选项都在这个部分中设置。为了保持兼容性,haproxy新的版本依然保留了listen组件配置试。两种配置方式任选一中
5.Listen : (Fronted和backend的组合体) 比如haproxy实例状态监控部分配置
global部分配置说明
通常主要定义全局配置主要用于设定义全局参数,属于进程级的配置,通常和操作系统配置有关。
global
log 127.0.0.1 local3 #定义haproxy日志输出设置
log 127.0.0.1 local1 notice
#log loghost local0 info #定义haproxy 日志级别
ulimit-n 82000 #设置每个进程的可用的最大文件描述符
maxconn 20480 #默认最大连接数
chroot /usr/local/haproxy #chroot运行路径
uid 99 #运行haproxy 用户 UID
gid 99 #运行haproxy 用户组gid
daemon #以后台形式运行harpoxy
nbproc 1 #设置进程数量
pidfile /usr/local/haproxy/run/haproxy.pid #haproxy 进程PID文件
#debug #haproxy调试级别,建议只在开启单进程的时候调试
#quiet
log:全局的日志配置,local0是日志输出设置,info表示日志级别(err,waning,info,debug);
maxconn:设定每个HAProxy进程可接受的最大并发连接数,此选项等同于linux命令选项”ulimit -n”;
chroot:修改haproxy的工作目录至指定的目录并在放弃权限之前执行chroot()操作,可以提升haproxy的安全级别,不过需要注意的是要确保指定的目录为空目录且任何用户均不能有写权限;
daemon:让haproxy以守护进程的方式工作于后台,其等同于“-D”选项的功能,当然,也可以在命令行中以“-db”选项将其禁用;
nbproc:指定启动的haproxy进程个数,只能用于守护进程模式的haproxy;默认只启动一个进程,鉴于调试困难等多方面的原因,一般只在单进程仅能打开少数文件描述符的场景中才使用多进程模式;
pidfile:将haproxy的进程写入pid文件;
ulimit-n:设定每进程所能够打开的最大文件描述符数目,默认情况下其会自动进行计算,因此不推荐修改此选项;
stats socket <path>定义统计信息保存位置;
如要设置haproxy的日志内容,可参考以下配置:
capture request header Host len 40
capture request header Content-Length len 10
capture request header Referer len 200
capture response header Server len 40
capture response header Content-Length len 10
capture response header Cache-Control len 8
defaults部分配置说明
用于设置配置默认参数,这些参数可以被用到frontend,backend,Listen组件;
此部分中设置的参数值,默认会自动引用到下面的frontend、backend、listen部分中,因引,某些参数属于公用的配置,只需要在defaults部分添加一次即可。而如果frontend、backend、listen部分也配置了与defaults部分一样的参 数,Defaults部分参数对应的值自动被覆盖;
defaults
log global #引入global定义的日志格式
mode http #所处理的类别(7层代理http,4层代理tcp)
maxconn 50000 #最大连接数
option httplog #日志类别为http日志格式
option httpclose #每次请求完毕后主动关闭http通道
option dontlognull #不记录健康检查日志信息
option forwardfor #如果后端服务器需要获得客户端的真实ip,需要配置的参数,
可以从http header 中获取客户端的IP
retries 3 #3次连接失败就认为服务器不可用,也可以通过后面设置
option redispatch
#《---上述选项意思是指serverID 对应的服务器挂掉后,强制定向到其他健康的服务器, 当使用了 cookie时,
haproxy将会将其请求的后端服务器的serverID插入到cookie中,以保证会话的SESSION持久性;而此时,如果
后端的服务器宕掉了,但是客户端的cookie是不会刷新的,如果设置此参数,将会将客户的请求强制定向到另外一个
后端server上,以保证服务的正常---》
stats refresh 30 #设置统计页面刷新时间间隔
option abortonclose #当服务器负载很高的时候,自动结束掉当前队列处理比较久的连接
balance roundrobin #设置默认负载均衡方式,轮询方式
#balance source #设置默认负载均衡方式,类似于nginx的ip_hash
#contimeout 5000 #设置连接超时时间
#clitimeout 50000 #设置客户端超时时间
#srvtimeout 50000 #设置服务器超时时间
timeout http-request 10s #默认http请求超时时间
timeout queue 1m #默认队列超时时间
timeout connect 10s #默认连接超时时间
timeout client 1m #默认客户端超时时间
timeout server 1m #默认服务器超时时间
timeout http-keep-alive 10s #默认持久连接超时时间
timeout check 10s #设置心跳检查超时时间
mode http:设置haproxy的运行模式,有三种{http|tcp|health}。注意:如果haproxy中还要使用4层的应用(mode tcp)的话,不建议在此定义haproxy的运行模式。
设置HAProxy实例默认的运行模式有tcp、http、health三种可选:
tcp模式:在此模式下,客户端和服务器端之前将建立一个全双工的连接,不会对七层报文做任何检查,默认为tcp模式,经常用于SSL、SSH、SMTP等应用。
http模式:在此模式下,客户端请求在转发至后端服务器之前将会被深度分板,所有不与RFC格式兼容的请求都会被拒绝。
health:已基本不用了。
log global:设置日志继承全局配置段的设置。
option httplog:表示开始打开记录http请求的日志功能。
option dontlognull:如果产生了一个空连接,那这个空连接的日志将不会记录。
option http-server-close:打开http协议中服务器端关闭功能,使得支持长连接,使得会话可以被重用,使得每一个日志记录都会被记录。
option forwardfor except 127.0.0.0/8:如果上游服务器上的应用程序想记录客户端的真实IP地址,haproxy会把客户端的IP信息发送给上游服务器,在HTTP请求中添加”X-Forwarded-For”字段,但当是haproxy自身的健康检测机制去访问上游服务器时是不应该把这样的访问日志记录到日志中的,所以用except来排除127.0.0.0,即haproxy身。
option redispatch:当与上游服务器的会话失败(服务器故障或其他原因)时,把会话重新分发到其他健康的服务器上,当原来故障的服务器恢复时,会话又被定向到已恢复的服务器上。还可以用”retries”关键字来设定在判定会话失败时的尝试连接的次数。
retries 3:向上游服务器尝试连接的最大次数,超过此值就认为后端服务器不可用。
option abortonclose:当haproxy负载很高时,自动结束掉当前队列处理比较久的链接。
timout http-request 10s:客户端发送http请求的超时时间。
timeout queue 1m:当上游服务器在高负载响应haproxy时,会把haproxy发送来的请求放进一个队列中,timeout queue定义放入这个队列的超时时间。
timeout connect 5s:haproxy与后端服务器连接超时时间,如果在同一个局域网可设置较小的时间。
timeout client 1m:定义客户端与haproxy连接后,数据传输完毕,不再有数据传输,即非活动连接的超时时间。
timeout server 1m:定义haproxy与上游服务器非活动连接的超时时间。
timeout http-keep-alive 10s:设置新的http请求连接建立的最大超时时间,时间较短时可以尽快释放出资源,节约资源。
timeout check 10s:健康检测的时间的最大超时时间。
maxconn 3000:最大并发连接数。
contimeout 5000:设置成功连接到一台服务器的最长等待时间,默认单位是毫秒,新版本的haproxy使用timeout connect替代,该参数向后兼容。
clitimeout 3000:设置连接客户端发送数据时的成功连接最长等待时间,默认单位是毫秒,新版本haproxy使用timeout client替代。该参数向后兼容。
srvtimeout 3000:设置服务器端回应客户度数据发送的最长等待时间,默认单位是毫秒,新版本haproxy使用timeout server替代。该参数向后兼容。
balance roundrobin:设置负载算法为:轮询算法rr
balance :用来定义负载均衡算法
1.roundrobin:基于权重进行的轮叫算法,在服务器的性能分布经较均匀时这是一种最公平的,最合量的算法。
2.static-rr:也是基于权重时行轮叫的算法,不过此算法为静态方法,在运行时调整其服务权重不会生效。
3.source:是基于请求源IP的算法,此算法对请求的源IP时行hash运算,然后将结果与后端服务器的权理总数相除后转发至某台匹配的后端服务器,这种方法可以使用一个客户端IP的请求始终转发到特定的后端服务器。
4.leastconn:此算法会将新的连接请求转发到具有最少连接数目的后端服务器。在会话时间较长的场景中推荐使用此算法。例如数据库负载均衡等。此算法不适合会话较短的环境,如基于http的应用。
5.uri:此算法会对部分或整个URI进行hash运算,再经过与服务器的总权重要除,最后转发到某台匹配的后端服务器上。
6.uri_param:此算法会椐据URL路径中的参数时行转发,这样可以保证在后端真实服务器数量不变时,同一个用户的请求始终分发到同一台机器上。
7.hdr:此算法根据httpd头时行转发,如果指定的httpd头名称不存在,则使用roundrobin算法进行策略转发。
8.rdp-cookie(name):示根据据cookie(name)来锁定并哈希每一次TCP请求。
frontend部分配置说明
frontend是在haproxy 1.3版本以后才引入的一个组件,同时引入的还有backend组件。通过引入这些组件,在很大程度上简化了haproxy配置文件的复杂性。frontend根据任意 HTTP请求头内容做ACL规则匹配,然后把请求定向到相关的backend
frontend http_80_in
bind 0.0.0.0:80 #设置监听端口,即haproxy提供的web服务端口,和lvs的vip 类似
mode http #http 的7层模式
log global #应用全局的日志设置
option httplog #启用http的log
option httpclose #每次请求完毕后主动关闭http通道,HAproxy不支持keep-alive模式
option forwardfor #如果后端服务器需要获得客户端的真实IP需要配置此参数,将可以从HttpHeader中获得客户端IP
default_backend wwwpool #设置请求默认转发的后端服务池
frontend http_80_in:定义一个名为http_80_in的frontend。
bind 0.0.0.0:80:定义haproxy前端部分监听的端口。
mode http:定义为http模式。
log global:继承global中log的定义。
option forwardfor:使后端server获取到客户端的真实IP。
backend部分配置说明
用来定义后端服务集群的配置,真实服务器,一个Backend对应一个或者多个实体服务器
backend wwwpool #定义wwwpool服务器组。
mode http #http的7层模式
option redispatch
option abortonclose
balance source #负载均衡的方式,源哈希算法
cookie SERVERID #允许插入serverid到cookie中,serverid后面可以定义
option httpchk GET /test.html #心跳检测
server web1 10.1.1.2:80 cookie 2 weight 3 check inter 2000 rise 2 fall 3 maxconn 8
listen部分配置说明
常常用于状态页面监控,以及后端server检查,是Fronted和backend的组合体。
如下为haproxy访问状态监控页面配置:
listen admin_status #Frontend和Backend的组合体,监控组的名称,按需自定义名称
bind 0.0.0.0:8888 #监听端口
mode http #http的7层模式
log 127.0.0.1 local3 err #错误日志记录
stats refresh 5s #每隔5秒自动刷新监控页面
stats uri /admin?stats #监控页面的url访问路径
stats realm itnihao welcome #监控页面的提示信息
stats auth admin:admin #监控页面的用户和密码admin,可以设置多个用户名
stats auth admin1:admin1 #监控页面的用户和密码admin1
stats hide-version #隐藏统计页面上的HAproxy版本信息
stats admin if TRUE #手工启用/禁用,后端服务器(haproxy-1.4.9以后版本)
haproxy日志中的 CD SD问题:增大下边两个配置的时间;
timeout client 8h
timeout server 8h
碰到with 或者别的状态时修改
timeout http-keep-alive 10s
timeout check 10s
timeout http-request 10s
timeout queue 1m
timeout connect 10s
以上是关于高并发Haproxy压力测试与优化之道的主要内容,如果未能解决你的问题,请参考以下文章