Mac 下修改Eclipse内存

    Mac下如果Eclipse使用默认的参数会非常非常痛苦的,甚至退化到Windows时候的感觉。所以下载Eclipse以后第一步就是设置Eclipse JVM参数,设置的位置为$ECLIPSE_HOME/Eclipse.app/Contents/MacOS/eclipse.ini。加入以下参数

    -vmargs

    -Xms512m

    -Xmx2048m

 

    其中$ECLIPSE_HOME是你安装Eclipse的home目录。

Maven加入新的source问题

    最近将之前做的hadoop-raid移植到2.4.0上面,因为之前的RPC都是通过POJO,而现在2.x的RPC都是通过PB(参见我之前写过的Blog),所以需要将新加入的Protocol进行PB的改写。

    其中写好proto文件后,需要用hadoop写好的hadoop-maven-plugin插件将proto文件生成java文件。

 <plugin>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-maven-plugins</artifactId>
        <executions>
          <execution>
            <id>compile-protoc-raid</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>protoc</goal>
            </goals>
            <configuration>
              <protocVersion>${protobuf.version}</protocVersion>
              <protocCommand>${protoc.path}</protocCommand>
              <imports>
                <param>${basedir}/../../hadoop-common-project/hadoop-common/src/main/proto</param>
                <param>${basedir}/src/main/proto</param>
              </imports>
              <source>
                <directory>${basedir}/src/main/proto</directory>
                <includes>
                  <include>RaidProtocol.proto</include>
                </includes>
              </source>
              <output>${project.build.directory}/generated-sources/java</output>
            </configuration>
          </execution>
        </executions>
      </plugin>

    同时需要将生成的java文件加入ClassPath中,采用的是org.codehaus.mojo.build-helper-maven-plugin插件。

      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>build-helper-maven-plugin</artifactId>
        <executions>
          <execution>
            <id>add-raid-generated-sources-directory</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>add-source</goal>
            </goals>
            <configuration>
              <sources>
                <source>${project.build.directory}/generated-sources/java</source>
              </sources>
            </configuration>
          </execution>
        </executions>
      </plugin>

    但是使用后能够在terminal中顺利编译,而eclipse却显示没有加入这个classpath。

    最后想到还是用maven命令生成一遍,mvn clean generate-sources eclipse:eclipse

就解决问题了。

Maven out of memory 解决方法

    有时候使用maven的时候,如果采用默认的jvm参数会报oom错误,这个所有java程序员都知道为什么,那修改方法只要加入maven jvm参数就可以了。方法是在环境变量中,加入以下

    export MAVEN_OPTS=”-Xms1024m -Xmx2000m”

Hadoop配置问题

    Hadoop 启用HA的时候,必须要配置dfs.client.failover.proxy.provider属性,并且将所有的ns都进行配置,否则会认为是非HA模式。

java classpath加载顺序

    Java Classpath的加载是有顺序的,简单的说就是如果在Classpath中有多个条目具有相同的名称,那么前面的会被加载,后面的会被忽略。

Maven使用总结

    近期在做hadoop 2.4集群的fast-copy功能,最后需要进行编译,测试等,发现在$HADOOP_HOME下,对所有module进行mvn compile没有任何问题。当进入hadoop hdfs module进行单独编译的时候,总是提示cannot find symbol,提示的是我新加入的方法无法找到。

    最后发现时maven仓库中的那个jar包是老的jar包,导致编译别的module引用这个jar包得时候就会报错。以前也遇到过这个问题,没有引起重视,这次记录下来。附:打包并拷贝至本地库命令

    mvn clean package install -DskipTests

Java Runnable convert to Callable Test

package com.jiangyu;
 
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
 
public class TestConvertThread {
  public static final Random r = new Random();
 
  class Call implements Callable<Object> {
 
    @Override
    public Object call() throws Exception {
      Thread.sleep(r.nextInt(5)*1000);
      System.out.println("finished callable");
      return true;
    }
 
  }
 
  class Run implements Runnable {
 
    @Override
    public void run() {
      try {
        Thread.sleep(r.nextInt(5)*1000);
        System.out.println("finished runnable");
      } catch (InterruptedException e) {
      }
    }
 
  }
 
  public void startJob() throws InterruptedException, ExecutionException, TimeoutException {
    ExecutorService executor = Executors.newCachedThreadPool();
    Future<Object> result = null;
    // this is for callable
    result = executor.submit(new Call());
    result.get(10, TimeUnit.SECONDS);
 
    // this is for runnable convert to callable
    result = executor.submit(Executors.callable(new Run()));
    result.get(10, TimeUnit.SECONDS);
  }
 
  public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
    TestConvertThread tt = new TestConvertThread();
    tt.startJob();
  }
}

测试了一下Runnable convert 到 Callable,需要Future返回类型为Object。JDK中可以使用Executors的Callable方法将Runnalbe直接转化为Callable。

Hadoop 2.0 Datanode

Hadoop 2.0 Datanode 更加细分,将结构分为两个大部分。

DataNode相当于一个包装转发器,将请求发送给相应的处理单元。

DataNode 分为以下两部分:

1、与NameNode汇报的逻辑,block report,heartbeat

2、底层与文件系统交互的datanode 存储逻辑

 

其中第一部分的调用如下:

DataNode —>  BlockProolManager  —>  BPOfferService  —>   BPServiceActor

第二部分的调用如下:

DataNode  —>  FSDataSetImpl     —>     FSVolumeList(FSVolume)     —>     BLockPoolSlice

 

DataNode启动流程:

1、Main

2、StartDatanode

3、初始化BlockPoolManager

4、doRefreshNamenodes

     从配置里面读出相应的namespace id,namenode id(HA)

     初始化BPOfferService,每个namespace对应一个BPOfferService。

     初始化BPActor,每个namenode对应一个BPActor,即Active NameNode和StandbyNameNode各对应一个BPActor。

5、启动所有的BPActor。

     BPActor启动过程如下:

     (1)与NameNode进行handshake,首先建立BPActor对NameNode的RPC连接

     (2)获得namespace info,比较一下与现有的version,目前不会由于svn version不一致直接报错了

     (3)verifyAndSetNamespaceInfo,BPOfferService搞定后,调用DataNode的initBlockPool

     首先向BlockPoolManager注册该BPOfferService。在这个阶段,初始化FSDataSet,初始化存储层,初始化FSVolume,初始化FSVolumeList和ReplicaMap。启动DataBlockScanner和DirectoryScanner。向底层的文件交互FSVolume注册该BlockPool

     (4)handshake第二部,向NameNode注册,NameNode向其内部的DataNode注册该DataNode

     (5)设置BlockReport的细节

VIP配置方法

    通过系统管理员找到一个VIP地址,添加虚拟网卡命令:ifconfig eth0:0 10.210.225.31 up

    关闭虚拟网卡命令 ifconfig eth0:0 down