1.configuration类简介
Hadoop没有使用java.util.Properties管理配置文件,也没有使用Apache Jakarta Commons Configuration管理配置文件,而是使用了一套独有的配置文件管理系统,并提供自己的API,即使用org.apache.hadoop.conf.Configuration处理配置信息。这个类是作业的配置信息类,任何作用的配置信息必须通过Configuration传递,因为通过Configuration可以实现在多个mapper和多个reducer任务之间共享信息。
2.Hadoop配置文件的格式:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<property>
<name>dfs.name.dir</name>
<value>/home/hdfs/name</value>
<description>.......</description>
<final>true</final>
</property>
<property>
<name>dfs.data.dir</name>
<value>/home/hdfs/data</value>
</property>
</configuration>
3.configuration类代码:
public class Configuration implements Iterable<Map.Entry<String,String>>,
Writable {
private static final Log LOG =
LogFactory.getLog(Configuration.class);
// 用来设置加载配置的模式。为true(默认值),在加载解析配置文件过程中,不输出日志信息。
// quietmode只是一个方便开发人员调试的变量。
private boolean quietmode = true;
// resources用于存储整个XML文件,并不是存键值对,即表明资源列表
private ArrayList<Object> resources = new ArrayList<Object>();
// finalParameters的类型是Set<String>,用来保存所有在配置文件中已经被声明为final的键–值对的键
private Set<String> finalParameters = new HashSet<String>();
// 用于确定是否加载默认资源
private boolean loadDefaults = true;
private static final WeakHashMap<Configuration,Object> REGISTRY =
new WeakHashMap<Configuration,Object>();
// 存放默认添加的XML文件资源
private static final CopyOnWriteArrayList<String> defaultResources =
new CopyOnWriteArrayList<String>();
static{
addDefaultResource("core-default.xml");
addDefaultResource("core-site.xml");
}
// 配置文件解析后的键–值对,都存放在properties中,即用来存储加载出来的属性
private Properties properties;
// 变量overlay用于记录通过set()方式改变的配置项。即出现在overlay中的键–值对是应用设置的,而不是通过对配置资源解析得到的。
private Properties overlay;
// 类加载器变量,可以通过它来加载指定类,也可以通过它加载相关的资源
private ClassLoader classLoader;
{
classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
classLoader = Configuration.class.getClassLoader();
}
}
public Configuration() {
this(true);
}
public Configuration(boolean loadDefaults) {
}
public Configuration(Configuration other) {
}
/************************************************/
/**********向resources中添加XML资源**************/
/************************************************/
public static synchronized void addDefaultResource(String name) {
if(!defaultResources.contains(name)) {
defaultResources.add(name);
for(Configuration conf : REGISTRY.keySet()) {
if(conf.loadDefaults) {
conf.reloadConfiguration();
}
}
}
}
// 添加XML文件,在add完成XML文件的时候,不会去更新属性列表的,
// 只有当有需要读取属性值的时候才会进行资源的加载。
// 要注意的是,在addResource()的时候,会将给定的资源放到一个资源resources里面
public void addResource(Path file) {
addResourceObject(file);
}
// 添加资源,输入参数为XML文件名
public void addResource(String name) {
addResourceObject(name);
}
public void addResource(URL url) {
addResourceObject(url);
}
public void addResource(InputStream in) {
addResourceObject(in);
}
private synchronized void addResourceObject(Object resource) {
resources.add(resource); // XML添加到resources中
reloadConfiguration();
}
// 重新加载配置
public synchronized void reloadConfiguration() {
properties = null; // 清除之前加载进来的全部属性
finalParameters.clear(); // 因为可在属性里面标注final属性,这里将全部final属性清除掉。
}
/************************************************/
/*********通过属性name获得其对应的值*************/
/************************************************/
// 返回属性name对应的值
public String get(String name) {
return substituteVars(getProps().getProperty(name));
}
public String getRaw(String name) {
return getProps().getProperty(name);
}
// return property value, or defaultValue if the property doesn't exist.
public String get(String name, String defaultValue) {
return substituteVars(getProps().getProperty(name, defaultValue));
}
// return property value as an int, or defaultValue.
public int getInt(String name, int defaultValue) {
String valueString = get(name);
if (valueString == null)
return defaultValue;
try {
String hexString = getHexDigits(valueString);
if (hexString != null) {
return Integer.parseInt(hexString, 16);
}
return Integer.parseInt(valueString);
} catch (NumberFormatException e) {
return defaultValue;
}
}
public long getLong(String name, long defaultValue) {
}
public float getFloat(String name, float defaultValue) {
}
public boolean getBoolean(String name, boolean defaultValue) {
}
public Collection<String> getStringCollection(String name) {
String valueString = get(name);
return StringUtils.getStringCollection(valueString);
}
public String[] getStrings(String name) {
String valueString = get(name);
return StringUtils.getStrings(valueString);
}
public String[] getStrings(String name, String... defaultValue) {
}
/************************************************/
/*********通过属性name设置其对应的值*************/
/************************************************/
// 设置属性name对应的值
public void set(String name, String value) {
getOverlay().setProperty(name, value);
getProps().setProperty(name, value);
}
// 设置不存在的属性name对应的值
public void setIfUnset(String name, String value) {
if (get(name) == null) {
set(name, value);
}
}
// 通过int型设置属性name对应的值
public void setInt(String name, int value) {
set(name, Integer.toString(value));
}
public void setLong(String name, long value) {
set(name, Long.toString(value));
}
public void setFloat(String name, float value) {
set(name,Float.toString(value));
}
public void setBoolean(String name, boolean value) {
set(name, Boolean.toString(value));
}
public void setBooleanIfUnset(String name, boolean value) {
setIfUnset(name, Boolean.toString(value));
}
public void setStrings(String name, String... values) {
set(name, StringUtils.arrayToString(values));
}
/************************************************************/
/*********将resources中的XML资源加载到properties*************/
/************************************************************/
private synchronized Properties getProps() {
if (properties == null) {
properties = new Properties();
// 加载资源
loadResources(properties, resources, quietmode);
if (overlay!= null)
properties.putAll(overlay);
}
return properties;
}
private void loadResources(Properties properties,
ArrayList resources,
boolean quiet) {
if(loadDefaults) {
for (String resource : defaultResources) {
loadResource(properties, resource, quiet);
}
if(getResource("hadoop-site.xml")!=null) {
loadResource(properties, "hadoop-site.xml", quiet);
}
}
for (Object resource : resources) {
loadResource(properties, resource, quiet);
}
}
// 利用java DOM API对resource(XML)进行遍历,将全部的属性值加载到properties
private void loadResource(Properties properties, Object name, boolean quiet) {
// 部分代码省略
// Ignore this parameter if it has already been marked as 'final'
if (attr != null && value != null) {
if (!finalParameters.contains(attr)) {
// 添加属性(键值对)
properties.setProperty(attr, value);
if (finalParameter)
finalParameters.add(attr);
}
}
/************************************************************/
/*********其余方法********************************************/
/************************************************************/
/**
* Get the URL for the named resource.
* @param name resource name.
* @return the url for the named resource.
*/
public URL getResource(String name) {
return classLoader.getResource(name);
}
// Get an input stream attached to the configuration resource with the given name
public InputStream getConfResourceAsInputStream(String name) {
}
public Reader getConfResourceAsReader(String name) {
}
public int size() {
return getProps().size();
}
public void clear() {
getProps().clear();
getOverlay().clear();
}
/**
* Get an Iterator to go through the list of String
* key-value pairs in the configuration.
* @return an iterator over the entries.
*/
public Iterator<Map.Entry<String, String>> iterator() {
// Get a copy of just the string to string pairs. After the old object
// methods that allow non-strings to be put into configurations are removed,
// we could replace properties with a Map<String,String> and get rid of this
// code.
Map<String,String> result = new HashMap<String,String>();
for(Map.Entry<Object,Object> item: getProps().entrySet()) {
if (item.getKey() instanceof String &&
item.getValue() instanceof String) {
result.put((String) item.getKey(), (String) item.getValue());
}
}
return result.entrySet().iterator();
}
public synchronized void setQuietMode(boolean quietmode) {
this.quietmode = quietmode;
}
/** For debugging. List non-default properties to the terminal and exit. */
public static void main(String[] args) throws Exception {
}
public void readFields(DataInput in) throws IOException {
clear();
int size = WritableUtils.readVInt(in);
for(int i=0; i < size; ++i) {
set(org.apache.hadoop.io.Text.readString(in),
org.apache.hadoop.io.Text.readString(in));
}
}
public void write(DataOutput out) throws IOException {
Properties props = getProps();
WritableUtils.writeVInt(out, props.size());
for(Map.Entry<Object, Object> item: props.entrySet()) {
org.apache.hadoop.io.Text.writeString(out, (String) item.getKey());
org.apache.hadoop.io.Text.writeString(out, (String) item.getValue());
}
}
}
说明:Configuration实现了Iterable和Writable两个接口,其中实现Iterable是为了迭代,迭代出Configuration对象加载到内存中的所有name-value键值对。实现Writable是为了实现hadoop框架要求的序列化,可以将内存中的name-value序列化到硬盘,关于这两个接口的具体实现的话,我想不用再多说了,应该想的明白。
4.Configuration使用
合并资源指将多个配置文件合并,产生一个配置。如果有两个配置文件,也就是两个资源,如core-default.xml和core-site.xml,通过Configuration类的loadResources()方法,把它们合并成一个配置。代码如下:
Configuration conf = new Configuration();
conf.addResource("core-default.xml");
conf.addResource("core-site.xml");
如果这两个配置资源都包含了相同的配置项,而且前一个资源的配置项没有标记为final,那么,后面的配置将覆盖前面的配置。
Hadoop配置系统还有一个很重要的功能,就是属性扩展。如配置项dfs.name.dir的值是${hadoop.tmp.dir}/dfs/name,其中,${hadoop.tmp.dir}会使用Configuration中的相应属性值进行扩展。
使用Configuration类的一般过程是:构造Configuration对象,并通过类的addResource()方法添加需要加载的资源;然后就可以使用get*方法和set*方法访问/设置配置项,资源会在第一次使用的时候自动加载到对象中。
http://f.dataguru.cn/thread-258563-1-1.html
http://www.cnblogs.com/shaoyexin/archive/2013/03/23/2977235.html
http://www.hackbase.com/tech/2014-12-12/70073.html