实际上要理解本质需求,例如领导说需要每个监控服务器的CPU和内存的平均值与最大值,其实不建议用python走爬虫的方式去获取zabbix web server api的数据,性能与效率、成本、耗时都太差了,加入多线程可以加快获取的速度。
SQL方式
简单直接,就【获取每个监控服务器的CPU、内存的平均值与最大值】这个需求来说,简单的sql就搞定了:
select h.hostid,h.name,i.itemid,FROM_UNIXTIME(his.clock) as date_, i.key_,
max(round(his.value,3)) as max_val,
avg(round(his.value,3)) as avg_val
from hosts h join items i on h.hostid=i.hostid join history his
on his.itemid=i.itemid where h.name='192.168.159.139'
and clock group by i.itemid;
上面的SQL研究下都可以改进,比如分组统计或不指定host统计等。
其实仔细研究zabbix web api接口可以发现,本质上都是取的zabbox mysql的数据,对于简单的平均值、最大值这种需求,研究一下zabbix的数据表通过SQL查询就可以做到。
爬虫方式调用zabbix web api
回到文章的主题,如果非要用python去获取zabbix API的方式获取数据,下面附上python3调用zabbix api简单实现的源代码(web爬虫方式):
import urllib.request,urllib.parse,json
ZABBIX_WEB_URL="http://192.168.159.131:81/api_jsonrpc.php"
class ZabbixAPI():
def __init__(self):
self.url = ZABBIX_WEB_URL
self.headers = {
'User-Agent':' Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36',
'Content-Type':'application/json'
}
#request请求到zabbix server获取数据
def getRequest(self,postdata):
postdata = bytes(json.dumps(postdata),'utf8')
try:
request = urllib.request.Request(self.url,postdata,headers=self.headers)
reponse = urllib.request.urlopen(request).read()
content = json.loads(reponse.decode('utf8'))
return content
except Exception as ErrorMsg:
print(str(ErrorMsg))
return ErrorMsg
#获取Token(auth data),只需要初始化时获取token,后续请求直接使用token
def initToken(self):
Authdata = {"jsonrpc": "2.0","method": "user.login","params": {"user": "Admin", "password": "zabbix"},"id": 0}
res = self.getRequest(Authdata)
if 'result' not in res:
print("获取token信息失败!")
return res['error']['data']
#print(res['result'])
self.Token = res['result']
def getResByKey(self, APIKey, _params={"output": "extend",}):
rdata = {"jsonrpc":"2.0","method":APIKey,"params":_params,"auth":self.Token,"id":1}
res = self.getRequest(rdata)
reslist = res['result']
return reslist
'''
Possible values:关于数据类型的说明
0 - numeric float;
1 - character;
2 - log;
3 - numeric unsigned;
4 - text.
另外,对于zabbix,item是独立的,
'''
if __name__=="__main__":
zbx = ZabbixAPI()
zbx.initToken()
resHost = zbx.getResByKey("host.get")
dataKeys = ["system.cpu.intr", "system.cpu.util", "system.sw.arch", "system.sw.os",
"system.sw.packages", "system.swap.size[,free]", "system.swap.size[,pfree]",
"system.swap.size[,total]", "vfs.fs.size[/,pused]", "vfs.fs.size[/,total]",
"vfs.fs.size[/,used]", "vm.memory.size[available]", "vm.memory.size[pavailable]",
"vm.memory.size[total]", "vm.memory.utilization"]
dictKeys = {}
#应当再建立主机ID:主机IP的字典,用于后期调试
#应当再建立item监控项ID与具体指标的字典,用于调试打印具体指标的获取情况
for subHost in resHost:
hostid = subHost["hostid"]
_host = subHost["host"]
_name = subHost["name"]
print("%s : %s - %s" % (hostid,_name,_host))
for subItemKey in dataKeys:
#实际上item监控项可能会变化,最好每次取数据获取一下
paramItem = {"output":["itemid", "key_", "name", "value_type"],"hostids":hostid,"search": {
"key_":subItemKey}}
resItem = zbx.getResByKey("item.get",paramItem)
for subItem in resItem:
itemKey = subItem["itemid"]
itemName = subItem["key_"]
dictKeys[itemKey] = itemName
for itemKey in dictKeys: #对每个指标获取历史数据
paramHis = {"output": "extend","history": 0,"itemids": itemKey,"hostids": hostid,
"sortfield": "clock","sortorder": "DESC","limit": 10000}
resHis = zbx.getResByKey("history.get",paramHis)
if not resHis:
#print("[Error] IP地址:%s, keyID:%s,指标:%s获取失败" % (_name, itemKey, dictKeys[itemKey]))
continue
print("[Success] IP地址:%s, keyID:%s,指标:%s获取成功" % (_name, itemKey, dictKeys[itemKey]))
print(resHis)