Flume源码阅读记录(3)flume启动组件Application代码分析

奇安信大数据岗面试复盘:技术栈准备与场景设计题全解析 大数据技术栈的掌握程度,往往决定了面试的深度与广度。从Hadoop生态到实时计算引擎,再从数据仓库分层到集群部署策略,每一环节都考验着工程师对底层原理的理解。在安全场景下,海量日志数据的实时处理与威胁分析,对数据采集、消息队列、计算框架提出了更高要求,数据一致性、数据倾斜、反压机制等难题也成了面试中的高频追问。无论是HDFS读写流程、MapReduce Shuffle细节,还是Spark任务调度与Kafka分区策略,都需要体系化的知识图谱支撑。本文以奇安信大数据岗的完整面试流程为例,拆解技术准备要点、真实面 阅读详情
public class Application {

  private static final Logger logger = LoggerFactory
      .getLogger(Application.class);

  public static final String CONF_MONITOR_CLASS = "flume.monitoring.type";
  public static final String CONF_MONITOR_PREFIX = "flume.monitoring.";

  private final List<LifecycleAware> components;
  private final LifecycleSupervisor supervisor;
  private MaterializedConfiguration materializedConfiguration;
  private MonitorService monitorServer;
  //类持有的锁
  private final ReentrantLock lifecycleLock = new ReentrantLock();

  public Application() {
    this(new ArrayList<LifecycleAware>(0));
  }

  public Application(List<LifecycleAware> components) {
    this.components = components;
    supervisor = new LifecycleSupervisor();
  }


  //启动方法
  public void start() {
    lifecycleLock.lock();
    try {
      for (LifecycleAware component : components) {
        supervisor.supervise(component,
            new SupervisorPolicy.AlwaysRestartPolicy(), LifecycleState.START);
      }
    } finally {
      lifecycleLock.unlock();
    }
  }

  //更新配置文件时,执行以下方法。
  @Subscribe
  public void handleConfigurationEvent(MaterializedConfiguration conf) {
    try {
      lifecycleLock.lockInterruptibly();
      //先停止,再启动所有组件。
      stopAllComponents();
      startAllComponents(conf);
    } catch (InterruptedException e) {
      logger.info("Interrupted while trying to handle configuration event");
      return;
    } finally {
      // If interrupted while trying to lock, we don't own the lock, so must not attempt to unlock
      if (lifecycleLock.isHeldByCurrentThread()) {
        lifecycleLock.unlock();
      }
    }
  }

  //停止方法
  public void stop() {
    //先加锁
    lifecycleLock.lock();
    stopAllComponents();
    try {
      supervisor.stop();
      if (monitorServer != null) {
        monitorServer.stop();
      }
    } finally {
      lifecycleLock.unlock();
    }
  }

  //停止所有组件  停止组件的顺序是 Source---Sink---Channel
  private void stopAllComponents() {
    if (this.materializedConfiguration != null) {
      logger.info("Shutting down configuration: {}", this.materializedConfiguration);
      //停止所有Source
      for (Entry<String, SourceRunner> entry :
           this.materializedConfiguration.getSourceRunners().entrySet()) {
        try {
          logger.info("Stopping Source " + entry.getKey());
          supervisor.unsupervise(entry.getValue());
        } catch (Exception e) {
          logger.error("Error while stopping {}", entry.getValue(), e);
        }
      }

      //停止Sink
      for (Entry<String, SinkRunner> entry :
           this.materializedConfiguration.getSinkRunners().entrySet()) {
        try {
          logger.info("Stopping Sink " + entry.getKey());
          supervisor.unsupervise(entry.getValue());
        } catch (Exception e) {
          logger.error("Error while stopping {}", entry.getValue(), e);
        }
      }

      //停止Channel
      for (Entry<String, Channel> entry :
           this.materializedConfiguration.getChannels().entrySet()) {
        try {
          logger.info("Stopping Channel " + entry.getKey());
          supervisor.unsupervise(entry.getValue());
        } catch (Exception e) {
          logger.error("Error while stopping {}", entry.getValue(), e);
        }
      }
    }
    if (monitorServer != null) {
      monitorServer.stop();
    }
  }


  //启动方法    启动的顺序是 Channel--> Sink -->Source
  private void startAllComponents(MaterializedConfiguration materializedConfiguration) {
    logger.info("Starting new configuration:{}", materializedConfiguration);

    this.materializedConfiguration = materializedConfiguration;

    for (Entry<String, Channel> entry :
        materializedConfiguration.getChannels().entrySet()) {
      try {
        logger.info("Starting Channel " + entry.getKey());
        supervisor.supervise(entry.getValue(),
            new SupervisorPolicy.AlwaysRestartPolicy(), LifecycleState.START);
      } catch (Exception e) {
        logger.error("Error while starting {}", entry.getValue(), e);
      }
    }

    /*
     * Wait for all channels to start.
     */
    for (Channel ch : materializedConfiguration.getChannels().values()) {
      while (ch.getLifecycleState() != LifecycleState.START
          && !supervisor.isComponentInErrorState(ch)) {
        try {
          logger.info("Waiting for channel: " + ch.getName() +
              " to start. Sleeping for 500 ms");
          Thread.sleep(500);
        } catch (InterruptedException e) {
          logger.error("Interrupted while waiting for channel to start.", e);
          Throwables.propagate(e);
        }
      }
    }

    for (Entry<String, SinkRunner> entry : materializedConfiguration.getSinkRunners().entrySet()) {
      try {
        logger.info("Starting Sink " + entry.getKey());
        supervisor.supervise(entry.getValue(),
            new SupervisorPolicy.AlwaysRestartPolicy(), LifecycleState.START);
      } catch (Exception e) {
        logger.error("Error while starting {}", entry.getValue(), e);
      }
    }

    for (Entry<String, SourceRunner> entry :
         materializedConfiguration.getSourceRunners().entrySet()) {
      try {
        logger.info("Starting Source " + entry.getKey());
        supervisor.supervise(entry.getValue(),
            new SupervisorPolicy.AlwaysRestartPolicy(), LifecycleState.START);
      } catch (Exception e) {
        logger.error("Error while starting {}", entry.getValue(), e);
      }
    }

    this.loadMonitoring();
  }

  //监控加载,监控可以检测启动的配置文件,当修改配置文件并保存时,会被监控检测到。
  @SuppressWarnings("unchecked")
  private void loadMonitoring() {
    Properties systemProps = System.getProperties();
    Set<String> keys = systemProps.stringPropertyNames();
    try {
      if (keys.contains(CONF_MONITOR_CLASS)) {
        String monitorType = systemProps.getProperty(CONF_MONITOR_CLASS);
        Class<? extends MonitorService> klass;
        try {
          //Is it a known type?
          klass = MonitoringType.valueOf(
              monitorType.toUpperCase(Locale.ENGLISH)).getMonitorClass();
        } catch (Exception e) {
          //Not a known type, use FQCN
          klass = (Class<? extends MonitorService>) Class.forName(monitorType);
        }
        this.monitorServer = klass.newInstance();
        Context context = new Context();
        for (String key : keys) {
          if (key.startsWith(CONF_MONITOR_PREFIX)) {
            context.put(key.substring(CONF_MONITOR_PREFIX.length()),
                systemProps.getProperty(key));
          }
        }
        monitorServer.configure(context);
        monitorServer.start();
      }
    } catch (Exception e) {
      logger.warn("Error starting monitoring. "
          + "Monitoring might not be available.", e);
    }

  }
}

对于Application的源代码,主要由几点需要注意:

1.start(),stop()方法中,组件的启动与关闭顺序是不同的。其中start方法顺序是,Channel-->Sink-->Source。而stop方法中关闭的顺序是Source-->Sink-->Channel。代码中所写的SinkRunner,SourceRunner控制Sink,Source 的启动关闭。

2.各组件都实现LifecycleAware接口,并由LifecycleSupervisor控制组件的状态变化。

3.loadMonitoring()方法用于加载监控。读取启动时的flume.monitoring.type加载对于的监控器类型。

4.handleConfigurationEvent()方法更新配置,若修改启动命令行所指定的配置文件,会被检测到并重启所有组件。

 

PollingZooKeeperConfigurationProvider类

provider负责各个组件的启动停止。

那么该类跟Application中的startAllCompoments有何关联。

这里LifecycleSupervisor的对象调用sipervise方法,并参入LifecycleState.START作为启动参数。

上面说到,各组件都实现LifecycleAware接口,LifecycleAware接口如下:

而PollingZooKeeperConfigurationProvider也实现了LifecycleAware接口,那么这里实际上是用的provider的start方法 ,修改组件的启动状态,并加入监听器监听组件的状态。

 

 

CTF竞赛入门指南:从零构建安全实验室与Web、逆向、密码学实战 网络安全竞赛(CTF)是理解计算机系统安全原理与实践的重要途径。其核心在于通过模拟攻防场景,深入理解软件漏洞、加密算法和系统底层的运作机制。从技术价值看,CTF训练能系统化提升问题拆解、逻辑推理和工程实践能力,尤其有助于培养以攻击者视角审视系统脆弱性的安全意识。在应用场景上,它不仅是安全研究员的练兵场,其锤炼出的技能对软件开发、系统运维等领域同样具有高迁移价值。本文聚焦CTF中的Web安全、逆向工程和密码学三大基础方向,详细介绍了如何从零搭建包含Kali Linux和VirtualBox的虚拟化安全实验室, 阅读详情

相关推荐

Flume【使用篇】01:如何使用Flume-Hello Flume

如何使用Flume-Hello Flume

weixin_40612128的博客 533

【Flume】【源码分析】从入口Application来分析Flume的启动过程

大家在启动flume的时候,输入的命令就可以看出flume的启动入口了 [root@com21 apache-flume-1.5.2-bin]# sh bin/flume-ng agent -c conf -f conf/server.conf -n a1 Info: Sourcing environment configuration script /home/flume/apache-flu

三也_攻城狮 7447

Flume源码分析(Flume Source Code Analysis)

作者:禅与计算机程序设计艺术 1.简介 Apache Flume是一个开源、分布式、高可用的海量日志采集、聚合和传输系统。它最初起源于Yahoo!公司,由开发者在2007年创建,主要用于收集网站访问日志并将其传送到HDFS上。目前Flume已经成为Apache顶级项目,并已经成为大数据处理中必不可少的组

AI天才研究院 1983

flume源码分析

1、LifecycleAware public interface LifecycleAware {    public void start();    public void stop();    public LifecycleState getLifecycleState();  } 所有核心组件,全都实现这个接口。通过start,stop启动关闭,通过

亚瑟的守护的专栏 2745

基于Spark Streaming的新闻数据实时分析系统架构与实战

实时数据处理是应对海量、高速数据挑战的核心技术,其原理在于对连续到达的数据流进行即时计算与分析,而非传统的批量处理。这项技术的价值在于能够实现业务指标的秒级甚至毫秒级反馈,为决策提供即时依据。在应用场景上,实时处理广泛用于监控告警、实时推荐、舆情分析等领域。本文聚焦于一个典型的实时分析系统案例,深入探讨了如何利用Spark Streaming构建新闻网大数据实时分析平台。系统集成了Kafka作为高吞吐数据管道,并采用Redis和HDFS实现多级存储策略,有效支撑了热点话题发现与实时可视化等核心功能。

weixin_34160277的博客 353

flume1.7.0源码

flume源码

flume执行流程及源码解读

1、flume 指定配置文件启动 bin/flume-ng agent -c conf -f conf/LogDetailExpose4KafkaFlume.conf -n aApacheFlume --classpath /home/dmpflume-jar-with-dependencies.jar -Dflume.root.logger=INFO,console #注意:因为需要指定自己实现...

weixin_40809627的博客 1072

IEEE 754浮点数与十六进制转换:从原理到实战避坑指南

在计算机系统中,数据的二进制表示与内存布局是底层开发的核心基础。IEEE 754标准定义了浮点数在内存中的精确格式,包括符号位、指数位和尾数位的分工,以及零、无穷大和NaN等特殊值的编码。理解这一原理对于处理原始字节流至关重要,尤其是在涉及跨平台或跨设备通信时。其技术价值在于,它能帮助开发者从根本上解决数据解析错误、通信协议不一致以及程序调试中的“灵异”问题。在嵌入式开发、网络通信(如Modbus协议)和固件解析等应用场景中,浮点数与十六进制的转换是高频操作。然而,字节序(大端/小端)是转换过程中最常见的“

weixin_33835103的博客 430

16_Flume之源码分析

随后,这个轮询线程会通过 Guava 的 EventBus 机制通知 Application 类配置发生了更新,从而触发 Application#handleConfigurationEvent 方法,重新加载所有的组件。组件的start方法是在 MonitorRunnable 的run方法中调用的,MonitorRunnable 是一个线程,run方法中会获取当前组件的状态(默认STOP)以及预期的状态(START),如果不相等则通过预期的状态执行相应的逻辑(ETCD直呼内行~~~)

weixin_40727028的博客 545

Ubuntu 22.04 局域网安装GitLab

下面直接给你一份。

u013250861的博客 666

遥感常用相关指数和计算方法(植被指数/水体指数/雪和冰指数/矿物指数/地表温度指数/云和阴影指数/农业指数)

遥感常用相关指数和计算方法(植被指数/水体指数/雪和冰指数/矿物指数/地表温度指数/云和阴影指数/农业指数)

m0_64361769的博客 1万+

Flume源码阅读记录(2)flume启动过程

flume-ng 启动 当flume配置好后,使用 bin/flume-ng agent -n agent -c conf -f conf/flume-demo.conf -Dflume.root.logger=INFO,console ,即可利用flume-ng脚本以及传入的各参数启动flume服务。 flume-ng脚本 在这里注意,FLUME_AGENT_CLASS=“org.apache...

SW_LCC的博客 309

wifi/BT芯片RTL8723DS驱动移植和测试之一wifi篇

本文主要介绍如何在stm32mp157中移植并测试芯片RTL8723DS的wifi功能。

汉尼拔勇闯天涯 8740

Spring Cloud Alibaba源码深度解析:Nacos服务注册与Sentinel限流实现原理

在微服务架构中,服务发现与流量治理是保障系统稳定性的核心技术。服务发现通过注册中心实现服务的动态注册与发现,其核心机制包括心跳检测、健康检查与负载均衡,确保服务实例的可用性。流量治理则通过限流、熔断与降级等策略,保护系统免受过载流量的冲击,提升整体韧性。理解这些底层原理对于构建高可用、可扩展的分布式系统至关重要。以Spring Cloud Alibaba生态为例,Nacos作为服务发现与配置中心,其客户端通过自动装配与事件驱动完成服务注册,并依赖心跳机制维持实例健康状态;Sentinel则通过责任链模式与滑

weixin_34326179的博客 745

AD20/Altium designer——元器件批量命名与编号的高效技巧

本文详细介绍了在AD20/Altium Designer中实现元器件批量命名与编号的高效技巧。通过解析核心的“原理图标注”功能,从基础全局操作到进阶的按模块分区、利用标识符及合并BOM等智能方法,帮助硬件工程师彻底告别手动编号,大幅提升设计效率与文档规范性,并融入了一套完整的实战工作流。

whisky的博客 568

OsgEarth开发笔记(三):Osg3.6.3+OsgEarth3.1+vs2019x64开发环境搭建(下)

上一篇编译了proj6.2.0、gdal3.2.1,本篇继续。 OsgEarth的编译,是基于Osg和OsgEarth结合在一起的,先要编译Osg,然后编译OsgEarth。OsgEarth的依赖库较多,分为上、中、下三篇,然后单独有一篇如何将编译好的osgEarth集成到Qt中。

长沙红胖子 Qt・西安|省级科研团队从业背景,深耕双一流体系高精尖技术配套研发|剥离高精尖机理,沉淀高端特种行业领域 Qt 工程化落地经验|博文仅分享通用技术总结,输出公开普适工程思路。 4万+

DeepSeek Harness:多智能体系统框架的核心原理与应用实践

多智能体系统(MAS)是人工智能领域的重要分支,它通过多个智能体之间的协同与交互,解决单一智能体难以处理的复杂任务。其核心原理在于将任务分解、角色分配与协作机制相结合,通过通信协议和协调策略实现整体目标。这一技术显著提升了AI系统的模块化、可扩展性和任务处理能力,在自动化流程、复杂决策支持、客服系统等场景中具有重要价值。DeepSeek Harness作为专门的多智能体系统框架,通过封装上下文管理、执行轨迹追踪等基础设施,有效解决了智能体间协作、状态管理和长对话处理等工程挑战。该框架特别针对上下文过大等常见

weixin_34087307的博客 348

SAM3 几行代码支持任意图像分辨率,减少显存占用(针对transformers库)

几行代码让sam3支持任意图像分辨率

qq_41234663的博客 156

【大数据】Flume源码分析之启动过程

要分析flume的源码,首先要从Flume的启动开始,然后再分析Flume的各个组件服务Source、Channel、Sink的源码,接下来我们就来看下Flume是如何启动的吧 Flume的启动入口 org.apache.flume.node.Application 1、校验命令行 Options options = new Options(); Option option = new Option("n", "name", true, "the name of this agent".

像风走过八千里 1002

某勾网之登录过程逆向

拉勾网的登录过程逆向,包含请求头(X-S-HEADER、X-K-HEADER、X-SS-REQ-HEADER等) 以及 请求参数/返回数据的加解密。

shanf7921的博客 3万+

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Flume 1.9.0 源码解析 : 一篇文章弄清Flume 程序启动流程

一 .环境准备. 1.配置文件: example.conf # example.conf: A single-node Flume configuration # Name the components on this agent a1.sources = r1 a1.sinks = k1 a1.channels = c1 # Describe/configure t...

张伯毅的专栏 5067

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

如何编译及运行flume源码

一、从源码开始编译 1、github(https://github.com/apache/flume)上fork分支,下载到本地 2、编译 mvn clean package -DskipTests=true  ,要求JDK7及以上版本,maven3及以上版本 编译过程中,可能有很多jar下载不了,建议用google搜索,相应的jar,下载到本地仓库(本人反复下载缺失jar,拷贝到maven

zhujianlin1990的专栏 4784

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Flume常见错误整理(持续更新ing...)

进来看!

光于前裕于后的博客 2万+

Flume-ng源码分析--启动脚本解析

Flume源码分析–flume-ng解析 以此篇作为研究、学习源码的起步。 Flume简介 Flume 是一个高可用的、高可靠的分布式系统,可以从不同的数据源进行日志的采集、聚合、传输,可以将采集到的日志传输到HDFS、HBase、MySQL等。数据源和接收数据的端都是可定制的。 Flume本地化调试 1、安装java JDK。 2、从FLume官网下载编译好的flume包和flume源码包,并进...

BattleWolf_HUA的博客 1035

【Hadoop】Flume-ng源码解析之启动流程

通过源码解读了Flume-ng的启动流程

_朝和 2140

Flume源码编译、打包、修改Taildir Source支持递归

为什么要编译源码? 修改各组件版本,为了跟生产上其他组件版本匹配 bug修复 新特性的增加 二次开发 flume源码编译 编译方式:IDEA + MAVEN 编译版本:flume-ng-1.6.0-cdh5.15.1-src 编译注意事项: 带cdh标志的部分jar包国内不方便下载,可以借助阿里云的香港云主机下载后拷贝到本地。 在flume-ng-sinks下的pom.xml中找到fl...

边看边学 994
上一篇: Flume源码阅读记录(2)flume启动过程
下一篇: DecimalFormat用于格式化数据简单使用
SW_LCC
博客等级 码龄11年 4粉丝 114原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值