前言
关键基础设施的四环图,是zabbix开发中的重点和难点。不管是数据处理的复杂程序,数据爬取→数据过滤→数据清洗→数据结构化→数据入库→数据输出→数据图表渲染和统计,基本上将数据可视化在前端的展示和后端的对接,充分调动了起来。
一、zabbix-API数据爬虫
zabbix-API数据爬虫,通过curl爬取对应的API即可。
/* * zabbix-API数据爬虫 * $url,默认爬取地址; */ function getZabAPI($url, $group_id) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $resp = curl_exec($ch); curl_close($ch); return $resp; }
注意:配置访问https网站的时,是为true,否则可能会报400错误。
curl_setopt(c u r l , C U R L O P T S S L V E R I F Y P E E R , t r u e ) ; c u r l s e t o p t ( curl, CURLOPT_SSL_VERIFYPEER, true); curl_setopt(curl,CURLOPT
S
SL
V
ERIFYPEER,true);curl
s
etopt(curl, CURLOPT_SSL_VERIFYHOST, true);
CURLOPT_SSL_VERIFYPEER 设置为FALSE 禁止 cURL 验证对等证书(peer’s
certificate)。要验证的交换证书可以在 CURLOPT_CAINFO 选项中设置,或在
CURLOPT_CAPATH中设置证书目录。
CURLOPT_SSL_VERIFYHOST 设置为 1 是检查服务器SSL证书中是否存在一个公用名(common name)。公用名(Common Name)一般来讲就是填写你将要申请SSL证书的域名 (domain)或子域名(sub domain)。 设置成 2,会检查公用名是否存在,并且是否与提供的主机名匹配。 在生产环境中,这个值应该是 2(默认值)。
二、主机ID封装接口
1.封装API接口
public function getZabBasics() { global $db, $res, $CONF; dbc(); $quota = get_param("quota");//获取指标数量; $group = $this->getGroupId(); $hostids = $group["basicsid"]; if ($hostids && $hostids != "0") { $res = getZabAPI($CONF['zab_url'] . 'api/api.php?act=getItem&hostids=' . $hostids . '&token=' . $CONF['zab_token']); $dataInfo = json_decode($res, true); //01.按照设备名称进行数组合并; $list = array(); foreach ($dataInfo as $v) { if (stripos($v["name"], 'CPU') !== false || stripos($v["name"], '内存') !== false || stripos($v["name"], '硬盘守护') !== false || stripos($v["name"], '网口守护') !== false || stripos($v["name"], '存储') !== false) { $list[explode('|', $v['name'])[0]][] = $v; } } //02.筛选键值; $dName = array(); foreach ($dataInfo as $v) { $key = explode('|', $v['name'])[0]; if (!isset($dName[$key])) { $dName[$key] = $v['name']; } } //保留唯一值; $unique = array_values($dName); $len = count($unique); //03前端数据格式; @$dataInfoNew = array(); for ($n = 0; $n < $len; $n++) { $dataInfoNew[$n] = makeZabArr($list[explode('|', $unique[$n])[0]], $quota); } //echo "<pre>"; //die(json_encode_lockdata($dataInfoNew)); @$listArr = array(); foreach ($dataInfoNew as $k => $v) { if (array_key_exists("name", $dataInfoNew[$k])) { $listArr[] = $v; } } //04.将数据总条数入库; $len1 = count($listArr); $row = $db->fetch('basics', 'group_id,total', array('group_id' => $hostids), ' id DESC'); if (!$row) { $db->insert('basics', array('group_id' => $hostids, 'total' => $len1)); } else { $db->update('basics', array('total' => $len1), 'group_id=' . $hostids); } //05.输出JSON die(json_encode_lockdata($listArr)); } else { $res["data"] = NULL; die(json_encode_lockdata($res)); } }
2.数据处理封装函数
/*关键基础设施数据清洗封装函数*/ function makeZabArr($dd, $quota) { //01.将数据遍历输出; $data = array(); $bStatus = array(); $cpu = array(); $ddr = array(); $disk = array(); $wlan = array(); $storage = array(); $dhcp = array();//服务1 $dns = array();//服务2 for ($i = 0; $i < count($dd); $i++) { //var_dump($dd[$i]["state"] . " "); //设备名称; $data["name"] = explode('|', $dd[$i]["name"])[0]; //CPU; if (stripos($dd[$i]["name"], 'cpu') !== false) { $cpu[] = $dd[$i]["lastvalue"]; $bStatus["cpu"][] = [$dd[$i]["status"], $dd[$i]["triggers"][0]['value'], $dd[$i]["triggers"][1]['value']]; } //内存; if (stripos($dd[$i]["name"], "内存") !== false) { $ddr[] = $dd[$i]["lastvalue"]; $bStatus["ddr"][] = [$dd[$i]["status"], $dd[$i]["triggers"][0]['value'], $dd[$i]["triggers"][1]['value']]; } //硬盘; if ($dd[$i]["name"] == '硬盘') { $disk[] = $dd[$i]["lastvalue"]; $bStatus["disk"] = [$dd[$i]["status"], $dd[$i]["triggers"][0]['value'], $dd[$i]["triggers"][1]['value']]; } //网口; if ($dd[$i]["name"] == "网口") { $wlan[] = $dd[$i]["lastvalue"]; $bStatus["wlan"] = [$dd[$i]["status"], $dd[$i]["triggers"][0]['value'], $dd[$i]["triggers"][1]['value']]; } //存储-列表API展示,图表不渲染; if (stripos($dd[$i]["name"], "存储") !== false) { $storage[] = $dd[$i]["lastvalue"]; $bStatus["storage"][] = [$dd[$i]["status"], $dd[$i]["triggers"][0]['value'], $dd[$i]["triggers"][1]['value']]; } //DHCP; if (stripos($dd[$i]["name"], "服务1") !== false) { $dhcp[] = $dd[$i]["lastvalue"]; $bStatus["dhcp"][] = [$dd[$i]["status"], $dd[$i]["triggers"][0]['value'], $dd[$i]["triggers"][1]['value']]; } //DNS; if (stripos($dd[$i]["name"], "服务2") !== false) { $dns[] = $dd[$i]["lastvalue"]; $bStatus["dns"][] = [$dd[$i]["status"], $dd[$i]["triggers"][0]['value'], $dd[$i]["triggers"][1]['value']]; } } //02.防止设备传入空数据; if (empty(count($cpu))) { $cpu = array("0" => 0); $bStatus["cpu"] = "0"; } if (empty(count($ddr))) { $ddr = array("0" => 0); $bStatus["ddr"] = "0"; } if (empty(count($disk))) { $disk = array("0" => 0); $bStatus["disk"] = "0"; } if (empty(count($wlan))) { $wlan = array("0" => 0); $bStatus["wlan"] = "0"; } if (empty(count($storage))) { $storage = array("0" => 0); $bStatus["storage"] = "0"; } //03.六环指标 By Poleung 2021.07.24; if ($quota == "sixNorm") { if (empty(count($dns))) { $dns = array("0" => 0); $bStatus["dns"][] = "无设备"; } if (empty(count($dhcp))) { $dhcp = array("0" => 0); $bStatus["dhcp"][] = "无设备"; } $data["dhcp"] = round(array_sum($dhcp) / count($dhcp), 1); $data["dns"] = round(array_sum($dns) / count($dns), 1); } //04.输入$data; $data["cpu"] = round(array_sum($cpu) / count($cpu), 1); $data["ddr"] = round(array_sum($ddr) / count($ddr), 1); $data["disk"] = round(array_sum($disk) / count($disk), 1); $data["wlan"] = round(array_sum($wlan) / count($wlan), 1); $data["storage"] = round(array_sum($storage) / count($storage), 1); //05.状态灯; $data["status"] = $bStatus; return $data; }
三、组ID封装接口
1.格式化数据所需格式
2.初始化默认数据
zabbix-API对接过来的数据,为统一设备下不同数据指标的json数据,同时内部存在很多非本项目需要的干扰数据。项目需求需将下面的数据格式化成为上述1所需的格式。
3.数据过滤
通过数据遍历,将name中含有CPU使用率、内存使用率、硬盘2和守护接口关键字符的数据筛选出来。
//01.按照设备名称进行数组合并; $list = array(); $dName = array(); foreach ($dataInfo as $v) { if (stripos($v["name"], 'CPU使用率') !== false || stripos($v["name"], '内存使用率') !== false || stripos($v["name"], '硬盘2') !== false || stripos($v["name"], '守护接口') !== false) { $key = $v["tags"][2]["value"]; $list[$v["tags"][2]["value"]][] = $v; if (!isset($dName[$key])) { $dName[$key] = $v["tags"][2]["value"]; } } }
4.数据结构化处理
数据遍历
$unique = array_values($dName); $len = count($unique); //die(json_encode_lockdata($list[$unique[0]])); @$dataInfoNew = array(); for ($n = 0; $n < $len; $n++) { $dataInfoNew[$n] = makeZabArr($list[$unique[$n]]); }
结构化数据makeZabArr函数
for ($i = 0; $i < count($dd); $i++) { //设备名称; $data["name"] = $dd[$i]["tags"][2]["value"]; //设备状态; $triggers = $dd[$i]["triggers"]; //CPU; if (stripos($dd[$i]["name"], 'CPU使用率') !== false) { $cpu[] = $dd[$i]["lastvalue"]; for ($j = 0; $j < count($triggers); $j++) { $bStatus["cpu"][] = $triggers[$j]["value"]; } } //内存; if (stripos($dd[$i]["name"], "内存使用率") !== false) { $ddr[] = $dd[$i]["lastvalue"]; for ($j = 0; $j < count($triggers); $j++) { $bStatus["ddr"][] = $triggers[$j]["value"]; } } //硬盘; if ($dd[$i]["name"] == "硬盘2") { $disk[] = $dd[$i]["lastvalue"]; for ($j = 0; $j < count($triggers); $j++) { $bStatus["disk"][] = $triggers[$j]["value"]; } } //守护接口; if (stripos($dd[$i]["name"], "守护接口") !== false) { $wlan[] = $dd[$i]["lastvalue"]; for ($j = 0; $j < count($triggers); $j++) { $bStatus["wlan"][] = $triggers[$j]["value"]; } } }
//02.防止设备传入空数据; if (empty(count($cpu))) { $cpu = array("0" => 0); $bStatus["cpu"] = "0"; } if (empty(count($ddr))) { $ddr = array("0" => 0); $bStatus["ddr"] = "0"; } if (empty(count($disk))) { $disk = array("0" => 0); $bStatus["disk"] = "0"; } if (empty(count($wlan))) { $wlan = array("0" => 0); $bStatus["wlan"] = "0"; }
//03.输入$data; $data["cpu"] = $cpu[0]; $data["ddr"] = $ddr[0]; $data["disk"] = $disk[0]; $data["wlan"] = $wlan[0]; //05.状态灯; $data["status"] = $bStatus; return $data;
总结
在实际开发中,使用到array_values、array_key_exists等php array数据函数,以及字符串stripos包含函数,是快速处理数据和解决问题的关键;也只有在实战中,不断地按照目标的需求,去学习和总结,才是不断能提升和进步的关键所在。
@lockdata.cn