s4启动一个node后,该node 要监听zookeeper是否有新的app。如果有新的app,则该node读取app在zookeeper上的相关信息,并加载app的相关类。最后调用app的init()和start()方法,启动app。整个过程涉及到多个类,所以为了便于讲述,将该部分拆成几部分来谈。
一 解析Tools.java
1、Tools.java(package org.apache.s4.tools)是S4启动的一个入口,包含了启动zookeeper,创建cluster,部署application,启动node等命令。例如,./s4 newCluster -c=cluster1 -nbTasks=2 -flp=12000, 就是在s4脚本中调用Tools,然后Tools调用DefineCluster.java创建一个新的cluster。源码中,Tools中的所有命令由一个枚举类型表示。
enum Task {
deploy(Deploy.class), node(S4Node.class), zkServer(ZKServer.class), newCluster(DefineCluster.class), adapter(
null), newApp(CreateApp.class), s4r(Package.class), status(Status.class);
Class<?> target;
Task(Class<?> target) {
this.target = target;
}
public void dispatch(String[] args) {
try {
Method main = target.getMethod("main", String[].class);
main.invoke(null, new Object[] { args });
} catch (Exception e) {
e.printStackTrace();
logger.error("Cannot dispatch to task [{}]: wrong arguments [{}]", this.name(), Arrays.toString(args));
}
}
}
在Tools的main方法中,首先获取task,由于第一个参数为隐藏的s4ScriptPath,所以task为第二个参数。
task = Task.valueOf(args[1]);
然后获取task后的所有参数,如果task不是“node”时,要添加s4ScriptPath,这里暂不管它。当所有参数获取后,调用该task的dispatch方法。在dispatch中,调用task对应类的main方法。taskArgs就是该类main方法的参数。然后task对应的类就启动了。
List<String> taskArgs = new ArrayList<String>();
if (!task.name().equals("node")) {
taskArgs.add(args[0]); // s4 script (only for s4-tools project classes)
}
if (args.length > 1) {
taskArgs.addAll(Arrays.asList(Arrays.copyOfRange(args, 2, args.length)));
}
task.dispatch(taskArgs.toArray(new String[] {}));