三大主流软件负载均衡器对比(LVS VS Nginx VS Haproxy)
|
总结HAProxy主要优点:
一、免费开源,稳定性也是非常好,这个可通过我做的一些小项目可以看出来,单Haproxy也跑得不错,稳定性可以与LVS相媲美;
二、根据官方文档,HAProxy可以跑满10Gbps-New benchmark of HAProxy at 10 Gbps using Myricom's 10GbE NICs (Myri-10G PCI-Express),这个作为软件级负载均衡,也是比较惊人的;
三、HAProxy可以作为MySQL、邮件或其它的非web的负载均衡,我们常用于它作为MySQL(读)负载均衡;
四、自带强大的监控服务器状态的页面,实际环境中我们结合Nagios进行邮件或短信报警,这个也是我非常喜欢它的原因之一;
五、HAProxy支持虚拟主机。
global # 全局参数的设置
log 127.0.0.1 local2 # log语法:log <address_1>[max_level_1] # 全局的日志配置,使用log关键字,
指定使用127.0.0.1
上的syslog服务中的local0日志设备,记录日志等级为info的日志
chroot /var/lib/haproxy #改变当前工作目录
pidfile /var/run/haproxy.pid #当前进程id文件
maxconn 4000 #最大连接数
user haproxy #所属用户
group haproxy #所属组
daemon #以守护进程方式运行haproxy
stats socket /var/lib/haproxy/stats
defaults
mode http #默认的模式mode { tcp|http|health },tcp是4层,http是7层,health只会返回OK
log global #应用全局的日志配置
option httplog # 启用日志记录HTTP请求,默认haproxy日志记录是不记录HTTP请求日志
option dontlognull # 启用该项,日志中将不会记录空连接。所谓空连接就是在上游的负载均衡器
或者监控系统为了探测该
服务是否存活可用时,需要定期的连接或者获取某
一固定的组件或页面,或者探测扫描端口是否在监
听或开放等动作被称为空连接;
官方文档中标注,如果该服务上游没有其他的负载均衡器的话,建议
不要使用
该参数,因为互联网上的恶意扫描或其他动作就不会被记录下来
option http-server-close #每次请求完毕后主动关闭http通道
option forwardfor except 127.0.0.0/8 #如果服务器上的应用程序想记录发起请求的客户端的IP地址,
需要在HAProxy
上 配置此选项,
这样
HAProxy会把客户端的IP信息发送给服务器,在HTTP
请求中添加"X-Forwarded-For"字
段。
启用 X-Forwarded-For,在requests
头部插入客户端IP发送给后端的server,使后端server获
取到客户端的真实IP。
option redispatch # 当使用了cookie时,haproxy将会将其请求的后端服务器的serverID插入到
cookie中,以保证
会话的SESSION持久性;而此时,如果后端的服务器宕掉
了, 但是客户端的cookie是不会刷新
的,如果设置此参数,将会将客户的请
求强制定向到另外一个后端server上,以保证服务的正常。
retries 3 # 定义连接后端服务器的失败重连次数,连接失败次数超过此值后将会将对应后端
服务器标记为不可用
timeout http-request 10s #http请求超时时间
timeout queue 1m #一个请求在队列里的超时时间
timeout connect 10s #连接超时
timeout client 1m #客户端超时
timeout server 1m #服务器端超时
timeout http-keep-alive 10s #设置http-keep-alive的超时时间
timeout check 10s #检测超时
maxconn 3000 #每个进程可用的最大连接数
frontend main *:80 #监听地址为80
acl url_static path_beg -i /static /images /javascript /stylesheets
acl url_static path_end -i .jpg .gif .png .css .js
use_backend static if url_static
default_backend
my_webserver
#定义一个名为my_app前端部分。此处将对于的请求转发给后端
backend static #使用了静态动态分离(如果url_path匹配
.jpg .gif .png .css .js静态文件则
访问此后端)
balance roundrobin #负载均衡算法(
#banlance roundrobin 轮询,balance source 保存session值,
支持static-rr,leastconn,first,uri等参数)
server static 127.0.0.1:80 check #静态文件部署在本机(也可以部署在其他机器或者squid缓存服务器)
backend my_webserver #定义一个名为
my_webserver后端部分。PS:此处
my_webserver只是一个
自定义名字而已,
但是需要与frontend里面
配置项default_backend 值相一致
balance roundrobin
#负载均衡算法
server
web01 172.31.2.33:80 check inter 2000 fall 3 weight 30 #定义的多个后端
server
web02 172.31.2.34:80 check inter 2000 fall 3 weight 30
#定义的多个后端
server
web03 172.31.2.35:80 check inter 2000 fall 3 weight 30
#定义的多个后端
|
1、实验环境
centos 7.1 X64 mini版
2、配置web服务器(node33/34/35):
测试方便,关闭selinux、关闭iptables
一下都采用默认,不做配置即可。
yum install httpd -y
# vim /etc/httpd/conf/httpd.conf
httpd监听端口:
DocumentRoot:网页存放的路径,文档的根目录
重启httpd
# systemctl restart httpd
页面访问httpd:
修改显示内容:
# vim /var/www/html/index.html
I'm node33!!! My IP is 172.31.2.33...
再次访问:
这样三个web服务33/34/35搭建成功!!!!
接下来配置负载均衡(本次实验只用一个Haproxy:172.31.2.31):
ACL定制法则:
开放策略:拒绝所有,只开放已知
拒绝策略:允许所有,只拒绝某些
事实上实现安全策略,无非也就是以上两种方法
redirect
参考:http://cbonte.github.io/haproxy-dconv/configuration-1.4.html#4-redirect
如果符合某种特定条件,则返回某种新的前缀
aclclear dst_port 80
acl secure dst_port 8080
acl login_page url_beg /login #如果url的地址,除了主机名之外是login的页面则定义成logon,如果是登录页面却又属于不安全的连接 那么
acl logout url_beg /logout
acl uid_given url_reg /login?userid=[^&]+
acl cookie_set hdr_sub(cookie)SEEN=1 #取得cookie的子串,如果没有cookie则:
redirect prefix https://mysite.com set-cookie SEEN=1 if!cookie_set #如果定义的第一个用户来访问我们的站点的时候,没有被设置cookie 在将用户的请求转为https
redirect prefix https://mysite.com iflogin_page !secure
redirect prefix http://mysite.com drop-query if login_page !uid_given
redirect locationhttp://mysite.com/ if !login_page secure
redirect location / clear-cookie USERID= if logout
我们自定定义一个acl
如果访问的是/bbs开头的地址,那么将其跳转到/forum
acl acbbs url_beg/bbs
redirect /forum if/bbs #if判断是否匹配/bbs 如果匹配则将/bbs 跳转至/forum
只不过对于haproxy来讲需要基于acl的机制来实现,所以要比nginx要麻烦一点
reqadd
如果访问的是ssl则则加入X-Proto首部
acl is-ssldst_prot 81
reqadd X-Proto:\SSL if is-ssl
rspadd
响应报文首部,所有响应首部都需要经过haproxy,因此经过haproxy的时候,想通告其客户端是通过haproxy来转发过来的,因此这时候会在首部添加一个 X-Via首部,明确说明是通过代理服务器转发的
#只要是通过haproxy转发的请求统统添加首部信息,如下所示:
rspadd X-Via:\ 10.0.10.61 #haproxy的IP地址
Server的检测机制
backup
check
disabled
fall #检测机[1]制,检测超过几次认为失败
inter #检测的时间间隔
另外inter还可以对其做优化:
fastinter #快速检测
downinter #慢速检测
以上可以做启发式检测,如果发现故障了可以将其快速检测几次
限制最大连接数
Maxconn参数为最大连接数,可以将其限制最大连接数,如下所示
backend webserver
balance uri
hash-type consistent
server web1 10.0.10.82:80 check weight 1 maxconn 2000
server web2 10.0.10.83:80 check weight 1 maxconn 3000
访问管理页面:
如果请求过多,所有超出这个最大连接数 ,如果还被转发至这个服务器中会被放入至等待队列中,如果队列也超时了,这个请求则会直接被响应403
maxqueue
维持每个队列的长度
minconn
最少连接,用来将maxconn定制为动态值
observer<mode>
健康状态监测,如果存活则不对其检查
可以根据4/7层做观测
redir
所有发往这个服务器的请求做重定向,因此可以实现单台服务器的重定向
实现重定向:
server web1 10.0.10.82:80 check weight 1 maxconn 2000 redir http://www.baidu.com
访问测试,可发现最后访问其haproxy的IP地址 最后被跳转至百度页面中了
slowstart
让haproxy支持慢启动,但是对于haproxy来讲第一启动是没有任何意义的
慢启动只在服务器故障又重新上线的时候才有效果
weight
权重
HAproxy 的 ACL 机制
http访问控制参数
rediect blockhttp-request use_backend
但凡是使用if的时候必须使用acl进行定义,访问控制列表的定义可以通过源地址/目标地址,源端口目标端口来定义,所以acl中所支持定义的标准和机制还是比较多的
·ACL 基本定义语法
·acl 名称 acl标准 [标志位][操作]
·acl 区分大小写
通常参数都是 -i
值的类型
e.g 1024:65535
比较操作
eg ge gt le lt
字符串
常用参数 -i
常用的匹配标准:
dst 目标地址
dst_port 目标端口
src 源地址
src_prot 源端口
acl goodguys src ip/24 如果是goodguys则允许访问
tcp-request content accept if goodguys 如果是goodguys则允许发起连接请求
tcp-request content reject 没有if语句 则拒绝所有(reject)
定义ACL
基于SRC做访问控制
我们期望用户访问的时候如果来源地址是10.0.10.1则拒绝访问
frontend web_server
bind*:80
default_backendwebservers
acl badguy src 10.0.10.1
block if badguy
acl定义规则名称为badguy,并且定义如果来源是10.0.10.1的IP地址拒绝访问
block表示拒绝的意思,if后面加判断,如果匹配badguy名称定义的规则那么就执行block的操作
再次访问
使用重定向
如果想访问403页面重定向到其他页面的话,则:
frontend web_server
bind *:80
default_backend webserver
acl badguy src 10.0.10.1
block if badguy
errorloc 403 http://baidu.com/ #定义错误页面重定向
在七层做其他的匹配
hdr
检查首部是否属于某个指定字符的
frontend web_server
bind *:80
default_backend webserver
acl badguy src 10.0.10.1
acl dstipaddrhdr(Host) 10.0.10.61
redirectlocation http://www.qq.com/ if dstipaddr
errorloc 403 http://baidu.com
以上,通过har机制检测 如果头部信息包含此IP地址那么将其重定向至qq.com
如果非此IP地址,那么请求的uri返回是403,那么则直接跳转到baidu.com
hdr_reg 正则表达式匹配
说明某个首部的值只要匹配这个正则,则执行跳转
http_first_req
第一次请求匹配
method 访问方法匹配(GET或POST等)
实现简单动静分离功能
acl read method GET
acl read methodHEAD
acl write methodPUT
acl write methodPOST
use_backend imgserif read
use_backend uploadif write
基于path http路径做访问控制
是做精确匹配的,因此通常只匹配用户已经知道的文件路径
来自某个ip的主机访问的是1.html 则拒绝访问,其他全部放行,则:
#首先定义acl 名称denyfile 根据path来做访问控制,而path一定跟的是具体访问路径
#http-reques 来做规则 如果是badguy 并且访问的是denyfile 如果匹配两者则deny掉
frontend web_server
bind *:80
default_backend webserver
acl badguy src 10.0.10.1
acl denyfile path/1.html
http-request deny if badguy denyfile
重新加载配置文件,并且访问测试:
访问/1.html 则返回403 ,访问其他uri则正常返回
path_beg
path只能定义单一路径或文件,但是path_beg可以定义多个文件或路径
实例:实现动静分离功能
首先定义两个backend,分别以动态和静态进行分组
backend jingtai
balance roundrobin
server web1 10.0.10.82:80 check weight 1maxconn 2000
balance roundrobin
server web2 10.0.10.83:80 check weight 1maxconn 3000
配置frontend
frontend web_server
bind *:80
default_backend webservers
acl badguy src 10.0.10.1
acl denyfile path /1.html
#http-request deny if badguy denyfile
acl static path_end .html
use_backend jingtai if static
default_backend dongtai
定义acl名称为static ,如果访问匹配是.html的文件,那么直接跳转至jingtai 这个backend
如果访问的不匹配.html 那么直接跳转至默认backend dongtai组
重新加载规则,访问测试:
实现完全动静分离
在path_end中可以使用-i参数指定多个选项
修改配置信息,将一系列尽可能出现的静态内容文件类型加入acl的static组内
bind *:80
default_backend webservers
acl badguy src 10.0.10.1
acl denyfile path /1.html
#http-request deny if badguy denyfile
acl static path_end -i .html .jpg .png.jpeg .gif .swf .css .xml .txt .pdf
use_backend jingtai if static
default_backend dongtai
path_reg
正在表达式匹配
acl url_static path_reg -i .jpg$ .html$ 等 ^/static ^/images^/stylsheets
基于正则表达式匹配要比基于字符匹配慢很多,所以如果可以写成字符匹配就尽可能使用 path_end path_end 而不要使用path_reg
url
之前我们在用path做匹配的时候发现,path不包含头部信息,而url全部包含
做url匹配要做整个路径匹配,但事实上用的最多的是path 而不是url,以为用户访问文件的时候,可能是这样访问:
http://xxx.com/login.php?name=test&password=xxxx
很显然login.php 才是访问的文件,而根据整个路径结尾进行判断的话则不能判断其类型的,所以更多用到的是path_end ,因为path_end顶多只能匹配到login.php
而不包含后面的内容
url_beg
url开头
url_end
url结尾
有些时候我们用url做匹配的时候可能会使用多条进行组合起来
比如:
#如果badguy 访问的是除了denyfile之外的其他文件,则将被拒绝
http-request denyif badguy !denyfile
如果badguy 或其他人 访问的是除了denyfile之外的其他文件,则将被拒绝
http-request denyif badguy OR denyfile
健康状态检查机制
monitor-uri
通过web组件实现监控的,明确指定监控哪个uri而不是内部监控机制(check)
frontend www
bind :80
monitor-uri /haproxy
意思为做状态监测必须去请求这个uri的页面,能请求到并且状态为200则认为正常的
httpchk
做服务器的健康状态监测的时候明确说明http协议,可以指定检查那个uri,还可以指定那种方式检查uri,只启用就明确说明只做uri监测 而后面的监测方法全部省略了
backendhttps_relay
mode tcp
option httpchk OPTIONS * HTTP/1.1\r\nHost:\ www
server apache1 192.168.1.1:443 check port 80
也就意味着我们做健康检测的时候,是发送自定义信息去check
也就是说httpchk是发送的自定义的方法以及发送的请求报文格式的,只有发送的请求返回值是200,才认为正常否则失败的
http请求格式:
<method><uri> <version>
<header>
<body>
将OPTIONS *HTTP/1.1\r\nHost:\ www 转换成标准格式,如下所示:
OPTIONS * HTTP/1.1
Host: www
例:定义对mysql进行检测
option mysqlchkuser mysqlusername
使用option参数套mysqlchk插件以mysqlusername的名称去连接mysql,只要能连接上,则认为数据库正常,否则不允许连接
综合示例:
示例1.实现动静分离
匹配以/static/images /img /css 目录的URI,并匹配以静态文件内容的URI
acl usr_staticpath_beg -i /static /images /img /css
acl usr_staticpath_end -i .gif .png .jpg
#判断用户访问如果主机名以www开头的话则标示为host_www
acl host_wwwhdr_beg(host) -i www
如果主机是以img video download 的域名开头,都被认为是静态内容
acl host_statichdr_beg(host) -i img. video. download.
#而后做匹配内容,如果三者匹配其中一个则分发至backend static组
use_backend static if host_static or host_www or url_static
default_backendappservers
实例2
global
pidfile /var/run/haproxy.pid
log 127.0.0.1 local0 info
defaults
mode http
clitimeout 600000 # maximum inactivity time on the client side
srvtimeout 600000 # maximum inactivity time on the server side
timeout connect 8000 # maximum time to wait for aconnection
attempt to a server to succeed
stats enable
stats auth admin:password
stats uri /monitor
stats refresh 5s
option httpchk GET /status
retries 5
option redispatch
errorfile 503 /path/to/503.text.file
balance roundrobin # each server isused in turns, according to assigned weight
frontend http
bind :80
monitor-uri /haproxy # end point tomonitor HAProxy status (returns 200)
#只要用户访问的path路径是以api开头则匹配
acl api1 path_reg ^/api1/?
acl api2 path_reg ^/api2/?
如果是api1的话则使用backend api1 以此类推
use_backend api1 if api1
use_backend api2 if api2
backend api1
# option httpclose
server srv0 127.0.0.1:9000 weight 1 maxconn 100 check inter4000
server srv1 127.0.0.1:9001 weight 1 maxconn 100 check inter4000
server srv2 127.0.0.1:9002 weight 1 maxconn 100 check inter4000
backend api2
option httpclose
server srv01 127.0.0.1:8000 weight 1 maxconn 50 check inter 4000
但是没有默认服务器也就意味着只允许用户请求api1api2,以别的任何方式都访问不到
haproxylisten配置示例:
基于COOKIE做持久连接
只要在listen中还是在backend中是要使用cookie指令 就意味着server中去引用这个cookie的,每个用户都加上sessionid,因此会为每个用户请求插入一个会话ID,因此基于这个会话id做负载均衡调度
listen webfarm
bind 192.168.0.99:80
mode http
stats enable
stats auth someuser:somepassword #指定某个用户某个密码
balance roundrobin #指定调度算法
cookie JSESSIONID prefix #基于cookie做负载均衡
option httpclose
option forwardfor #添加首部信息
option httpchk HEAD /check.txt HTTP/1.0 #http首部请求的方法是head 请求的是 /check.txt 协议是1.0 ,没有跟主机就意味着请求的是默认主机,而不是检测虚拟主机
server webA 192.168.0.102:80 cookie A check #使用cookie做了负载均衡
server webB 192.168.0.103:80 cookie B check
对mysql读集群做负载均衡
只是对于读请求可以做负载均衡,如果对于写做负载均衡的时候直接这样调度是不合适的
frontendmysqlserversbind *:3306
default_backend myservs
backend myservs
balance leastconn
option mysqlchk user root
server myserv1 172.16.100.11:3306 check
server myserv2 172.16.100.12:3306 check