Flume监控流程
首先在flume-ng-node中org.apache.flume.node.Application的main方法中,有两个方法分别是startAllComponents()和startAllComponents(conf)方法
其中startAllComponents(conf)方法有一个this.loadMonitoring();来启动监控方法loadMonitoring()
loadMonitoring()方法
|
其中monitorServer.configure(context);来加载监控服务的配置信息,monitorServer.start();启动监控服务。
这里的monitorServer就会有两种:GangliaServer和HTTPMetricsServer,他们都实现了MonitorService这个接口。这里我们只追踪HTTPMetricsServer。
其中会初始化一个jettyServer来提供监控数据的访问服务,里面的核心方法还是handle方法,定义了监控数据访问的url,这里的url就是获取监控json格
式数据的http地址。通过源码我们可以看到 metricsMap = JMXPollUtil.getAllMBeans();具体的数据都是从这条语句得来的,再仔细看可以得知,这些监
控数据是同JMX的方式得到的。除了以上的源码,我们需要关注以外,我们还需要关注具体监控组件的源码,这些源码都是在flume-ng-core中的org.apache.flume.instrumentation包下面,所有的监控组件都会继承MonitoredCounterGroup实现xxxCounterMBean接口,MonitoredCounterGroup中定义了一些基本公有的监控属性,xxxCounterMBean定义了获取监控元素的方法接口,具体实现还是在监控组件中实现。
监控指标数据的流向图
http监控
简介
Flume可以通过HTTP以JSON形式报告metrics,启用HTTP监控,内部会启动一个jetty服务,Flume需要配置一个端口,flume默认的端口是41414
这个在http监控组件的源码中可以看到
public class HTTPMetricsServer implements MonitorService {
private Server jettyServer;
private int port;
private static Logger LOG = LoggerFactory.getLogger(HTTPMetricsServer.class);
public static int DEFAULT_PORT = 41414;
public static String CONFIG_PORT = "port";
使用方式
如果仅仅想查看flume运行时的相关的数据量,则使用http这种监控方式,只需要在启动flume的时候在启动参数上面加上监控配置,例如这样:
#!/bin/sh
nohup /data/server/flume-1.8.0/bin/flume-ng agent -c /data/server/flume-1.8.0/conf -f /data/server/flume-1.8.0/conf/kafka_channel.conf -n a0 -Dflume.monitoring.type=http -Dflume.monitoring.port=5653 -Dflume.root.logger=INFO,console> /data/server/flume-1.8.0/conf/flume-client.log &
其中-Dflume.monitoring.type=http表示使用http方式来监控,后面的-Dflume.monitoring.port=1234表示我们需要启动的监控服务的端口号为5653,这个端口号可以自己随意配置。然后启动flume之后,通过http://ip:5653/metrics就可以得到flume的一个json格式的监控数据.
注意1:41414是flume监控的默认端口,在配置启动参数时可以更改这个参数,按照自己的需求更改这个端口。
json数据网页显示
不同的浏览器显示的方式和结果也不一样,比如360浏览器会让你下载的metrics文件中有json格式的数据,无法刷新,体验感极差。Google Chrome浏览器会将该json数据直接显示到网页上,字体非常小,也没有一定的显示格式。而Firefox浏览器会将json处理后再显示到网页上,很形象和友好,看相关监控指标数据很直观,目前是感觉显示效果最好的浏览器。
下面展示不同浏览器展示json数据的区别:
Google Chrome浏览器
火狐浏览器:
对比效果一目了然,推荐使用火狐浏览器查看flume监控指标
flume重启监控指标变化
只要Flume不重启服务这里就会一直做增量的变更,因为所有的监控指标其实就是一个累加器,flume运行采集数据,相关监控指标就会一直做加1的操作。这个在源码也能看出来。
如果flume服务挂了,重启后所有的指标就又从0开始计数。
监控指标的各个含义
监控程序的书写
通过上面的介绍,我们已经知道flume监控原理和流程,flume运行时会启动一个jetty服务,把相关的监控指标通过HTTP以JSON形式报告metrics,同理我们也可以通过java程序获取这个json字符串,从而得到相关的监控指标。通过逻辑判断,获知flume运行的问题,触发相关条件就以发短信或邮件的形式报警,及时解决flume出现的问题。
比如当前的报警条件是:连接不上服务,或者获取的json字符串为空,tailDirsource和kafkaChannel处理的数据量相差超过1000,则进行报警,代码如下。
public class myThread extends Thread { private String URL; public myThread(String URL) { this.URL = URL; } @Override public void run() { long timeInterval = 10000; int i = 0; //获取配置文件中的ip String[] str = URL.split(":"); String ip = str[0]; Properties prop = getPropInfo.getProp(); while (true) { System.out.println("循环调用 !!! 时间=" + new Date()); try { String s=""; //发送 GET 请求,获取连接 sendGet sendGet = new sendGet(); s = sendGet.sendGet(URL); //获取flume监控指标的json字符串 JSONObject jsonObject = JSON.parseObject(s); //获取各个监控指标 JSONObject channel = jsonObject.getJSONObject("CHANNEL.c1"); JSONObject source = jsonObject.getJSONObject("SOURCE.r1"); //成功写入channel且提交的日志总数量 Object channelCount = channel.get("EventPutSuccessCount"); //目前为止source已经接收到的日志总数量 Object sourceReceivedCount = source.get("EventReceivedCount"); //成功写出到channel的日志总数量 Object sourceAcceptedCount = source.get("EventAcceptedCount"); int intChannelCount = Integer.parseInt(channelCount.toString()); int intSourceCount = Integer.parseInt(sourceAcceptedCount.toString()); int data1 = intSourceCount - intChannelCount; if (s != null && s != "" &&(data1<1000)) { System.out.println("成功写入channel且提交的日志总数量: " + channelCount); System.out.println("目前为止source已经接收到的日志总数量: " + sourceReceivedCount); System.out.println("成功写出到channel的日志总数量: " + sourceAcceptedCount); } else { long timestamps = System.currentTimeMillis(); System.out.println(timestamps+"============================================================"); String times = new SimpleDateFormat("").format(new Date(timestamps)); //发送报警邮件 SendMailFunction.errorSendFunction(times, prop.getProperty("mailContent"), "/data/src/flume_data_monitor/flume.properies"); //发送报警短信 SendMessages sendMessages = new SendMessages(); sendMessages.sendMessage(prop.getProperty("phone1"),"服务器:"+"【"+ip+"】"+prop.getProperty("messageContent") ); sendMessages.sendMessage(prop.getProperty("phone2"),"服务器:"+"【"+ip+"】"+prop.getProperty("messageContent")); sendMessages.sendMessage(prop.getProperty("phone3"),"服务器:"+"【"+ip+"】"+prop.getProperty("messageContent")); System.out.println(times+"============================================================"); //出现异常时的各个指标的数据量 System.out.println("成功写入channel且提交的日志总数量: " + channelCount); System.out.println("目前为止source已经接收到的日志总数量: " + sourceReceivedCount); System.out.println("成功写出到channel的日志总数量: " + sourceAcceptedCount); //如果出现异常,等待五分钟处理时间,五分钟处理不好继续发送警告 Thread.sleep(1000*60*5); i++; } Thread.sleep(timeInterval); } catch (Exception e) { e.printStackTrace(); } //超过三次报警跳出循环结束报警 if(i>3){ break; } } }