• 【Java】【Flume】Flume-NG启动过程源代码分析(一)


    从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方法中的componentlifecycleAware在构造之初将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()停止顺序相反。相信大伙非常easy理解。是通过supervisor.supervise启动组件的。另外须要注意的是启动channel组件后须要等待一定时间,是为了让所有channel所有启动。

      另外为什么要先stop再start呢?由于考虑到要动态载入配置文件啊。载入配置文件后就须要又一次启动全部组件。所以先停止全部的,再又一次启动全部的。

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

  • 相关阅读:
    Pandas DataFrame操作
    Pandas Series数据结构基本操作
    Locally weighted regression algorithm
    Python Numpy线性代数操作
    Python Numpy 矩阵级基本操作(2)
    分布式锁1 Java常用技术方案(转)
    设计模式
    设计模式
    设计模式
    Lock和synchronized比较详解(转)
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/6917535.html
Copyright © 2020-2023  润新知