HAProxy
简介
HAProxy是一个免费的负载均衡软件,可以运行于大部分主流的Linux操作系统上。HAProxy提供了L4(TCP)和L7(HTTP)两种负载均衡能力,具备丰富的功能。HAProxy具备媲美商用负载均衡器的性能和稳定性。
HAProxy的核心功能
- 负载均衡:L4和L7两种模式,支持RR/静态RR/LC/IP Hash/URI Hash/URL_PARAM Hash/HTTP_HEADER Hash等丰富的负载均衡算法
- 健康检查:支持TCP和HTTP两种健康检查模式
- 会话保持:对于未实现会话共享的应用集群,可通过Insert Cookie/Rewrite Cookie/Prefix Cookie,以及上述的多种Hash方式实现会话保持
- SSL:HAProxy可以解析HTTPS协议,并能够将请求解密为HTTP后向后端传输
- HTTP请求重写与重定向
- 监控与统计:HAProxy提供了基于Web的统计信息页面,展现健康状态和流量数据。基于此功能,使用者可以开发监控程序来监控HAProxy的状态
HAProxy的关键特性
性能好
单个HAProxy进程的处理能力突破了10万请求/秒,并轻松占满了10Gbps的网络带宽。HAProxy进程的消耗比其系统同类消耗的少20倍。
基于:
- A single-process:采用单线程、事件驱动、非阻塞模型,减少上下文切换的消耗,能在1ms内处理数百个请求。并且每个会话只占用几KB的内存。
- O(1) event checker:事件查看器允许其在高并发连接中对任何连接的任何事件实现即时探测。
- Delayed updates:使用惰性事件缓存对事件检查器进行的延迟更新可确保除非绝对必要,否则我们绝不会更新事件。
- Single-buffereing:单缓冲机制, 尽可能在读取和写入之间没有任何数据复制。这样可以节省大量CPU周期和有用的内存带宽。通常,瓶颈将是CPU和网络接口之间的I/O总线。在10-100 Gbps时,内存带宽也可能成为瓶颈。
- Zero-copy forwarding:零复制转发,使用Linux下的splice()系统调用来实现,在Linux kernel 3.5以上还支持零复制启动
- MRU:使用固定大小的内存池进行即时内存分配,这大大减少了创建新会话所需的时间。
- Tree-based storage:采用树型存储
- HAProxy大量利用操作系统本身的功能特性,使得其在处理请求时能发挥极高的性能,通常情况下,HAProxy自身只占用15%的处理时间,剩余的85%都是在系统内核层完成的。
稳定性好
作为单进程模式运行的程序,HAProxy对稳定性的要求是十分严苛的。HAProxy的大部分工作都是在操作系统内核完成的,所以HAProxy的稳定性主要依赖于操作系统,对sysctls参数进行精细的优化,并且确保主机有足够的内存。
负载均衡模式
无负载均衡

四层负载均衡

用户访问负载均衡器,负载均衡器将用户的请求转发给后端服务器的Web后端组。无论选择哪个后端服务器,都将直接响应用户的请求。通常,Web后端中的所有服务器应该提供相同的内容 - 否则用户可能会收到不一致的内容。
七层负载均衡

如果用户请求yourdomain.com/blog,则会将其转发到博客后端,后端是一组运行博客应用程序的服务器。其他请求被转发到web-backend,后端可能正在运行另一个应用程序。
安装
bash
复制代码
apt-get install haproxy # 源码安装 # https://pkgs.org/download/haproxy wget http://www.haproxy.org/download/1.7/src/haproxy-1.7.2.tar.gz tar -xzf haproxy-1.7.2.tar.gz cd haproxy-1.7.2 make make install
命令输出
ini
复制代码
Usage : haproxy [-f <cfgfile>]* [ -vdVD ] [ -n <maxconn> ] [ -N <maxpconn> ] [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] -v displays version ; -vv shows known build options. -d enters debug mode ; -db only disables background mode. -dM[<byte>] poisons memory with <byte> (defaults to 0x50) -V enters verbose mode (disables quiet mode) -D goes daemon ; -C changes to <dir> before loading files. -q quiet mode : don't display messages -c check mode : only check config files and exit -n sets the maximum total # of connections (2000) -m limits the usable amount of memory (in MB) -N sets the default, per-proxy maximum # of connections (2000) -L set local peer name (default to hostname) -p writes pids of all children to this file -de disables epoll() usage even when available -dp disables poll() usage even when available -dS disables splice usage (broken on old kernels) -dV disables SSL verify on servers side -sf/-st [pid ]* finishes/terminates old pids. Must be last arguments.
HAProxy基础配置
检查配置是否有错误:sudo haproxy -c -f /etc/haproxy/haproxy.cfg
reload:sudo systemctl reload haproxy.service
添加/etc/haproxy/sites-enabled/配置子目录
ini
复制代码
$ vi /lib/systemd/system/haproxy.service [Service] EnvironmentFile=-/etc/default/haproxy EnvironmentFile=-/etc/sysconfig/haproxy Environment="CONFIG=/etc/haproxy/haproxy.cfg" "PIDFILE=/run/haproxy.pid" "EXTRAOPTS=-S /run/haproxy-master.sock" ExecStartPre=/usr/sbin/haproxy -f $CONFIG -f /etc/haproxy/sites-enabled/ -c -q $EXTRAOPTS ExecStart=/usr/sbin/haproxy -Ws -f $CONFIG -f /etc/haproxy/sites-enabled/ -p $PIDFILE $EXTRAOPTS ExecReload=/usr/sbin/haproxy -f $CONFIG -f /etc/haproxy/sites-enabled/ -c -q $EXTRAOPTS ExecReload=/bin/kill -USR2 $MAINPID KillMode=mixed Restart=always SuccessExitStatus=143 Type=notify $ systemctl daemon-reload $ systemctl restart haproxy.service
haproxy 配置/etc/haproxy/haproxy.cfg中分成五部分内容
-
global: 设置全局配置参数,属于进程的配置,通常是和操作系统相关。
-
defaults:配置默认参数,这些参数可以被用到frontend,backend,Listen组件;
-
frontend:接收请求的前端虚拟节点(即HAProxy自身提供的服务),Frontend可以更加规则直接指定具体使用后端的backend;(一般直接使用listen)
-
backend:后端服务集群的配置(即HAProxy后面接的服务),是真实服务器,一个Backend对应一个或者多个实体服务器;(一般直接使用listen)
-
Listen :frontend和backend的组合体,示例如下
vbscript复制代码
# HTTP listen lb-8083 10.176.xxx:8083 mode http option httplog option httpclose balance roundrobin option redispatch # 类似监控检测 option forwardfor server nlb6 10.176.xx:8083 check inter 10s server nlb5 10.176.yy:8083 check inter 10s # TCP listen xx-server 10.176.xxx:18080 mode tcp balance roundrobin option redispatch server cyqnlb5 10.176.xx:18080 check inter 10s server cyqnlb6 10.176.yy:18080 check inter 10s
根据后端返回到结果调度ha
agent-check agent-inter 10s agent-port 19001
vbscript
复制代码
listen nrp-9002 10.195.0.251:9002 mode http balance roundrobin option redispatch option httpchk GET /operation/internal/api/health/status option httplog server pub4-lxc4-nrp1 10.195.xxx:9001 check inter 10s rise 3 fall 3 agent-check agent-inter 10s agent-port 19001 server pub4-lxc5-nrp2 10.195.xxx:9001 check inter 10s rise 3 fall 3 agent-check agent-inter 10s agent-port 19001
| Text it sends back | Result |
|---|---|
| down | server is put into the down state |
| up | server is put into the up state |
| maint | server is put into maintenance mode |
| ready | server is taken out of maintenance mode |
| 50% | server’s weight is halved |
| maxconn:10 | server’s maxconn is set to 10 |
| drain | Set the weight to 0 and gradually drain the traffic from this server for maintenance |
| stop | Stop all traffic immediately, kill this backend server |
配置参数讲解
bash
复制代码
global # 全局参数的设置 log 127.0.0.1 local0 info # log语法:log [address] [device] [maxlevel] [minlevel] # 如log 127.0.0.1 local0 info warning,即向本机rsyslog或syslog的local0输出info到warning级别的日志 # 其中[minlevel]可以省略。HAProxy的日志共有8个级别,从高到低为emerg/alert/crit/err/warning/notice/info/debug user haproxy group haproxy # 设置运行haproxy的用户和组,也可使用uid,gid关键字替代之 daemon # 以守护进程的方式运行 nbproc 16 # 设置haproxy启动时的进程数,默认启动1个进程 # 该值的设置应该和服务器的CPU核心数一致, ,创建多个进程数,可以减少每个进程的任务队列,但是过多的进程数也可能会导致进程的崩溃。 nbthread 4 # 线程数 maxconn 40960 # 定义每个haproxy进程的最大连接数,由于每个连接包括一个客户端和一个服务器端,所以单个进程的TCP会话最大数目将是该值的两倍。 # 会根据ulimit -n的值自动调整,不建议设置 pidfile /var/run/haproxy.pid # 定义haproxy的pid stats socket /var/run/haproxy.sock mode 666 # 定义stats的sock debug # debug mode quiet # quiet mode defaults # 默认部分的定义 mode http # mode语法:mode {http|tcp|health} 。http是七层模式,tcp是四层模式,health是健康检测,返回OK balance roundrobin # 调度算法 # roundrobin 基于权重的轮询 # leastconn 最少连接数,适用于长连接的会话 # source 源地址hash,同一个客户端IP的请求始终被派发至某特定的服务器 # uri 基于uri生成hash表的算法,主要用于后端是缓存服务器 retries 3 # 定义连接后端服务器的失败重连次数,连接失败次数超过此值后将会将对应后端服务器标记为不可用 option httpchk GET /bill/v1/health/status HTTP/1.0 # 开启对后端服务器的健康检测 option httplog # 详细的记录http的请求信息,如果记录访问数据到文件的话。默认记录很简单,源目IP option redispatch # 当使用了cookie时,haproxy将会将其请求的后端服务器的serverID插入到cookie中,以保证会话的SESSION持久性;\ 而此时,如果后端的服务器宕掉了,但是客户端的cookie是不会刷新的,如果设置此参数,将会将客户的请求强制定向到另外一个后端server上,以保证服务的正常。 option abortonclose # 当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接 option dontlognull # 启用该项,日志中将不会记录空连接。 # 所谓空连接就是在上游的负载均衡器或者监控系统为了探测该服务是否存活可用时,需要定期的连接或者获取某一固定的组件或页面,或者探测扫描端口是否在监听或开放等动作被称为空连接;官方文档中标注,如果该服务上游没有其他的负载均衡器的话,建议不要使用该参数,因为互联网上的恶意扫描或其他动作就不会被记录下来 option httpclose # 表示在客户端和服务端完成第一次数据请求后,Haproxy将主动关闭此选项。 # 另外Haproxy在http mode下支持五种连接相应模式。默认是keep alive(option http-keep-alive),连接保持开放但是在相应结束之前和下一个新的请求来之间是空闲的 # 另外的tunnel ("option http-tunnel")在1.0-1.5-dev21的默认模式,只有第一个请求和响应才会出来,其他的只转发不做处理。不能用在http请求,问题很多 # 还有另外的两种:server close ("option http-server-close")、forced close ("option forceclose") option forwardfor # 启用X-Forwarded-For,在requests头部插入客户端IP发送给后端的server,使后端server获取到客户端的真实IP timeout connect 5000 # haproxy连接RS最长时间,默认单位是毫秒 timeout client 3s # 客户端发送数据时最长等待时间 timeout server 3s # 服务器回应给客户端数据最长等待时间 ##### server [name] [ip]:[port] [params] server php_server_1 10.12.25.68:80 cookie 1 check inter 2000 rise 3 fall 3 weight 2 server php_server_2 10.12.25.72:80 cookie 2 check inter 2s rise 3 fall 3 weight 1 server php_server_bak 10.12.25.79:80 cookie 3 check inter 2s rise 3 fall 3 backup # 使用server关键字来设置后端服务器 # 为后端服务器所设置的内部名称[php_server_1](该名称将会呈现在日志或警报中), # 后端服务器的IP地址,支持端口映射[10.12.25.68:80] # 指定该服务器的SERVERID为1[cookie 1] # 接受健康监测[check]、监测的间隔时长,单位毫秒[inter 2000]、监测正常多少次后被认为后端服务器是可用的[rise 3]、监测失败多少次后被认为后端服务器是不可用的[fall 3]、\ # 分发的权重[weight 2] # 最后为备份用的后端服务器,当正常的服务器全部都宕机后,才会启用备份服务器[backup] ##### acl [name] [criterion] [flags] [operator] [value] acl white_list src 10.166.84.215 10.166.84.216 acl static_down nbsrv(static_server) lt 1 # 定义一个名叫static_down的acl,当backend static_sever中存活机器数小于1时会被匹配到 acl php_web url_reg /*.php$ # 定义一个名叫php_web的acl,当请求的url末尾是以.php结尾的,将会被匹配到 acl static_web url_reg /*.(css|jpg|png|jpeg|js|gif)$ # 定义一个名叫static_web的acl,当请求的url末尾是以.css、.jpg、.png、.jpeg、.js、.gif结尾的,将会被匹配到 ##### use_backend [backend] if|unless [acl] 与ACL搭配使用,在满足/不满足ACL时转发至指定的backend use_backend php_server if static_down # 如果满足策略static_down时,就将请求交予backend php_server use_backend php_server if php_web # 如果满足策略php_web时,就将请求交予backend php_server use_backend static_server if static_web # 如果满足策略static_web时,就将请求交予backend static_server listen status # 定义一个名为status的部分 bind 0.0.0.0:1080 # 定义监听的套接字 mode http log global stats refresh 30s # stats是haproxy的一个统计页面的套接字,该参数设置统计页面的刷新间隔为30s stats uri /admin?stats # 设置统计页面的uri为/admin?stats stats realm Private lands # 设置统计页面认证时的提示内容 stats auth admin:password # 设置统计页面认证的用户和密码,如果要设置多个,另起一行写入即可 stats hide-version # 隐藏统计页面上的haproxy版本信息
监控
一般有两种方式来使用socat连接socket
socat /var/run/haproxy.sock stdio:这个通常是发送一个脚本到haproxy
socat /var/run/haproxy.sock readline:这个是通过手动发送命令
常用命令
bash
复制代码
show info # 可以看到HAProxy版本等信息 show backend # 列举所有backend show servers state # 查看server列表及状态 show stat # 查看统计信息 disable server servers/tomcat1 # 关闭一台server enable server servers/tomcat1 # 启动一台server get weight servers/tomcat1 # 获取server的权重 set server servers/tomcat1 weight 100# 设置server的权重
例如
shell
复制代码
$ echo "show info" |socat /var/run/haproxy.sock stdio $ echo "show stat" |socat /var/run/haproxy.sock stdio
指标解释
lua
复制代码
pxname:代理的前缀名称 svname:服务器的名称 qcur:当前队列中的请求数量 qmax:队列中最大请求数量 scur:当前连接数 smax:最大连接数 slim:最大连接限制 stot:服务器被处理的连接总数 bin:接收到的字节数 bout:发送的字节数 dreq:在请求队列中的请求数 dresp:在响应队列中的请求数 ereq:失败的请求数量 econ:与服务器建立连接的数量 eresp:失败的响应数量 wretr:重试的数量 wredis:重试失败的数量 status:服务器状态 weight:服务器的权重 act:服务器活动状态 bck:被认为是备用的服务器数 chkfail:检查失败的次数 chkdown:检查失败导致服务器被认为是下线的次数 lastchg:服务器上一次状态改变的时间 downtime:服务器下线的时间 qlimit:队列的限制 pid:haproxy进程ID iid:haproxy实例ID sid:haproxy服务器ID throttle:haproxy服务器限制 lbtot:haproxy服务器负载均衡总数 tracked:haproxy服务器跟踪 type:haproxy服务器类型 rate:haproxy服务器速率 rate_lim:haproxy服务器速率限制 rate_max:haproxy服务器速率最大值 check_status:检查状态 check_code:检查返回的HTTP状态码 check_duration:检查持续时间 hrsp_1xx:1xx响应码的数量 hrsp_2xx:2xx响应码的数量 hrsp_3xx:3xx响应码的数量 hrsp_4xx:4xx响应码的数量 hrsp_5xx:5xx响应码的数量 hrsp_other:其他响应码的数量 hanafail:Haproxy处理请求失败的数量 req_rate:请求速率 req_rate_max:请求速率最大值 req_tot:总请求数 cli_abrt:客户端中止连接的数量 srv_abrt:服务器中止连接的数量 comp_in:压缩输入字节数 comp_out:压缩输出字节数 comp_byp:由于某些原因未被压缩的字节数 comp_rsp:压缩的响应字节数 lastsess:上一次会话的时间戳 last_chk:上一次检查的时间戳 last_agt:上一次代理检查的时间戳 qtime:请求等待时间 ctime:客户端连接建立时间 rtime:服务器响应时间 ttime:总时间 agent_status:代理状态 agent_code:代理返回的HTTP状态码 agent_duration:代理持续时间 check_desc:检查描述 agent_desc:代理描述 check_rise:检查成功的次数 check_fall:检查失败的次数 check_health:检查健康值 agent_rise:代理成功的次数 agent_fall:代理失败的次数 agent_health:代理健康值 addr:服务器地址 cookie:服务器cookie mode:代理模式 algo:负载均衡算法 conn_rate:连接速率 conn_rate_max:连接速率最大值 conn_tot:总连接数 intercepted:拦截的连接数 dcon:已关闭的连接数 dses:已关闭的会话数 wrew:尝试重新写入的数量 connect:已连接的客户端数 reuse:重用的连接数 cache_lookups:在缓存中查找数据的次数 cache_hits:缓存命中次数 srv_icur:服务器当前连接数 src_ilim:服务器连接限制 qtime_max:请求等待时间最大值 ctime_max:客户端连接建立时间最大值 rtime_max:服务器响应时间最大值 ttime_max:总时间最大值 eint:内部错误数量 idle_conn_cur:当前空闲连接数 safe_conn_cur:当前安全连接数 used_conn_cur:当前已使用的连接数 need_conn_est:需要建立的连接数
监控脚本,因为有些后端为主备模式,端口就是不通的,减少误告警。
swift
复制代码
#!/bin/bash # pxname,svname,qcur,qmax,scur,smax,slim,stot,bin,bout,dreq,dresp,ereq,econ,eresp,wretr,wredis,status,weight,act,bck,chkfail,chkdown,lastchg,downtime,qlimit,pid,iid,sid,throttle,lbtot,tracked,type,rate,rate_lim,rate_max,check_status,check_code,check_duration,hrsp_1xx,hrsp_2xx,hrsp_3xx,hrsp_4xx,hrsp_5xx,hrsp_other,hanafail,req_rate,req_rate_max,req_tot,cli_abrt,srv_abrt,comp_in,comp_out,comp_byp,comp_rsp,lastsess,last_chk,last_agt,qtime,ctime,rtime,ttime,agent_status,agent_code,agent_duration,check_desc,agent_desc,check_rise,check_fall,check_health,agent_rise,agent_fall,agent_health,addr,cookie,mode,algo,conn_rate,conn_rate_max,conn_tot,intercepted,dcon,dses,wrew,connect,reuse,cache_lookups,cache_hits,srv_icur,src_ilim,qtime_max,ctime_max,rtime_max,ttime_max,eint,idle_conn_cur,safe_conn_cur,used_conn_cur,need_conn_est, # qcur 当前队列中的请求数量 # scur 当前连接数 # ereq 失败的请求数量 # status 服务器状态 # qtime 请求等待时间 # rtime 服务器响应时间 STAT_FILE=/tmp/haproxy.status if [[ -f $STAT_FILE ]]; then mv $STAT_FILE $STAT_FILE.old fi echo "==haproxy" echo "show stat" | socat /var/run/haproxy.sock stdio | awk -F, '{ if ( !($1 in FRONTENDS) ) { FRONTENDS[$1] } else { if ( $2 != "BACKEND" && $2 != "FRONTEND" ){ conns[$1"@@"$2] = $0 } } } END{ for (c in conns) { split(conns[c],session,",") for ( i in session ) { if ( session[i] == "" ) { session[i] = 0 } } if ( session[18] == "UP" ) { session[18] = 1 } else { session[18] = 0 } split(c,node,"@@") if ( !( session[18] == 1 && session[3] == 0 && session[5] == 0 && session[13] == 0 && session[59] == 0 && session[61] == 0) ){ print "frontend="node[1]"-"node[2]","\ "qcur="session[3]","\ "scur="session[5]","\ "ereq="session[13]","\ "status="session[18]","\ "qtime="session[59]","\ "rtime="session[61] } } }' > $STAT_FILE if [[ -f $STAT_FILE.old ]]; then grep $STAT_FILE.old status=0|awk -F "," '{print $1}' grep -v -f <(grep $STAT_FILE.old -e 'status=0' | awk -F "," '{print $1}' | sed 's/^/^/') $STAT_FILE else cat $STAT_FILE fi
haproxy+keepalived
haproxy配置主备需要保持一致,keepalived配置参考如下

主
markdown
复制代码
vrrp_script chk_haproxy { script "pidof haproxy" # 检查pid是否存在 interval 2 } vrrp_instance VI_1 { interface eth1 state MASTER priority 200 virtual_router_id 33 unicast_src_ip primary_private_IP unicast_peer { secondary_private_IP } authentication { auth_type PASS auth_pass password } track_script { chk_haproxy } notify_master /etc/keepalived/master.sh }
备
markdown
复制代码
vrrp_script chk_haproxy { script "pidof haproxy" interval 2 } vrrp_instance VI_1 { interface eth1 state BACKUP priority 100 virtual_router_id 33 unicast_src_ip secondary_private_IP unicast_peer { primary_private_IP } authentication { auth_type PASS auth_pass password } track_script { chk_haproxy } notify_master /etc/keepalived/master.sh }
本文介绍了HAProxy,它是免费的负载均衡软件,可运行于主流Linux系统,具备L4和L7负载均衡能力。阐述了其核心功能、关键特性,包括高性能和稳定性,介绍了负载均衡模式、安装方法、基础配置、监控方式,还提及了与keepalived的搭配使用。
3854

被折叠的 条评论
为什么被折叠?



