본문 바로가기

Cloudata

Cloudata Error : at org.cloudata.core.common.util.NetworkUtil.getAddress(NetworkUtil.java:41) NullPointerException

08-26 18:31:04 633 INFO main tabletserver.TabletServer.startupShutdownMessage() : STARTUP_MSG:

/************************************************************

STARTUP_MSG: Starting TabletServer

STARTUP_MSG:   host = datanode1/127.0.1.1

STARTUP_MSG:   args = []

************************************************************/

08-26 18:31:05 594 INFO main tabletserver.TabletServer.init() : TableServer lock created:/cloudata/lock/server/datanode1:7001

08-26 18:31:05 595 INFO main tabletserver.TabletServer.init() : Turn on tablet distribution mode

08-26 18:31:05 615 ERROR Thread-10 tabletserver.TabletServer.run() : Can't send heartbeat to CloudataMaster: datanode1:7001: null

java.lang.NullPointerException

        at org.cloudata.core.common.util.NetworkUtil.getAddress(NetworkUtil.java:41)

        at org.cloudata.core.tabletserver.TabletServer$HeartbeatThread.run(TabletServer.java:2307)

08-26 18:31:05 668 INFO Thread-11 tabletserver.TabletServer.run() : TabletServer[datanode1:7001] started

08-26 18:31:06 618 ERROR Thread-10 tabletserver.TabletServer.run() : Can't send heartbeat to CloudataMaster: datanode1:7001: null



$CLOUDATA_HOME/bin/start.sh  <--실행 명령어

명령어 실행시 에러 발생. Log로는 getAddress가 NULL이라고 표시된다.
국내에서 만든 sw라서 그런지 자료가 많지 않다. 직접 소스를 보면서 찾아야 한다.
일단 TabletServer.java 의 2307 라인으로 간다.

 while(true) {
        try {
          String masterHostName = CloudataMaster.getMasterServerHostName(conf, zk);
          TabletMasterProtocol masterServer = (TabletMasterProtocol) CRPC.getProxy(TabletMasterProtocol.class,
                TabletMasterProtocol.versionID, NetworkUtil.getAddress(masterHostName), conf);
.......

문제는 getAddress메소드 파라미터에 masterHostName이라는 String 자료형 변수가 있다.
그 변수가 null이다.
String 변수를 초기화는 getMasterServerHostName 메소드가 초기화 해준다.
함수로 들어가서 자세히 본다.


 public static String getMasterServerHostName(CloudataConf conf, ZooKeeper zk) throws IOException {
    List<String> values = null;

    try {
      try {
        values = zk.getChildren(LockUtil.getZKPath(conf, Constants.MASTER), false);
      } catch(NoNodeException e) {
      }

      if(values == null || values.size() == 0) {
        return null;
      }

      Collections.sort(values);

      String leaderNode = values.get(0);

      if(zk.exists(LockUtil.getZKPath(conf, MASTER + "/" + leaderNode), false) == null) {
        LOG.info("No master path [" + LockUtil.getZKPath(conf, MASTER)  + "/" + leaderNode + "]");
        return null;
      }

      byte[] data;
      try {
        data = zk.getData(LockUtil.getZKPath(conf, MASTER + "/" + leaderNode), false, null);
      } catch (NoNodeException e) {
        return null;
      }
      if (data == null) {
        return null;
      }
      return new String(data);
    } catch (Exception e) {
      throw new IOException(e);
    }
  }
....

 

문제는 return null; 이 문제다. 저 중에 어떤부분에서 null이 뜨는지 확인하는 방법은 println()으로 찍어보면 된다. 나의 문제는 4번째 null에서 문제가 발생했다. 네번째 return null;이 뜨려면 data == null 이어야한다. 보니까 바로 위 파란색 메소드 getData()가 초기화한다. 저 메소드는 주키퍼 관련된 클래스와 메소드이다. 한마디로 저기 MASTER +"/"+leaderNode 의 경로를 읽어와야 하는데 그 경로가 없으니까 못 읽어서 data 값을 null로 채우는것 같다. 결론은 저 경로를 주키퍼에서 만들어 주면된다.

참고로 MASTER +"/"+leaderNode 은

public static final String MASTER = "/lock/master"; 이다.

고로 /lock/master/+leaderNode 라는 것이다. 주키퍼에서 /lock/master 디렉터리만 만들어 주면 된다.

주키퍼로가자

$ZOOKEEPER_HOME/bin/zkCli.sh 하면 실행된다.
shell이 뜨면 
ls / 를 치면 목록이뜬다.

[zk: localhost:2181(CONNECTED) 1] ls /
[cloudata, zookeeper]

그런데 그 목록에 /lock 디렉터리가 없다.
그래서 만든다.

[zk: localhost:2181(CONNECTED) 2] create /lock lock
Created /lock            // 만들어 졌단다.

[zk: localhost:2181(CONNECTED) 3] ls /        //확인한다.
[lock, cloudata, zookeeper]        //떴다 lock
[zk: localhost:2181(CONNECTED) 4] create /lock/master master        //그 밑에 master도 만들어준다.
Created /lock/master            //만들어졌단다. 확인안한다.
[zk: localhost:2181(CONNECTED) 6] quit
Quitting...                             //나간다.

바로 켜보자

root@namenode1:~/cloudata# bin/start.sh
INFO [main] 2012-08-26 18:40:41,459 CloudataMaster.java (680) start release lock
INFO [main] 2012-08-26 18:40:41,657 CloudataMaster.java (701) end release lock
datanode3: starting commitlogserver, logging to /root/cloudata/logs/cloudata-root-commitlogserver-datanode3.out
datanode2: starting commitlogserver, logging to /root/cloudata/logs/cloudata-root-commitlogserver-datanode2.out
datanode1: starting commitlogserver, logging to /root/cloudata/logs/cloudata-root-commitlogserver-datanode1.out
starting cloudatamaster, logging to /root/cloudata/logs/cloudata-root-cloudatamaster-namenode1.out
datanode3: starting tabletserver, logging to /root/cloudata/logs/cloudata-root-tabletserver-datanode3.out
datanode2: starting tabletserver, logging to /root/cloudata/logs/cloudata-root-tabletserver-datanode2.out
datanode1: starting tabletserver, logging to /root/cloudata/logs/cloudata-root-tabletserver-datanode1.out


commitlogserver와
tabletserver가 잘 돌아간다

http://masternode:57000 들어가서 노드 3개뜨면 성공.
 
다음엔 examples을 돌려봐야 겠다.
실은 이 에러를 확인하고 구동해봤으나 또 에러가 발생한다.

Hbase와 달리 cloudate는 자료가 많이 없다. 해결은 직접 소스를 보고 해결해야 한다.

참고로 구동 방법은

bin/cloudata jar [jar path ex) $CLOUDATA_HOME/cloudata-1.0.0-core.jar] [example class name]  이다.

물론 에러가 뜬다. example class name 기본은 FirstApp class이다.

p.s : 2012 - 10 - 02 수정완료