从bin/flume 这个shell脚本可以看到Flume的起始于org.apache.flume.node.Application类,这是flume的main函数所在。

  main方法首先会先解析shell命令,如果指定的配置文件不存在就甩出异常。

  根据命令中含有"no-reload-conf"参数,决定采用那种加载配置文件方式:一、没有此参数,会动态加载配置文件,默认每30秒加载一次配置文件,因此可以动态修改配置文件;二、有此参数,则只在启动时加载一次配置文件。实现动态加载功能采用了发布订阅模式,使用guava中的EventBus实现。

     EventBus eventBus = new EventBus(agentName + "-event-bus");
PollingPropertiesFileConfigurationProvider configurationProvider =
new PollingPropertiesFileConfigurationProvider(agentName,
configurationFile, eventBus, 30); //这里是发布事件的类,这里的30则是动态加载配置文件时间间隔,单位是s
components.add(configurationProvider);
application = new Application(components);
eventBus.register(application); //将订阅类注册到Bus中

  订阅类是application = new Application(components);发布代码在PollingPropertiesFileConfigurationProvider中的FileWatcherRunnable.run方法中。在这只是先构建一个PollingPropertiesFileConfigurationProvider对象,PollingPropertiesFileConfigurationProvider extends  PropertiesFileConfigurationProvider implements LifecycleAware,继续跟踪PropertiesFileConfigurationProvider extends AbstractConfigurationProvider,再跟踪AbstractConfigurationProvider implements  ConfigurationProvider可以看到这些类的构造方法都是初始化,AbstractConfigurationProvid的构造方法初始化了sink、channel、source的工厂类。

  Application.handleConfigurationEvent(MaterializedConfiguration conf)有@Subscribe注解,是订阅方法,当eventBus.post(MaterializedConfiguration conf)执行时,会触发执行handleConfigurationEvent方法。

  new Application(components)时,会构建一个对象supervisor = new LifecycleSupervisor()会启动10个线程用来执行配置文件中的各个组件,并监控组件的整个运行过程。

  application.start()方法会启动配置文件的加载过程supervisor.supervise(component, new SupervisorPolicy.AlwaysRestartPolicy(), LifecycleState.START); //LifecycleState.START开始运行,在这的component就是上面的PollingPropertiesFileConfigurationProvider对象。supervise方法会对component创建一个MonitorRunnable进程,并放入默认有10个线程的monitorService去执行

    Supervisoree process = new Supervisoree();
process.status = new Status(); process.policy = policy;
process.status.desiredState = desiredState;
process.status.error = false; MonitorRunnable monitorRunnable = new MonitorRunnable();
monitorRunnable.lifecycleAware = lifecycleAware;//组件
monitorRunnable.supervisoree = process;
monitorRunnable.monitorService = monitorService; supervisedProcesses.put(lifecycleAware, process);
//创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟。如果任务的任一执行遇到异常,就会取消后续执行。
ScheduledFuture<?> future = monitorService.scheduleWithFixedDelay(
monitorRunnable, 0, 3, TimeUnit.SECONDS); //启动MonitorRunnable,结束之后3秒再重新启动,可以用于重试
monitorFutures.put(lifecycleAware, future);

  看MonitorRunnable类,其run方法主要是根据supervisoree.status.desiredState的值执行对应的操作。这里的lifecycleAware就是上面supervise方法中的component,lifecycleAware在构造之初将lifecycleState=IDLE,application.start()方法通过supervisor.supervise方法将supervisoree.status.desiredState=START。所以在run方法中会执行lifecycleAware.start(),也就是PollingPropertiesFileConfigurationProvider.start()方法。

  PollingPropertiesFileConfigurationProvider.start()方法会启动一个单线程FileWatcherRunnable每隔30s去加载一次配置文件(如果配置文件有修改):eventBus.post(getConfiguration())。getConfiguration()是AbstractConfigurationProvider.getConfiguration()这个方法解析了配置文件获取了所有组件及其配置属性。这个方法较为复杂,放在后续再讲解。

  待eventBus.post(getConfiguration())之后会触发Application.handleConfigurationEvent方法:

  @Subscribe
public synchronized void handleConfigurationEvent(MaterializedConfiguration conf) {
stopAllComponents();
startAllComponents(conf);
}

  stopAllComponents()方法会依次stop各个组件的运行,顺序是:source、sink、channel。之所以有顺序是因为:一、source是不停的读数据放入channel的;二、sink是不停的从channel拿数据的,channel两头都在使用应该最后停止,停止向channel发送数据后sink停止才不会丢数据。stop是通过supervisor.unsupervise方法来完成的。

  startAllComponents(conf)是启动各个组件的,顺序正好和stopAllComponents()停止顺序相反,相信大伙很容易理解。是通过supervisor.supervise启动组件的。另外需要注意的是启动channel组件后需要等待一定时间,是为了让所有channel全部启动。

  另外为什么要先stop再start呢?因为考虑到要动态加载配置文件啊,加载配置文件后就需要重新启动所有组件,所以先停止所有的,再重新启动所有的。

  main方法的最后还有一个钩子函数Runtime.getRuntime().addShutdownHook,主要是用来进行内存清理、对象销毁等操作。

  

欢迎大伙交流

Flume-NG启动过程源码分析(一)(原创)的更多相关文章

  1. Flume-NG启动过程源码分析(二)(原创)

    在上一节中讲解了——Flume-NG启动过程源码分析(一)(原创)  本节分析配置文件的解析,即PollingPropertiesFileConfigurationProvider.FileWatch ...

  2. Android系统默认Home应用程序(Launcher)的启动过程源码分析

    在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还须要有一个Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home应 ...

  3. Android Content Provider的启动过程源码分析

    本文參考Android应用程序组件Content Provider的启动过程源码分析http://blog.csdn.net/luoshengyang/article/details/6963418和 ...

  4. 10.4 android输入系统_框架、编写一个万能模拟输入驱动程序、reader/dispatcher线程启动过程源码分析

    1. 输入系统框架 android输入系统官方文档 // 需FQhttp://source.android.com/devices/input/index.html <深入理解Android 卷 ...

  5. Spark(五十一):Spark On YARN(Yarn-Cluster模式)启动流程源码分析(二)

    上篇<Spark(四十九):Spark On YARN启动流程源码分析(一)>我们讲到启动SparkContext初始化,ApplicationMaster启动资源中,讲解的内容明显不完整 ...

  6. Spark(四十九):Spark On YARN启动流程源码分析(一)

    引导: 该篇章主要讲解执行spark-submit.sh提交到将任务提交给Yarn阶段代码分析. spark-submit的入口函数 一般提交一个spark作业的方式采用spark-submit来提交 ...

  7. Activity启动过程源码分析(Android 8.0)

    Activity启动过程源码分析 本文来Activity的启动流程,一般我们都是通过startActivity或startActivityForResult来启动目标activity,那么我们就由此出 ...

  8. Netty入门一:服务端应用搭建 & 启动过程源码分析

    最近周末也没啥事就学学Netty,同时打算写一些博客记录一下(写的过程理解更加深刻了) 本文主要从三个方法来呈现:Netty核心组件简介.Netty服务端创建.Netty启动过程源码分析 如果你对Ne ...

  9. Spring启动过程源码分析基本概念

    Spring启动过程源码分析基本概念 本文是通过AnnotationConfigApplicationContext读取配置类来一步一步去了解Spring的启动过程. 在看源码之前,我们要知道某些类的 ...

  10. Netty 启动过程源码分析 (本文超长慎读)(基于4.1.23)

    前言 作为一个 Java 程序员,必须知道Java社区最强网络框架-------Netty,且必须看过源码,才能说是了解这个框架,否则都是无稽之谈.今天楼主不会讲什么理论和概念,而是使用debug 的 ...

随机推荐

  1. 次小生成树模板(poj1679)

    prim #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath&g ...

  2. 《挑战程序设计竞赛》2.1 穷竭搜索 POJ2718 POJ3187 POJ3050 AOJ0525

    POJ2718 Smallest Difference Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6509   Acce ...

  3. Springboot 1.5.x版本上读取自定义配置文件问题

    原来的解决方案: 现在1.5.x以后取消了location地址 1.5以后解决方案:

  4. iOS KVO详解

    一.KVO 是什么? KVO 是 Objective-C 对观察者设计模式的一种实现.[另外一种是:通知机制(notification),详情参考:iOS 趣谈设计模式——通知]: KVO 提供一种机 ...

  5. Django 路由系统(URL)

    介绍 Django 1.11版本 URLConf官方文档 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表. 你就是以这种方式告 ...

  6. 我的Android进阶之旅------>Android使用cmd窗口进行adb logcat时出现中文乱码问题的解决办法

    今天用CMD命令进行adb logcat时显示一堆的乱码,乱码如下: C:\Users\Administrator>adb logcat -s logcat --------- beginnin ...

  7. StringBuffer、StringBuilder

    相信大家都知道StringBuffer.StringBuilder,但是这两个的用法都差不多,到底有什么区别呢,这也是面试的时候问的比较多的一道题,这里我就来说说,这两个的区别结合String来说~ ...

  8. Longest Common Prefix -最长公共前缀

    问题:链接 Write a function to find the longest common prefix string amongst an array of strings. 解答: 注意 ...

  9. gitattributes手册

    gitattributes(5) Manual Page 1.gitattributes是什么? gitattributes用于定义每个路径的属性. 其语法是:pattern attr1 attr2 ...

  10. JavaScript实现自适应窗口大小的网页

    <!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content ...