对于flume的监控,只需要监控channel的性能数据即可,source和sink的性能一部分可以从channel中表现出来。
以MemoryChannel为例,在MemoryTransaction的构造函数中会实例化一个org.apache.flume.instrumentation.ChannelCounter对象
public MemoryTransaction( int transCapacity, ChannelCounter counter) {
putList = new LinkedBlockingDeque<Event>(transCapacity);
takeList = new LinkedBlockingDeque<Event>(transCapacity);
channelCounter = counter;
}
org.apache.flume.instrumentation.ChannelCounter 定义了几个计数器用来记录channel的性能数据
private static final String COUNTER_CHANNEL_SIZE = "channel.current.size"; //已经使用的容量大小
private static final String COUNTER_EVENT_PUT_ATTEMPT = "channel.event.put.attempt"; //source到channel尝试插入的数据(不管是否成功)
private static final String COUNTER_EVENT_TAKE_ATTEMPT = "channel.event.take.attempt"; //sink从channel尝试消费的数据(不管是否成功)
private static final String COUNTER_EVENT_PUT_SUCCESS = "channel.event.put.success"; //source到channel成功插入的数据
private static final String COUNTER_EVENT_TAKE_SUCCESS = "channel.event.take.success"; //sink从channel成功消费的数据
private static final String COUNTER_CHANNEL_CAPACITY = "channel.capacity"; //总容量大小
并封装了相关的方法,来操作这些性能计数器:
比如channel.event.put.attempt的由getEventPutAttemptCount和incrementEventPutAttemptCount操作:
public long incrementEventPutAttemptCount() { //用于数量增加1
return increment( COUNTER_EVENT_PUT_ATTEMPT);
}
public long getEventPutAttemptCount() { //用于获取值
return get( COUNTER_EVENT_PUT_ATTEMPT);
}
而在channel的相关操作中会使用到这些方法:
protected void doPut(Event event) throws InterruptedException {
channelCounter.incrementEventPutAttemptCount(); //比如在插入数据的操作开始时,增加channel.event.put.attempt的值
int eventByteSize = (int)Math.ceil(estimateEventSize(event)/ byteCapacitySlotSize);
if (! putList.offer(event)) {
throw new ChannelException(
"Put queue for MemoryTransaction of capacity " +
putList.size() + " full, consider committing more frequently, " +
"increasing capacity or increasing thread count" );
}
putByteCounter += eventByteSize;
}
counter的注册使用,以memorychannel相关为例:
ChannelCounter扩展了MonitoredCounterGroup类并实现了ChannelCounterMBean接口
MonitoredCounterGroup是一个抽象类,其具体的实现类定义了具体的组件的性能计数器和对应的封装方法
ChannelCounter中包含的所有的可用的counter:
private static final String[] ATTRIBUTES = {
COUNTER_CHANNEL_SIZE, COUNTER_EVENT_PUT_ATTEMPT,
COUNTER_EVENT_TAKE_ATTEMPT, COUNTER_EVENT_PUT_SUCCESS,
COUNTER_EVENT_TAKE_SUCCESS, COUNTER_CHANNEL_CAPACITY
};
ChannelCounter的构造方法调用MonitoredCounterGroup的构造方法:
public ChannelCounter(String name) {
super(MonitoredCounterGroup.Type. CHANNEL, name, ATTRIBUTES ); //调用MonitoredCounterGroup构造方法
}
MonitoredCounterGroup构造方法:
private final Map<String, AtomicLong> counterMap;
....
protected MonitoredCounterGroup(Type type, String name, String... attrs) {
this. type = type;
this. name = name;
Map<String, AtomicLong> counterInitMap = new HashMap<String, AtomicLong>(); // 声明一个初始的hashmap,用来存放counter name到value的对应关系
// Initialize the counters
for (String attribute : attrs) {
counterInitMap.put(attribute, new AtomicLong(0L)); //初始value都为0
}
counterMap = Collections.unmodifiableMap(counterInitMap); //返回hashmap不可更改的映射视图
startTime = new AtomicLong(0L);
stopTime = new AtomicLong(0L);
}
这里Type是一个enum类型,可取值:
public static enum Type {
SOURCE,
CHANNEL_PROCESSOR,
CHANNEL,
SINK_PROCESSOR,
SINK,
INTERCEPTOR,
SERIALIZER,
OTHER
};
在MemoryChannel中的start方法中启动:
public synchronized void start() {
channelCounter.start(); //调用MonitoredCounterGroup的start方法
channelCounter.setChannelSize( queue.size());
channelCounter.setChannelCapacity(Long. valueOf(
queue.size() + queue.remainingCapacity()));
super.start();
}
MonitoredCounterGroup.start:
public void start() {
register(); //调用register方法注册counter,主要是调用ManagementFactory. getPlatformMBeanServer().registerMBean( this, objName);进行注册mbean操作,把ChannelCounter对象作为mbean进行注册
stopTime.set(0L);
for (String counter : counterMap.keySet()) {
counterMap.get(counter).set(0L); //设置值都为0
}
startTime.set(System. currentTimeMillis());
logger.info( "Component type: " + type + ", name: " + name + " started" );
}
这样就可以通过jmx获取的监控项
转载于:https://blog.51cto.com/caiguangguang/1617019