#书接上回,我们已经配置好了zabbix Service,并通过SNMP协议获取了交换机流量负载等的数据,公司的要求是调用zabbix API获取监控项信息并存入mysql中(后续还有使用其他平台从myql中读取数据并显示,实现实时读取并监控的智慧平台效果),所以我们继续来完成#

一、思路

        首先,代码实现就有很多种,例如:java、python...都可以调用zabbix API的库函数,我这里是使用java实现的,不过应该大同小异。

二、实现

2.1导入依赖

        话不多说,直接代码展示,首先,导入的依赖如下:

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>io.github.hengyunabc</groupId>
            <artifactId>zabbix-api</artifactId>
            <version>0.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.4</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
    </dependencies>

2.2项目整体结构

        然后我们项目的整体结构如下:

zabbix api 图形 zabbix api文档_java

        其中InsertDataToMysql这个文件是我们没有用到的,这里就不删啦,大家自行忽略。测试类是我们所需要的,后续会详细说明,大家不要忽略。

2.3 ZabbixConfig配置文件

         ok,我们继续展示代码,按照项目结构顺序来,首先,config包下ZabbixConfig这个文件:

@Component
@ConfigurationProperties(prefix = "zabbix.config")
@Data
public class ZabbixConfig {

    private String url;
    private String username;
    private String password;
}

        以上的配置类代码用于读取以 zabbix.config 前缀开头的配置属性。我们在appliocation.yaml文件中进行了相关配置,读取配置文件中以 zabbix.config 为前缀的属性,并将其映射到对应的变量上。appliocation.yaml文件中代码如下:

2.4 application.yaml文件

zabbix:
  config:
    url: http://xx.xx.xx.xx/zabbix/api_jsonrpc.php
    username: Admin
    password: zabbix

        这里的url是如我第一篇配置zabbix的那个url,username以及password都是zabbix默认的,如果大家配置时有修改则要对应修改,“/api_jsonrpc.php”这个后缀是我阅读了zabbix API官方文档后加上的,加上才能正确连接。zabbix API官方文档链接给大家附上:https://www.zabbix.com/documentation/5.0/zh/manual/ap(这个文档很重要,大家可以仔细阅读,后续,函数参数的选择等,也会用到这个文档)

2.5AbstractZabbixService 抽象类

        接下来:AbstractZabbixService这个抽象类,其中包含了使用Zabbix API进行请求的方法和处理错误的方法。代码如下:

public abstract class AbstractZabbixService {


    protected JSONObject zabbixRequest(ZabbixApi zabbixApi,Request request) throws Exception {
        JSONObject response = zabbixApi.call(request); // 使用ZabbixApi对象调用call方法发起请求,并将响应存储在JSONObject对象中
        return response; // 返回响应结果
    }

    protected void zabbixError(JSONObject response) throws Exception {
        if (!isBlank(response.getString("error")))
            throw new Exception("向Zabbix请求出错了!" + JSON.parseObject(response.getString("error")).getString("data"));
    }

}

        该抽象类封装了与Zabbix API的交互逻辑。zabbixRequest方法用于发送Zabbix API请求并返回响应结果。它接受一个ZabbixApi对象和一个Request对象作为参数,通过调用ZabbixApi对象的call方法发送请求,并将响应结果存储在JSONObject对象中,最后返回该对象。

   zabbixError方法用于处理Zabbix API的错误响应。它接受一个JSONObject对象作为参数,通过判断响应中是否存在"error"字段且不为空,如果存在错误,则抛出一个Exception异常,错误信息为 "向Zabbix请求出错了!" 加上从错误响应中解析出的"data"字段的值。

2.6 ZabbixService

         接下来,就是我们的重中之重了(我们先跳过InsertDataService),这个Service层包含了我们对zabbix所要做的所有操作,代码如下:

@Service
public class ZabbixService  extends AbstractZabbixService{

    @Autowired
    private ZabbixUtil zabbixUtil;

    //获取主机列表
    public String getHostList() throws Exception {
        ZabbixApi zabbixApi = zabbixUtil.getZabbixApi();
        Request request = RequestBuilder.newBuilder().method("host.get")
                .paramEntry("output", new String[]{"host", "name", "description", "hostid"})
                .paramEntry("selectGroups", "extend")
                .build();
        JSONObject response = zabbixRequest(zabbixApi,request);
        zabbixError(response);
        JSONArray result = response.getJSONArray("result");
        return result.toJSONString();
    }

    //获取监控项
    public String getMonitorItems(String hostId) throws Exception {
        ZabbixApi zabbixApi = zabbixUtil.getZabbixApi();
        Request request = RequestBuilder.newBuilder().method("item.get")
                .paramEntry("output", new String[]{"extend", "name"})
                .paramEntry("hostids", hostId)
                .build();
        JSONObject response = zabbixRequest(zabbixApi, request);
        zabbixError(response);
        JSONArray result = response.getJSONArray("result");

        List<String> desiredItems = Arrays.asList("Interface eth0(): Bits received");

        JSONArray filteredResult = new JSONArray();
        for (int i = 0; i < result.size(); i++) {
            JSONObject item = result.getJSONObject(i);
            String name = item.getString("name");
            if (desiredItems.contains(name)) {
                filteredResult.add(item);
            }
        }

        return filteredResult.toJSONString();
    }

    //获取监控项历史数据,paramEntry根据zabbixAPI设置,limit==481设定获取从timeform开始的为时一天的历史数据
    public String getHistory(String itemId, long timeform) throws Exception {
        ZabbixApi zabbixApi = zabbixUtil.getZabbixApi();
        Request request = RequestBuilder.newBuilder().method("history.get")
                .paramEntry("output", "extend")
                .paramEntry("itemids", itemId)
                .paramEntry("time_from", timeform)
//                .paramEntry("time_till", 1675424400)
                .paramEntry("sortfield","clock")
                .paramEntry("sortorder","ASC")
                .paramEntry("limit",481)
                .build();
        JSONObject response = zabbixRequest(zabbixApi, request);
        zabbixError(response);
        JSONArray result = response.getJSONArray("result");
        return result.toJSONString();
    }


}

        我们在这里封装了三个函数,分别是: getHostList()、getMonitorItems(String hostId)以及getHistory(String itemId, long timeform),这三个函数的功能是环环相扣的,这里我们只详细解释一下第一个函数,后面的两个函数稍作讲解,因为只是参数类型有不同。

        该方法首先通过zabbixUtil对象获取了一个ZabbixApi对象,用于与Zabbix API进行交互。然后,使用RequestBuilder创建一个Request对象,并设置请求方法为"host.get",.paramEntry后面接的是将被传递给API方法的参数,首先指定要获取的主机属性为"host"、"name"...。接下来,调用zabbixRequest方法发送Zabbix API请求,并将响应结果存储在JSONObject对象中。然后,调用zabbixError方法处理错误响应,如果存在错误,则会抛出异常。最后,从响应中获取主机列表数据,并将其转换为JSON字符串并返回。

        接下来根据,第一个函数getHostList(),获取到的主机Id作为第二个函数的参数引用,来获取这台主机的监控项Id(!!这里的监控项Id,我是根据监控项的名称来获取的,大家如果参阅了官方API文档有更好的方式欢迎讨论!!),然后同理第三个函数:getHistory(String itemId, long timeform),根据监控项Id获取到我们所需要的历史数据(),并将其转换为JSON字符串并返回。(!!!第三个函数传入到param参数这里再详细解释一下吧,首先timeform,表示起始的时间戳,也是我们写的这个函数需要传入的参数;clock以及ASC表示打印顺序是按照时间戳升序排列;limit481,结合后面数据库中每隔三分钟取一次历史数据值则刚好可以实现每天取一次历史数据值,大家可以自行计算验证一下,作者因为时间戳的问题就憋了两天,这里可能有点绕,我就再罗嗦一下,数据库取值是同时进行的,意思是每隔三分钟取一次值,取481次,这是同一时间完成的,大家运行以下代码再结合官方API文档可能就更好理解了!!!)此时,我们就已经通过zabbix API获取到了历史数据了。我们可以用测试类中的代码来测试一下。

2.7 测试类

       测试代码如下:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ZabbixApiDemoApplication.class)
public class ZabbixApiTest {

    @Autowired
    private ZabbixService zabbixService;


    @Test
    public void getHostList() throws Exception {
        String hostList = zabbixService.getHostList();
        System.out.println(hostList);

    }

    @Test
    public void getMonitorItems() throws Exception {
        String monitorItems = zabbixService.getMonitorItems("10439");
        System.out.println("1111111111");
        System.out.println(monitorItems);
        System.out.println("1111111111");
    }

        这里给出的测试类代码,即可以调用2.6节中的函数在控制台打印出相应的主机列表以及选定主机Id的监控项,我们也可以在控制台中确定再得到要获取历史数据的监控项Id。

三、总结

         因为篇幅原因,就先说到这里啦,后面还会出一篇编写时间函数,存入数据库实现获取每天的历史数据,以及显示到dataease平台上的文章。希望大家多多支持!因为时间比较紧,所以写作可能不是很详细,还有问题欢迎大家私聊以及评论区讨论。这里引用了gitee平台上作者名为yanzhen的部分代码结构,但是再次在平台上搜索时并未找到,很感谢大佬。