最近集群存储倾斜,个别节点存储超过85%,启动balancer之后效果明显,但是有时候balancer启动也不能解决问题。从运维阶段就知道有这么一个balancer,今天终于憋了一口气看看balancer到底咋回事。版本还是1.0.3
首先balancer在org.apache.hadoop.hdfs.server.balancer,balancer作为一个独立程序启动,听说之前是在namenode内部,这个还真没见过。
public static void main(String[] args) {
try {
System.exit( ToolRunner.run(null, new Balancer(), args) );
} catch (Throwable e) {
LOG.error(StringUtils.stringifyException(e));
System.exit(-1);
}
}
我擦,一看,是熟悉的ToolRunner,不用说Balancer就是个tool,重写run方法。
进去balancer的run看看吧。
run代码相对比较长,不全部贴出来了,一步步看一下吧。
init(parseArgs(args));
首先是解析程序传递参数,然后执行init方法。什么程序参数?很简单,因为balancer是这么用的bin/start-balancer.sh -threshold 5,看到了吗,有个阈值,需要管理员指定。
这个阈值是啥下面再说,这个解析参数,就是拿到咱们threshold的值,这里是5,那就把5传给init。
this.threshold = threshold;
this.namenode = createNamenode(conf);//得到集群namenode对象
this.client = DFSClient.createNamenode(conf);//弄一个客户端对象
this.fs = FileSystem.get(conf);//文件系统对象
这就是init主要的方法,剩下的安全认证的这里就不说了,这里主要是弄个namenode的代理,弄个hdfs的客户端,然后弄个hdfs文件系统的对象。好了,继续:
out = checkAndMarkRunningBalancer();
/*任意时刻只能有一个balancer存在,如何判断?就是往集群写一个文件/system/balancer.id,写的时候本身会有已存在的报错返回null
* 往里写的应该是byte类型的数据,即balancer所在的机器信息。
* */
if (out == null) {
System.out.println("Another balancer is running. Exiting...");
return ALREADY_RUNNING;
}
这里一看,就是检查一下有木有balancer进程已经在工作了,这个方法很简单,程序写死了要往hdfs的/system/balancer.id这个文件写进去点东西,写的东西是balancer所在机器的信息:
private OutputStream checkAndMarkRunningBalancer() throws IOException {
try {
DataOutputStream out = fs.create(BALANCER_ID_PATH);
out. writeBytes(InetAddress.getLocalHost().getHostName());
out.flush();
return out;
看到了吗。然后写的过程中判断这个文