前言
说实话,以前没碰见过必须只获取一次对象供全局使用的地方,或者说多重复实例化获得新的句柄对程序也没什么影响,但是这种习惯是非常很不好的,比如我最近在向hdfs写入文件的时候我希望FileSystem fs这个句柄只获得一次,后面所有的fs操作都用这一个对象就行,因为有kerberos的验证,如果每次操作都需要获取FileSystem fs这个句柄一来浪费验证的时间,二来会多占用一点内存!
代码
package com.bodyproperty.util;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.security.UserGroupInformation;
import org.springframework.stereotype.Component;
import java.io.IOException;
/**
* @Auther: kc
* @Date: 2018/12/19 11:22
* @Description:
*/
@Component
public class HdfsUtil {
static FileSystem fs;
static{
if (System.getProperty("os.name").toLowerCase().startsWith("win")) {
// Windows系统
System.setProperty("java.security.krb5.conf", "C:/Program Files/MIT/Kerberos/krb5.ini");
} else {
// linux系统
System.setProperty("java.security.krb5.conf", "/etc/krb5.conf");
}
Configuration conf = new Configuration();
//这里设置namenode新
conf.set("fs.defaultFS", "hdfs://test-da-shanghai:8020");
//需要增加hadoop开启了安全的配置
conf.setBoolean("hadoop.security.authorization", true);
//配置安全认证方式为kerberos
conf.set("hadoop.security.authentication", "kerberos");
//设置namenode的principal
conf.set("dfs.namenode.kerberos.principal", "nn/[email protected]");
//设置datanode的principal值为“hdfs/[email protected]”
conf.set("dfs.datanode.kerberos.principal", "dn/[email protected]");
conf.set("dfs.support.append", "true");
conf.set("dfs.client.block.write.replace-datanode-on-failure.policy", "NEVER");
conf.set("dfs.client.block.write.replace-datanode-on-failure.enable", "true");
//通过hadoop security下中的 UserGroupInformation类来实现使用keytab文件登录
UserGroupInformation.setConfiguration(conf);
//设置登录的kerberos principal和对应的keytab文件,其中keytab文件需要kdc管理员生成给到开发人员
try {
UserGroupInformation.loginUserFromKeytab("[email protected]", "file:/usr/lihong/lihong.keytab");
} catch (Exception e) {
System.out.println("身份认证异常: " + e.getMessage());
e.printStackTrace();
}
try {
fs = FileSystem.get(conf);
} catch (IOException e) {
e.printStackTrace();
}
}
public static FileSystem getFs() {
return fs;
}
}
其实整个代码中间的验证全部不用看,主要就是我用static代码块将验证的逻辑包围起来,然后fs这个对象就只会生成一次了,每次调用getFs()方法获得的都是同一个fs对象 。