ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Hadoop配置信息处理(源码解析)

2021-09-05 21:02:41  阅读:154  来源: 互联网

标签:XML 信息处理 name 配置文件 Hadoop 源码 Configuration properties 加载


一、配置文件简介

    配置文件是一个系统灵活不可缺少的一部分

1.1windows配置文件

  1. 1
    windows系统广泛使用一种特殊化ASCII文件(以“ini”为文件扩展命)作为它的主要配置文件标准。以下为INI文件片段。
    在这里插入图片描述
    应用程序可以拥有自己的配置文件,来存储应用的设置信息。INI文件将配置信息分为一部分一部分“节”,上图[info]就是节标题。

每一节就是对各个项进行赋值。

ro

1. 2 Java配置文件

JDK提供了java.util.Properties类,他继承于Hashtable,由于它继承Hashtable它只支持键-值类型,并没有INI文件的“节”标题。

java.util.Properties用于处理属性列表主要方法如下

//在属性列表中搜索属性并提供默认值
public String getProperty(String key,String defautValue)
//用于更新属性列表更新属性值
public synchronized object setProperty(String key,String value )

Properties中的属性通过load()方法加载,从输入流中读取键-值对,store()方法将Properties表中的属性列表写入输出流。
Propertice也可用XML格式保存

二、Hadoop Configuration详解

他并没有使用java.util.Properties管理配置文件,也没有使用Apach Jakarta Commons Configuration管理配置文件,而是使用自己独有的org.apache.hadoop.conf.Configuration处理配置信息。

2. 1Hadoop配置文件格式

采用XML格式,以下为例子

<property>
    <name>fs.defaultFS</name>
<value>hdfs://hadp01:9000</value>
</property>
<property>
    <name>hadoop.tmp.dir</name>
<value>/home/root/apps/hadoop-2.9.2/tmp</value>
</property>

hadoop配置文件根元素configuration,一般只包含子元素property,每个property就是一个配置项。每个配置项一般包含name ,value,以及对他的描述describe,final表示固定不变

合并多个配置文件
Configuration conf= new Configuration() ; conf.addResource("core -default.xml" ) ; conf.addResouce("core-site.xml");

属性扩展
如配置项dfs.name.dir值是${hadoop.tmp.dir}/dfs/name
如hadoop.tmp.dir的值是/data
那么扩展后原配置项的值就为/data/dfs/name

使用Configuration类的一般步骤
1.构造Configuration对象,并通过addResouce()方法加载需要的资源,
2.用get和set方法访问配置项,资源会第一次使用的时候自动加载到配置项。

2.2Configuration的成员变量

org.apache.hadoop.conf.configuration类图如下
在这里插入图片描述
如图可以看出Configuration有七个非静态成员变量
1.布尔变量quietmode,设置加载配置的模式,如为ture则不输出日志信息。
2.数组resource:保存了所有通过addResource()方法添加到 Configuration对象的资源
Configurationg.addResouce()有四种形式
在这里插入图片描述

  • 一个输入流
  • Hadoop文件路径org.apache,hadoop.fs.Path形式的资源
  • URI
  • core-default.xml形式

3.布尔变量loadDefaults:是否加载默认资源,这些默认资源加载在defaultResource中,defaultResouce是个静态成员变量,通过方法addDefaultrResource()可以添加。在hdfs中hdfs-default.xml和hdfs-site.xml作为默认资源

456.properties,overlay,finalParameters都是和配置项相关的成员变量
hadoop解析后的键-值对都存放在properties,finalParameters存放已经被声明为final的键-值对,overlay记录通过方法设置的键-值对,他是应用设置的,而不是资源解析到的。

7.classLoader:他是一个累加器变量,可加载指定类或相关资源,上面提到的addResource()可以通过字符串的方式加载CLASSPATH资源,他其实是通过Configuration中的getResource()将字符串转换为URL资源

public URL getResouce(String name){
return classLoder.getResource(name)
}

2.3资源加载

资源通过对象的addResource()或者类的静态addDefaultResource()方法添加到Configuration对象中。添加的对象并不会立即加载,而通过reloadConfiguration()清空properties和finalParameters。
addResource()清空如下

public void addResouce(String name){
	addResourceObject(name);
}
private synchronized void addResourceObject(Object resouce){
	resources.add(resource);
	reloadConfiguration();
}
public synchronized reloadConfiguration(){
	properties = null;
	finalParameter.clear();
}

静态方法addDefaultResoure()通过类的静态成员REGIATRY作为媒介清空Configuration对象。
REGIASTRY记录了系统中所有的Configuration对象。
所有,addDefaultResource()调用时遍历REGIASTRY中的元素并在元素上调用reloadConfiguration(),则触发资源的重加载。

public  static synchronized void addDefaultResource(String name){
	if(!defaultResource.contain(name)){
		defaultResource.add(name)
		for(Configuration conf:REGIASTRY.keySet()){
			if(conf.loadDeafaults){
				conf.reloadConfiguration();//出发资源的重加载
			}
		}
	}  
}

理解了资源加载的清空,现在了解一下加载;

成员变量properties中的数据直到需要才会被加载进来,在getProps()方法中,如果发现properties为空,则出发loadResources()方法加载配置资源,采用了延迟加载的设计模式,真正需要配置数据时才开始分析配置文件

private synchronized Properties getProps(){
	if(Properties == null){
		properties = new Properties();
		loadResoures(properties,resources,quietmode);
		......
	}
}

再来了解一下XML

hadoop配置文件都是XML形式,JAXP(java api for XML processing)是一种稳定的可靠的XML处理的API,支持SAX(simple api for XML)和DOM(Document Object Module)两种处理XML文件的方式。

SAX是流式、事件驱动的XML处理方式,编写较复杂,适合较大XML文件

DOM:先将XML文档一次性装入内存,然后根据文档中定义的元素和属性创建一个“树形结构”也是一个文档模型,将文档对象化,文档中每个节点对应模型中的一个对象;然后使用对象提供的编程接口访问XML文档来访问XML。hadoop配置文件都比较小,所以使用DOM。

首先分析DOM加载部分的代码:

private void loadResource(Properties properties,Object name,Boolean quiet){
	try{
			//得到用于创建DOM解析器的工厂
		DocumentBuilderFactory docBuilderFactory= DocumentBuilderFactory.newInstance();
		//忽略XML中的注释
		docBuilderFactory.setIgnoringComments(ture);
		//提供对XML名称空间的支持
		docBuilderFactory.setNamespaceAware(ture);
		try	{
			//设置XInclude处理状态为ture,即允许XIcloude机制
			docBuilderFactory.setXIncludeAware(true);
			}catch(UnsupportedOperationException e){
				......
			}
		//获取解析XML的DocumentBuilder对象
		DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();
		Document doc = null;
		Element root = null;
		
		//根据不同的资源,做预处理并调用相应形式的DocumentBuilder.parse
		if(name instaneof URL)
		{	doc =  builder.parse(url.toString());
		}else if(...)
		.......
	   }

}

一般的JAXP处理从工厂开始,通过调用DBF的newInstance()方法获得创建DOM解析器的工厂。之后对这个新创建的工厂对象进行一些设置,才能进行这个工厂得到解析器对象builder。
针对新创建的工厂对象docBuilderFactory进行的主要设置包括:

  • 忽略文档XML文档注释

  • 支持XMl空间

  • 支持XML的包含机制
    XInclude机制可把一个配置文件分成多个可管理的快,让后将多个较小的文档组成一个大型文档,即一个配置文件可将其他配置文件包含进行一并处理。
    该机制把conf4performance.xml嵌入到当前配置文件,该方法更利用对配置文件进行模块化管理。

    对新工厂设置完毕后,通过该工厂获得解析器对象,用于各种输入源解析XML,在loadResource()根据Configuration支持的四种资源分别进行处理,但最终都调用DocumentBuilder.parse()函数,返回一个DOM解析结果。
    成员函数loadresource()第二部分代码就是根据DOM解析结果设置Configuration的成员变量properties和finalParameters
    在确认configuration是根节点之后,获取根节点 的所有子节点并对所有子节点进行处理,如子节点式configuration,则递归调用loadResource()
    如子节点式property,成功获取name,value,final时根据情况设置成员变量properties和finalParameters。代码如下:

if(root==null){
	root = doc.getDocumentElement();
}
//根节点应该是configuration
if(!"configuration".equals(root.getTagname()))
	LOG.fatal("bad conf file:top-level element not<configuration>");
//获取根节点的所有子节点
NodeList props = root.getChildNodes();
for(int i=0;i<props.getLength();i++)
	Node propNode = props.item(i);
	if(!(propNode instanceof Element))
		continue;//如果子节点不是element。忽略
	Element prop=(Element)propNode;
	if("configuration".equals(prop.getTagName())){//子节点时configuration递归调用loadResource
		loadResoure(properties,prop,quiet);
		continue;
	}
	//子节点是properties
	if(!"properties".equals(prop.getTagName()))
		LOG.ware(...)
	NodeList fields = prop.getChildNodes();
		String attr = null;
		String value = null;
		boolean finalParameter = false;

		//查找name,value,和final的值
		for(int j=0;j<fields.getLength();j++){
			Node fieldNode = fields.item(j);
			if(!(fieldNode instanceof Element))
				continue;
			Element field = (Element)fieldNode;
			if("name".equals(field.getTagName())&& field.hasChildNodes())
				attr = ((Text)field.getFirstChild()).getData().trim();
			if("value".equals(field.getTagName())&& field.hasChildNodes())
				value= ((Text)field.getFirstChild()).getData();
			if("final".equals(field.getTagName())&& field.hasChildNodes())
				finalParameter="ture".equals( ((Text)field.getFirstChild()).getData());	
		}
		......

2.4使用get* 和set*访问/设置配置项

  1. get*
    get*一共有21种方法,他们用于在Configuration对象中获取相应的配置信息。
    最重要的是get()方法,它通过配置项的键获取对应的值。如果建不在则返回默认值defaultValue。其他的方法都会依赖于Configuration.get(),并在get()的基础上做进一步的理解。

Configuration.get()会自动调用configuration的私有方法substituteVars(),该方法可完成配置的属性扩展,属性扩展指配置项中的变量包含${key}会自动替换成以key为键的值,substituteVars()工作依赖正则表达式。

2.set*
这些方法对类型转换等处理后,最终都调用了Configuration.set()
set()只是简单的调用了成员变量properties和overlay的setproperty()方法,保存传入的键-值对。

2.5configurable接口

如果一个类实现了Configurable接口,可以通过这个类传入一个Configuration实例,提供对象工作的一些配置信息。
例如:RegexFilter对象工作时需要一个正则表达式,用于过滤读取到的记录,由于它的父类实现了configurable接口,Regex可以在在它的setConf()方法中使用Configuration.get()方法获取以字符串传入的正则表达式,并初始化成员变量p。代码如下:

public void setConf(Configuration Conf){
	//在Conf中获取键为FILTER_REGEX的配置项
	String	regax = Conf.get(FILTER_REGEX);

	if(regex == null){
		throw new RuntimeException(FILTER_REGEX + "not set");
	this.p = Pattern.compile(regex);
	this.conf = conf;
	}
}

setConf()应在对象创建 后应该立即调用,为简化创建调用两个步骤org.apache.hadoop.util.ReflectionUtils提供静态方法newInstance()

public static <T> T newInstance(Class<T>theClass,Configuration Conf)

它利用java反射机制,根据对象类型信息,创建一个相应类型的对象,让后调用ReflectiongUtils另一个静态方法setConf()配置对象,在此方法中,如果对象实现了Configuratable接口,那么对象的setConf()方法会被调用,并根据Configuration类的实例Conf进一步初始化对象。

public static void setConf(Object theObject,Configuration Conf){
	if(Conf != null){
		//传入的对象实现了Configurable接口
		if(theObject instanceof Configurable){
			//调用对象的setConf方法,传入Configuration对象
			((Configurable)theObject).setConf(conf);
		}
		setJobConf(theObject,conf);
		}
}

总结

作为hadoop common的第一个组件org.apache.hadoop.conf.Configution在各个子项目中发挥着重要的作用。

标签:XML,信息处理,name,配置文件,Hadoop,源码,Configuration,properties,加载
来源: https://blog.csdn.net/m0_47130698/article/details/120100679

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有