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가 잘 돌아간다
다음엔 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 수정완료