haproxy是一个前端调度器,它可以工作在第四层,基于TCP进行调度。也可以工作在第七层,针对http协议进行调度。当然它最出名的地方就是作为web服务的反向代理,而当它工作在第四层的时候,其实并没有像lvs工作在kernel空间,它是工作在用户空间。所以不管是基于TCP或者HTTP,它的性能都和Nginx作为前端调度器差不多。套接字限制使其最多只能响应差不多3w并发(接收client一个套接字,转发给server一个套接字)。实际上也就差不多2w。不过这个性能以及足够变态了。就现在看来,瓶颈基本都在DB,再然后就是APP Server。
我是用yum安装的,安装版本为:haproxy-1.5.4-2.el6.x86_64
官方文档:http://cbonte.github.io/haproxy-dconv/
配置段大概配置内容:
- global :全局配置段,看下内容是什么就知道它是配置什么了
- defaults :默认配置段,一般配置默认配置。如果下面2段有且和这个不同,则以下面的为准
- frontend :相当于虚拟主机
- backend :定义一组一组的后端server
- listen :既有forntend,又有backend
初始主配置文件解释
//因为主配置内容,很多一下子扯不清,文档中又有,所以很多就不解释了
frontend main *:5000 //定义一个名字为main的frontend,监听5000端口(一般为80)
acl url_static path_beg -i /static /images /javascript /stylesheets
//设置一个名字为url_static的acl,匹配uri路径开始(path_beg)为/static...的请求
//这句话说明白点就是所有以/static /images ...开头的资源请求都让url_staic这个acl匹配
acl url_static path_end -i .jpg .gif .png .css .js
//path_beg为匹配开头,那么path_end就是匹配结尾,名字和上面一样为url_static
//那么匹配的时候都会归纳到url_static。这条和上面一条都应该根据实际情况来
use_backend static if url_static
//所有被url_static匹配到的资源请求都交给static这个backend
default_backend app //默认,上面没匹配到的都给这个backend
backend static //定义一个backend
balance roundrobin //定义算法
server static 127.0.0.1:4331 check //具体后端服务器,check为启用健康监测
backend app
balance roundrobin
server app1 127.0.0.1:5001 check
server app2 127.0.0.1:5002 check
设置一个简单的调度配置
frontend main *: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 app
backend static
balance roundrobin
server static 192.168.100.21:80 check
backend app
balance roundrobin
server app1 192.168.100.22:80 check
//定义一个监控页面
listen statistics //定义个listen
bind *:1218 //监听的端口,和上面那种放在上面无区别
stats enable //开启stats
stats uri /itcys?adm //uri所在地
stats auth admin:itcys //认证
从1218端口的/itcys?adm进行测试。
开启statistics页面的管理功能
listen statistics
bind *:1218
stats enable
stats uri /itcys?adm
stats auth admin:itcys
stats admin if TRUE //为认证通过的登陆者开启管理功能
也可以定义在backend段。
不过如果定义在backend,就需要注意你输入地址frontend会不会调度到这个backend来,什么意思呢?就是如果你上面的内容定义在static
这个backend中,输入http://192.168.100.5/itcys?adm
,根据acl匹配规则,它是不会被匹配到url_static
这个acl来的,也就是说在浏览器输入上面那条URL,是永远到达不了static
这个backend,如果需要,可以在url_static
这条acl的配置规则里面加入/itcys
(请各位读者对号入座),这样访问上面那条URL才会被调度到static
来。
当然,如果想用web管理功能,而且还有其他人想要使用web统计功能,可以使用多个listen,一个只开启统计,还有一个开启管理功能。
动静分离
其实上面就配置过动静分离了,动静分离很重要一个点就是ACL。
那我们就来说说ACL:
acl <aclname> <criterion> [flags] [operator] <value> ...
<criterion>
: 匹配规则,那上面那段ACL来说就是path_beg
src
: Client IP
src_port
Client Port
dst
Server IP
dst_port
Server Port
path_beg
从前面开始匹配资源的所在路径
path_end
资源所在路径的后面(一般都是资源的后缀)
….. 林林总总有几十项,就不一一列出来了
[flages]
:
-i 不区分字符大小写
… 还有一些其他没啥用的
[operator]
:
eq、ge、gt、le、lt (大于小于等参数)
acl invalid_src src 0.0.0.0/7 224.0.0.0/3
//请求的Clinet IP为0.0.0.0/7或者224.0.0.0/3网段的都匹配为invalid_src
acl invalid_src src_port 0:1023
//源端口为0~1023的都匹配为invalid_src
acl local_dst hdr(host) -i localhost
//请求报文首部中的host若为localhost(不区分大小写),则匹配为local_dst
当然ACL的作用很多,不过最重要的还是动静分离。我现在就可以看配置文件中最初的ACL到底是什么意思了。
acl url_static path_beg -i /static /images /javascript /stylesheets
acl url_static path_end -i .jpg .gif .png .css .js
如果你们公司有/document
/media``等目录为静态内容目录,有html、css、js、图片等内容为静态内容。那么就可以这样匹配
acl url_name path_beg -i /document /media
acl url_nae path_end -i .jpg .gif .png .css .js .html .peng
当然你也可以定义动态内容,然后其余的转给静态,那我现在就用虚拟机进行演示:
[root@web-node1 html]# cat index.html test1.php
<h1>21 - static test page</h1>
<h1>21 - php test page</h1>
----------------------------------------------------
[root@web-node2 html]# cat index.html test1.php //node2测试页面
<h1>22 - static test page</h1>
<h1>22 - php test page</h1>
PHP的效果都展示出来了。html标签无效,当然因为后端没有架设真正的php Server,所以就用文本展示调度效果,其实这样展示更容易理解,给人感觉就是不管是什么,反正就看你怎么调度。
调度算法,配置中有一个blance的指令。其参数为roundrobin
。其实blance为使用调度算法,roundrobin
算法。
balance roundrobin
官方文档:http://cbonte.github.io/haproxy-dconv/1.5/configuration.html#balance
下面的内容看不懂的话可以翻一下我写的lvs那篇理论,里面详细的介绍lvs的调度算法,看了那个然后再来看下面的内容才会看的懂,因为这下面的我会忽略很多内容。
roundrobin
:
权重轮调,不指定权重默认为1,不过是动态的,服务器运行时候的权重能动态调整以让之前掉线现在又加入的Server的慢启动
慢启动:指的新加入的Server上线不一下就把所有的请求都调度给它,
而是让其权重慢慢增加,这样之前的Server的缓存都不会浪费。
static-rr
:
静态的权重轮调,下线的服务器新上线了,不像上面慢慢的往新上线的服务上面调度请求,而是它应该负责多少,就直接调度过去。不会慢启动。
leastconn
:
支持权重的最少连接。一般只适用哪些较长会话的协议,也是动态的,也是慢启动
source
:
Client-IP hash,然后保存在一张表中。对hash结果相同的请求都发往同一个后端Server。任何Client的第一个请求都由WLC算法调度(hash表找不到的时候)。保持session可以使用这个。用在TCP模块中,但是如果支持cookie做保持,那就不需要使用这个了,cookie保持比这个好
uri
:
分2种:一种是path,另一种是从path后面的全部都算,hash%weight,然后落在哪台服务器上面。就交给哪台服务器。使用hash-type支持consistent(一致性算法),让其支持动态权重,支持慢启动,len指令可以指定长度(字节)。depth可以指定深度(文件夹几层)
url_param
:
根据param段来进行调度,如果是“参数=值”,那么hash的就是那个值。并除以权重之和。通常param段是user=tom(url Syntax的内容,下面会讲一下),在用户认证场景中可以让同一个用户调度到同一个服务器。如果没有参数或者没有值。那么就使用round robin。可以使用hash-type指定一致性hash算法。
hdr(<name>)
:
明确指定根据http请求报文的某特定首部进行调度。如果没有这个首部,或者首部没有值,那么就使用roundrobin算法,默认也是静态,hash%weight,可以使用hash-type指定hash一致性算法,如果改为host进行调度,可以将对于同一虚拟主机的请求调度到同一个后端server上面去。
- 调度众多的Mysql从服务器。建议使用
leastconn
- 调度web图片服务器,建议使用
rounddobin
- 调度web的应用程序服务器,建议使用
source
- 调度web缓存服务器组,建议使用
URI
注:如果后端为cache服务器的时候,一定要加上hash-type consistent
这条指令,不然到时候增减server,会导致后端cache server的缓存大量失效。负载比较大的集群,又是全靠cache支撑起的时候,一旦出现上面那种情况,可能整个集群都会像被拒绝服务那样。提供不了访问。
上面提到的path,param:
URL Syntax:
<scheam>://<user>.<password>@<host>:<port>/<path>;<params>?<query>#<frage>
https://www.google.com.sg/search?site=&source=hp&q=Linux&_locale=zh_CN
http://cbonte.github.io/haproxy-dconv/1.5/configuration.html#balance 我们拿两条url来做对比:
<scheam>:
- http or https
<path>:
- /home.php
- /haproxy-dconv/1.5/configuration.html
<params>:
- 参数
<query>:
- 一般是与Datebase相关
<frage>:
- 这个一般都是本地生效,在页内跳转用,
#balance
MYSQL读请求的负载均衡
frontend main *:3306
mode tcp
default_backend mysqlServers
backend mysqlServers
balance leastconn
server mysqlServer1 192.168.100.21:3306 check port 3306 inter 2 rise 1 fall 2 maxconn 400
//检查3306端口,inter: 2,2s检查一次,rise 1,上线只需要检查一次
server mysqlServer2 192.168.100.22:3306 check port 3306 inter 2 rise 1 fall 2 maxconn 400
//fall 2,下线需要检查2次,maxconn 400,最多能承受400并发
具体的调度简单,但是上面defaults
的参数需要读者根据实际情况进行调整,因为我这里并没有讲上面参数如何使用,所以就不把它们列出来了。不过如果不修改的上面的内容的话,启动的时候会报错,根据报错修改一下就好。
为了测试我将改了balance
为roundrobin
。
mysql> CREATE DATABASE db1;
Query OK, 1 row affected (0.00 sec)
mysql> GRANT ALL ON *.* TO "itcys"@"192.168.100.%" IDENTIFIED BY "itcys";
Query OK, 0 rows affected (0.00 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
_____________________________________________________________________________
imac:~ cys$ mysql -h 192.168.100.21 -uitcys -pitcys -e "SHOW DATABASES;"
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| mysql |
| test |
+--------------------+
imac:~ cys$ mysql -h 192.168.100.22 -uitcys -pitcys -e "SHOW DATABASES;"
+--------------------+
| Database |
+--------------------+
| information_schema |
| db2 |
| mysql |
| test |
+--------------------+
效果:
imac:~ cys$ mysql -h192.168.100.5 -uitcys -pitcys -e "SHOW DATABASES;"
+--------------------+
| Database |
+--------------------+
| information_schema |
| db2 |
| mysql |
| test |
+--------------------+
imac:~ cys$ mysql -h192.168.100.5 -uitcys -pitcys -e "SHOW DATABASES;"
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| mysql |
| test |
+--------------------+
好了差不多到这里就差不多了,很多很多东西没有讲。有兴趣的读者可以去看官方文档,算法的话,有兴趣的读者可以自己去测试,高可用实现方案的话,因为haproxy只是一个应用,可以当做资源来使用,所以不管是标准的HA套件,还是轻量级的keepalived,都可以实现对其高可用。有兴趣的读者可以翻翻我前面讲的HA实现方案。
真的很多很多东西没有讲,看看官方文档就知道有多少东西了,其实这篇blog我个人觉得写的真的很一般,比前面几篇差多了,可能是因为参数太多了,又有5个配置段。结果就造成了理不顺。上面只是给出一个基本的示例,详细的参数还需要大家去看官方文档。