HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。根据官方数据,其最高极限支持10G的并发。
HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持或七层处理。HAProxy运行在当前的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整合进您当前的架构中,同时可以保护你的web服务器不被暴露到网络上。
haproxy配置
(确保没有rhcs套件的影响,关闭tgtd clvmd mysql luci ricci在浏览器中清除资源,删除集群,节点,最好是换一个虚拟机,之前高可用实验中的corosync对本次实验有影响
)
1,安装haproxy软件
构建rpm包需要的软件和依赖
yum install -y rpm-build
yum install gcc -y
yum install -y pcre-devel
rpmbuild -tb haproxy-1.6.11.tar.gz -tb 把tar包转化为二进制文件
Wrote: /root/rpmbuild/RPMS/x86_64/haproxy-1.6.11-1.x86_64.rpm 这个就是rpm包的位置
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.Xmz1AH
+ umask 022
+ cd /root/rpmbuild/BUILD
+ cd haproxy-1.6.11
+ '[' /root/rpmbuild/BUILDROOT/haproxy-1.6.11-1.x86_64 '!=' / ']'
+ /bin/rm -rf /root/rpmbuild/BUILDROOT/haproxy-1.6.11-1.x86_64
+ exit 0
安装rpm -ivh haproxy-1.6.11-1.x86_64.rpm
2,配置haproxy
rpm -qpl haproxy-1.6.11-1.x86_64.rpm 查看安装会生成的文件
/etc/haproxy
/etc/rc.d/init.d/haproxy
/usr/sbin/haproxy
/usr/share/doc/haproxy-1.6.11
/usr/share/doc/haproxy-1.6.11/CHANGELOG
/usr/share/doc/haproxy-1.6.11/README
/usr/share/doc/haproxy-1.6.11/architecture.txt
/usr/share/doc/haproxy-1.6.11/configuration.txt
/usr/share/doc/haproxy-1.6.11/intro.txt
/usr/share/doc/haproxy-1.6.11/management.txt
/usr/share/doc/haproxy-1.6.11/proxy-protocol.txt 没有配置文件,需要自己建立
tar zxf haproxy-1.6.11.tar.gz 用一个存在的配置文件模版改写,在tar包里面找example
cd haproxy-1.6.11
(find -name *.spec 之所以可以构建rpm包是因为有.spec文件,只要是以spec结尾的文件都会自动出现rpm包的构建模板,vim test.spec可以看到,已经出现的模板)
cd examples/
content-sw-sample.cfg 这个是主配置模版文件
cp content-sw-sample.cfg /etc/haproxy/haproxy.cfg
(/etc/rc.d/init.d/haproxy
# processname: haproxy
# config: /etc/haproxy/haproxy.cfg 这里有要读取的配置文件的位置和名字
# pidfile: /var/run/haproxy.pid)
修改配置文件
#
# This is a sample configuration. It illustrates how to separate static objects
# traffic from dynamic traffic, and how to dynamically regulate the server load.
#
# It listens on 192.168.1.10:80, and directs all requests for Host 'img' or
# URIs starting with /img or /css to a dedicated group of servers. URIs
# starting with /admin/stats deliver the stats page.
#
global 定义全局变量
maxconn 10000 并发最大链接数
stats socket /var/run/haproxy.stat mode 600 level admin
log 127.0.0.1 local0 日志保存在本地 local0是自定义
uid 200 指定了用户uid gid,所以必须要创建用户
gid 200
chroot /var/empty chroot是切换根目录,安全,防黑客
daemon 后台运行
defaults backend和frontend共有的放在defaults
mode http 默认使用 http 的 7 层模式 tcp: 4 层
log global 表示在全局变量里面找
option httplog http 日志格式
option dontlognull 禁用空链接日志
monitor-uri /monitoruri 检测haproxy服务本身
maxconn 8000 覆盖全局变量
timeout client 30s 客户端超时
stats uri /admin/stats haproxy监控页面
option prefer-last-server
retries 2 重试2次失败认为服务器不可用
option redispatch 当 client 连接到挂掉的机器时,重新分配到健康的主机
timeout connect 5s 连接超时
timeout server 5s 服务端超时
# The public 'www' address in the DMZ
frontend public
bind *:80 name clear 监听所有的80端口
#bind 192.168.1.10:443 ssl crt /etc/haproxy/haproxy.pem
#use_backend static if { hdr_beg(host) -i img }
#use_backend static if { path_beg /img /css }
default_backend static 默认返回后端的static
# The static backend backend for 'Host: img', /img and /css.
backend static
mode http
balance roundrobin 轮询算法
server statsrv1 172.25.28.2:80 check inter 1000 后端httpd服务器
server statsrv2 172.25.28.3:80 check inter 1000
3,创建haproxy用户
[root@server1 haproxy]# grep 200 /etc/passwd 全局配置要求uid和gid是200
[root@server1 haproxy]# groupadd -g 200 haproxy
[root@server1 haproxy]# useradd -u 200 -g 200 -M haproxy 这里不创建也不指定家目录
-M, --no-create-home do not create the user's home directory
[root@server1 haproxy]# id haproxy
uid=200(haproxy) gid=200(haproxy) groups=200(haproxy)
[root@server1 haproxy]# su - haproxy
su: warning: cannot change directory to /home/haproxy: No such file or directory
-bash-4.1$ logout #没有家目录但是有bash
[root@server1 haproxy]# vim /etc/security/limits.conf 实验可以不写,但是生产中必须要写
# End of file
haproxy - nofile 10000
(sysctl -a | grep file
fs.file-nr = 544 0 98861
fs.file-max = 98861 内核限制>操作系统>程序 等于也不会出错
4,server1启动服务
/etc/init.d/haproxy start
server2,server3开启httpd
5,客户端访问测试
访问172.25.28.1/monitoruri 200ok那么haproxy服务本身是正常的,跟server2,3httpd服务是否启动无关
访问172.25.28.1/admin/stats 监控页面,颜色都有说明,显示监控服务的状态
访问172.25.28.1 轮询server2,server3httpd服务器
配置haproxy日志
1,修改日志文件系统的配置文件
/etc/rsyslog.conf
# Provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514
local0不保存在/var/log/messages
# Save boot messages also to boot.log
local7.* /var/log/boot.log
local0.* /var/log/haproxy.log
#local0.*保存在/var/log/haproxy.log
2,重启日志系统
/etc/init.d/rsyslog restart
3,客户端访问测试
curl和网页随便访问都行
tail -f /var/log/haproxy.log -f 表示追加显示最新数据
haproxy调度后端服务器的多种算法
本机客户端改变或者后端服务器挂了,否则分配的后端服务器是不会改变的
注意:这个有先后顺序,这个server2坏了,server3上,如果server2又好了,那么server2上,因为sevrer2写在前面
八种算法
1、roundrobin
表示简单的轮询,每个服务器根据权重轮流使用,在服务器的处理时间平均分配的情况下这是最流畅和公平的算法。该算法是动态的,对于实例启动慢的服务器权重会在运行中调整。
2、leastconn
连接数最少的服务器优先接收连接。leastconn建议用于长会话服务,例如LDAP、SQL、TSE等,而不适合短会话协议。如HTTP.该算法是动态的,对于实例启动慢的服务器权重会在运行中调整。
3、static-rr
每个服务器根据权重轮流使用,类似roundrobin,但它是静态的,意味着运行时修改权限是无效的。另外,它对服务器的数量没有限制。
该算法一般不用;
4、source
对请求源IP地址进行哈希,用可用服务器的权重总数除以哈希值,根据结果进行分配。只要服务器正常,同一个客户端IP地址总是访问同一个服务器。如果哈希的结果随可用服务器数量而变化,那么客户端会定向到不同的服务器;
该算法一般用于不能插入cookie的Tcp模式。它还可以用于广域网上为拒绝使用会话cookie的客户端提供最有效的粘连;
该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。
5、uri
表示根据请求的URI左端(问号之前)进行哈希,用可用服务器的权重总数除以哈希值,根据结果进行分配。只要服务器正常,同一个URI地址总是访问同一个服务器。一般用于代理缓存和反病毒代理,以最大限度的提高缓存的命中率。该算法只能用于HTTP后端;
该算法一般用于后端是缓存服务器;
该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。
6、url_param
在HTTP GET请求的查询串中查找中指定的URL参数,基本上可以锁定使用特制的URL到特定的负载均衡器节点的要求;
该算法一般用于将同一个用户的信息发送到同一个后端服务器;
该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。
7、hdr(name)
在每个HTTP请求中查找HTTP头
如果缺少头或者头没有任何值,则用roundrobin代替;
该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。
8、rdp-cookie(name)
为每个进来的TCP请求查询并哈希RDP cookie
该机制用于退化的持久模式,可以使同一个用户或者同一个会话ID总是发送给同一台服务器。如果没有cookie,则使用roundrobin算法代替;
该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。
haproxy动静分离
1,修改配置文件
frontend public
bind *:80 name clear
#bind 192.168.1.10:443 ssl crt /etc/haproxy/haproxy.pem
#use_backend static if { hdr_beg(host) -i img }
use_backend static2 if { path_end -i .php } 如果uri路径是以.php结尾那么就去static2策略,这里php是动态请求
default_backend static1 如果不满足上面的,默认访问static1策略,这个名字是随便起的,但是要和下面策略对应上
# The static backend backend for 'Host: img', /img and /css.
backend static1
balance roundrobin
#balance source
server statsrv1 172.25.28.2:80 check inter 1000
#分开了两个策略看实验现象,实际每个方法里面都可以有多个服务器
backend static2
balance roundrobin
server statsrv1 172.25.28.3:80 check inter 1000
2,重启服务/etc/init.d/haproxy restart
3,server3作为动态请求的响应
安装php 重启httpd
index.php
phpinfo();
?>
如果apache安装了php,同时存在index.php和index.html那么默认找index.php
4,访问测试
路径中以.php结尾 172.25.28.1/index.php那么就访问server3的动态服务器
否则默认返回static1的静态服务器
acl访问控制
1,403报错重定向
frontend public
bind *:80 name clear
#bind 192.168.1.10:443 ssl crt /etc/haproxy/haproxy.pem
#use_backend static if { hdr_beg(host) -i img }
#可以对src dst src_port dst_port 进行acl访问控制 #
acl blacklist src 172.25.28.250 源重定向
#acl blacklist src 172.25.28.251 这个可以多次添加到黑名单
#acl blacklist src 172.25.28.0/24 网段黑名单
http-request deny if blacklist 在黑名单的直接出现403Forbidden报错
errorloc 403 http://172.25.28.1:8080 也可以不写,那么就不会重定向,如果4403Forbidden报错,那么重定向到这个地址8080端口(server1安装httpd,index.html页面可以是 网站正在维护,修改httpd.conf监听端口为8080,因为80端口被haproxy占用)
use_backend static2 if { path_end -i php }
default_backend static1
/etc/init.d/haproxy reload 每次修改都要重新加载配置
客户端访问测试
注意curl 172.25.28.1是不会显示重点向页面的,因为curl不支持,但是curl -I 可以看到
HTTP/1.1 302 Found 这是做了重定向的)
这个网站是做了两个重定向,taobao.com--->http://www.taobao.com--->https://www.taobao.com
2,直接重定向
frontend public
bind *:80 name clear
#bind 192.168.1.10:443 ssl crt /etc/haproxy/haproxy.pem
#use_backend static if { hdr_beg(host) -i img }
acl blacklist src 172.25.28.250
#http-request deny if blacklist
#errorloc 403 http://172.25.28.1:8080
redirect location http://172.25.28.3 黑名单访问直接访问这个地址
use_backend static2 if { path_end -i php }
default_backend static1
客户端访问测试:
浏览器访问172.25.28.3
haproxy读写分离
配置文件
frontend public
bind *:80 name clear
#bind 192.168.1.10:443 ssl crt /etc/haproxy/haproxy.pem
#use_backend static if { hdr_beg(host) -i img }
#use_backend static if { path_beg /img /css }
acl blacklist src 172.25.28.250
acl write method POST 请求
acl write method PUT 上传
#redirect location http://172.25.28.3
#use_backend static2 if { path_end -i .php }
use_backend static2 if write 如果是请求,上传那么交给static2策略
default_backend static1 否则默认返回static1策略
# The static backend backend for 'Host: img', /img and /css.
backend static1
balance roundrobin
server statsrv1 172.25.28.2:80 check inter 1000
backend static2
balance roundrobin
server statsrv2 172.25.28.3:80 check inter 1000
server2和server3
yum install php -y
在默认发布目录下建立upload目录并且给777权限,允许任何人上传,实际是apache身份
vim upload_file.php
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/pjpeg"))
&& ($_FILES["file"]["size"] < 2000000)) 上传文件要求属性要求
{
if ($_FILES["file"]["error"] > 0)
{
echo "Return Code: " . $_FILES["file"]["error"] . "
";
}
else
{
echo "Upload: " . $_FILES["file"]["name"] . "
";
echo "Type: " . $_FILES["file"]["type"] . "
";
echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb
";
echo "Temp file: " . $_FILES["file"]["tmp_name"] . "
";
if (file_exists("upload/" . $_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " already exists. ";
}
else
{
move_uploaded_file($_FILES["file"]["tmp_name"],
"upload/" . $_FILES["file"]["name"]);
echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
}
}
}
else
{
echo "Invalid file";
}
?>
vim index.php
重启httpd服务
/etc/init.d/httpd restart
客户端访问测试
这个页面其实读的是static1 ,server2作为静态服务
这个页面上传是static2,server3作为动态服务器
#可以查看上传的文件只在server3中,实现了读写分离
[root@server3 upload]# pwd
/var/www/html/upload
[root@server3 upload]# ll
total 56
-rw-r--r-- 1 apache apache 54157 Aug 4 23:06 redhat.jpg 身份,组都是apache