spring xd依赖于两个重要spring 工具:spring batch 和spring integration。
spring xd本身的环境信息,存储于zookeeper。
spring xd的操作过程,完全依赖于zookeeper:通过zookeeper的树结构,存储运行时的动态信息。
所以我们的出发点从绘制zookeeper目录结构开始。
- deploy job 的目录树分析
先不要看蓝色底色框的信息,只看“zookeeper”节点及其子节点描述的这棵树,否则容易混乱。
目录树从根节点开始看,有三个子节点:deployments,queue和jobs。
deployments是已经部署的内容信息,queue是请求队列,而jobs则存储了job的定义。
在xd运行的过程中,就是通过操作zookeeper各个目录结构,从而实现了xd组件间的调用和反馈。
- deploy过程解析
- JobController接收到请求后,会立即将请求打包,发布到队列中。队列是通过zookeeper实现的,路径为“queue/deployments”。
- JobController发出请求后,不是立即返回,而是等待执行结果。这里采用的方式是,根据请求的id,建立路径“deployments/responses/requestid”。同步等待此路径的信息变化,从而获得任务的执行结果。
- 请求发出后,DeploymentMessageConsumer会从队列读取请求,并做相应的处理。
- Consumer 根据请求的类型,调用不同的Deployer实现job的上线。图中描述了JobDeployer的详细信息。(本文只描述Job的上线操作)
- JobDeployer会在zookeeper上记录job的信息,以及运行态信息。
- JobDeployer最终会通过ModuleDeploymentwriter,将部署任务通知Container,Container完成Job的加载。
xd的代码写的很妖娆,看起来特别绕。但是总结来说,就是两步:第一步,在zookeeper上注册job的定义信息和运行态信息;第二部通知container部署job。
- container加载job
上面说到xd通知container加载job,没有说通知方式。其实和其他的规则一样,都是通过zookeeper的路径监听触发的。
xd新建了“deployments/modules/allocated/container_id”的子目录,从而让container加载子目录信息,也就是job信息。
container的DeploymentListener读取并分析信息,通过ModuleDeployer来加载job。
- job 定时任务分析
到目前为止,job已经部署到container中。
Job 的定时运行,需要另外一个trigger,定时触发job执行。我们的环境中采用kafka作为消息中间件。
xd采用spring integration 实现消息通信。在job deploy的时候,就会创建channel,监听topic。
新建trigger时候,trigger会注册此topic的productor。trigger根据cron表达式,定期发送消息触发job,从而实现了job的定期执行。
container中接收消息,并执行job的代码找了好久,终于在配置文件中发现。xml定义了一个id =input的MessageChannel。将channel的输出定位到JobLaunchRequestTransformer,JobLaunchRequestTransformer的输出定位到JobLaunchingMessageHandler。JobLaunchingMessageHandler运行job。
JobPlugin将input channel 绑定到具体的message上。
这些bean都是spring batch 和integration的实现,xd只是组装了起来。