大部分的DNS解析都是一个域名对应一个IP地址,但是通过DNS轮循技术可以做到一个域名对应多个IP,从而实现最简单且高效的负载平衡,不过此方案最大的弊端是目标主机不可用时无法被自动剔除,因此做好业务主机的服务可用监控至关重要。本示例通过分析当前域名的解析IP,再结合服务端口探测来实现自动监控,在域名解析中添加、删除IP时,无须对监控脚本进行更改。实现架构图如图1-1所示。
1. 步骤
1)实现域名的解析,获取域名所有的A记录解析IP列表;
2)对IP列表进行HTTP级别的探测。
2. 代码解析
本示例第一步通过dns.resolver.query()方法获取业务域名A记录信息,查询出所有IP地址列表,再使用httplib模块的request()方法以GET方式请求监控页面,监控业务所有服务的IP是否服务正常。
# Python 2.x中的"httplib"模块在Python 3.x中变成了"http.client"
import os
import http.client
import dns.resolver
iplist=[] #定义域名IP列表变量
appdomain="www.baidu.com" #定义业务域名
def get_iplist(domain=""): #域名解析函数,解析成功IP将被追加到iplist
try:
A = dns.resolver.query(domain, 'A') #解析A记录类型
except Exception as e:
print ("dns resolver error:"+str(e))
return
for i in A.response.answer:
for j in i.items:
if j.rdtype == 1:
iplist.append(j.address) #追加到iplist
return True
def checkip(ip):
checkurl=ip+":80"
getcontent=""
http.client.socket.setdefaulttimeout(5) #定义http连接超时时间(5秒)
conn=http.client.HTTPConnection(checkurl) #创建http连接对象
try:
conn.request("GET", "/",headers = {"Host": appdomain}) #发起URL请求,添加host主机头
r=conn.getresponse()
getcontent =r.read(15) #获取URL页面前15个字符,以便做可用性校验
# print(getcontent) # 输出的是b'<!DOCTYPE html>'。需要用bytes转换下
finally:
if getcontent==bytes("<!DOCTYPE html>", 'utf-8'): #监控URL页的内容一般是事先定义好的,比如“HTTP200”等
print (ip+" [OK]")
else:
print (ip+" [Error]" ) #此处可放告警程序,可以是邮件、短信通知
if __name__=="__main__":
if get_iplist(appdomain) and len(iplist)>0: #条件:域名解析正确且至少返回一个IP
for ip in iplist:
checkip(ip)
else:
print ("dns resolver error.")
我们可以将此脚本放到crontab中定时运行,再结合告警程序,这样一个基于域名轮循的业务监控已完成。运行程序,显示结果如下:
python simple5.py
74.125.31.94 [OK]
74.125.128.199 [OK]
173.194.72.94 [OK]
从结果可以看出,域名www.google.com.hk解析出3个IP地址,并且服务都是正常的。