HAProxy学习笔记
Posted 刘元涛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HAProxy学习笔记相关的知识,希望对你有一定的参考价值。
安装参考:https://my.oschina.net/liuyuantao/blog/5119858
HAProxy组成
程序环境:
主程序:/usr/sbin/haproxy
配置文件:/etc/haproxy/haproxy.cfg
Unit file:/usr/lib/systemd/system/haproxy.service
配置段:
global:全局配置段,进程及安全配置相关的参数,性能调整相关参数
proxies:代理配置段
defaults:为frontend, backend, listen提供默认配置
frontend:前端,相当于nginx中的server {}
backend:后端,相当于nginx中的upstream {}
listen:同时拥有前端和后端配置
配置段
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方法,可用于实现更多应用层检测功能。
示例:
backend backend_test
mode http
balance roundrobin
server web1 192.168.153.102:80 check
server web2 192.168.153.101:80 check
server web3 192.168.153.103:80 check
后端服务器状态监测及相关配置
•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:根据服务器在列表中的位置,自上而下进行调度,但是其只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务,因此会忽略服务器的权重设置。
#官网业务访问入口=====================================
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的访问日志就可以收集到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学习笔记的主要内容,如果未能解决你的问题,请参考以下文章
sh Unbounce脚本片段,用于在零停机时间内重新启动HAProxy
[原创]java WEB学习笔记61:Struts2学习之路--通用标签 property,uri,param,set,push,if-else,itertor,sort,date,a标签等(代码片段