haproxy
概念
HAProxy是一个使用C语言编写的自由及开放源代码软件,其提供高可用性、负载均衡,以及基于TCP和HTTP的应用程序代理。
- HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持或七层处理。HAProxy运行在当前的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整合进您当前的架构中, 同时可以保护你的web服务器不被暴露到网络上。
- HAProxy实现了一种事件驱动, 单一进程模型,此模型支持非常大的并发连接数。多进程或多线程模型受内存限制 、系统调度器限制以及无处不在的锁限制,很少能处理数千并发连接。事件驱动模型因为在有更好的资源和时间管理的用户空间(User-Space) 实现所有这些任务,所以没有这些问题。此模型的弊端是,在多核系统上,这些程序通常扩展性较差。这就是为什么他们必须进行优化以 使每个CPU时间片(Cycle)做更多的工作。
- HAProxy 支持连接拒绝 : 因为维护一个连接的打开的开销是很低的,有时我们很需要限制攻击蠕虫(attack bots),也就是说限制它们的连接打开从而限制它们的危害。 这个已经为一个陷于小型DDoS攻击的网站开发了而且已经拯救了很多站点,这个优点也是其它负载均衡器没有的。
- HAProxy 支持全透明代理(已具备硬件防火墙的典型特点): 可以用客户端IP地址或者任何其他地址来连接后端服务器. 这个特性仅在Linux 2.4/2.6内核打了cttproxy补丁后才可以使用. 这个特性也使得为某特殊服务器处理部分流量同时又不修改服务器的地址成为可能。
proxy&Haproxy
相同点:在功能上,proxy通过反向代理方式实现 WEB均衡负载。和 Nginx,ApacheProxy,lighttpd,Cheroke 等一样。
不同点:Haproxy 并不是 web 服务器。以上提到所有带反向代理均衡负载的产品,都清一色是 WEB 服务器。简单说,就是他们能处理解析页面的。而Haproxy 仅仅是一款的用于均衡负载的应用代理。其自身并不能提供web服务。但其配置简单,拥有非常不错的服务器健康检查功能还有专门的系统状态监控页面,当其代理的后端服务器出现故障, HAProxy会自动将该服务器摘除,故障恢复后再自动将该服务器加入。
简单的实现
实验设备:
web node1 192.168.0.196
web node2 192.168.0.197
ha node3 192.168.0.151
ha安装方式:
- rpm 包方式:
rpmbuild -tb haproxy-1.4.23.tar.gz
rpm -ivh /root/rpmbuild/RPMS/x86_64/haproxy-1.4.23-1.x86_64.rpm
- 源码方式:
tar zxf haproxy-1.4.23.tar.gz
cd haproxy-1.4.23
make TARGET=linux26 ARCH=x86_64 USE_PCRE=1 PREFIX=/usr/local/haproxy install
node3
yum install haproxy -y (建议用rpm包装)
cd /etc/haproxy/
vim haproxy.cfg
> ###配置文件说明 global log 127.0.0.1 local2 #全局的日志配置,使用log关键字 chroot /var/lib/haproxy #改变当前工作目录
> #修改haproxy的工作目录至指定的目录并在放弃权限之前执行chroot()操作,可以提升haproxy的安全级别,不过需要注意的是要确保指定的目录为空目录且任何用户均不能有写权限
>
> pidfile /var/run/haproxy.pid #当前进程id文件 maxconn 4000
> #设定每个haproxy进程所接受的最大并发连接数 user haproxy group haproxy daemon #让haproxy以守护进程的方式工作于后台
>
> 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
> 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 #每个进程可用的最大连接数
(1)添加节点信息法一
vim /etc/haproxy/haproxy.cfg
63 frontend main
64 bind *:80
65 default_backend webserver
70 backend webserver
71 balance roundrobin
72 server web1 192.168.0.196:80 check
73 server web1 192.168.0.197:80 check
listen admin *:8080
stats enable
stats uri /status # 监控页面地址
stats auth admin:westos # 管理帐号和密码
stats refresh 5s #刷新频率
(2)添加节点信息法二:
#listen:可以理解为frontend和backend的组合体
vim /etc/haproxy/haproxy.cfg
listen admin *:8080
stats enable
stats uri /status # 监控页面地址
stats auth admin:westos # 管理帐号和密码
stats refresh 5s #刷新频率
listen westos *:80 #监听的实例名称,地址和端口
balance roundrobin #负载均衡算法
server web1 192.168.0.196:80 check
server web2 192.168.0.197:80 check
监控配置
stats uri /status #haproxy 监控页面
listen www.example.com *:80 #监听的实例名称,地址和端口
balance roundrobin #负载均衡算法
server web1 192.168.0.196:80 cookie app1inst1 check inter 2000 rise 2 fall 5
server web2 192.168.0.197:80 cookie app1inst2 check inter 2000 rise 2 fall 5
#cookie app1inst1:表示 serverid 为 app1inst1
#check inter 2000 :检测心跳频率
#rise 2:表示 2 次正确认为服务器可用
#fall 5:表示 5 次失败认为服务器不可用
haproxy 日志:
vim /etc/rsyslog.conf
$ModLoad imudp #接受 haproxy 日志
$UDPServerRun 514
*.info;mail.none;authpriv.none;cron.none;local2.none /var/log/messages
local2.* /var/log/haproxy.log #日志文件位置
#rsyslog restart
node1/2
打开http服务,修改默认发布页面
测试
此时访问node3,测试负载
访问node3/status ,查看监控页面,;down noe1,测试ha是否成功
添加动静分离
node3
#frontend:用来匹配接收客户所请求的域名,uri等,并针对不同的匹配,做不同的请求处理
frontend westos *:80
acl url_static path_beg -i /images
acl url_static path_end -i .jpg .gif .png
use_backend static if url_static
default_backend app (默认访问app)
#backend:定义后端服务器集群
backend static (静态)
#balance roundrobin
server web2 192.168.0.197:80 check
backend app (动态)
#balance roundrobin
server web1 192.168.0.196:80 check
server local 192.168.0.151:8000 backup
(如果后端real server down掉,则调度报错页面,但是正常情况下不会访问,因为是“backup”)
安装http,作默认页面
node1
在httpd默认发布目录下新建images目录,上传一张.jpg的图片。
测试
node3/images,得到图片
down 1 2,node3,看见的是3的页面
错误重定向
node3
####错误页面
frontend westos *:80
acl url_static path_beg -i /images (以什么开头 默认根目录)
acl url_static path_end -i .jpg .gif .png (以什么结尾)
acl badhost src 192.168.0.1 (设定谁不能访问我)
block if badhost
errorloc 403 http://192.168.0.151:8000 (注意端口不要冲突)(403:服务器拒绝你的访问 服务器设定你是坏的 )(如果是403错误就重定向到 192.168.0.151:8000)
use_backend static if url_static
default_backend app
backend static
balance roundrobin
server web2 192.168.0.197:80 check
backend app
balance roundrobin
server web1 192.168.0.196:80 check
####重定向
frontend westos *:80
acl url_static path_beg -i /images (以什么开头 默认根目录)
acl url_static path_end -i .jpg .gif .png (以什么结尾)
acl badhost src 192.168.0.1 (设定谁不能访问我)
redirect location http://192.168.0.151:8000 if badhost (如果出现错误访问 就重定向 不管是什么错误)
use_backend static if url_static
default_backend app
backend static
balance roundrobin
server web2 192.168.0.197:80 check
backend app
balance roundrobin
server web1 192.168.0.196:80 check
301永久重定向:(一般推荐用301 302临时重定向 有恶意刷点击的嫌疑)
301 redirect: 301 代表永久性转移(Permanently Moved)
302 redirect: 302 代表暂时性转移(emporarily Moved )
详细来说,301和302状态码都表示重定向,就是说浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这个地址可以从响应的Location首部中获取(用户看到的效果就是他输入的地址A瞬间变成了另一个地址B)——这是它们的共同点。他们的不同在于。301表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址;302表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。
vim /etc/haproxy/haproxy.cfg
frontend westos*:80
acl westos.org hdr_beg(host) -i westos.org
acl 192.168.0.151 hdr_beg(host) -i 192.168.0.151
redirect code 301 location http://www.westos.org if westos.org
(以westos.org访问 自动重定向 www.westos.org)
redirect code 301 location http://www.westos.org if 192.168.0.151
(以192.168.0.151访问 自动重定向 www.westos.org)
use_backend static if url_static
default_backend app
可以用curl命令查看细节
读写分离
node1/2
yum install php -y
php页面:
chmod 777 upload (默认上传目录一定要给权限)
node3
acl read method GET
acl read method HEAD //两个read write 只用一个就行
acl write method PUT
acl write method POST
use_backend app if write
default_backend static
(默认静态页面 为了测试 刚开始 www.westos.org 是192.168.0.197 而
写(上传时 却是在192.168.0.196上进行的) 做到了读写分离)
backend static
balance roundrobin
server web2 192.168.0.197:80 check
backend app
balance roundrobin
server web1 192.168.0.196:80 check (默认会上传到这个real server)
server local 192.168.0.151:8000 backup
systemctl restart haproxy
测试
nginx虚拟主机
基于域名的虚拟主机
就是通过不同的域名区分不同的虚拟主机,基于域名的虚拟主机是企业应用最广的虚拟主机类型,几乎所有对外提供服务的网站使用的都是基于域名的虚拟主机
查看nginx状态信息
with-http_stub_status_module 这个模块的主要功能是记录nginx的基本访问状态信息,让使用者了解nginx的工作装陶,例如连接数等信息
检查编译安装nginx时是否设定了上述模块:
../sbin/nginx -V
nginx version: nginx/1.10.3
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module
mkdir /usr/local/nginx/conf/extra
cd /usr/local/nginx/conf/extra
vim status.conf
server{
listen 80;
server_name status.westos.org;
location / {
stub_status on;
access_log off;
}
}
cd /usr/local/nginx/conf
vim nginx.conf
include extra/status.conf;
38
39 #gzip on;
40
41 server {
42 listen 80;
43 server_name www.westos.org westos.org;
44 location / {
45 root html/www;
46 index index.html index.htm;
47 }
物理:vim /etc/hosts
添加域名:status.westos.org
location语法
这个URL可以是普通的字符串地址路径,或者是正则表达,匹配成功则执行后面大括号里的相关指令
正则表达式的前面还可以有‘~’或‘~*’等特殊的字符
server {
listen 80;
server_name www.westos.org westos.org;
root html/www;
location / { #所有location都不能匹配后的默认匹配
return 401;
}
location = / { #精确匹配/
return 402;
}
location /documents/ { #匹配常规字符串,如果有正则,则优先匹配正则
#匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索
return 403;
}
location ^~ /images/ { #匹配常规字符串,不做正则匹配检查
# 匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条
return 404;
}
location ~* \.(gif|jpg|jpeg)$ { #正则匹配
# 匹配所有以 gif,jpg或jpeg 结尾的请求
# 然而,所有请求 /images/ 下的图片会被 config D 处理,因为 ^~ 到达不了这一条正则
return 500;
}
}
####
location = / {
# 精确匹配 / ,主机名后面不能带任何字符串
[ configuration A ]
}
location / {
# 因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求
# 但是正则和最长字符串会优先匹配
[ configuration B ]
}
location /documents/ {
# 匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索
# 只有后面的正则表达式没有匹配到时,这一条才会采用这一条
[ configuration C ]
}
location ~ /documents/Abc {
# 匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索
# 只有后面的正则表达式没有匹配到时,这一条才会采用这一条
[ configuration CC ]
}
location ^~ /images/ {
# 匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条。
[ configuration D ]
}
location ~* \.(gif|jpg|jpeg)$ {
# 匹配所有以 gif,jpg或jpeg 结尾的请求
# 然而,所有请求 /images/ 下的图片会被 config D 处理,因为 ^~ 到达不了这一条正则
[ configuration E ]
}
server {
listen 80;
server_name www.westos.org westos.org;
root html/www;
location = / {
# 精确匹配 / ,主机名后面不能带任何字符串
return 401;
}
location / {
# 因为所有的地址都以 / 开头,所以这条规则将匹配到所有
请求
# 但是正则和最长字符串会优先匹配
return 402;
}
location /documents/ {
# 匹配任何以 /documents/ 开头的地址,匹配符合以后,还
要继续往下搜索
# # 只有后面的正则表达式没有匹配到时,这一条才会采>用这一条
return 403;
}
location ~ /documents/Abc {
# 匹配任何以 /documents/ 开头的地址,匹配符合以后,还
要继续往下搜索
# # 只有后面的正则表达式没有匹配到时,这一条才会采>用这一条
return 503;
}
location ^~ /images/ {
# 匹配任何以 /images/ 开头的地址,匹配符合以后,停止>往下搜索正则,采用这一条。
return 404;
}
location ~* \.(gif|jpg|jpeg)$ {
# 匹配所有以 gif,jpg或jpeg 结尾的请求
# # 然而,所有请求 /images/ 下的图片会被 config D >处理,因为 ^~ 到达不了这一条正则
return 405;
}
}
}
测试
[root@foundation0 Desktop]# curl -s -o /dev/null -I -w "%{http_code}\n" http://www.westos.org/images/abc/def
000
[root@foundation0 Desktop]# curl -s -o /dev/null -I -w "%{http_code}\n" http://www.westos.org/images
402
[root@foundation0 Desktop]# curl -s -o /dev/null -I -w "%{http_code}\n" http://www.westos.org/images/
404
[root@foundation0 Desktop]# curl -s -o /dev/null -I -w "%{http_code}\n" http://www.westos.org/images/abc
407
[root@foundation0 Desktop]# curl -s -o /dev/null -I -w "%{http_code}\n" http://www.westos.org/documents/Abc.jpg
503
[root@foundation0 Desktop]# curl -s -o /dev/null -I -w "%{http_code}\n" http://www.westos.org/documents/images
403
[root@foundation0 Desktop]# curl -s -o /dev/null -I -w "%{http_code}\n" http://www.westos.org/images
402
[root@foundation0 Desktop]# curl -s -o /dev/null -I -w "%{http_code}\n" http://www.westos.org/images/abc
407
[root@foundation0 Desktop]# curl -s -o /dev/null -I -w "%{http_code}\n" http://www.westos.org/images/l/jpg
404