HAProxy动静分离&MySQL读负载均衡

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/

配置段大概配置内容:

初始主配置文件解释

//因为主配置内容,很多一下子扯不清,文档中又有,所以很多就不解释了

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上面去。

注:如果后端为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>:

<path>:

<params>:

<query>:

<frage>:

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的参数需要读者根据实际情况进行调整,因为我这里并没有讲上面参数如何使用,所以就不把它们列出来了。不过如果不修改的上面的内容的话,启动的时候会报错,根据报错修改一下就好。

为了测试我将改了balanceroundrobin

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个配置段。结果就造成了理不顺。上面只是给出一个基本的示例,详细的参数还需要大家去看官方文档。