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[] {}));