欢迎各位兄弟 发布技术文章
这里的技术是共享的
在 director (我的ip (DIP) 192.168.0.75 ) 上 80 端口启动起来了
[root@mail ~]# service httpd start
启动 httpd: [确定]
[root@mail ~]# netstat -tnlp | grep 80
tcp 0 0 0.0.0.0:32803 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 4080/sshd
tcp 0 0 :::80 :::* LISTEN 14578/httpd
tcp 0 0 :::22 :::* LISTEN 4080/sshd
[root@mail ~]#
[root@mail ~]#
我的ip (DIP) 192.168.0.75
找不到 httpd 安装在哪里目录下了 ,只看到 首页以 index.html 开始,用如下命令发觉到在 /www/a.org/index.html 目录里面
[root@mail test]# locate index.html | xargs -I {} echo {}| xargs grep "^index.html"
/www/a.org/index.html:index.html
[root@mail test]#
[root@mail test]# echo "<h1>Director.magedu.com</h1>" > /www/a.org/index.html
[root@mail test]#
我的ip (DIP) 192.168.0.75 看到效果了
把自己的director 作为 rs 加上去
[root@mail test]# ipvsadm -a -t 192.168.0.77:80 -r 127.0.0.1 -g -w 5
[root@mail test]#
[root@mail test]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.0.77:80 wlc
-> 192.168.0.45:80 Route 2 0 0
-> 127.0.0.1:80 Local 5 0 0
-> 192.168.0.55:80 Route 1 0 0
[root@mail test]#
为了防止干扰,把director 和两个 rs 的iptables 全部清空 #iptables -F
可以看出三个都能够显示
director 本身是一个负载均衡器,目的不是为了让别人访问,而是作为一个调度器的, director 的http服务页面不是为了提供服务的,而是紧急情况下(比如rs全都宕机了),此时可以 director的服务器提供一个错误页面,您所访问的服务器正在维护当中
我们可以保存ipvsadm规则
service ipvsadm save
ipvsadm -S
对 director上 VIP,路由设置不能保存
RS上的:arp_ignore,arp_announce,(对于all,对于eth0或lo),VIP地址,路由条目,怎么自动实现
所以我们需要服务脚本
[root@mail test]# chkconfig --list ipvsadm
ipvsadm 0:关闭 1:关闭 2:关闭 3:关闭 4:关闭 5:关闭 6:关闭
[root@mail test]#
ipvsadm 是在内核中生效的,本身并不是一个服务,所以需要其它额外的配置,它还依赖于别的配置文件来保存规则,所以我们就不用它了,我们自己写脚本吧
Director脚本
DR类型中,Director和 RealServer的配置脚本示例
266 行 iptables -Z :将iptables的计数器清0
281行,建的是锁文件,前面start时应该是加判断,不存在锁文件的时候,才能start
Real Server脚本
345 行应该后面加上删掉 339 行添加的路由
rs 提供主页面,我们看能不能访问,
# elinks url 就是交互式的,加上 -dump选项,就是把内容加载下来,退出命令
[root@mail test]# elinks -dump http://192.168.0.45/index.html
RS1.magedu.com
[root@mail test]#
[root@mail test]# echo $? #美元符问号是上次命令的状态码 上一个命令(上一个进程)执行状态返回值
0
[root@mail test]#
[root@mail test]# elinks -dump http://192.168.0.9/index.html 不存在的页面 卡半天 我们可以定义它的超时时间
[root@mail test]# echo $? #结果为1,不对了
1
[root@mail test]#
如果rs 在线,不管;;如果rs不在线,就从real server 列表中移除
如果移除了rs,过一会儿又在线了,就又加到real server 列表中
我们也可以在rs (192.168.0.45)上提供一个测试页
[root@rs1 a.org]# pwd
/www/a.org
[root@rs1 a.org]# vim .health_check.html
OK
在 director (192.168.0.75)上 elinks 一下
[root@mail ~]# elinks -dump http://192.168.0.45/.health_check.html
OK
[root@mail ~]#
[root@mail ~]# elinks -dump http://192.168.0.45/.health_check.html | grep "OK" &> /dev/null
[root@mail ~]# echo $? #说明能正常访问
0
[root@mail ~]#
如果 elinks 访问错误(rs 挂了),那么会等待,会很慢的
在 director (192.168.0.75)上 curl
[root@mail ~]# curl http://192.168.0.45/index.html
RS1.magedu.com
[root@mail ~]#
[root@mail ~]# curl http://192.168.0.9/index.html #不存在的页面 也会卡住
curl: (7) couldn't connect to host
[root@mail ~]#
curl 命令选项
--cacert <file> CA证书(SSL)
--capath <directory> CA目录(made using C rehash) to verify peer against (SSL)
--compressed要求返回是压缩的形势(using deflate or gzip)
--connect-timeout <seconds> 设置最大请求时间
-H/--header <line>自定义头信息传递给服务器
-i/--include输出时包括protocol头信息
-I/--head只显示头部文档信息
--interface <interface>使用指定网络接口/地址
-s/--silent静音模式。不输出任何东西 #静默模式,不显示进度表或错误信息,但是仍然会显示网页内容
-u/--user <user[ :password]>设置服务器的用户和密码
-p/--proxytunnel使用HTTP代理
[root@mail ~]# curl --connect-timeout 1 http://192.168.0.9/index.html #--connect-timeout设置连接请求超时时间,会快点吧
curl: (28) connect() timed out!
[root@mail ~]#
[root@mail ~]# curl -I http://192.168.0.45/index.html #-I header方式获取数据,不获取网页真正内容,只获取页面的响应首部
HTTP/1.1 200 OK #这里 200 或 301 之类,,,,2或3开头的,说明是能访问到的
Date: Wed, 11 Nov 2020 01:02:30 GMT
Server: Apache/2.4.4 (Unix) PHP/5.4.13
Last-Modified: Thu, 05 Nov 2020 06:50:22 GMT
ETag: "f-5b35682870780"
Accept-Ranges: bytes
Content-Length: 15
Content-Type: text/html
[root@mail ~]#
root@mail ~]# curl -s http://192.168.0.45/index.html #静默模式,不显示进度表或错误信息,但是仍然会显示网页内容
RS1.magedu.com
[root@mail ~]#
[root@mail ~]# curl http://192.168.0.45/index.html &> /dev/null #送到null 中
[root@mail ~]# echo $? #根据状态返回值来判断是否在线
0
[root@mail ~]#
[root@mail ~]# curl --connect-timeout 1 http://192.168.0.9/index.html &> /dev/null #不存在服器务
[root@mail ~]# echo $? #非零值
7
[root@mail ~]#
[root@mail ~]# man curl
状态返回值 除了0,其它数字是各式各样的错
检测 rs 服务器是否在线的脚本
RIP=("192.168.10.7" "192.168.10.8") #这是一个数组
数组 有如下图的两种赋值方式
Array_name[index]
第一种方式
Array_name=("element1""element2")
第二种方式;如果中间 没有元素值,都为null,都为未赋值的元素
Array_name[0]="element1"
Array_name[7]="element8"
[root@mail ~]# RS=("192.168.10.7" "192.168.10.8")
[root@mail ~]# echo $RS[0]
192.168.10.7[0]
[root@mail ~]# echo $RS[1]
192.168.10.7[1]
[root@mail ~]# echo ${RS[0]} #引用的时候,一定要加花括号(大括号) 美元符号花括号
192.168.10.7
[root@mail ~]# echo ${RS[1]} #引用的时候,一定要加花括号(大括号) 美元符号花括号
192.168.10.8
[root@mail ~]#
[root@mail ~]# echo $RS #直接数组变量,表示是数组的第一个元素
192.168.10.7
[root@mail ~]#
[root@mail ~]# echo ${#RS} # 井号表示第一个元素的字符个数
12
[root@mail ~]# echo ${#RS[*]} # 井号变量中括号星号 表示 元素的个数
2
[root@mail ~]# echo ${RS[*]} # 变量中括号星号或艾特符号 表示数组中所有元素
192.168.10.7 192.168.10.8
[root@mail ~]# echo ${RS[@]}
192.168.10.7 192.168.10.8
[root@mail ~]#
[root@mail ~]#
由下图 每个 real server 其实是有端口的 只是我们添加时,80 与 集群服务的80 一样,所以添加时省略掉了
在director 上
[root@mail ~]# vim health_check.sh
#!/bin/bash
#
VIP=192.168.0.77
CPORT=80
FAIL_BACK=127.0.0.1
RS=("192.168.0.45" "192.168.0.55")
RSTATUS=("1" "1") #这里状态,1表示启用,0表示禁用
RW=("2" "1") #这是权重
RPORT=80
let COUNT=0
TYPE=g
add() {
ipvsadm -a -t $VIP:$CPORT -r $1 -$TYPE -w $2
[ $? -eq 0 ] && return 0 || return 1
}
del() {
ipvsadm -d -t $VIP:$CPORT -r $1
[ $? -eq 0 ] && return 0 || return 1
}
for I in ${RS[*]}; do
if curl --connect-timeout 1 http://$I/index.html &> /dev/null; then
if [ ${RSTATUS[$COUNT]} -eq 0 ]; then
add $I ${RW[$COUNT]}
[ $? -eq 0 ] && RSTATUS[$COUNT]=1
fi
else
if [ ${RSTATUS[$COUNT]} -eq 1 ]; then
del $I
[ $? -eq 0 ] && RSTATUS[$COUNT]=0
fi
fi
let COUNT++
done
rs2 上的 http服务停掉看看
[root@rs2 ~]# service httpd stop
停止 httpd: [确定]
[root@rs2 ~]#
[root@mail ~]# bash -x health_check.sh
+ VIP=192.168.0.77
+ CPORT=80
+ FAIL_BACK=127.0.0.1
+ RS=("192.168.0.45" "192.168.0.55")
+ RSTATUS=("1" "1")
+ RW=("2" "1")
+ RPORT=80
+ let COUNT=0
+ TYPE=g
+ for I in '${RS[*]}'
+ curl --connect-timeout 1 http://192.168.0.45/index.html
+ '[' 1 -eq 0 ']'
+ let COUNT++
+ for I in '${RS[*]}'
+ curl --connect-timeout 1 http://192.168.0.55/index.html
+ '[' 1 -eq 0 ']'
+ let COUNT++
[root@mail ~]#
停掉 rs2 (192.168.0.55) 看看
[root@rs2 ~]# service httpd stop
停止 httpd: [确定]
[root@rs2 ~]#
停掉后 在 director 执行health_check.sh 看看
[root@mail ~]# bash -x health_check.sh # 看到了 从集群中 删除了 rs2 (192.168.0.55)
+ VIP=192.168.0.77
+ CPORT=80
+ FAIL_BACK=127.0.0.1
+ RS=("192.168.0.45" "192.168.0.55")
+ RSTATUS=("1" "1")
+ RW=("2" "1")
+ RPORT=80
+ let COUNT=0
+ TYPE=g
+ for I in '${RS[*]}'
+ curl --connect-timeout 1 http://192.168.0.45/index.html
+ '[' 1 -eq 0 ']'
+ let COUNT++
+ for I in '${RS[*]}'
+ curl --connect-timeout 1 http://192.168.0.55/index.html
+ '[' 1 -eq 1 ']'
+ del 192.168.0.55
+ ipvsadm -d -t 192.168.0.77:80 -r 192.168.0.55
+ '[' 0 -eq 0 ']'
+ return 0
+ '[' 0 -eq 0 ']'
+ RSTATUS[$COUNT]=0
+ let COUNT++
[root@mail ~]#
[root@mail ~]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.0.77:80 wlc
-> 192.168.0.45:80 Route 2 0 0
-> 127.0.0.1:80 Local 5 0 0
[root@mail ~]#
rs2 ( 192.168.0.55 ) 的web再启动一下
[root@rs2 ~]# service httpd start
启动 httpd:AH00557: httpd: apr_sockaddr_info_get() failed for rs2.magedu.com
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1. Set the 'ServerName' directive globally to suppress this message
[确定]
[root@rs2 ~]#
启动后,在 director 执行health_check.sh 看看
[root@mail ~]# bash -x health_check.sh
+ VIP=192.168.0.77
+ CPORT=80
+ FAIL_BACK=127.0.0.1
+ RS=("192.168.0.45" "192.168.0.55")
+ RSTATUS=("1" "1")
+ RW=("2" "1")
+ RPORT=80
+ let COUNT=0
+ TYPE=g
+ for I in '${RS[*]}'
+ curl --connect-timeout 1 http://192.168.0.45/index.html
+ '[' 1 -eq 0 ']'
+ let COUNT++
+ for I in '${RS[*]}'
+ curl --connect-timeout 1 http://192.168.0.55/index.html
+ '[' 1 -eq 0 ']'
+ let COUNT++
[root@mail ~]#
[root@mail ~]# ipvsadm -L -n # 好像 rs2 192.168.0.55 没有加进来 看 health_check.sh 代码 因为事实上 RSTATUS的初始数组里面的元素永远都为1 ,,我们应该删除rs时,把RSTATUS里面相应的元素的值(应该为0)写到某配置文件里吧,随着脚本health_check.sh的启动而启动;;或者上来先测试状态,保留状态结果,然后再一个一个的检测???或者我们的脚本执行起来后,不让退出,随时进行检测
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.0.77:80 wlc
-> 192.168.0.45:80 Route 2 0 0
-> 127.0.0.1:80 Local 5 0 0
[root@mail ~]#
在 director 上 修改health_check.sh 为 health_check2.sh
root@mail ~]# vim health_check2.sh
#!/bin/bash
#
VIP=192.168.0.77
CPORT=80
FAIL_BACK=127.0.0.1
RS=("192.168.0.45" "192.168.0.55")
RSTATUS=("1" "1")
RW=("2" "1")
RPORT=80
TYPE=g
add() {
ipvsadm -a -t $VIP:$CPORT -r $1 -$TYPE -w $2
[ $? -eq 0 ] && return 0 || return 1
}
del() {
ipvsadm -d -t $VIP:$CPORT -r $1
[ $? -eq 0 ] && return 0 || return 1
}
while : ; do
let COUNT=0
for I in ${RS[*]}; do
if curl --connect-timeout 1 http://$I/index.html &> /dev/null; then
if [ ${RSTATUS[$COUNT]} -eq 0 ]; then
add $I ${RW[$COUNT]}
[ $? -eq 0 ] && RSTATUS[$COUNT]=1
fi
else
if [ ${RSTATUS[$COUNT]} -eq 1 ]; then
del $I
[ $? -eq 0 ] && RSTATUS[$COUNT]=0
fi
fi
let COUNT++
done
sleep 5
done
root@mail ~]# bash health_check2.sh #一直在循环执行着
director (192.168.0.75) 另一个窗口
[root@mail ~]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.0.77:80 wlc
-> 192.168.0.45:80 Route 2 0 0
-> 127.0.0.1:80 Local 5 0 0
[root@mail ~]#
[root@mail ~]# ipvsadm -L -n # 没看到 rs2 (192.168.0.55)
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.0.77:80 wlc
-> 192.168.0.45:80 Route 2 0 0
-> 127.0.0.1:80 Local 5 0 0
[root@mail ~]#
重启 rs2 (192.168.0.55)
[root@rs2 ~]# service httpd restart
停止 httpd: [确定]
启动 httpd:AH00557: httpd: apr_sockaddr_info_get() failed for rs2.magedu.com
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1. Set the 'ServerName' directive globally to suppress this message
[确定]
[root@rs2 ~]#
director (192.168.0.75) 另一个窗口
[root@mail ~]# ipvsadm -L -n #依然没有 rs2 (192.168.0.55)
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.0.77:80 wlc
-> 192.168.0.45:80 Route 2 0 0
-> 127.0.0.1:80 Local 5 0 0
[root@mail ~]#
手动添加 #ipvsadm -a -t 192.168.0.77:80 -r 192.168.0.55 -g -w 1
再在 rs2 (192.168.0.55) 上执行web服务停掉,正常了,,为什么上一次不正常?也许是没有回到初始状态吧
director上
[root@mail ~]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.0.77:80 wlc
-> 192.168.0.45:80 Route 2 0 0
-> 127.0.0.1:80 Local 5 0 0
[root@mail ~]#
启动,正常了
director上
[root@mail ~]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.0.77:80 wlc
-> 192.168.0.55:80 Route 1 0 0
-> 192.168.0.45:80 Route 2 0 0
-> 127.0.0.1:80 Local 5 0 0
[root@mail ~]#
在 rs1 (192.168.0.45) 上执行web服务停掉,启动,也正常了 (就不贴代码了
)
如果两个rs 都挂了,,那么就把 127.0.0.1加进来
127.0.0.1是为了rs全挂的情况下,才加进来的,叫做 fallback server
[root@mail ~]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.0.77:80 wlc
-> 192.168.0.55:80 Route 1 0 0
-> 192.168.0.45:80 Route 2 0 0
-> 127.0.0.1:80 Local 5 0 0
[root@mail ~]#
先删掉本机作为rs的那个规则
[root@mail ~]# ipvsadm -d -t 192.168.0.77:80 -r 127.0.0.1
[root@mail ~]#
director 上 (health_check3.sh 是对 health_check2.sh的改动)
[root@mail ~]# vim health_check3.sh #马哥说 这个代码就自己写吧
当两个rs全挂的时候,把127.0.0.1添加进来,
但有一个rs上线的时候,再把127.0.0.1删掉