Configuration是Flume项目的入口程序了,当我们输入

bin/flume-ng agent --conf conf --conf-file conf/kafka1.properties --name test -Dflume.root.logger=INFO,console -Dorg.apache.flume.log.printconfig=true -Dorg.apache.flume.log.rawdata=true

后,脚本会导入环境变量,并且启动org.apache.flume.node.Application


FLUME_AGENT_CLASS="org.apache.flume.node.Application" # finally, invoke the appropriate command
# 判断是agent,然后调用run_flume
if [ -n "$opt_agent" ] ; then
run_flume $FLUME_AGENT_CLASS $args
elif [ -n "$opt_avro_client" ] ; then
run_flume $FLUME_AVRO_CLIENT_CLASS $args
elif [ -n "${opt_version}" ] ; then
run_flume $FLUME_VERSION_CLASS $args
elif [ -n "${opt_tool}" ] ; then
run_flume $FLUME_TOOLS_CLASS $args
else
error "This message should never appear" 1
fi run_flume() {
local FLUME_APPLICATION_CLASS if [ "$#" -gt 0 ]; then
FLUME_APPLICATION_CLASS=$1
shift
else
error "Must specify flume application class" 1
fi if [ ${CLEAN_FLAG} -ne 0 ]; then
set -x
fi
$EXEC $JAVA_HOME/bin/java $JAVA_OPTS $FLUME_JAVA_OPTS "${arr_java_props[@]}" -cp "$FLUME_CLASSPATH" \
-Djava.library.path=$FLUME_JAVA_LIBRARY_PATH "$FLUME_APPLICATION_CLASS" $*
}

然后调用Application类的main方法,这个方法里面加载了配置,并且启动了每个组件。

 public static void main(String[] args) {

    try {
//flume 的zookeeper在1.7版本中还是一个实验特性
boolean isZkConfigured = false;
//设置一些必要的参数
Options options = new Options(); Option option = new Option("n", "name", true, "the name of this agent");
option.setRequired(true);
options.addOption(option); option = new Option("f", "conf-file", true,
"specify a config file (required if -z missing)");
option.setRequired(false);
options.addOption(option); option = new Option(null, "no-reload-conf", false,
"do not reload config file if changed");
options.addOption(option); // Options for Zookeeper
option = new Option("z", "zkConnString", true,
"specify the ZooKeeper connection to use (required if -f missing)");
option.setRequired(false);
options.addOption(option); option = new Option("p", "zkBasePath", true,
"specify the base path in ZooKeeper for agent configs");
option.setRequired(false);
options.addOption(option); option = new Option("h", "help", false, "display help text");
options.addOption(option); CommandLineParser parser = new GnuParser();
CommandLine commandLine = parser.parse(options, args); if (commandLine.hasOption('h')) {
new HelpFormatter().printHelp("flume-ng agent", options, true);
return;
} String agentName = commandLine.getOptionValue('n');
boolean reload = !commandLine.hasOption("no-reload-conf"); if (commandLine.hasOption('z') || commandLine.hasOption("zkConnString")) {
isZkConfigured = true;
}
Application application = null;
if (isZkConfigured) {
// get options
String zkConnectionStr = commandLine.getOptionValue('z');
String baseZkPath = commandLine.getOptionValue('p'); if (reload) {
EventBus eventBus = new EventBus(agentName + "-event-bus");
List<LifecycleAware> components = Lists.newArrayList();
PollingZooKeeperConfigurationProvider zookeeperConfigurationProvider =
new PollingZooKeeperConfigurationProvider(
agentName, zkConnectionStr, baseZkPath, eventBus);
components.add(zookeeperConfigurationProvider);
application = new Application(components);
eventBus.register(application);
} else {
StaticZooKeeperConfigurationProvider zookeeperConfigurationProvider =
new StaticZooKeeperConfigurationProvider(
agentName, zkConnectionStr, baseZkPath);
application = new Application();
application.handleConfigurationEvent(zookeeperConfigurationProvider.getConfiguration());
}
} else {
File configurationFile = new File(commandLine.getOptionValue('f')); /*
* The following is to ensure that by default the agent will fail on
* startup if the file does not exist.
*/
if (!configurationFile.exists()) {
// If command line invocation, then need to fail fast
if (System.getProperty(Constants.SYSPROP_CALLED_FROM_SERVICE) ==
null) {
String path = configurationFile.getPath();
try {
path = configurationFile.getCanonicalPath();
} catch (IOException ex) {
logger.error("Failed to read canonical path for file: " + path,
ex);
}
throw new ParseException(
"The specified configuration file does not exist: " + path);
}
}
List<LifecycleAware> components = Lists.newArrayList();
//如果reload为真,每过30秒钟加载一次配置文件
if (reload) {
EventBus eventBus = new EventBus(agentName + "-event-bus");
//通过PollingPropertiesFileConfigurationProvider来创建一个线程,每隔30秒读取一次配置文件
PollingPropertiesFileConfigurationProvider configurationProvider =
new PollingPropertiesFileConfigurationProvider(
agentName, configurationFile, eventBus, 30);
components.add(configurationProvider);
application = new Application(components);
eventBus.register(application);
} else {
//一次性加载配置文件
PropertiesFileConfigurationProvider configurationProvider =
new PropertiesFileConfigurationProvider(agentName, configurationFile);
application = new Application();
application.handleConfigurationEvent(configurationProvider.getConfiguration());
}
}
//依次启动每个应用component
application.start();
//在应用程序结束的时候,调用stop()函数。
final Application appReference = application;
Runtime.getRuntime().addShutdownHook(new Thread("agent-shutdown-hook") {
@Override
public void run() {
appReference.stop();
}
}); } catch (Exception e) {
logger.error("A fatal error occurred while running. Exception follows.", e);
}
}

在这个里面使用了PollingPropertiesFileConfigurationProviderPropertiesFileConfigurationProvider 两个类,实际作用是提供每个组件的配置。

他们的类图如下:

ConfigurationProvider是一个接口,所有***ConfigurationProvider都是为了各种组件提供配置。

public interface ConfigurationProvider {
MaterializedConfiguration getConfiguration();
}

中间有一个抽象类,public abstract class AbstractConfigurationProvider implements ConfigurationProvider ,它会实现getConfiguration()接口,为每个一个组件添加配置。

  public MaterializedConfiguration getConfiguration() {
MaterializedConfiguration conf = new SimpleMaterializedConfiguration();
//获取配置,getFlumeConfiguration这个方法会在不同的子类中进行实现。
FlumeConfiguration fconfig = getFlumeConfiguration();
//获取不同agent的配置
AgentConfiguration agentConf = fconfig.getConfigurationFor(getAgentName());
if (agentConf != null) {
Map<String, ChannelComponent> channelComponentMap = Maps.newHashMap();
Map<String, SourceRunner> sourceRunnerMap = Maps.newHashMap();
Map<String, SinkRunner> sinkRunnerMap = Maps.newHashMap();
try {
//加载channels,source,sinks,这里会创建出对应的对象
loadChannels(agentConf, channelComponentMap);
loadSources(agentConf, channelComponentMap, sourceRunnerMap);
loadSinks(agentConf, channelComponentMap, sinkRunnerMap);
//如果某个channel没有和source、sink做关联,就删除掉
//如果关联着,就加入到conf里面,
Set<String> channelNames = new HashSet<String>(channelComponentMap.keySet());
for (String channelName : channelNames) {
ChannelComponent channelComponent = channelComponentMap.get(channelName);
if (channelComponent.components.isEmpty()) {
LOGGER.warn(String.format("Channel %s has no components connected" +
" and has been removed.", channelName));
channelComponentMap.remove(channelName);
Map<String, Channel> nameChannelMap =
channelCache.get(channelComponent.channel.getClass());
if (nameChannelMap != null) {
nameChannelMap.remove(channelName);
}
} else {
LOGGER.info(String.format("Channel %s connected to %s",
channelName, channelComponent.components.toString()));
conf.addChannel(channelName, channelComponent.channel);
}
}
//将source、sink加入从里面
for (Map.Entry<String, SourceRunner> entry : sourceRunnerMap.entrySet()) {
conf.addSourceRunner(entry.getKey(), entry.getValue());
}
for (Map.Entry<String, SinkRunner> entry : sinkRunnerMap.entrySet()) {
conf.addSinkRunner(entry.getKey(), entry.getValue());
}
} catch (InstantiationException ex) {
LOGGER.error("Failed to instantiate component", ex);
} finally {
channelComponentMap.clear();
sourceRunnerMap.clear();
sinkRunnerMap.clear();
}
} else {
LOGGER.warn("No configuration found for this host:{}", getAgentName());
}
return conf;
}

话说里面的名字起的比较奇怪,SourceRunner,SinkRunner,ChannelComponent

前面两个都是Runner,后面就是Component

接下来就是public class PropertiesFileConfigurationProvider extends AbstractConfigurationProvider

在这个类里面实现了getFlumeConfiguration()方法。

最后就是

public class PollingPropertiesFileConfigurationProvider extends PropertiesFileConfigurationProvider implements LifecycleAware

这个类,就是实现了每隔30秒读取一次配置文件。它的start函数里面启动了一个单任务延迟线程池,来做文件操作。


@Override
public void start() {
LOGGER.info("Configuration provider starting"); Preconditions.checkState(file != null,
"The parameter file must not be null");
//启动一个线程池
executorService = Executors.newSingleThreadScheduledExecutor(
new ThreadFactoryBuilder().setNameFormat("conf-file-poller-%d")
.build()); FileWatcherRunnable fileWatcherRunnable =
new FileWatcherRunnable(file, counterGroup); executorService.scheduleWithFixedDelay(fileWatcherRunnable, 0, interval,
TimeUnit.SECONDS); lifecycleState = LifecycleState.START; LOGGER.debug("Configuration provider started");
}

里面的FlieWatchRunnable类会判断文件是否更新,如果更新了,就重新调用getConfiguration方法。

整个配置加载的大体就是这样子,整个过程涉及到了FlumeConfiguration,下次记录一下Flume的配置类。

整个代码结构写的也很清晰,我觉得是这样子,笑。每个类,每个函数都能看出它的作用。这是需要学习的地方。

Flume 启动的更多相关文章

  1. [Spark][Flume]Flume 启动例子

    Flume 启动例子: flume-ng agent --conf /etc/flume-ng/conf --conf-file /etc/flume-ng/conf/flume.conf --nam ...

  2. flume 启动,停止,重启脚本

    #!/bin/bash #echo "begin start flume..." #flume的安装根目录(根据自己情况,修改为自己的安装目录) path=/sysware/apa ...

  3. Flume启动运行时报错org.apache.flume.ChannelFullException: Space for commit to queue couldn't be acquired. Sinks are likely not keeping up with sources, or the buffer size is too tight解决办法(图文详解)

        前期博客 Flume自定义拦截器(Interceptors)或自带拦截器时的一些经验技巧总结(图文详解) 问题详情 启动agent服务 [hadoop@master flume-1.7.0]$ ...

  4. Flume启动错误之:Bootstrap Servers must be specified

    今天测试项目的时候需要启动Flume,然而在启动时遇到了Bootstrap Servers must be specified错误,错误日志如下: [kfk@bigdata-pro01 flume-- ...

  5. Flume启动时报错Caused by: java.lang.InterruptedException: Timed out before HDFS call was made. Your hdfs.callTimeout might be set too low or HDFS calls are taking too long.解决办法(图文详解)

    前期博客 Flume自定义拦截器(Interceptors)或自带拦截器时的一些经验技巧总结(图文详解) 问题详情 -- ::, (agent-shutdown-hook) [INFO - org.a ...

  6. Flume启动报错[ERROR - org.apache.flume.sink.hdfs. Hit max consecutive under-replication rotations (30); will not continue rolling files under this path due to under-replication解决办法(图文详解)

    前期博客 Flume自定义拦截器(Interceptors)或自带拦截器时的一些经验技巧总结(图文详解)   问题详情 -- ::, (SinkRunner-PollingRunner-Default ...

  7. flume启动报错

    执行flume-ng agent -c conf -f conf/load_balancer_server.conf -n a1 -Dflume.root.logger=DEBUG,console , ...

  8. flume【源码分析】分析Flume的启动过程

    h2 { color: #fff; background-color: #7CCD7C; padding: 3px; margin: 10px 0px } h3 { color: #fff; back ...

  9. [转] flume使用(六):后台启动及日志查看

    [From] https://blog.csdn.net/maoyuanming0806/article/details/80807087 处理的问题flume 普通方式启动会有自己自动停掉的问题,这 ...

随机推荐

  1. group_concat函数

  2. Android技术归档

    各位小伙伴们.以后小巫的一些开源码都会上传到github中,所以欢迎大家Follow https://github.com/devilWwj 基于眼下我基本的技术领域在Android上,以后关于And ...

  3. artTemplate的使用

    引言 腾讯的前端模板引擎,不逊于doT.js 1.引入 <script type="text/javascript" src="../plugin/artTempl ...

  4. cximage功能简介

    CxImage是一个可以用于MFC 的C++图像处理类库类,它可以打开,保存,显示,转换各种常见格式的图像文件,比如BMP, JPEG, GIF, PNG, TIFF, MNG, ICO, PCX, ...

  5. http请求常出现的状态码

    服务器返回的 响应报文 中第一行为状态行,包含了状态码以及原因短语,用来告知客户端请求的结果. 状态码 类别 原因短语 1XX Informational(信息性状态码) 接收的请求正在处理 2XX ...

  6. Android自定义TabBar

    转载请说明出处:http://www.sunhome.org.cn 我发现现在的移动开发界面都被iOS主导了,UI动不动设计出来的东西都是ios的风格,对于一个做Android的程序员来说甚是苦恼啊, ...

  7. 乌班图 之 apt命令 及 VMware共享文件夹

    apt是Advanced Packaging Tool ,是Ubuntu下的一个安装包管理工具 大部分软件的安装.更新.卸载 都是利用apt命令来实现 直接在终端输入apt即可查阅命令的帮助信息 常用 ...

  8. LR编写post请求

    函数列表: web_submit_data(); web_custom_request(); web_get_int_property(); 1.web_submit_data(); 2.web_cu ...

  9. CorelDRAW X6低价再次冲破底线

    平时我们看到的标志设计.杂志排版.产品商标.插图描画......这些都是设计师们使用CorelDRAW设计而来.如今CorelDRAW已经成为每个设计师必装的软件,从12年发布CorelDRAW X6 ...

  10. n阶方阵,数字从1~n^2,顺时针增大

    运行结果如下图: 解题思路:可以将这个问题分解成x个外围正方形所围成的图形,外围的正方形又可以分为4个步骤,向右依次增大.向下依次增大.向左依次增大.向上依次增大.基本思路就是如此,最关键的就是什么时 ...