【原创】storm源码之巧用java反射反序列化clojure的defrecord获取属性值
【原创】storm源码之巧用java反射反序列化clojure的defrecord获取属性值
storm源码是clojure、java、python的混合体。在解决storm-0.8.2的nimbus单点问题的过程中需要从zookeeper上读取目前storm集群中正在运行的assignments信息,以获取其代码在nimbus机器上的绝对路径(PS:通过java代码实现自定义的storage)。
assignments信息可以通过CuratorFramework框架的客户端读取zookeeper上对应目录的data,如下:
1 byte[] data = curatorFramework.getData().forPath(assignments_dir);
其中data字节码数组保存的是storm nimbus在topology分配任务时序列化到zookeeper的Assignment字节码,Assignment定义如下:
1 (defrecord Assignment [master-code-dir node->host executor->node+port executor->start-time-secs])
PS:defrecord是clojure独有的一种数据结构,主要用来简便轻量地将数据组织在一起。详细可参考:defrecord
由于Assignment是在clojure源码编译后才会产生对应的Assignment类class文件,而storm的clojure源码编译又在其java源码编译之后(前者依赖后者定义的诸多接口及Utils),因此在编码期java代码中是无法import Assignment类的,只能将data反序列化成Object类,如下:
1 ByteArrayInputStream bis = new ByteArrayInputStream(serialized); 2 ObjectInputStream ois = new ObjectInputStream(bis); 3 Object assignment = ois.readObject(); 4 ois.close();
得到的assignment Object结构如下图:
反序列化之后就需要从Object中获取master_code_dir属性值。这里可以通过反射的方式获取:
1 String master_code_dir = assignment.getClass().getDeclaredField("master_code_dir").get(assignment).toString();
如此实现了java代码中不import Assignment类即可从zookeeper获取clojure序列化的master_code_dir属性值。