3.3 Haproxy的访问规则设置
3.3.1 Haproxy的规则设置
在上一节的案例中我们看到,通过acl可设定URI的访问规则,那么里面的hdr(host)是什么意思,又有哪些其他可以做设置的项呢?下面我们就来具体分析一下。
在haproxy的配置文件中,可以使用acl关键字来定义访问规则,然后使用use_backend ... if ... 来使用定义的acl规则,语法格式如下:
acl 规则名 类型 条件内容
use_backend 后端集群名 if acl名
从上面的语义来看就是,当有客户访问满足指定的acl名时,转交到指定的后端backend上。
acl可定义的条件类型有很多,总结来看,有几下几种:
地址类(四层):src源ip地址 src_port源端口 dst目的ip地址 dst_port目的端口;
域名路径类(七层):hdr请求的目的域名 path域名后子地址的路径 url统一资源定位,
其中每一个类型下又可分为多个子项,大体解释如下:
来看下面的几个案例(以下案例建议在haproxy配置文件中先注释之前手动输入的内容后再写入,否则容易由于先后顺序问题,造成实验效果不准确):
例1:设置ip为202.0.1.0/24地址段的客户端,转发给名为ttWeb的backend集群:
frontend ttWeb
bind 202.0.0.1:80
mode http
acl c1 src202.0.0.0/24
use_backend ttServersif c1
backend ttServers
balance roundrobin
server web1 192.168.10.102:80 check weight 30
注:本例中backend中仅设置了一个节点,其实可以设置多个。
例2:访问域名rzz.com下的所有请求,都转发给转发给名为ttWeb的backend集群。
frontend ttWeb
bind 202.0.0.1:80
mode http
acl c1 hdr_reg(host)-i rzz
use_backend ttServersif c1
default_backendWebServers
backend ttServers
balance roundrobin
server web1 192.168.10.100:80 check weight 30
注:其实这样写,rzz1.com、rzz2.com这样的相似域名,也符合该规则。那是不是该写成acl c1 hdr_reg(host) -i rzz.com就更精确一些了呢?
另外,如果我们把规则写成acl www hrd_reg(host) -i ^(www.rzz.com) 呢?大家可以复习之前学过的特殊字符,自行考虑、试验该结果。
例3:访问以bbs开头的子路径(如:http://www.rzz.com/bbs/)的请求,都转发给名为ttWeb的backend集群。
frontend ttWeb
bind 202.0.0.1:80
mode http
acl c1 path_beg -i /bbs
use_backend ttServersif c1
default_backendWebServers
backend ttServers
balance roundrobin
server web2 192.168.10.101:80 check weight 30
例4:访问以.jpg .png结尾的子路径(如:http://www.rzz.com/bbs/a.jpg)的请求,都转发给名为ttWeb的backend集群。
frontend ttWeb
bind 202.0.0.1:80
mode http
acl c1 path_end -i .jgp .png
use_backend ttServersif c1
default_backendWebServers
backend ttServers
balance roundrobin
server web2 192.168.10.101:80 check weight 30
注:acl的定义中,是允许指定多个值项的,如本例中的acl c1 path_end -i .jgp .png,其他类型的acl(如hdr、url等)也是如此,可以设置多个值项。
例5:访问地址中包含login字符的请求,都转发给名为ttWeb的backend集群。
frontend ttWeb
bind 202.0.0.1:80
mode http
acl c1 url_sub -i login
use_backend ttServersif c1
default_backendWebServers
backend ttServers
balance roundrobin
server web2 192.168.10.101:80 check weight 30
好了,到此我们给acl的配置管理,通过案例做了几个较具代表性的实验,总结来看,对于acl的管理,常用的有三个类型的使用,就是hdr、path、url三项,每项下又支持多个分支,一般不加_后缀的是对原项的精确匹配,如:acl a1 hdr(Host) -i www.rzz1.com;加_beg是对地址的开始字符做匹配;加_end是对地址的结束字符做匹配;加_reg的是对地址做正则表达式匹配。所以大家在实际工作中可以借鉴这些规律,自行设计,以满足生产环境中的需求。有本文中未能涉及的较复杂需求,可以查找相关资料或官方文档,个人研究解决。
3.3.2 Haproxy的访问管理、重定向(跳转)
我们借助于acl,不仅可以完成针对性的分流,还可以对访问做允许/拒绝管理或重定向(又称跳转)操作。使用的关键字有redir、http-request redirect、redirect。
首先来分析一下对于访问端口的重定向管理该如何操作,可以使用redir做路径重定向,而redir设置,一般是写在server项中的,来看一下下面的案例:
例1:所有访问到haporxy服务器(即202.0.0.1)的81端口的请求,全部转到内部节点的80端口上
frontend ttWeb
bind 202.0.0.1:81
mode http
acl c1 dst_port 81
use_backend ttServers if c1
backend ttServers
balance roundrobin
server web1 202.0.0.1:81check weight 30 redir http://192.168.10.100:80
server web2 202.0.0.1:81 check weight 30 redirhttp://192.168.10.101:80
注:此例中,frontend监听的是81端口(bind行设置的是81),web1的地址也是本haproxy的地址,通过redir转发到了内部两个节点的80端口上。
再来介绍一下request请求重定向,一般会用到http-request redirect或redirect关键字。这两个关键字功能类似,语法也是一样的,只不过http-requestredirect更偏向于http模式的转发,支持日志格式变量(即可使用相关配置文件中预定义好的变量);而redirect只依赖于对静态字符串的审核,可以说http-request redirect是redirect的一种升级。
这两种重定向,无论哪一种,都有三种重定向方式
我们同样分别举例说明。
例2:所有访问www.rzz.com及子路径的请求全部转到www.rzz1.com的对应子路径上。
frontend ttWeb
bind 202.0.0.1:80
mode http
acl c1 hdr(host) -iwww.rzz.com
redirect prefixhttp://www.rzz1.com if c1
default_backendWebServers
backend WebServers
balance roundrobin
server web1 192.168.10.100:80 check weight 30
server web2 192.168.10.101:80 check weight 30
注:该例中由于是要做域名地址的转换,所以使用了prefix方式。当客户端在浏览器中输入http://www.rzz.com/bbs后,会发现地址栏中自动变为http://www.rzz1.com/bbs了,说明做了域名替换。
例3:所有访问www.rzz.com及子路径的请求全部转到www.rzz1.com上,并不进子路径。
frontend ttWeb
bind 202.0.0.1:80
mode http
acl c1 hdr(host) -iwww.rzz.com
redirect locationhttp://www.rzz1.com if c1
default_backendWebServers
backend WebServers
balance roundrobin
server web1 192.168.10.100:80 check weight 30
server web2 192.168.10.101:80 check weight 30
注:该例中由于使用了location方式。当客户端在浏览器中输入http://www.rzz.com/bbs后,会发现地址栏中自动变为http://www.rzz1.com了,说明仅做地址重定向,不做域名替换。
综上两例,可看出在实际应用中还是prefix方式更实用些。
例4:将所有http协议的访问自动转为https协议
分析:在第3.2.2节最后部分,我们介绍了haproxy分流https访问的方式,里面设置的是mode tcp,当时解释是只可以用tcp模式,因为我们仅在内部web节点上做了ssl验证功能,而在haproxy上并未做ssl验证,所以只能采用tcp模式,这种方式被称为haproxy的ssl穿透(或称透明)模式,即由内部节点做ssl,haproxy服务器仅转发请求,不做ssl验证。
还有一种方式是使用haProxy服务器作为SSL验证终端,那么则需要在haprox上创建证书了,创建证书的过程我们在上一本书《Linux服务部署》的apache章节中已做了介绍,读者可以自行创建证书。在这里,为了方便,我们直接使用Linux系统自带的证书来完成验证,命令如下:
yum –y install openssl mod_ssl ---安装ssl相关软件包
安装完毕后,我们采用如下命令创建秘钥及证书
cd /etc/haproxy
openssl genrsa -out /etc/haproxy/haproxy.key 1024 ---生成秘钥
openssl req -new -key /etc/haproxy/haproxy.key -out/etc/haproxy/ haproxy.csr ---生成申请
openssl x509 -req -days 3655 -in haproxy.csr -signkey haproxy.key-out haproxy.crt ---生成证书
然后再来创建haproxy的验证文件
cat haproxy.crt haproxy.key > haproxy.pem
最后我们来编写haproxy配置文件
frontend ttWeb
bind 202.0.0.1:443 sslcrt /etc/haproxy/haproxy.pem ---指定使用验证文件做验证
mode http ---使用http模式
default_backendWebServers
backend WebServers
balance roundrobin
server web1 192.168.10.100:80 check weight 30
server web2 192.168.10.101:80 check weight 30
注:由于已经在haproxy服务器上做了ssl验证,所以在内部节点上就无需再做ssl验证了,因此可以直接转发到内部节点的80端口上。
然而,如果我们需要把所有的http访问,都转为https访问的话,则可以写为:
frontend ttWeb
bind 202.0.0.1:80
bind 202.0.0.1:443 sslcrt /etc/haproxy/haproxy.pem
mode http
redirect scheme https if !{ ssl_fc } #协议重定向,ssl_fc前后有空格
default_backendWebServers
其中监听了80端口,表示监控http访问;redirect使用了协议重定向,而if后面的!{ ssl_fc }的意思是判断如果不是ssl的访问请求(!表示取反),则可实现非https协议转为https的功能。后面的backend书写不变,此处略。
3.3.3 http-request访问过滤
使用http-request关键字,不仅可以在后面写入redirect做重定向,还可以写入其他配置,完成对访问的过滤功能,可用项如下:
allow:接受该http请求。
auth:提示输入用户认证信息,指定realm时将给出提示信息。
redirect:重定向功能。
deny:拒绝该http请求。
其中最常用的当然是allow、deny、redirect了。下面我们来看一下过滤案例:
例:仅接受目标端口80、443的访问通信
frontend ttWeb
bind 202.0.0.1:80
bind 202.0.0.1:443 sslcrt /etc/haproxy/haproxy2.pem
mode http
acl c1 dst_port 80
acl c2 dst_port 443
http-request allow ifc1
http-request allow ifc2
http-request deny ---拒绝其他通信访问
use_backendWebServers if c2
use_backendttServers if c1
default_backendWebServers
backend WebServers
balance roundrobin
server web2 192.168.10.101:80 check weight 30
backend ttServers
balance roundrobin
server web1 192.168.10.100:80 check weight30
通过案例我们可以看到,使用http-request过滤可是实现对客户端的限制,那么延伸一下,我们是不是就可以使用acl的src、url等规则实现客户白名单、黑名单的管理呢?当然是可以的,先定义白名单、黑名单的acl,在针对acl做allow、deny就能够实现了,读者可以自行设计一下。
3.4 动静分离机制
现今的企业网站,按其所具备的功能划分,可分为动态站点、静态站点两类。动态与静态的区别并不是指页面上是否有动画、flash等动图效果,它的正规解释是与客户有无数据交互功能,其实就是页面上是否有注册、登录、查询等与客户互通数据的功能。有,则被视为动态站点;无,则是静态站点。
从动静态网站的功能来看,静态页面下服务器只需要给客户发送页面内容即可,不需要进行数据处理,所以针对用户请求的服务进程无需做太多工作,所需内存、CPU资源少,运行速度快;而动态页面由于需要对用户数据进程处理,所以针对客户服务的进程需要更多的cpu、内存资源,运行速度可能会变慢。总结来说,就是动态页面与静态页面相比,消耗系统资源较多,运行速度相对略慢,支持的并发少。
因此,在大规模互联网企业中,为了提高整体服务集群的工作效率,会对客户请求访问的目标页面做分类处理,比如:让客户访问静态页面时分流到一组集群中,如nginx集群;而访问动态页面时,则分流到另一组集群上,如apache、tomcat集群。由此我们将之称为动静分离。
关于动态页面,页面后台的代码一般都是由固定语言编写的,通常页面代码有php语言或jsp语言(即java语言)两种语言。php页面的后缀一般为.php,java页面的后缀一般为.jsp,所以可认定.php、.jsp的页面一般都为动态页面;而静态页面主要是一些文字、图片、动画、动图等资源,所以后缀一般是 .jpg .gif .png.css .js的。
基于Haproxy的http模式原理,就可以对客户所访问的不同目标资源做动静态的分别处理。下面我们来写一下具体的代码:
frontend ttWeb
bind 202.0.0.1:80
mode http
acl c1 path_end -i .js .php .jsp ---定义动态页面后缀
use_backend ttServers if c1
default_backend WebServers
backend WebServers
balance roundrobin
server web2 192.168.10.101:80 check weight 30
backend ttServers
balance roundrobin
server web1 192.168.10.100:80 check weight 30
好了,到这里,一个简单的动静分离设置就实现了。
3.5 haproxy监控
有同学可能会问了,有了分流的设置,我们该如何查看每个集群、节点的访问量、并发数等信息呢?其实很简单,我们只需要在haproxy的配置文件中开启一个端口,使用stats关键字设定监控即可,下面来看一下具体配置:
listen status_page
bind 202.0.0.1:8888 ---设定监控页面的地址及端口
stats enable ---启用状态监测功能
stats uri /haproxy-status ---指定页面在服务器上的url
stats realm "Welcome to the haproxy page" ---启用验证,并设置显示文字,需要配合stats auth使用
stats auth admin:123456 ---登录页面时验证使用的账号、密码
stats hide-version ---启用统计报告,但隐藏HAProxy的版本
stats admin if TRUE ---满足指定条件时,启用监控页面的管理功能,允许通过web页面启用或禁用后端服务器
stats refresh 5s ---监控页面刷新时间
好了,写完这些我们就可以重启haproxy服务。通过客户端的浏览器,输入http://202.0.0.1:8888/haproxy-status,访问监控页面,会有弹窗要求输入账号密码如下图所示:
输入账号admin、密码123456后即可打开监控页面了。如下图所示:
里面的frontend、backend是可以点击的,这样我们就能直观的看到每个frontend、backend、节点的工作状态了。
3.6 小结
到此,我们的haproxy的主要内容就讲解完了,大家可以多多练习。在实际工作中根据项目需求,设计对应的分流规则。当然,haproxy的功能还有很多,我们只讲解了其中的主要部分,其他配置,如果在工作中有所需要,大家可以查询一些相关资料,自行学习完成。