Commit fa7b66f6fa35680162c95e9aeb502bab3b0fde24

Authored by 欧保权
0 parents

lts1.7.2源代码

Showing 58 changed files with 4812 additions and 0 deletions

Too many changes to show.

To preserve performance only 58 of 1201 files are displayed.

  1 +*.js linguist-language=Java
  2 +*.html linguist-language=Java
  3 +*.css linguist-language=Java
\ No newline at end of file
... ...
  1 +*.iml
  2 +.idea
  3 +.DS_Store
  4 +target
  5 +/dist/
... ...
  1 +Apache License
  2 +Version 2.0, January 2004
  3 +http://www.apache.org/licenses/
  4 +
  5 +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
  6 +
  7 +1. Definitions.
  8 +
  9 +"License" shall mean the terms and conditions for use, reproduction, and
  10 +distribution as defined by Sections 1 through 9 of this document.
  11 +
  12 +"Licensor" shall mean the copyright owner or entity authorized by the copyright
  13 +owner that is granting the License.
  14 +
  15 +"Legal Entity" shall mean the union of the acting entity and all other entities
  16 +that control, are controlled by, or are under common control with that entity.
  17 +For the purposes of this definition, "control" means (i) the power, direct or
  18 +indirect, to cause the direction or management of such entity, whether by
  19 +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
  20 +outstanding shares, or (iii) beneficial ownership of such entity.
  21 +
  22 +"You" (or "Your") shall mean an individual or Legal Entity exercising
  23 +permissions granted by this License.
  24 +
  25 +"Source" form shall mean the preferred form for making modifications, including
  26 +but not limited to software source code, documentation source, and configuration
  27 +files.
  28 +
  29 +"Object" form shall mean any form resulting from mechanical transformation or
  30 +translation of a Source form, including but not limited to compiled object code,
  31 +generated documentation, and conversions to other media types.
  32 +
  33 +"Work" shall mean the work of authorship, whether in Source or Object form, made
  34 +available under the License, as indicated by a copyright notice that is included
  35 +in or attached to the work (an example is provided in the Appendix below).
  36 +
  37 +"Derivative Works" shall mean any work, whether in Source or Object form, that
  38 +is based on (or derived from) the Work and for which the editorial revisions,
  39 +annotations, elaborations, or other modifications represent, as a whole, an
  40 +original work of authorship. For the purposes of this License, Derivative Works
  41 +shall not include works that remain separable from, or merely link (or bind by
  42 +name) to the interfaces of, the Work and Derivative Works thereof.
  43 +
  44 +"Contribution" shall mean any work of authorship, including the original version
  45 +of the Work and any modifications or additions to that Work or Derivative Works
  46 +thereof, that is intentionally submitted to Licensor for inclusion in the Work
  47 +by the copyright owner or by an individual or Legal Entity authorized to submit
  48 +on behalf of the copyright owner. For the purposes of this definition,
  49 +"submitted" means any form of electronic, verbal, or written communication sent
  50 +to the Licensor or its representatives, including but not limited to
  51 +communication on electronic mailing lists, source code control systems, and
  52 +issue tracking systems that are managed by, or on behalf of, the Licensor for
  53 +the purpose of discussing and improving the Work, but excluding communication
  54 +that is conspicuously marked or otherwise designated in writing by the copyright
  55 +owner as "Not a Contribution."
  56 +
  57 +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
  58 +of whom a Contribution has been received by Licensor and subsequently
  59 +incorporated within the Work.
  60 +
  61 +2. Grant of Copyright License.
  62 +
  63 +Subject to the terms and conditions of this License, each Contributor hereby
  64 +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
  65 +irrevocable copyright license to reproduce, prepare Derivative Works of,
  66 +publicly display, publicly perform, sublicense, and distribute the Work and such
  67 +Derivative Works in Source or Object form.
  68 +
  69 +3. Grant of Patent License.
  70 +
  71 +Subject to the terms and conditions of this License, each Contributor hereby
  72 +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
  73 +irrevocable (except as stated in this section) patent license to make, have
  74 +made, use, offer to sell, sell, import, and otherwise transfer the Work, where
  75 +such license applies only to those patent claims licensable by such Contributor
  76 +that are necessarily infringed by their Contribution(s) alone or by combination
  77 +of their Contribution(s) with the Work to which such Contribution(s) was
  78 +submitted. If You institute patent litigation against any entity (including a
  79 +cross-claim or counterclaim in a lawsuit) alleging that the Work or a
  80 +Contribution incorporated within the Work constitutes direct or contributory
  81 +patent infringement, then any patent licenses granted to You under this License
  82 +for that Work shall terminate as of the date such litigation is filed.
  83 +
  84 +4. Redistribution.
  85 +
  86 +You may reproduce and distribute copies of the Work or Derivative Works thereof
  87 +in any medium, with or without modifications, and in Source or Object form,
  88 +provided that You meet the following conditions:
  89 +
  90 +You must give any other recipients of the Work or Derivative Works a copy of
  91 +this License; and
  92 +You must cause any modified files to carry prominent notices stating that You
  93 +changed the files; and
  94 +You must retain, in the Source form of any Derivative Works that You distribute,
  95 +all copyright, patent, trademark, and attribution notices from the Source form
  96 +of the Work, excluding those notices that do not pertain to any part of the
  97 +Derivative Works; and
  98 +If the Work includes a "NOTICE" text file as part of its distribution, then any
  99 +Derivative Works that You distribute must include a readable copy of the
  100 +attribution notices contained within such NOTICE file, excluding those notices
  101 +that do not pertain to any part of the Derivative Works, in at least one of the
  102 +following places: within a NOTICE text file distributed as part of the
  103 +Derivative Works; within the Source form or documentation, if provided along
  104 +with the Derivative Works; or, within a display generated by the Derivative
  105 +Works, if and wherever such third-party notices normally appear. The contents of
  106 +the NOTICE file are for informational purposes only and do not modify the
  107 +License. You may add Your own attribution notices within Derivative Works that
  108 +You distribute, alongside or as an addendum to the NOTICE text from the Work,
  109 +provided that such additional attribution notices cannot be construed as
  110 +modifying the License.
  111 +You may add Your own copyright statement to Your modifications and may provide
  112 +additional or different license terms and conditions for use, reproduction, or
  113 +distribution of Your modifications, or for any such Derivative Works as a whole,
  114 +provided Your use, reproduction, and distribution of the Work otherwise complies
  115 +with the conditions stated in this License.
  116 +
  117 +5. Submission of Contributions.
  118 +
  119 +Unless You explicitly state otherwise, any Contribution intentionally submitted
  120 +for inclusion in the Work by You to the Licensor shall be under the terms and
  121 +conditions of this License, without any additional terms or conditions.
  122 +Notwithstanding the above, nothing herein shall supersede or modify the terms of
  123 +any separate license agreement you may have executed with Licensor regarding
  124 +such Contributions.
  125 +
  126 +6. Trademarks.
  127 +
  128 +This License does not grant permission to use the trade names, trademarks,
  129 +service marks, or product names of the Licensor, except as required for
  130 +reasonable and customary use in describing the origin of the Work and
  131 +reproducing the content of the NOTICE file.
  132 +
  133 +7. Disclaimer of Warranty.
  134 +
  135 +Unless required by applicable law or agreed to in writing, Licensor provides the
  136 +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
  137 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
  138 +including, without limitation, any warranties or conditions of TITLE,
  139 +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
  140 +solely responsible for determining the appropriateness of using or
  141 +redistributing the Work and assume any risks associated with Your exercise of
  142 +permissions under this License.
  143 +
  144 +8. Limitation of Liability.
  145 +
  146 +In no event and under no legal theory, whether in tort (including negligence),
  147 +contract, or otherwise, unless required by applicable law (such as deliberate
  148 +and grossly negligent acts) or agreed to in writing, shall any Contributor be
  149 +liable to You for damages, including any direct, indirect, special, incidental,
  150 +or consequential damages of any character arising as a result of this License or
  151 +out of the use or inability to use the Work (including but not limited to
  152 +damages for loss of goodwill, work stoppage, computer failure or malfunction, or
  153 +any and all other commercial damages or losses), even if such Contributor has
  154 +been advised of the possibility of such damages.
  155 +
  156 +9. Accepting Warranty or Additional Liability.
  157 +
  158 +While redistributing the Work or Derivative Works thereof, You may choose to
  159 +offer, and charge a fee for, acceptance of support, warranty, indemnity, or
  160 +other liability obligations and/or rights consistent with this License. However,
  161 +in accepting such obligations, You may act only on Your own behalf and on Your
  162 +sole responsibility, not on behalf of any other Contributor, and only if You
  163 +agree to indemnify, defend, and hold each Contributor harmless for any liability
  164 +incurred by, or claims asserted against, such Contributor by reason of your
  165 +accepting any such warranty or additional liability.
  166 +
  167 +END OF TERMS AND CONDITIONS
  168 +
  169 +APPENDIX: How to apply the Apache License to your work
  170 +
  171 +To apply the Apache License to your work, attach the following boilerplate
  172 +notice, with the fields enclosed by brackets "[]" replaced with your own
  173 +identifying information. (Don't include the brackets!) The text should be
  174 +enclosed in the appropriate comment syntax for the file format. We also
  175 +recommend that a file or class name and description of purpose be included on
  176 +the same "printed page" as the copyright notice for easier identification within
  177 +third-party archives.
  178 +
  179 + Copyright [yyyy] [name of copyright owner]
  180 +
  181 + Licensed under the Apache License, Version 2.0 (the "License");
  182 + you may not use this file except in compliance with the License.
  183 + You may obtain a copy of the License at
  184 +
  185 + http://www.apache.org/licenses/LICENSE-2.0
  186 +
  187 + Unless required by applicable law or agreed to in writing, software
  188 + distributed under the License is distributed on an "AS IS" BASIS,
  189 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  190 + See the License for the specific language governing permissions and
  191 + limitations under the License.
... ...
  1 +
  2 +# LTS用户文档
  3 +
  4 +LTS(light-task-scheduler)主要用于解决分布式任务调度问题,支持实时任务,定时任务和Cron任务。有较好的伸缩性,扩展性,健壮稳定性而被多家公司使用,同时也希望开源爱好者一起贡献。
  5 +
  6 +## ---> 底部有招人帖
  7 +
  8 +## 项目地址
  9 +github地址:
  10 +[https://github.com/ltsopensource/light-task-scheduler](https://github.com/ltsopensource/light-task-scheduler)
  11 +
  12 +oschina地址:
  13 +[http://git.oschina.net/hugui/light-task-scheduler](http://git.oschina.net/hugui/light-task-scheduler)
  14 +
  15 +例子:
  16 +[https://github.com/ltsopensource/lts-examples](https://github.com/ltsopensource/lts-examples)
  17 +
  18 +文档地址(正在更新中,后面以这个为准):
  19 +[https://www.gitbook.com/book/qq254963746/lts/details](https://www.gitbook.com/book/qq254963746/lts/details)
  20 +
  21 +这两个地址都会同步更新。感兴趣,请加QQ群:109500214 (加群密码: hello world)一起探讨、完善。越多人支持,就越有动力去更新,喜欢记得右上角star哈。
  22 +
  23 +## 1.7.2-SNAPSHOT(master)变更主要点
  24 +1. 优化JobContext中的BizLogger,由原来的去掉了threadlocal,解决taskTracker多线程的问题, 去掉LtsLoggerFactory.getLogger()用法
  25 +
  26 +## 框架概况
  27 +LTS 有主要有以下四种节点:
  28 +
  29 +* JobClient:主要负责提交任务, 并接收任务执行反馈结果。
  30 +* JobTracker:负责接收并分配任务,任务调度。
  31 +* TaskTracker:负责执行任务,执行完反馈给JobTracker。
  32 +* LTS-Admin:(管理后台)主要负责节点管理,任务队列管理,监控管理等。
  33 +
  34 +其中JobClient,JobTracker,TaskTracker节点都是`无状态`的。
  35 +可以部署多个并动态的进行删减,来实现负载均衡,实现更大的负载量, 并且框架采用FailStore策略使LTS具有很好的容错能力。
  36 +
  37 +LTS注册中心提供多种实现(Zookeeper,redis等),注册中心进行节点信息暴露,master选举。(Mongo or Mysql)存储任务队列和任务执行日志, netty or mina做底层通信, 并提供多种序列化方式fastjson, hessian2, java等。
  38 +
  39 +LTS支持任务类型:
  40 +
  41 +* 实时任务:提交了之后立即就要执行的任务。
  42 +* 定时任务:在指定时间点执行的任务,譬如 今天3点执行(单次)。
  43 +* Cron任务:CronExpression,和quartz类似(但是不是使用quartz实现的)譬如 0 0/1 * * * ?
  44 +
  45 +支持动态修改任务参数,任务执行时间等设置,支持后台动态添加任务,支持Cron任务暂停,支持手动停止正在执行的任务(有条件),支持任务的监控统计,支持各个节点的任务执行监控,JVM监控等等.
  46 +
  47 +## 架构图
  48 +
  49 +![LTS architecture](http://git.oschina.net/hugui/light-task-scheduler/raw/master/docs/LTS_architecture.png?dir=0&filepath=docs%2FLTS_architecture.png&oid=262a5234534e2d9fa8862f3e632c5551ebd95e21&sha=d01be5d59e8d768f49bbdc66c8334c37af8f7af5)
  50 +
  51 +## 概念说明
  52 +
  53 +### 节点组
  54 +1. 英文名称 NodeGroup,一个节点组等同于一个小的集群,同一个节点组中的各个节点是对等的,等效的,对外提供相同的服务。
  55 +2. 每个节点组中都有一个master节点,这个master节点是由LTS动态选出来的,当一个master节点挂掉之后,LTS会立马选出另外一个master节点,框架提供API监听接口给用户。
  56 +
  57 +### FailStore
  58 +1. 顾名思义,这个主要是用于失败了存储的,主要用于节点容错,当远程数据交互失败之后,存储在本地,等待远程通信恢复的时候,再将数据提交。
  59 +2. FailStore主要用户JobClient的任务提交,TaskTracker的任务反馈,TaskTracker的业务日志传输的场景下。
  60 +3. FailStore目前提供几种实现:leveldb,rocksdb,berkeleydb,mapdb,ltsdb,用于可以自由选择使用哪种,用户也可以采用SPI扩展使用自己的实现。
  61 +
  62 +
  63 +## 流程图
  64 +下图是一个标准的实时任务执行流程。
  65 +
  66 +![LTS progress](http://git.oschina.net/hugui/light-task-scheduler/raw/master/docs/LTS_progress.png?dir=0&filepath=docs%2FLTS_progress.png&oid=22f60a83b51b26bac8dabbb5053ec9913cefc45c&sha=774aa73d186470aedbb8f4da3c04a86a6022be05)
  67 +
  68 +## LTS-Admin新版界面预览
  69 +
  70 +![LTS Admin](http://git.oschina.net/hugui/light-task-scheduler/raw/master/docs/LTS-Admin/LTS-Admin-cron-job-queue.png?dir=0&filepath=docs%2FLTS-Admin%2FLTS-Admin-cron-job-queue.png&oid=aecaf01bca5270a53b144891baaa3d7e56d47706&sha=a4fd9f31df9e1fc6d389a16bdc8d1964bb854766)
  71 +目前后台带有由[ztajy](https://github.com/ztajy)提供的一个简易的认证功能. 用户名密码在auth.cfg中,用户自行修改.
  72 +
  73 +## 特性
  74 +### 1、Spring支持
  75 +LTS可以完全不用Spring框架,但是考虑到很用用户项目中都是用了Spring框架,所以LTS也提供了对Spring的支持,包括Xml和注解,引入`lts-spring.jar`即可。
  76 +### 2、业务日志记录器
  77 +在TaskTracker端提供了业务日志记录器,供应用程序使用,通过这个业务日志器,可以将业务日志提交到JobTracker,这些业务日志可以通过任务ID串联起来,可以在LTS-Admin中实时查看任务的执行进度。
  78 +### 3、SPI扩展支持
  79 +SPI扩展可以达到零侵入,只需要实现相应的接口,并实现即可被LTS使用,目前开放出来的扩展接口有
  80 +
  81 +1. 对任务队列的扩展,用户可以不选择使用mysql或者mongo作为队列存储,也可以自己实现。
  82 +2. 对业务日志记录器的扩展,目前主要支持console,mysql,mongo,用户也可以通过扩展选择往其他地方输送日志。
  83 +
  84 +### 4、故障转移
  85 +当正在执行任务的TaskTracker宕机之后,JobTracker会立马将分配在宕机的TaskTracker的所有任务再分配给其他正常的TaskTracker节点执行。
  86 +### 5、节点监控
  87 +可以对JobTracker,TaskTracker节点进行资源监控,任务监控等,可以实时的在LTS-Admin管理后台查看,进而进行合理的资源调配。
  88 +### 6、多样化任务执行结果支持
  89 +LTS框架提供四种执行结果支持,`EXECUTE_SUCCESS`,`EXECUTE_FAILED`,`EXECUTE_LATER`,`EXECUTE_EXCEPTION`,并对每种结果采取相应的处理机制,譬如重试。
  90 +
  91 +* EXECUTE_SUCCESS: 执行成功,这种情况,直接反馈客户端(如果任务被设置了要反馈给客户端)。
  92 +* EXECUTE_FAILED:执行失败,这种情况,直接反馈给客户端,不进行重试。
  93 +* EXECUTE_LATER:稍后执行(需要重试),这种情况,不反馈客户端,重试策略采用1min,2min,3min的策略,默认最大重试次数为10次,用户可以通过参数设置修改这个重试次数。
  94 +* EXECUTE_EXCEPTION:执行异常, 这种情况也会重试(重试策略,同上)
  95 +
  96 +### 7、FailStore容错
  97 +采用FailStore机制来进行节点容错,Fail And Store,不会因为远程通信的不稳定性而影响当前应用的运行。具体FailStore说明,请参考概念说明中的FailStore说明。
  98 +
  99 +## 项目编译打包
  100 +项目主要采用maven进行构建,目前提供shell脚本的打包。
  101 +环境依赖:`Java(jdk1.6+)` `Maven`
  102 +
  103 +用户使用一般分为两种:
  104 +### 1、Maven构建
  105 +可以通过maven命令将lts的jar包上传到本地仓库中。在父pom.xml中添加相应的repository,并用deploy命令上传即可。具体引用方式可以参考lts中的例子即可。
  106 +### 2、直接Jar引用
  107 +需要将lts的各个模块打包成单独的jar包,并且将所有lts依赖包引入。具体引用哪些jar包可以参考lts中的例子即可。
  108 +
  109 +## JobTracker和LTS-Admin部署
  110 +提供`(cmd)windows`和`(shell)linux`两种版本脚本来进行编译和部署:
  111 +
  112 +1. 运行根目录下的`sh build.sh`或`build.cmd`脚本,会在`dist`目录下生成`lts-{version}-bin`文件夹
  113 +
  114 +2. 下面是其目录结构,其中bin目录主要是JobTracker和LTS-Admin的启动脚本。`jobtracker` 中是 JobTracker的配置文件和需要使用到的jar包,`lts-admin`是LTS-Admin相关的war包和配置文件。
  115 +lts-{version}-bin的文件结构
  116 +
  117 +```java
  118 +-- lts-${version}-bin
  119 + |-- bin
  120 + | |-- jobtracker.cmd
  121 + | |-- jobtracker.sh
  122 + | |-- lts-admin.cmd
  123 + | |-- lts-admin.sh
  124 + | |-- lts-monitor.cmd
  125 + | |-- lts-monitor.sh
  126 + | |-- tasktracker.sh
  127 + |-- conf
  128 + | |-- log4j.properties
  129 + | |-- lts-admin.cfg
  130 + | |-- lts-monitor.cfg
  131 + | |-- readme.txt
  132 + | |-- tasktracker.cfg
  133 + | |-- zoo
  134 + | |-- jobtracker.cfg
  135 + | |-- log4j.properties
  136 + | |-- lts-monitor.cfg
  137 + |-- lib
  138 + | |-- *.jar
  139 + |-- war
  140 + |-- jetty
  141 + | |-- lib
  142 + | |-- *.jar
  143 + |-- lts-admin.war
  144 +
  145 +```
  146 +
  147 +3. JobTracker启动。如果你想启动一个节点,直接修改下`conf/zoo`下的配置文件,然后运行 `sh jobtracker.sh zoo start`即可,如果你想启动两个JobTracker节点,那么你需要拷贝一份zoo,譬如命名为`zoo2`,修改下`zoo2`下的配置文件,然后运行`sh jobtracker.sh zoo2 start`即可。logs文件夹下生成`jobtracker-zoo.out`日志。
  148 +4. LTS-Admin启动.修改`conf/lts-monitor.cfg`和`conf/lts-admin.cfg`下的配置,然后运行`bin`下的`sh lts-admin.sh`或`lts-admin.cmd`脚本即可。logs文件夹下会生成`lts-admin.out`日志,启动成功在日志中会打印出访问地址,用户可以通过这个访问地址访问了。
  149 +
  150 +## JobClient(部署)使用
  151 +需要引入lts的jar包有`lts-jobclient-{version}.jar`,`lts-core-{version}.jar` 及其它第三方依赖jar。
  152 +### API方式启动
  153 +```java
  154 +JobClient jobClient = new RetryJobClient();
  155 +jobClient.setNodeGroup("test_jobClient");
  156 +jobClient.setClusterName("test_cluster");
  157 +jobClient.setRegistryAddress("zookeeper://127.0.0.1:2181");
  158 +jobClient.start();
  159 +
  160 +// 提交任务
  161 +Job job = new Job();
  162 +job.setTaskId("3213213123");
  163 +job.setParam("shopId", "11111");
  164 +job.setTaskTrackerNodeGroup("test_trade_TaskTracker");
  165 +// job.setCronExpression("0 0/1 * * * ?"); // 支持 cronExpression表达式
  166 +// job.setTriggerTime(new Date()); // 支持指定时间执行
  167 +Response response = jobClient.submitJob(job);
  168 +```
  169 +
  170 +### Spring XML方式启动
  171 +```java
  172 +<bean id="jobClient" class="com.github.ltsopensource.spring.JobClientFactoryBean">
  173 + <property name="clusterName" value="test_cluster"/>
  174 + <property name="registryAddress" value="zookeeper://127.0.0.1:2181"/>
  175 + <property name="nodeGroup" value="test_jobClient"/>
  176 + <property name="masterChangeListeners">
  177 + <list>
  178 + <bean class="com.github.ltsopensource.example.support.MasterChangeListenerImpl"/>
  179 + </list>
  180 + </property>
  181 + <property name="jobFinishedHandler">
  182 + <bean class="com.github.ltsopensource.example.support.JobFinishedHandlerImpl"/>
  183 + </property>
  184 + <property name="configs">
  185 + <props>
  186 + <!-- 参数 -->
  187 + <prop key="job.fail.store">leveldb</prop>
  188 + </props>
  189 + </property>
  190 +</bean>
  191 +```
  192 +### Spring 全注解方式
  193 +```java
  194 +@Configuration
  195 +public class LTSSpringConfig {
  196 +
  197 + @Bean(name = "jobClient")
  198 + public JobClient getJobClient() throws Exception {
  199 + JobClientFactoryBean factoryBean = new JobClientFactoryBean();
  200 + factoryBean.setClusterName("test_cluster");
  201 + factoryBean.setRegistryAddress("zookeeper://127.0.0.1:2181");
  202 + factoryBean.setNodeGroup("test_jobClient");
  203 + factoryBean.setMasterChangeListeners(new MasterChangeListener[]{
  204 + new MasterChangeListenerImpl()
  205 + });
  206 + Properties configs = new Properties();
  207 + configs.setProperty("job.fail.store", "leveldb");
  208 + factoryBean.setConfigs(configs);
  209 + factoryBean.afterPropertiesSet();
  210 + return factoryBean.getObject();
  211 + }
  212 +}
  213 +```
  214 +## TaskTracker(部署使用)
  215 +需要引入lts的jar包有`lts-tasktracker-{version}.jar`,`lts-core-{version}.jar` 及其它第三方依赖jar。
  216 +### 定义自己的任务执行类
  217 +```java
  218 +public class MyJobRunner implements JobRunner {
  219 + @Override
  220 + public Result run(JobContext jobContext) throws Throwable {
  221 + try {
  222 + // TODO 业务逻辑
  223 + // 会发送到 LTS (JobTracker上)
  224 + jobContext.getBizLogger().info("测试,业务日志啊啊啊啊啊");
  225 +
  226 + } catch (Exception e) {
  227 + return new Result(Action.EXECUTE_FAILED, e.getMessage());
  228 + }
  229 + return new Result(Action.EXECUTE_SUCCESS, "执行成功了,哈哈");
  230 + }
  231 +}
  232 +```
  233 +### API方式启动
  234 +```java
  235 +TaskTracker taskTracker = new TaskTracker();
  236 +taskTracker.setJobRunnerClass(MyJobRunner.class);
  237 +taskTracker.setRegistryAddress("zookeeper://127.0.0.1:2181");
  238 +taskTracker.setNodeGroup("test_trade_TaskTracker");
  239 +taskTracker.setClusterName("test_cluster");
  240 +taskTracker.setWorkThreads(20);
  241 +taskTracker.start();
  242 +```
  243 +### Spring XML方式启动
  244 +```java
  245 +<bean id="taskTracker" class="com.github.ltsopensource.spring.TaskTrackerAnnotationFactoryBean" init-method="start">
  246 + <property name="jobRunnerClass" value="com.github.ltsopensource.example.support.MyJobRunner"/>
  247 + <property name="bizLoggerLevel" value="INFO"/>
  248 + <property name="clusterName" value="test_cluster"/>
  249 + <property name="registryAddress" value="zookeeper://127.0.0.1:2181"/>
  250 + <property name="nodeGroup" value="test_trade_TaskTracker"/>
  251 + <property name="workThreads" value="20"/>
  252 + <property name="masterChangeListeners">
  253 + <list>
  254 + <bean class="com.github.ltsopensource.example.support.MasterChangeListenerImpl"/>
  255 + </list>
  256 + </property>
  257 + <property name="configs">
  258 + <props>
  259 + <prop key="job.fail.store">leveldb</prop>
  260 + </props>
  261 + </property>
  262 +</bean>
  263 +```
  264 +### Spring注解方式启动
  265 +```java
  266 +@Configuration
  267 +public class LTSSpringConfig implements ApplicationContextAware {
  268 + private ApplicationContext applicationContext;
  269 + @Override
  270 + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  271 + this.applicationContext = applicationContext;
  272 + }
  273 + @Bean(name = "taskTracker")
  274 + public TaskTracker getTaskTracker() throws Exception {
  275 + TaskTrackerAnnotationFactoryBean factoryBean = new TaskTrackerAnnotationFactoryBean();
  276 + factoryBean.setApplicationContext(applicationContext);
  277 + factoryBean.setClusterName("test_cluster");
  278 + factoryBean.setJobRunnerClass(MyJobRunner.class);
  279 + factoryBean.setNodeGroup("test_trade_TaskTracker");
  280 + factoryBean.setBizLoggerLevel("INFO");
  281 + factoryBean.setRegistryAddress("zookeeper://127.0.0.1:2181");
  282 + factoryBean.setMasterChangeListeners(new MasterChangeListener[]{
  283 + new MasterChangeListenerImpl()
  284 + });
  285 + factoryBean.setWorkThreads(20);
  286 + Properties configs = new Properties();
  287 + configs.setProperty("job.fail.store", "leveldb");
  288 + factoryBean.setConfigs(configs);
  289 +
  290 + factoryBean.afterPropertiesSet();
  291 +// factoryBean.start();
  292 + return factoryBean.getObject();
  293 + }
  294 +}
  295 +```
  296 +## 参数说明
  297 +[参数说明](https://qq254963746.gitbooks.io/lts/content/use/config-name.html)
  298 +
  299 +## 使用建议
  300 +一般在一个JVM中只需要一个JobClient实例即可,不要为每种任务都新建一个JobClient实例,这样会大大的浪费资源,因为一个JobClient可以提交多种任务。相同的一个JVM一般也尽量保持只有一个TaskTracker实例即可,多了就可能造成资源浪费。当遇到一个TaskTracker要运行多种任务的时候,请参考下面的 "一个TaskTracker执行多种任务"。
  301 +## 一个TaskTracker执行多种任务
  302 +有的时候,业务场景需要执行多种任务,有些人会问,是不是要每种任务类型都要一个TaskTracker去执行。我的答案是否定的,如果在一个JVM中,最好使用一个TaskTracker去运行多种任务,因为一个JVM中使用多个TaskTracker实例比较浪费资源(当然当你某种任务量比较多的时候,可以将这个任务单独使用一个TaskTracker节点来执行)。那么怎么才能实现一个TaskTracker执行多种任务呢。下面是我给出来的参考例子。
  303 +
  304 +```java
  305 +/**
  306 + * 总入口,在 taskTracker.setJobRunnerClass(JobRunnerDispatcher.class)
  307 + * JobClient 提交 任务时指定 Job 类型 job.setParam("type", "aType")
  308 + */
  309 +public class JobRunnerDispatcher implements JobRunner {
  310 +
  311 + private static final ConcurrentHashMap<String/*type*/, JobRunner>
  312 + JOB_RUNNER_MAP = new ConcurrentHashMap<String, JobRunner>();
  313 +
  314 + static {
  315 + JOB_RUNNER_MAP.put("aType", new JobRunnerA()); // 也可以从Spring中拿
  316 + JOB_RUNNER_MAP.put("bType", new JobRunnerB());
  317 + }
  318 +
  319 + @Override
  320 + public Result run(JobContext jobContext) throws Throwable {
  321 + Job job = jobContext.getJob();
  322 + String type = job.getParam("type");
  323 + return JOB_RUNNER_MAP.get(type).run(job);
  324 + }
  325 +}
  326 +
  327 +class JobRunnerA implements JobRunner {
  328 + @Override
  329 + public Result run(JobContext jobContext) throws Throwable {
  330 + // TODO A类型Job的逻辑
  331 + return null;
  332 + }
  333 +}
  334 +
  335 +class JobRunnerB implements JobRunner {
  336 + @Override
  337 + public Result run(JobContext jobContext) throws Throwable {
  338 + // TODO B类型Job的逻辑
  339 + return null;
  340 + }
  341 +}
  342 +```
  343 +## TaskTracker的JobRunner测试
  344 +一般在编写TaskTracker的时候,只需要测试JobRunner的实现逻辑是否正确,又不想启动LTS进行远程测试。为了方便测试,LTS提供了JobRunner的快捷测试方法。自己的测试类集成`com.github.ltsopensource.tasktracker.runner.JobRunnerTester`即可,并实现`initContext`和`newJobRunner`方法即可。如[lts-examples](https://github.com/ltsopensource/lts-examples)中的例子:
  345 +
  346 +```java
  347 +public class TestJobRunnerTester extends JobRunnerTester {
  348 +
  349 + public static void main(String[] args) throws Throwable {
  350 + // Mock Job 数据
  351 + Job job = new Job();
  352 + job.setTaskId("2313213");
  353 +
  354 + JobContext jobContext = new JobContext();
  355 + jobContext.setJob(job);
  356 +
  357 + JobExtInfo jobExtInfo = new JobExtInfo();
  358 + jobExtInfo.setRetry(false);
  359 +
  360 + jobContext.setJobExtInfo(jobExtInfo);
  361 +
  362 + // 运行测试
  363 + TestJobRunnerTester tester = new TestJobRunnerTester();
  364 + Result result = tester.run(jobContext);
  365 + System.out.println(JSON.toJSONString(result));
  366 + }
  367 +
  368 + @Override
  369 + protected void initContext() {
  370 + // TODO 初始化Spring容器
  371 + }
  372 +
  373 + @Override
  374 + protected JobRunner newJobRunner() {
  375 + return new TestJobRunner();
  376 + }
  377 +}
  378 +```
  379 +
  380 +## Spring Quartz Cron任务无缝接入
  381 +对于Quartz的Cron任务只需要在Spring配置中增加一下代码就可以接入LTS平台
  382 +
  383 +```xml
  384 +<bean class="com.github.ltsopensource.spring.quartz.QuartzLTSProxyBean">
  385 + <property name="clusterName" value="test_cluster"/>
  386 + <property name="registryAddress" value="zookeeper://127.0.0.1:2181"/>
  387 + <property name="nodeGroup" value="quartz_test_group"/>
  388 +</bean>
  389 +```
  390 +## Spring Boot 支持
  391 +
  392 +```java
  393 +@SpringBootApplication
  394 +@EnableJobTracker // 启动JobTracker
  395 +@EnableJobClient // 启动JobClient
  396 +@EnableTaskTracker // 启动TaskTracker
  397 +@EnableMonitor // 启动Monitor
  398 +public class Application {
  399 + public static void main(String[] args) {
  400 + SpringApplication.run(Application.class, args);
  401 + }
  402 +}
  403 +```
  404 +
  405 +剩下的就只是在application.properties中添加相应的配置就行了, 具体见lts-example中的`com.github.ltsopensource.examples.springboot`包下的例子
  406 +
  407 +
  408 +## 多网卡选择问题
  409 +当机器有内网两个网卡的时候,有时候,用户想让LTS的流量走外网网卡,那么需要在host中,把主机名称的映射地址改为外网网卡地址即可,内网同理。
  410 +
  411 +## 关于节点标识问题
  412 +如果在节点启动的时候设置节点标识,LTS会默认设置一个UUID为节点标识,可读性会比较差,但是能保证每个节点的唯一性,如果用户能自己保证节点标识的唯一性,可以通过 `setIdentity` 来设置,譬如如果每个节点都是部署在一台机器(一个虚拟机)上,那么可以将identity设置为主机名称
  413 +
  414 +## SPI扩展说明
  415 +支持JobLogger,JobQueue等等的SPI扩展
  416 +
  417 +## [和其它解决方案比较](https://qq254963746.gitbooks.io/lts/content/introduce/compareother.html)
  418 +
  419 +
  420 +## LTS-Admin使用jetty启动(默认),不定期挂掉解决方案
  421 +[issue#389](https://github.com/ltsopensource/light-task-scheduler/issues/389)
  422 +
  423 +
  424 +# 招人!!!
  425 +工作年限 三年以上
  426 +
  427 +学历要求 本科
  428 +
  429 +期望层级 P6(资深Java工程师)/P7(技术专家)
  430 +
  431 +岗位描述
  432 +
  433 +会员平台,负责阿里巴巴集团的用户体系,支持集团内各线业务线用户类需求,支持集团对外合作的用户通和业务通。
  434 +包括各个端的用户登录&授权、Session体系、注册、账户管理、账户安全等功能,底层的用户信息服务,会话和凭证管理等等,是集团最核心的产品线之一,每天承载千亿次调用量、峰值千万QPS、以及分布全球的混合云架构等等。
  435 +
  436 +作为软件工程师,你将会在我们的核心产品上工作,这些产品为我们的商业基础设施提供关键功能,
  437 +取决于你的兴趣和经验,你可以在如下的一个或多个领域工作:全球化,用户体验,数据安全,机器学习,系统高可用性等等。
  438 +
  439 +1. 独立完成中小型项目的系统分析、设计,并主导完成详细设计和编码的任务,确保项目的进度和质量;
  440 +2. 能够在团队中完成code review的任务,确保相关代码的有效性和正确性,并能够通过code review提供相关性能以及稳定性的建议;
  441 +3. 参与建设通用、灵活、智能的业务支撑平台,支撑上层多场景的复杂业务。
  442 +岗位要求
  443 +1. 扎实的java编程基础,熟悉常用的Java开源框架;
  444 +2. 具有基于数据库、缓存、分布式存储开发高性能、高可用数据应用的实际经验,熟练掌握LINUX操作系统;
  445 +3. 具备良好的识别和设计通用框架及模块的能力;
  446 +4. 热爱技术,工作认真、严谨,对系统质量有近乎苛刻的要求意识,善于沟通与团队协作;
  447 +5. 具备大型电子商务网站或金融行业核心系统开发、设计工作经验者优先;
  448 +6. 具备大数据处理、算法、机器学习类工作经验优先。
  449 +感兴趣,可以发简历到 hugui.hg@alibaba-inc.com 欢迎投递
... ...
  1 +@echo off
  2 +
  3 +start mvn clean install -DskipTests
  4 +echo "LTS: mvn clean install -DskipTests"
  5 +echo "LTS: After sub window finished, close it , and press any key to continue" & pause>nul
  6 +
  7 +set VERSION=1.7.2-SNAPSHOT
  8 +set BASE_HOME=%~dp0%
  9 +set DIST_BIN_DIR=lts-%VERSION%-bin
  10 +
  11 +md "%BASE_HOME%\dist"
  12 +md "%BASE_HOME%\dist\%DIST_BIN_DIR%"
  13 +
  14 +set LTS_Bin_Dir=%BASE_HOME%dist\%DIST_BIN_DIR%
  15 +
  16 +set Startup_Dir=%BASE_HOME%\lts-startup
  17 +cd %Startup_Dir%
  18 +start mvn clean assembly:assembly -DskipTests -Pdefault
  19 +echo "LTS: mvn clean assembly:assembly -DskipTests -Pdefault"
  20 +echo "LTS: After sub window finished, close it , and press any key to continue" & pause>nul
  21 +
  22 +xcopy /e /y "%Startup_Dir%\target\lts-bin\lts" "%LTS_Bin_Dir%"
  23 +cd ..\..\
  24 +
  25 +cd %Startup_Dir%
  26 +start mvn clean assembly:assembly -DskipTests -Plts-admin
  27 +echo "LTS: mvn clean assembly:assembly -DskipTests -Plts-admin"
  28 +echo "LTS: After sub window finished, close it , and press any key to continue" & pause>nul
  29 +
  30 +xcopy /e /y "%Startup_Dir%\target\lts-bin\lts\lib" "%LTS_Bin_Dir%\war\jetty\lib"
  31 +cd ..\..\
  32 +
  33 +xcopy /e /y "%BASE_HOME%\lts-admin\target\lts-admin-%VERSION%.war" "%LTS_Bin_Dir%\war\lts-admin.war"
  34 +cd ..\..\
... ...
  1 +#!/usr/bin/env bash
  2 +
  3 +VERSION="1.7.2-SNAPSHOT"
  4 +
  5 +LTS_BIN="${BASH_SOURCE-$0}"
  6 +LTS_BIN="$(dirname "${LTS_BIN}")"
  7 +LTS_Bin_Dir="$(cd "${LTS_BIN}"; pwd)"
  8 +
  9 +cd $LTS_Bin_Dir
  10 +
  11 +mvn clean install -U -DskipTests
  12 +
  13 +Dist_Bin_Dir="$LTS_Bin_Dir/dist/lts-$VERSION-bin"
  14 +mkdir -p $Dist_Bin_Dir
  15 +
  16 +Dist_Bin_Dir="$(cd "$(dirname "${Dist_Bin_Dir}/.")"; pwd)"
  17 +
  18 +mkdir -p $Dist_Bin_Dir
  19 +
  20 +# 打包
  21 +Startup_Dir="$LTS_Bin_Dir/lts-startup/"
  22 +cd $Startup_Dir
  23 +mvn clean assembly:assembly -DskipTests -Pdefault
  24 +
  25 +cp -rf $Startup_Dir/target/lts-bin/lts/* $Dist_Bin_Dir
  26 +
  27 +mkdir -p $Dist_Bin_Dir/war/jetty/lib
  28 +mvn clean assembly:assembly -DskipTests -Plts-admin
  29 +cp -rf $Startup_Dir/target/lts-bin/lts/lib $Dist_Bin_Dir/war/jetty
  30 +cp -rf $LTS_Bin_Dir/lts-admin/target/lts-admin-$VERSION.war $Dist_Bin_Dir/war/lts-admin.war
  31 +
  32 + cd $LTS_Bin_Dir/dist
  33 + zip -r lts-$VERSION-bin.zip lts-$VERSION-bin/*
  34 + rm -rf lts-$VERSION-bin
... ...
No preview for this file type
  1 +```java
  2 +/**
  3 + * 下面是给的参考示例,
  4 + * 在其他Spring Bean 中就直接可以使用注解 @Autowired 注入使用了
  5 + * 这里为了方便起见写在一起的,一般这三种节点是分开的,注意单独写
  6 + * @author Robert HG (254963746@qq.com) on 8/22/15.
  7 + */
  8 +@Configuration
  9 +public class LTSSpringConfig implements ApplicationContextAware {
  10 +
  11 + private ApplicationContext applicationContext;
  12 +
  13 + @Override
  14 + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  15 + this.applicationContext = applicationContext;
  16 + }
  17 +
  18 + @Bean(name = "jobClient")
  19 + public JobClient getJobClient() throws Exception {
  20 + JobClientFactoryBean factoryBean = new JobClientFactoryBean();
  21 + // TODO 设置一些配置 属性
  22 + factoryBean.afterPropertiesSet();
  23 + // factoryBean.start();
  24 + return factoryBean.getObject();
  25 + }
  26 +
  27 + @Bean(name = "jobTracker")
  28 + public JobTracker getJobTracker() throws Exception {
  29 + JobTrackerFactoryBean factoryBean = new JobTrackerFactoryBean();
  30 + // TODO 设置一些配置 属性
  31 + factoryBean.afterPropertiesSet();
  32 + // factoryBean.start();
  33 + return factoryBean.getObject();
  34 + }
  35 +
  36 + @Bean(name = "taskTracker")
  37 + public TaskTracker getTaskTracker() throws Exception {
  38 + TaskTrackerAnnotationFactoryBean factoryBean = new TaskTrackerAnnotationFactoryBean();
  39 + factoryBean.setApplicationContext(applicationContext);
  40 + // TODO 设置一些配置 属性
  41 + factoryBean.afterPropertiesSet();
  42 + // factoryBean.start();
  43 + return factoryBean.getObject();
  44 + }
  45 +}
  46 +```
... ...
No preview for this file type
  1 +# LTS用户文档
  2 +
  3 +LTS(light-task-scheduler)主要用于解决分布式任务调度问题,支持实时任务,定时任务和Cron任务。有较好的伸缩性,扩展性,健壮稳定性而被多家公司使用,同时也希望开源爱好者一起贡献。
  4 +
  5 +## 项目地址
  6 +github地址:
  7 +[https://github.com/ltsopensource/light-task-scheduler](https://github.com/ltsopensource/light-task-scheduler)
  8 +
  9 +oschina地址:
  10 +[http://git.oschina.net/hugui/light-task-scheduler](http://git.oschina.net/hugui/light-task-scheduler)
  11 +
  12 +这两个地址都会同步更新。感兴趣,请加QQ群:109500214 一起探讨、完善。越多人支持,就越有动力去更新,喜欢记得右上角star哈。
  13 +
  14 +## 框架概况
  15 +LTS 有主要有以下四种节点:
  16 +
  17 +* JobClient:主要负责提交任务, 并接收任务执行反馈结果。
  18 +* JobTracker:负责接收并分配任务,任务调度。
  19 +* TaskTracker:负责执行任务,执行完反馈给JobTracker。
  20 +* LTS-Admin:(管理后台)主要负责节点管理,任务队列管理,监控管理等。
  21 +
  22 +其中JobClinet,JobTracker,TaskTracker节点都是`无状态`的。
  23 +可以部署多个并动态的进行删减,来实现负载均衡,实现更大的负载量, 并且框架采用FailStore策略使LTS具有很好的容错能力。
  24 +
  25 +LTS注册中心提供多种实现(Zookeeper,redis等),注册中心进行节点信息暴露,master选举。(Mongo or Mysql)存储任务队列和任务执行日志, netty做底层通信。
  26 +
  27 +LTS支持任务类型:
  28 +
  29 +* 实时任务:提交了之后立即就要执行的任务。
  30 +* 定时任务:在指定时间点执行的任务,譬如 今天3点执行(单次)。
  31 +* Cron任务:CronExpression,和quartz类似(但是不是使用quartz实现的)譬如 0 0/1 * * * ?
  32 +
  33 +## 架构图
  34 +
  35 +![LTS architecture](http://git.oschina.net/hugui/light-task-scheduler/raw/master/docs/LTS_architecture.png?dir=0&filepath=docs%2FLTS_architecture.png&oid=1e5daa62b8d032daaa47eab4a84ab1d4c8962c33&sha=774aa73d186470aedbb8f4da3c04a86a6022be05)
  36 +
  37 +## 概念说明
  38 +
  39 +###节点组
  40 +1. 英文名称 NodeGroup,一个节点组等同于一个小的集群,同一个节点组中的各个节点是对等的,等效的,对外提供相同的服务。
  41 +2. 没个节点组中都有一个master节点,这个master节点是由LTS动态选出来的,当一个master节点挂掉之后,LTS会立马选出另外一个master节点,框架提供API监听接口给用户。
  42 +
  43 +###FailStore
  44 +1. 顾名思义,这个主要是用于失败了存储的,主要用于节点容错,当远程数据交互失败之后,存储在本地,等待远程通信恢复的时候,再将数据提交。
  45 +2. FailStore主要用户JobClient的任务提交,TaskTracker的任务反馈,TaskTracker的业务日志传输的场景下。
  46 +3. FailStore目前提供三种实现:leveldb,rocksdb,berkeleydb,用于可以自由选择使用哪种。
  47 +
  48 +
  49 +## 流程图
  50 +下图是一个标准的实时任务执行流程。
  51 +
  52 +![LTS progress](http://git.oschina.net/hugui/light-task-scheduler/raw/master/docs/LTS_progress.png?dir=0&filepath=docs%2FLTS_progress.png&oid=22f60a83b51b26bac8dabbb5053ec9913cefc45c&sha=774aa73d186470aedbb8f4da3c04a86a6022be05)
  53 +
  54 +##特性
  55 +###1、Spring支持
  56 +LTS可以完全不用Spring框架,但是考虑到很用用户项目中都是用了Spring框架,所以LTS也提供了对Spring的支持,包括Xml和注解,引入`lts-spring.jar`即可。
  57 +###2、业务日志记录器
  58 +在TaskTracker端提供了业务日志记录器,供应用程序使用,通过这个业务日志器,可以将业务日志提交到JobTracker,这些业务日志可以通过任务ID串联起来,可以在LTS-Admin中实时查看任务的执行进度。
  59 +###3、SPI扩展支持
  60 +SPI扩展可以达到零侵入,只需要实现相应的接口,并实现即可被LTS使用,目前开放出来的扩展接口有
  61 +
  62 +1. 对任务队列的扩展,用户可以不选择使用mysql或者mongo作为队列存储,也可以自己实现。
  63 +2. 对业务日志记录器的扩展,目前主要支持console,mysql,mongo,用户也可以通过扩展选择往其他地方输送日志。
  64 +
  65 +###4、故障转移
  66 +当正在执行任务的TaskTracker宕机之后,JobTracker会立马分配在宕机的TaskTracker的所有任务再分配给其他正常的TaskTracker节点执行。
  67 +###5、节点监控
  68 +可以对JobTracker,TaskTracker节点进行资源监控,任务监控等,可以实时的在LTS-Admin管理后台查看,进而进行合理的资源调配。
  69 +###6、多样化任务执行结果支持
  70 +LTS框架提供四种执行结果支持,`EXECUTE_SUCCESS`,`EXECUTE_FAILED`,`EXECUTE_LATER`,`EXECUTE_EXCEPTION`,并对每种结果采取相应的处理机制,譬如重试。
  71 +
  72 +* EXECUTE_SUCCESS: 执行成功,这种情况,直接反馈客户端(如果任务被设置了要反馈给客户端)。
  73 +* EXECUTE_FAILED:执行失败,这种情况,直接反馈给客户端,不进行重试。
  74 +* EXECUTE_LATER:稍后执行(需要重试),这种情况,不反馈客户端,重试策略采用1min,2min,3min的策略,默认最大重试次数为10次,用户可以通过参数设置修改这个重试次数。
  75 +* EXECUTE_EXCEPTION:执行异常, 这中情况也会重试(重试策略,同上)
  76 +
  77 +###7、FailStore容错
  78 +采用FailStore机制来进行节点容错,Fail And Store,不会因为远程通信的不稳定性而影响当前应用的运行。具体FailStore说明,请参考概念说明中的FailStore说明。
  79 +
  80 +##项目编译打包
  81 +项目主要采用maven进行构建,目前提供shell脚本的打包。
  82 +环境依赖:`Java(jdk1.7)` `Maven`
  83 +
  84 +用户使用一般分为两种:
  85 +###1、Maven构建
  86 +可以通过maven命令将lts的jar包上传到本地仓库中。在父pom.xml中添加相应的repository,并用deploy命令上传即可。具体引用方式可以参考lts中的例子即可。
  87 +###2、直接Jar引用
  88 +需要将lts的各个模块打包成单独的jar包,并且将所有lts依赖包引入。具体引用哪些jar包可以参考lts中的例子即可。
  89 +
  90 +##JobTracker和LTS-Admin部署
  91 +提供`(cmd)windows`和`(shell)linux`两种版本脚本来进行编译和部署:
  92 +
  93 +1、运行根目录下的`sh build.sh`或`build.cmd`脚本,会在`dist`目录下生成`lts-{version}-bin`文件夹
  94 +2、下面是其目录结构,其中bin目录主要是JobTracker和LTS-Admin的启动脚本。`jobtracker` 中是 JobTracker的配置文件和需要使用到的jar包,`lts-admin`是LTS-Admin相关的war包和配置文件。
  95 +lts-{version}-bin的文件结构
  96 +
  97 +```java
  98 +├── bin
  99 +│   ├── jobtracker.cmd
  100 +│   ├── jobtracker.sh
  101 +│   ├── lts-admin.cmd
  102 +│   └── lts-admin.sh
  103 +├── jobtracker
  104 +│   ├── conf
  105 +│   │   └── zoo
  106 +│   │   ├── jobtracker.cfg
  107 +│   │   └── log4j.properties
  108 +│   └── lib
  109 +│   └── *.jar
  110 +├── lts-admin
  111 +│   ├── conf
  112 +│   │   ├── log4j.properties
  113 +│   │   └── lts-admin.cfg
  114 +│   ├── lib
  115 +│   │   └── *.jar
  116 +│   └── lts-admin.war
  117 +└── tasktracker
  118 + ├── bin
  119 + │   └── tasktracker.sh
  120 + ├── conf
  121 + │   ├── log4j.properties
  122 + │   └── tasktracker.cfg
  123 + └── lib
  124 + └── *.jar
  125 +```
  126 +
  127 +3、JobTracker启动。如果你想启动一个节点,直接修改下`conf/zoo`下的配置文件,然后运行 `sh jobtracker.sh zoo start`即可,如果你想启动两个JobTracker节点,那么你需要拷贝一份zoo,譬如命名为`zoo2`,修改下`zoo2`下的配置文件,然后运行`sh jobtracker.sh zoo2 start`即可。logs文件夹下生成`jobtracker-zoo.out`日志。
  128 +4、LTS-Admin启动.修改`lts-admin/conf`下的配置,然后运行`bin`下的`sh lts-admin.sh`或`lts-admin.cmd`脚本即可。logs文件夹下会生成`lts-admin.out`日志,启动成功在日志中会打印出访问地址,用户可以通过这个访问地址访问了。
  129 +
  130 +##JobClient(部署)使用
  131 +需要引入lts的jar包有`lts-jobclient-{version}.jar`,`lts-core-{version}.jar` 及其它第三方依赖jar。
  132 +###API方式启动
  133 +```java
  134 +JobClient jobClient = new RetryJobClient();
  135 +jobClient.setNodeGroup("test_jobClient");
  136 +jobClient.setRegistryAddress("zookeeper://127.0.0.1:2181");
  137 +jobClient.start();
  138 +
  139 +// 提交任务
  140 +Job job = new Job();
  141 +job.setTaskId("3213213123");
  142 +job.setParam("shopId", "11111");
  143 +job.setTaskTrackerNodeGroup("test_trade_TaskTracker");
  144 +// job.setCronExpression("0 0/1 * * * ?"); // 支持 cronExpression表达式
  145 +// job.setTriggerTime(new Date()); // 支持指定时间执行
  146 +Response response = jobClient.submitJob(job);
  147 +```
  148 +
  149 +###Spring XML方式启动
  150 +```java
  151 +<bean id="jobClient" class="com.github.ltsopensource.spring.JobClientFactoryBean">
  152 + <property name="clusterName" value="test_cluster"/>
  153 + <property name="registryAddress" value="zookeeper://127.0.0.1:2181"/>
  154 + <property name="nodeGroup" value="test_jobClient"/>
  155 + <property name="masterChangeListeners">
  156 + <list>
  157 + <bean class="com.github.ltsopensource.example.support.MasterChangeListenerImpl"/>
  158 + </list>
  159 + </property>
  160 + <property name="jobFinishedHandler">
  161 + <bean class="com.github.ltsopensource.example.support.JobFinishedHandlerImpl"/>
  162 + </property>
  163 + <property name="configs">
  164 + <props>
  165 + <!-- 参数 -->
  166 + <prop key="job.fail.store">leveldb</prop>
  167 + </props>
  168 + </property>
  169 +</bean>
  170 +```
  171 +###Spring 全注解方式
  172 +```java
  173 +@Configuration
  174 +public class LTSSpringConfig {
  175 +
  176 + @Bean(name = "jobClient")
  177 + public JobClient getJobClient() throws Exception {
  178 + JobClientFactoryBean factoryBean = new JobClientFactoryBean();
  179 + factoryBean.setClusterName("test_cluster");
  180 + factoryBean.setRegistryAddress("zookeeper://127.0.0.1:2181");
  181 + factoryBean.setNodeGroup("test_jobClient");
  182 + factoryBean.setMasterChangeListeners(new MasterChangeListener[]{
  183 + new MasterChangeListenerImpl()
  184 + });
  185 + Properties configs = new Properties();
  186 + configs.setProperty("job.fail.store", "leveldb");
  187 + factoryBean.setConfigs(configs);
  188 + factoryBean.afterPropertiesSet();
  189 + return factoryBean.getObject();
  190 + }
  191 +}
  192 +```
  193 +##TaskTracker(部署使用)
  194 +需要引入lts的jar包有`lts-tasktracker-{version}.jar`,`lts-core-{version}.jar` 及其它第三方依赖jar。
  195 +###定义自己的任务执行类
  196 +```java
  197 +public class MyJobRunner implements JobRunner {
  198 + @Override
  199 + public Result run(JobContext jobContext) throws Throwable {
  200 + try {
  201 + BizLogger bizLogger = jobContext.getBizLogger();
  202 + // TODO 业务逻辑
  203 + // 会发送到 LTS (JobTracker上)
  204 + bizLogger.info("测试,业务日志啊啊啊啊啊");
  205 +
  206 + } catch (Exception e) {
  207 + return new Result(Action.EXECUTE_FAILED, e.getMessage());
  208 + }
  209 + return new Result(Action.EXECUTE_SUCCESS, "执行成功了,哈哈");
  210 + }
  211 +}
  212 +```
  213 +###API方式启动
  214 +```java
  215 +TaskTracker taskTracker = new TaskTracker();
  216 +taskTracker.setJobRunnerClass(MyJobRunner.class);
  217 +taskTracker.setRegistryAddress("zookeeper://127.0.0.1:2181");
  218 +taskTracker.setNodeGroup("test_trade_TaskTracker");
  219 +taskTracker.setWorkThreads(20);
  220 +taskTracker.start();
  221 +```
  222 +###Spring XML方式启动
  223 +```java
  224 +<bean id="taskTracker" class="com.github.ltsopensource.spring.TaskTrackerAnnotationFactoryBean" init-method="start">
  225 + <property name="jobRunnerClass" value="com.github.ltsopensource.example.support.MyJobRunner"/>
  226 + <property name="bizLoggerLevel" value="INFO"/>
  227 + <property name="clusterName" value="test_cluster"/>
  228 + <property name="registryAddress" value="zookeeper://127.0.0.1:2181"/>
  229 + <property name="nodeGroup" value="test_trade_TaskTracker"/>
  230 + <property name="workThreads" value="20"/>
  231 + <property name="masterChangeListeners">
  232 + <list>
  233 + <bean class="com.github.ltsopensource.example.support.MasterChangeListenerImpl"/>
  234 + </list>
  235 + </property>
  236 + <property name="configs">
  237 + <props>
  238 + <prop key="job.fail.store">leveldb</prop>
  239 + </props>
  240 + </property>
  241 +</bean>
  242 +```
  243 +###Spring注解方式启动
  244 +```java
  245 +@Configuration
  246 +public class LTSSpringConfig implements ApplicationContextAware {
  247 + private ApplicationContext applicationContext;
  248 + @Override
  249 + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  250 + this.applicationContext = applicationContext;
  251 + }
  252 + @Bean(name = "taskTracker")
  253 + public TaskTracker getTaskTracker() throws Exception {
  254 + TaskTrackerAnnotationFactoryBean factoryBean = new TaskTrackerAnnotationFactoryBean();
  255 + factoryBean.setApplicationContext(applicationContext);
  256 + factoryBean.setClusterName("test_cluster");
  257 + factoryBean.setJobRunnerClass(MyJobRunner.class);
  258 + factoryBean.setNodeGroup("test_trade_TaskTracker");
  259 + factoryBean.setBizLoggerLevel("INFO");
  260 + factoryBean.setRegistryAddress("zookeeper://127.0.0.1:2181");
  261 + factoryBean.setMasterChangeListeners(new MasterChangeListener[]{
  262 + new MasterChangeListenerImpl()
  263 + });
  264 + factoryBean.setWorkThreads(20);
  265 + Properties configs = new Properties();
  266 + configs.setProperty("job.fail.store", "leveldb");
  267 + factoryBean.setConfigs(configs);
  268 +
  269 + factoryBean.afterPropertiesSet();
  270 +// factoryBean.start();
  271 + return factoryBean.getObject();
  272 + }
  273 +}
  274 +```
  275 +##参数说明
  276 +
  277 +| 参数 | 是否必须 | 默认值 | 使用范围 | 设置方式|参数说明 |
  278 +|:------------- |:------------- |:---------------:|:---------------:| -------------:| -------------:|
  279 +|registryAddress|必须|无|JobClient,JobTracker,TaskTracker|setRegistryAddress("xxxx")|注册中心,可以选用zk或者redis,参考值: zookeeper://127.0.0.1:2181|
  280 +|clusterName|必须|无|JobClient,JobTracker,TaskTracker|setClusterName("xxxx")|集群名称,clusterName相同的所有节点才会组成整个LTS架构|
  281 +|listenPort|必须|35001|JobTracker|setListenPort(xxx)|JobTracker的远程监听端口|
  282 +|job.logger|必须|console|JobTracker|addConfig("job.logger","xxx")|LTS业务日志记录器,可选值console,mysql,mongo,或者自己实现SPI扩展|
  283 +|job.queue|必须|mongo|JobTracker|addConfig("job.queue", "xx")|LTS任务队列,可选值mongo,mysql,或者自己实现SPI扩展|
  284 +|jdbc.url|可选|无|JobTracker|addConfig("jdbc.url", "xxx")|mysql连接URL,当job.queue为mysql的时候起作用|
  285 +|jdbc.username|可选|无|JobTracker|addConfig("jdbc.username", "xxx")|mysql连接密码,当job.queue为mysql的时候起作用|
  286 +|jdbc.password|可选|无|JobTracker|addConfig("jdbc.password", "xxx")|mysql连接密码,当job.queue为mysql的时候起作用|
  287 +|mongo.addresses|可选|无|JobTracker|addConfig("mongo.addresses", "xxx")|mongo连接URL,当job.queue为mongo的时候起作用|
  288 +|mongo.database|可选|无|JobTracker|addConfig("mongo.database", "xxx")|mongo数据库名,当job.queue为mongo的时候起作用|
  289 +|zk.client|可选|zkclient|JobClient,JobTracker,TaskTracker|addConfig("zk.client", "xxx")|zookeeper客户端,可选值zkclient, curator|
  290 +|job.pull.frequency|可选|3|TaskTracker|addConfig("job.pull.frequency", "xx")|TaskTracker去向JobTracker Pull任务的频率,针对不同的场景可以做相应的调整,单位秒|
  291 +|job.max.retry.times|可选|10|JobTracker|addConfig("job.max.retry.times", "xx")|任务的最大重试次数|
  292 +|stop.working|可选|false|TaskTracker|addConfig("stop.working", "true")|主要用于当TaskTracker与JobTracker出现网络隔离的时候,超过一定时间隔离之后,TaskTracker自动停止当前正在运行的任务|
  293 +
  294 +
  295 +
  296 +##使用建议
  297 +一般在一个JVM中只需要一个JobClient实例即可,不要为每种任务都新建一个JobClient实例,这样会大大的浪费资源,因为一个JobClient可以提交多种任务。相同的一个JVM一般也尽量保持只有一个TaskTracker实例即可,多了就可能造成资源浪费。当遇到一个TaskTracker要运行多种任务的时候,请参考下面的 "一个TaskTracker执行多种任务"。
  298 +##一个TaskTracker执行多种任务
  299 +有的时候,业务场景需要执行多种任务,有些人会问,是不是要每种任务类型都要一个TaskTracker去执行。我的答案是否定的,如果在一个JVM中,最好使用一个TaskTracker去运行多种任务,因为一个JVM中使用多个TaskTracker实例比较浪费资源(当然当你某种任务量比较多的时候,可以将这个任务单独使用一个TaskTracker节点来执行)。那么怎么才能实现一个TaskTracker执行多种任务呢。下面是我给出来的参考例子。
  300 +
  301 +```java
  302 +/**
  303 + * 总入口,在 taskTracker.setJobRunnerClass(JobRunnerDispatcher.class)
  304 + * JobClient 提交 任务时指定 Job 类型 job.setParam("type", "aType")
  305 + */
  306 +public class JobRunnerDispatcher implements JobRunner {
  307 +
  308 + private static final ConcurrentHashMap<String/*type*/, JobRunner>
  309 + JOB_RUNNER_MAP = new ConcurrentHashMap<String, JobRunner>();
  310 +
  311 + static {
  312 + JOB_RUNNER_MAP.put("aType", new JobRunnerA()); // 也可以从Spring中拿
  313 + JOB_RUNNER_MAP.put("bType", new JobRunnerB());
  314 + }
  315 +
  316 + @Override
  317 + public Result run(Job job) throws Throwable {
  318 + String type = job.getParam("type");
  319 + return JOB_RUNNER_MAP.get(type).run(job);
  320 + }
  321 +}
  322 +
  323 +class JobRunnerA implements JobRunner {
  324 + @Override
  325 + public Result run(Job job) throws Throwable {
  326 + // TODO A类型Job的逻辑
  327 + return null;
  328 + }
  329 +}
  330 +
  331 +class JobRunnerB implements JobRunner {
  332 + @Override
  333 + public Result run(Job job) throws Throwable {
  334 + // TODO B类型Job的逻辑
  335 + return null;
  336 + }
  337 +}
  338 +```
  339 +##SPI扩展说明
  340 +###LTS-Logger扩展
  341 +1. 引入`lts-core-{version}.jar`
  342 +2. 实现`JobLogger`和`JobLoggerFactory`接口
  343 +3. 在 resources `META-INF/lts/com.github.ltsopensource.biz.logger.JobLoggerFactory`文件,文件内容为`xxx=com.github.ltsopensource.biz.logger.xxx.XxxJobLoggerFactory`
  344 +4. 使用自己的logger扩展,修改jobtracker参数配置 configs.job.logger=xxx。(如果你自己引入JobTracker jar包的方式的话,使用 `jobtracker.addConfig("job.logger", "xxx"))`
  345 +
  346 +###LTS-Queue扩展
  347 +实现方式和LTS-Logger扩展类似,具体参考`lts-queue-mysql`或`lts-queue-mongo`模块的实现
  348 +##和其它解决方案比较
  349 +###和MQ比较
  350 +见docs/LTS业务场景说明.pdf
  351 +###和Quartz比较
  352 +见docs/LTS业务场景说明.pdf
  353 +
  354 +
  355 +
... ...
  1 +LTS 轻量级分布式任务调度框架(Light Task Scheduler)
  2 +-----------------
  3 +
  4 +###框架概况:
  5 + LTS是一个轻量级分布式任务调度框架。有三种角色, JobClient, JobTracker, TaskTracker。各个节点都是无状态的,可以部署多个,来实现负载均衡,实现更大的负载量, 并且框架具有很好的容错能力。
  6 + 采用多种注册中心(Zookeeper,redis等)进行节点信息暴露,master选举。(Mongo or Mysql)存储任务队列和任务执行日志, netty做底层通信。
  7 +* JobClient : 主要负责提交任务, 和 接收任务执行反馈结果。
  8 +* JobTracker : 负责接收并分配任务,任务调度。
  9 +* TaskTracker: 负责执行任务,执行完反馈给JobTracker。
  10 +
  11 +支持任务类型:
  12 +* 实时任务
  13 +* 也支持定时任务 (如:3天之后执行)
  14 +* CronExpression (如:0 0/1 * * * ?)
  15 +
  16 +感兴趣,请加QQ群:109500214 一起探讨、完善。越多人支持,就越有动力去更新,喜欢记得右上角star哈。
  17 +
  18 +github地址:[https://github.com/ltsopensource/light-task-scheduler](https://github.com/ltsopensource/light-task-scheduler)
  19 +
  20 +###架构图
  21 +![Aaron Swartz](http://git.oschina.net/hugui/light-task-scheduler/raw/master/docs/LTS_architecture.png?dir=0&filepath=docs%2FLTS_architecture.png&oid=1e5daa62b8d032daaa47eab4a84ab1d4c8962c33&sha=774aa73d186470aedbb8f4da3c04a86a6022be05)
  22 +####节点组:
  23 +* 1. 一个节点组等同于一个集群,同一个节点组中的各个节点是对等的,外界无论连接节点组中的任务一个节点都是可以的。
  24 +* 2. 每个节点组中都有一个master节点(master宕机,会自动选举出新的master节点),框架会提供接口API来监听master节点的变化,用户可以自己使用master节点做自己想做的事情。
  25 +* 3. JobClient和TaskTracker都可以存在多个节点组。譬如 JobClient 可以存在多个节点组。 譬如:JobClient 节点组为 ‘lts_WEB’ 中的一个节点提交提交一个 只有节点组为’lts_TRADE’的 TaskTracker 才能执行的任务。
  26 +* 4. (每个集群中)JobTacker只有一个节点组。
  27 +* 5. 多个JobClient节点组和多个TaskTracker节点组再加上一个JobTacker节点组, 组成一个大的集群。
  28 +
  29 +###工作流程:
  30 +* 1. JobClient 提交一个 任务 给 JobTracker, 这里我提供了两种客户端API, 一种是如果JobTracker 不存在或者提交失败,直接返回提交失败。另一种客户端是重试客户端, 如果提交失败,先存储到本地FailStore(可以使用NFS来达到同个节点组共享leveldb文件的目的,多线程访问,已经做了文件锁处理),返回给客户端提交成功的信息,待JobTracker可用的时候,再将任务提交。
  31 +* 2. JobTracker收到JobClient提交来的任务,将任务存入任务队列。JobTracker等待TaskTracker的Pull请求,然后将任务Push给TaskTracker去执行。
  32 +* 3. TaskTracker收到JobTracker分发来的任务之后,然后从线程池中拿到一个线程去执行。执行完毕之后,再反馈任务执行结果给JobTracker(成功or 失败[失败有失败错误信息]),如果发现JobTacker不可用,那么存储本地FailStore,等待JobTracker可用的时候再反馈。反馈结果的同时,询问JobTacker有没有新的任务要执行。
  33 +* 4. JobTacker收到TaskTracker节点的任务结果信息。根据任务信息决定要不要反馈给客户端。不需要反馈的直接删除,需要反馈的,直接反馈,反馈失败进入FeedbackQueue, 等待重新反馈。
  34 +* 5. JobClient收到任务执行结果,进行自己想要的逻辑处理。
  35 +* 详细请查看 [流程图](http://git.oschina.net/hugui/light-task-scheduler/raw/master/docs/LTS_progress.png?dir=0&filepath=docs%2FLTS_progress.png&oid=22f60a83b51b26bac8dabbb5053ec9913cefc45c&sha=774aa73d186470aedbb8f4da3c04a86a6022be05)
  36 +
  37 +###特性
  38 +* 负载均衡:
  39 + * JobClient和TaskTracker可是根据自己设置的负载均衡策略来请求JobTracker节点组中的一个节点。当连接上后将一直保持连接这个节点,保持连接通道,直到这个节点不可用,减少每次都重新连接一个节点带来的性能开销。
  40 +
  41 +* 健壮性:
  42 + * 当节点组中的一个节点当机之后,自动转到其他节点工作。当整个节点组当机之后,将会采用存储文件的方式,待节点组可用的时候进行重发。
  43 + * 当执行任务的TaskTracker节点当机之后,JobTracker会将这个TaskTracker上的未完成的任务(死任务),重新分配给节点组中其他节点执行。
  44 +
  45 +* 伸缩性:
  46 + * 因为各个节点都是无状态的,可以动态增加机器部署实例, 节点关注者会自动发现。
  47 +* 扩展性:
  48 + * 采用和dubbo一样的SPI扩展方式,可以实现任务队列扩展,日志记录器扩展等
  49 +
  50 +###日志记录
  51 +对于任务的分发,执行,还有用户通过 (BizLogger) 【JobContext#getBizLogger()】 输入的业务日志,LTS都有记录,用户可以在LTS Admin 后台界面查看某个任务的所有日志,可以实时查看这个任务的执行情况。
  52 +
  53 +###开发计划:
  54 +* WEB后台管理:性能统计分析,预警等
  55 +* 实现LTS的分布式队列存储
  56 +
  57 +###LTS Admin
  58 +后台首页 [http://localhost:8081/main.html](http://localhost:8081/main.html)
  59 +
  60 +![Aaron Swartz](http://git.oschina.net/hugui/light-task-scheduler/raw/master/docs/LTS_Admin.png?dir=0&filepath=docs%2FLTS_Admin.png&oid=a53f98823a0451a80a34467c7dfa2a01d568a9e2&sha=774aa73d186470aedbb8f4da3c04a86a6022be05)
  61 +###调用示例
  62 +下面提供的是最简单的配置方式。更多配置请查看 [lts-example](https://github.com/ltsopensource/light-task-scheduler/tree/master/lts-example/src/main/java/com/lts/example/api) 模块下的 API 调用方式例子.
  63 +
  64 +####JobTracker 端
  65 +```java
  66 + final JobTracker jobTracker = new JobTracker();
  67 + // 节点信息配置
  68 + jobTracker.setRegistryAddress("zookeeper://127.0.0.1:2181");
  69 + // 1. 任务队列用mongo
  70 + jobTracker.addConfig("job.queue", "mongo");
  71 + // mongo 配置
  72 + jobTracker.addConfig("mongo.addresses", "127.0.0.1:27017");
  73 + jobTracker.addConfig("mongo.database", "lts");
  74 + jobTracker.setOldDataHandler(new OldDataDeletePolicy());
  75 + // 启动节点
  76 + jobTracker.start();
  77 +```
  78 +
  79 +#### TaskTracker端
  80 +```java
  81 + TaskTracker taskTracker = new TaskTracker();
  82 + taskTracker.setJobRunnerClass(TestJobRunner.class);
  83 + taskTracker.setRegistryAddress("zookeeper://127.0.0.1:2181");
  84 + taskTracker.setNodeGroup("test_trade_TaskTracker");
  85 + taskTracker.setWorkThreads(20);
  86 + taskTracker.start();
  87 + // 任务执行类
  88 + public class TestJobRunner implements JobRunner {
  89 + @Override
  90 + public void run(Job job) throws Throwable {
  91 + System.out.println("我要执行"+ job);
  92 + System.out.println(job.getParam("shopId"));
  93 + // TODO 用户自己的业务逻辑, 应该保证幂等
  94 + try {
  95 + Thread.sleep(5*1000L);
  96 + } catch (InterruptedException e) {
  97 + e.printStackTrace();
  98 + }
  99 + }
  100 + }
  101 +```
  102 +
  103 +#### JobClient端
  104 +```java
  105 + JobClient jobClient = new RetryJobClient();
  106 + // final JobClient jobClient = new JobClient();
  107 + jobClient.setNodeGroup("test_jobClient");
  108 + jobClient.setRegistryAddress("zookeeper://127.0.0.1:2181");
  109 + jobClient.start();
  110 +
  111 + // 提交任务
  112 + Job job = new Job();
  113 + job.setTaskId("3213213123");
  114 + job.setParam("shopId", "11111");
  115 + job.setTaskTrackerNodeGroup("test_trade_TaskTracker");
  116 + // job.setCronExpression("0 0/1 * * * ?"); // 支持 cronExpression表达式
  117 + // job.setTriggerTime(new Date()); // 支持指定时间执行
  118 + Response response = jobClient.submitJob(job);
  119 +```
  120 +
  121 +##更新
  122 +1.5.5
  123 +1. 添加自动编译打包, LTS-Admin和JobTracker的shell脚本运行
  124 +
  125 +1.5.4.1
  126 +* 增加TaskTracker的监控数据,LTS-admin可以查看
  127 +
  128 +1.5.4:
  129 +* 1. 增加 lts-spring 工程对spring的支持 (见lts-example 中spring文件夹下的例子)
  130 +* 2. 对于TaskTracker 同时支持 JobRunner 中 注解注入bean 和xml注入的方式
\ No newline at end of file
... ...
  1 +# 查看远程地址
  2 +git remote -v
  3 +
  4 +# 添加新的远程地址
  5 +git remote add osc https://git.oschina.net/hugui/light-task-scheduler.git
  6 +git remote add github https://github.com/ltsopensource/light-task-scheduler.git
  7 +
  8 +# 推送develop的本地分支git, 所有分支的话使用--all
  9 +git push -u osc develop
  10 +git push -u github develop
  11 +
  12 +#推送所有的标签
  13 +git push osc --tags
  14 +git push github --tags
  15 +
  16 +#从远处拉取标签
  17 +git fetch osc --tags
  18 +git fetch github --tags
  19 +
  20 +# 查询远程标签
  21 +git ls-remote --tags osc
  22 +git ls-remote --tags github
  23 +
  24 +
  25 +
  26 +##
  27 +~/Data/Software/apache-maven-3.2.5/bin/mvn clean install -U -DskipTests
  28 +~/Data/Software/apache-maven-3.2.5/bin/mvn clean deploy -DskipTests
  29 +~/Data/Software/apache-maven-3.2.5/bin/mvn clean deploy -P release -Dgpg.passphrase=密码 -DskipTests
  30 +
... ...
  1 +
  2 +###包引入说明
  3 +
  4 +####1. JobTracker,JobClient,TaskTracker都需要引入的包
  5 +
  6 +#####1.1 lts-core
  7 +
  8 +```java
  9 +<dependency>
  10 + <groupId>com.github.ltsopensource</groupId>
  11 + <artifactId>lts-core</artifactId>
  12 + <version>${lts版本号}</version>
  13 +</dependency>
  14 +```
  15 +
  16 +#####1.2 zk客户端包
  17 +二选一, 通过 addConfig("zk.client", "可选值: curator, zkclient, lts") 设置, 如果用lts,可以不用引入包
  18 +
  19 +`zkclient`
  20 +
  21 +```java
  22 +<dependency>
  23 + <groupId>com.github.sgroschupf</groupId>
  24 + <artifactId>zkclient</artifactId>
  25 + <version>0.1</version>
  26 +</dependency>
  27 +```
  28 +
  29 +`curator`
  30 +
  31 +```java
  32 +<dependency>
  33 + <groupId>org.apache.curator</groupId>
  34 + <artifactId>curator-recipes</artifactId>
  35 + <version>2.9.1</version>
  36 +</dependency>
  37 +```
  38 +
  39 +`zookeeper包`
  40 +
  41 +```java
  42 +<dependency>
  43 + <groupId>org.apache.zookeeper</groupId>
  44 + <artifactId>zookeeper</artifactId>
  45 + <version>${zk.version}</version>
  46 + <exclusions>
  47 + <exclusion>
  48 + <groupId>org.jboss.netty</groupId>
  49 + <artifactId>netty</artifactId>
  50 + </exclusion>
  51 + <exclusion>
  52 + <groupId>log4j</groupId>
  53 + <artifactId>log4j</artifactId>
  54 + </exclusion>
  55 + </exclusions>
  56 +</dependency>
  57 +```
  58 +
  59 +#####1.3 通讯包
  60 +netty或者mina, 二选一, 通过 addConfig("lts.remoting", "可选值: netty, mina") 设置
  61 +
  62 +`netty`
  63 +
  64 +```java
  65 +<dependency>
  66 + <groupId>io.netty</groupId>
  67 + <artifactId>netty-all</artifactId>
  68 + <version>4.0.20.Final</version>
  69 +</dependency>
  70 +```
  71 +
  72 +`mina`
  73 +
  74 +```java
  75 +<dependency>
  76 + <groupId>org.apache.mina</groupId>
  77 + <artifactId>mina-core</artifactId>
  78 + <version>2.0.9</version>
  79 +</dependency>
  80 +```
  81 +
  82 +#####1.4 json包
  83 +fastjson或者jackson, 二选一, 通过 addConfig("lts.json", "可选值: fastjson, jackson") 设置
  84 +
  85 +`fastjson`
  86 +
  87 +```java
  88 +<dependency>
  89 + <groupId>com.alibaba</groupId>
  90 + <artifactId>fastjson</artifactId>
  91 + <version>1.2.7</version>
  92 +</dependency>
  93 +```
  94 +
  95 +`jackson`
  96 +
  97 +```java
  98 +<dependency>
  99 + <groupId>com.fasterxml.jackson.core</groupId>
  100 + <artifactId>jackson-core</artifactId>
  101 + <version>2.6.3</version>
  102 +</dependency>
  103 +<dependency>
  104 + <groupId>com.fasterxml.jackson.core</groupId>
  105 + <artifactId>jackson-databind</artifactId>
  106 + <version>2.6.3</version>
  107 +</dependency>
  108 +```
  109 +
  110 +#####1.5 日志包
  111 +可以选用 slf4j, jcl, log4j, 或者使用jdk原生logger
  112 +
  113 +LoggerFactory.setLoggerAdapter("可选值: slf4j, jcl, log4j, jdk"), 不手动设置, 默认按这个顺序加载
  114 +
  115 +
  116 +`log4j`
  117 +
  118 +```java
  119 +<dependency>
  120 + <groupId>log4j</groupId>
  121 + <artifactId>log4j</artifactId>
  122 + <version>1.2.16</version>
  123 +</dependency>
  124 +```
  125 +
  126 +`slf4j`
  127 +
  128 +```java
  129 +<dependency>
  130 + <groupId>org.slf4j</groupId>
  131 + <artifactId>slf4j-api</artifactId>
  132 + <version>1.7.5</version>
  133 +</dependency>
  134 +<dependency>
  135 + <groupId>org.slf4j</groupId>
  136 + <artifactId>slf4j-log4j12</artifactId>
  137 + <version>1.7.5</version>
  138 +</dependency>
  139 +```
  140 +
  141 +`jcl`
  142 +
  143 +```java
  144 +<dependency>
  145 + <groupId>commons-logging</groupId>
  146 + <artifactId>commons-logging-api</artifactId>
  147 + <version>1.1</version>
  148 +</dependency>
  149 +```
  150 +
  151 +#####1.6 如果需要spring的话,需要引入lts-spring及spring的相关包
  152 +
  153 +```java
  154 +<dependency>
  155 + <groupId>com.github.ltsopensource</groupId>
  156 + <artifactId>lts-spring</artifactId>
  157 + <version>${lts版本号}</version>
  158 +</dependency>
  159 +```
  160 +
  161 +####2. 对于JobTracker端
  162 +
  163 +#####2.1 必须引入的包:
  164 +
  165 +```java
  166 +<dependency>
  167 + <groupId>com.github.ltsopensource</groupId>
  168 + <artifactId>lts-jobtracker</artifactId>
  169 + <version>${lts版本号}</version>
  170 +</dependency>
  171 +```
  172 +
  173 +#####2.2 除了基础包之外还需要引入任务队列的包(可以是mongo或者mysql)
  174 +
  175 +`mysql`
  176 +
  177 +```java
  178 +<dependency>
  179 + <groupId>mysql</groupId>
  180 + <artifactId>mysql-connector-java</artifactId>
  181 + <version>5.1.26</version>
  182 +</dependency>
  183 +<dependency>
  184 + <groupId>com.alibaba</groupId>
  185 + <artifactId>druid</artifactId>
  186 + <version>1.0.14</version>
  187 +</dependency>
  188 +```
  189 +
  190 +`mongo`
  191 +
  192 +```java
  193 +<dependency>
  194 + <groupId>org.mongodb.morphia</groupId>
  195 + <artifactId>morphia</artifactId>
  196 + <version>1.0.0-rc1</version>
  197 +</dependency>
  198 +<dependency>
  199 + <groupId>org.mongodb</groupId>
  200 + <artifactId>mongo-java-driver</artifactId>
  201 + <version>3.0.2</version>
  202 +</dependency>
  203 +```
  204 +
  205 +####3. JobClient需要引入的包
  206 +
  207 +必须引入的包
  208 +
  209 +```java
  210 +<dependency>
  211 + <groupId>com.github.ltsopensource</groupId>
  212 + <artifactId>lts-jobclient</artifactId>
  213 + <version>${project.version}</version>
  214 +</dependency>
  215 +```
  216 +
  217 +FailStore存储包(四选一)
  218 +
  219 +通过 jobClient.addConfig("job.fail.store", "可选值: leveldb, mapdb, berkeleydb, rocksdb") 设置
  220 +
  221 +```java
  222 +<!--mapdb -->
  223 +<dependency>
  224 + <groupId>org.mapdb</groupId>
  225 + <artifactId>mapdb</artifactId>
  226 + <version>2.0-beta10</version>
  227 +</dependency>
  228 +<!-- leveldb -->
  229 +<dependency>
  230 + <groupId>org.fusesource.leveldbjni</groupId>
  231 + <artifactId>leveldbjni-all</artifactId>
  232 + <version>1.2.7<version>
  233 +</dependency>
  234 +<!-- berkeleydb -->
  235 +<dependency>
  236 + <groupId>com.sleepycat</groupId>
  237 + <artifactId>je</artifactId>
  238 + <version>5.0.73</version>
  239 +</dependency>
  240 +<!-- rocksdb -->
  241 +<dependency>
  242 + <groupId>org.rocksdb</groupId>
  243 + <artifactId>rocksdbjni</artifactId>
  244 + <version>3.10.1</version>
  245 +</dependency>
  246 +```
  247 +
  248 +####3. TaskTracker需要引入的包
  249 +
  250 +必须引入的包
  251 +
  252 +```java
  253 +<dependency>
  254 + <groupId>com.github.ltsopensource</groupId>
  255 + <artifactId>lts-tasktracker</artifactId>
  256 + <version>${project.version}</version>
  257 +</dependency>
  258 +```
  259 +
  260 +FailStore存储包(四选一)
  261 +
  262 +通过 taskTracker.addConfig("job.fail.store", "可选值: leveldb, mapdb, berkeleydb, rocksdb") 设置
  263 +
  264 +```java
  265 +<!--mapdb -->
  266 +<dependency>
  267 + <groupId>org.mapdb</groupId>
  268 + <artifactId>mapdb</artifactId>
  269 + <version>2.0-beta10</version>
  270 +</dependency>
  271 +<!-- leveldb -->
  272 +<dependency>
  273 + <groupId>org.fusesource.leveldbjni</groupId>
  274 + <artifactId>leveldbjni-all</artifactId>
  275 + <version>1.2.7<version>
  276 +</dependency>
  277 +<!-- berkeleydb -->
  278 +<dependency>
  279 + <groupId>com.sleepycat</groupId>
  280 + <artifactId>je</artifactId>
  281 + <version>5.0.73</version>
  282 +</dependency>
  283 +<!-- rocksdb -->
  284 +<dependency>
  285 + <groupId>org.rocksdb</groupId>
  286 + <artifactId>rocksdbjni</artifactId>
  287 + <version>3.10.1</version>
  288 +</dependency>
  289 +```
  290 +
... ...
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <artifactId>lts-parent</artifactId>
  7 + <groupId>com.github.ltsopensource</groupId>
  8 + <version>1.7.2-SNAPSHOT</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 + <packaging>war</packaging>
  12 + <artifactId>lts-admin</artifactId>
  13 +
  14 + <build>
  15 + <plugins>
  16 + <plugin>
  17 + <groupId>org.apache.tomcat.maven</groupId>
  18 + <artifactId>tomcat7-maven-plugin</artifactId>
  19 + <version>2.2</version>
  20 + <configuration>
  21 + <path>/</path>
  22 + <port>8081</port>
  23 + <server>tomcat</server>
  24 + <warFile>lts-admin.war</warFile>
  25 + <uriEncoding>utf-8</uriEncoding>
  26 + </configuration>
  27 + </plugin>
  28 + </plugins>
  29 + </build>
  30 +
  31 + <dependencies>
  32 + <dependency>
  33 + <groupId>com.github.ltsopensource</groupId>
  34 + <artifactId>lts-core</artifactId>
  35 + <version>${project.version}</version>
  36 + </dependency>
  37 + <dependency>
  38 + <groupId>com.github.ltsopensource</groupId>
  39 + <artifactId>lts-monitor</artifactId>
  40 + <version>${project.parent.version}</version>
  41 + </dependency>
  42 + <dependency>
  43 + <groupId>log4j</groupId>
  44 + <artifactId>log4j</artifactId>
  45 + </dependency>
  46 + <dependency>
  47 + <groupId>com.github.sgroschupf</groupId>
  48 + <artifactId>zkclient</artifactId>
  49 + </dependency>
  50 +
  51 + <dependency>
  52 + <groupId>org.aspectj</groupId>
  53 + <artifactId>aspectjrt</artifactId>
  54 + <version>${aspectj.version}</version>
  55 + </dependency>
  56 + <dependency>
  57 + <groupId>org.aspectj</groupId>
  58 + <artifactId>aspectjweaver</artifactId>
  59 + <version>${aspectj.version}</version>
  60 + </dependency>
  61 + <dependency>
  62 + <groupId>org.springframework</groupId>
  63 + <artifactId>spring-core</artifactId>
  64 + <version>${springframework.version}</version>
  65 + </dependency>
  66 + <dependency>
  67 + <groupId>org.springframework</groupId>
  68 + <artifactId>spring-web</artifactId>
  69 + <version>${springframework.version}</version>
  70 + </dependency>
  71 + <dependency>
  72 + <groupId>org.springframework</groupId>
  73 + <artifactId>spring-context-support</artifactId>
  74 + <version>${springframework.version}</version>
  75 + </dependency>
  76 + <dependency>
  77 + <groupId>org.springframework</groupId>
  78 + <artifactId>spring-webmvc</artifactId>
  79 + <version>${springframework.version}</version>
  80 + </dependency>
  81 + <dependency>
  82 + <groupId>org.springframework</groupId>
  83 + <artifactId>spring-orm</artifactId>
  84 + <version>${springframework.version}</version>
  85 + </dependency>
  86 +
  87 + <dependency>
  88 + <groupId>javax.servlet</groupId>
  89 + <artifactId>javax.servlet-api</artifactId>
  90 + <version>3.1.0</version>
  91 + <scope>provided</scope>
  92 + </dependency>
  93 +
  94 + <dependency>
  95 + <groupId>javax.servlet</groupId>
  96 + <artifactId>jstl</artifactId>
  97 + <version>1.2</version>
  98 + </dependency>
  99 +
  100 + <!-- Just the annotations; use this dependency if you want to attach annotations
  101 + to classes without connecting them to the code. -->
  102 + <dependency>
  103 + <groupId>com.fasterxml.jackson.core</groupId>
  104 + <artifactId>jackson-annotations</artifactId>
  105 + <version>${jackson.version}</version>
  106 + </dependency>
  107 +
  108 + <!-- databinding; ObjectMapper, JsonNode and related classes are here -->
  109 + <dependency>
  110 + <groupId>com.fasterxml.jackson.core</groupId>
  111 + <artifactId>jackson-databind</artifactId>
  112 + </dependency>
  113 +
  114 + <!-- smile (binary JSON). Other artifacts in this group do other formats. -->
  115 + <dependency>
  116 + <groupId>com.fasterxml.jackson.dataformat</groupId>
  117 + <artifactId>jackson-dataformat-smile</artifactId>
  118 + <version>${jackson.version}</version>
  119 + </dependency>
  120 + <!-- JAX-RS provider -->
  121 + <dependency>
  122 + <groupId>com.fasterxml.jackson.jaxrs</groupId>
  123 + <artifactId>jackson-jaxrs-json-provider</artifactId>
  124 + <version>${jackson.version}</version>
  125 + </dependency>
  126 + <!-- Support for JAX-B annotations as additional configuration -->
  127 + <dependency>
  128 + <groupId>com.fasterxml.jackson.module</groupId>
  129 + <artifactId>jackson-module-jaxb-annotations</artifactId>
  130 + <version>${jackson.version}</version>
  131 + </dependency>
  132 + <dependency>
  133 + <groupId>com.fasterxml.jackson.core</groupId>
  134 + <artifactId>jackson-core</artifactId>
  135 + <version>${jackson.version}</version>
  136 + </dependency>
  137 + <dependency>
  138 + <groupId>redis.clients</groupId>
  139 + <artifactId>jedis</artifactId>
  140 + </dependency>
  141 + <dependency>
  142 + <groupId>com.h2database</groupId>
  143 + <artifactId>h2</artifactId>
  144 + </dependency>
  145 + <dependency>
  146 + <groupId>org.apache.velocity</groupId>
  147 + <artifactId>velocity</artifactId>
  148 + <version>1.7</version>
  149 + </dependency>
  150 + <dependency>
  151 + <groupId>org.apache.velocity</groupId>
  152 + <artifactId>velocity-tools</artifactId>
  153 + <version>2.0</version>
  154 + <exclusions>
  155 + <exclusion>
  156 + <groupId>org.apache.struts</groupId>
  157 + <artifactId>struts-tiles</artifactId>
  158 + </exclusion>
  159 + <exclusion>
  160 + <groupId>org.apache.struts</groupId>
  161 + <artifactId>struts-taglib</artifactId>
  162 + </exclusion>
  163 + <exclusion>
  164 + <groupId>org.apache.struts</groupId>
  165 + <artifactId>struts-core</artifactId>
  166 + </exclusion>
  167 + <exclusion>
  168 + <groupId>commons-chain</groupId>
  169 + <artifactId>commons-chain</artifactId>
  170 + </exclusion>
  171 + <exclusion>
  172 + <groupId>commons-lang</groupId>
  173 + <artifactId>commons-lang</artifactId>
  174 + </exclusion>
  175 + <exclusion>
  176 + <groupId>commons-logging</groupId>
  177 + <artifactId>commons-logging</artifactId>
  178 + </exclusion>
  179 + <exclusion>
  180 + <groupId>commons-validator</groupId>
  181 + <artifactId>commons-validator</artifactId>
  182 + </exclusion>
  183 + <exclusion>
  184 + <groupId>oro</groupId>
  185 + <artifactId>oro</artifactId>
  186 + </exclusion>
  187 + <exclusion>
  188 + <groupId>sslext</groupId>
  189 + <artifactId>sslext</artifactId>
  190 + </exclusion>
  191 + <exclusion>
  192 + <groupId>dom4j</groupId>
  193 + <artifactId>dom4j</artifactId>
  194 + </exclusion>
  195 + </exclusions>
  196 + </dependency>
  197 + <dependency>
  198 + <groupId>com.alibaba</groupId>
  199 + <artifactId>fastjson</artifactId>
  200 + </dependency>
  201 + <dependency>
  202 + <groupId>mysql</groupId>
  203 + <artifactId>mysql-connector-java</artifactId>
  204 + </dependency>
  205 + <dependency>
  206 + <groupId>com.alibaba</groupId>
  207 + <artifactId>druid</artifactId>
  208 + </dependency>
  209 + <dependency>
  210 + <groupId>org.mongodb.morphia</groupId>
  211 + <artifactId>morphia</artifactId>
  212 + </dependency>
  213 + <dependency>
  214 + <groupId>org.mongodb</groupId>
  215 + <artifactId>mongo-java-driver</artifactId>
  216 + </dependency>
  217 + </dependencies>
  218 +</project>
... ...
  1 +package com.github.ltsopensource.admin.access;
  2 +
  3 +import com.github.ltsopensource.admin.access.face.*;
  4 +import com.github.ltsopensource.core.cluster.Config;
  5 +import com.github.ltsopensource.core.constant.ExtConfig;
  6 +import com.github.ltsopensource.core.spi.SPI;
  7 +
  8 +/**
  9 + * @author Robert HG (254963746@qq.com) on 3/9/16.
  10 + */
  11 +@SPI(key = ExtConfig.ACCESS_DB, dftValue = "mysql")
  12 +public interface BackendAccessFactory {
  13 +
  14 + BackendJobTrackerMAccess getJobTrackerMAccess(Config config);
  15 +
  16 + BackendJobClientMAccess getBackendJobClientMAccess(Config config);
  17 +
  18 + BackendJVMGCAccess getBackendJVMGCAccess(Config config);
  19 +
  20 + BackendJVMMemoryAccess getBackendJVMMemoryAccess(Config config);
  21 +
  22 + BackendJVMThreadAccess getBackendJVMThreadAccess(Config config);
  23 +
  24 + BackendNodeOnOfflineLogAccess getBackendNodeOnOfflineLogAccess(Config config);
  25 +
  26 + BackendTaskTrackerMAccess getBackendTaskTrackerMAccess(Config config);
  27 +}
... ...
  1 +package com.github.ltsopensource.admin.access;
  2 +
  3 +import com.github.ltsopensource.admin.access.domain.NodeOnOfflineLog;
  4 +import com.github.ltsopensource.admin.web.vo.NodeInfo;
  5 +import com.github.ltsopensource.core.cluster.Node;
  6 +import com.github.ltsopensource.core.cluster.NodeType;
  7 +import com.github.ltsopensource.monitor.access.domain.*;
  8 +import com.github.ltsopensource.store.jdbc.dbutils.ResultSetHandler;
  9 +
  10 +import java.sql.ResultSet;
  11 +import java.sql.SQLException;
  12 +import java.util.ArrayList;
  13 +import java.util.List;
  14 +
  15 +/**
  16 + * @author Robert HG (254963746@qq.com) on 3/9/16.
  17 + */
  18 +public class RshHandler {
  19 +
  20 + public static final ResultSetHandler<List<Node>> NODE_LIST_RSH = new ResultSetHandler<List<Node>>() {
  21 + @Override
  22 + public List<Node> handle(ResultSet rs) throws SQLException {
  23 + List<Node> nodes = new ArrayList<Node>();
  24 +
  25 + while (rs.next()) {
  26 + nodes.add(getNodeByRs(rs));
  27 + }
  28 + return nodes;
  29 + }
  30 + };
  31 +
  32 + public static final ResultSetHandler<Node> NODE_RSH = new ResultSetHandler<Node>() {
  33 + @Override
  34 + public Node handle(ResultSet rs) throws SQLException {
  35 + if (rs.next()) {
  36 + return getNodeByRs(rs);
  37 + }
  38 + return null;
  39 + }
  40 + };
  41 +
  42 + private static Node getNodeByRs(final ResultSet rs) throws SQLException {
  43 + Node node = new Node();
  44 + node.setIdentity(rs.getString("identity"));
  45 + node.setClusterName(rs.getString("cluster_name"));
  46 + node.setNodeType(NodeType.valueOf(rs.getString("node_type")));
  47 + node.setIp(rs.getString("ip"));
  48 + node.setPort(rs.getInt("port"));
  49 + node.setGroup(rs.getString("node_group"));
  50 + node.setCreateTime(rs.getLong("create_time"));
  51 + node.setThreads(rs.getInt("threads"));
  52 + node.setAvailable(rs.getInt("available") == 1);
  53 + node.setHostName(rs.getString("host_name"));
  54 + node.setHttpCmdPort(rs.getInt("http_cmd_port"));
  55 + return node;
  56 + }
  57 +
  58 + public static final ResultSetHandler<List<JobTrackerMDataPo>> JOB_TRACKER_SUM_M_DATA_RSH = new ResultSetHandler<List<JobTrackerMDataPo>>() {
  59 + @Override
  60 + public List<JobTrackerMDataPo> handle(ResultSet rs) throws SQLException {
  61 +
  62 + List<JobTrackerMDataPo> list = new ArrayList<JobTrackerMDataPo>();
  63 +
  64 + while (rs.next()) {
  65 + JobTrackerMDataPo po = new JobTrackerMDataPo();
  66 +// po.setId(rs.getString("id"));
  67 +// po.setGmtCreated(rs.getLong("gmt_created"));
  68 + po.setTimestamp(rs.getLong("timestamp"));
  69 +// po.setNodeType(NodeType.convert(rs.getString("node_type")));
  70 +// po.setNodeGroup(rs.getString("node_group"));
  71 +// po.setIdentity(rs.getString("identity"));
  72 + po.setReceiveJobNum(rs.getLong("receive_job_num"));
  73 + po.setPushJobNum(rs.getLong("push_job_num"));
  74 + po.setExeSuccessNum(rs.getLong("exe_success_num"));
  75 + po.setExeFailedNum(rs.getLong("exe_failed_num"));
  76 + po.setExeLaterNum(rs.getLong("exe_later_num"));
  77 + po.setExeExceptionNum(rs.getLong("exe_exception_num"));
  78 + po.setFixExecutingJobNum(rs.getLong("fix_executing_job_num"));
  79 + list.add(po);
  80 + }
  81 + return list;
  82 + }
  83 + };
  84 +
  85 + public static final ResultSetHandler<List<NodeOnOfflineLog>> NODE_ON_OFFLINE_LOG_LIST_RSH = new ResultSetHandler<List<NodeOnOfflineLog>>() {
  86 + @Override
  87 + public List<NodeOnOfflineLog> handle(ResultSet rs) throws SQLException {
  88 +
  89 + List<NodeOnOfflineLog> list = new ArrayList<NodeOnOfflineLog>();
  90 + while (rs.next()) {
  91 + NodeOnOfflineLog log = new NodeOnOfflineLog();
  92 + log.setLogTime(rs.getTimestamp("log_time"));
  93 + log.setEvent(rs.getString("event"));
  94 + log.setNodeType(NodeType.convert(rs.getString("node_type")));
  95 + log.setClusterName(rs.getString("cluster_name"));
  96 + log.setIp(rs.getString("ip"));
  97 + log.setPort(rs.getInt("port"));
  98 + log.setHostName(rs.getString("host_name"));
  99 + log.setGroup(rs.getString("group"));
  100 + log.setCreateTime(rs.getLong("create_time"));
  101 + log.setThreads(rs.getInt("threads"));
  102 + log.setIdentity(rs.getString("identity"));
  103 + log.setHttpCmdPort(rs.getInt("http_cmd_port"));
  104 + list.add(log);
  105 + }
  106 + return list;
  107 + }
  108 + };
  109 +
  110 + public static final ResultSetHandler<List<TaskTrackerMDataPo>> TASK_TRACKER_SUM_M_DATA_RSH = new ResultSetHandler<List<TaskTrackerMDataPo>>() {
  111 + @Override
  112 + public List<TaskTrackerMDataPo> handle(ResultSet rs) throws SQLException {
  113 + List<TaskTrackerMDataPo> list = new ArrayList<TaskTrackerMDataPo>();
  114 +
  115 + while (rs.next()) {
  116 + TaskTrackerMDataPo po = new TaskTrackerMDataPo();
  117 + po.setTimestamp(rs.getLong("timestamp"));
  118 +
  119 + po.setExeSuccessNum(rs.getLong("exe_success_num"));
  120 + po.setExeFailedNum(rs.getLong("exe_failed_num"));
  121 + po.setExeLaterNum(rs.getLong("exe_later_num"));
  122 + po.setExeExceptionNum(rs.getLong("exe_exception_num"));
  123 + po.setTotalRunningTime(rs.getLong("total_running_time"));
  124 +
  125 + list.add(po);
  126 + }
  127 + return list;
  128 + }
  129 + };
  130 +
  131 + public static final ResultSetHandler<List<JobClientMDataPo>> JOB_CLIENT_SUM_M_DATA_RSH = new ResultSetHandler<List<JobClientMDataPo>>() {
  132 + @Override
  133 + public List<JobClientMDataPo> handle(ResultSet rs) throws SQLException {
  134 + List<JobClientMDataPo> list = new ArrayList<JobClientMDataPo>();
  135 +
  136 + while (rs.next()) {
  137 + JobClientMDataPo po = new JobClientMDataPo();
  138 + po.setTimestamp(rs.getLong("timestamp"));
  139 +
  140 + po.setSubmitSuccessNum(rs.getLong("submit_success_num"));
  141 + po.setSubmitFailedNum(rs.getLong("submit_failed_num"));
  142 + po.setFailStoreNum(rs.getLong("fail_store_num"));
  143 + po.setSubmitFailStoreNum(rs.getLong("submit_fail_store_num"));
  144 + po.setHandleFeedbackNum(rs.getLong("handle_feedback_num"));
  145 + list.add(po);
  146 + }
  147 + return list;
  148 + }
  149 + };
  150 +
  151 + public static final ResultSetHandler<List<NodeInfo>> NODE_INFO_LIST_RSH = new ResultSetHandler<List<NodeInfo>>() {
  152 + @Override
  153 + public List<NodeInfo> handle(ResultSet rs) throws SQLException {
  154 + List<NodeInfo> list = new ArrayList<NodeInfo>();
  155 +
  156 + while (rs.next()) {
  157 + NodeInfo nodeInfo = new NodeInfo();
  158 + nodeInfo.setIdentity(rs.getString("identity"));
  159 + nodeInfo.setNodeGroup(rs.getString("node_group"));
  160 + list.add(nodeInfo);
  161 + }
  162 + return list;
  163 + }
  164 + };
  165 +
  166 + public static final ResultSetHandler<List<JVMMemoryDataPo>> JVM_MEMORY_SUM_M_DATA_RSH = new ResultSetHandler<List<JVMMemoryDataPo>>() {
  167 + @Override
  168 + public List<JVMMemoryDataPo> handle(ResultSet rs) throws SQLException {
  169 + List<JVMMemoryDataPo> list = new ArrayList<JVMMemoryDataPo>();
  170 +
  171 + while (rs.next()) {
  172 + JVMMemoryDataPo po = new JVMMemoryDataPo();
  173 + po.setTimestamp(rs.getLong("timestamp"));
  174 +
  175 + po.setHeapMemoryCommitted(rs.getLong("heap_memory_committed"));
  176 + po.setHeapMemoryInit(rs.getLong("heap_memory_init"));
  177 + po.setHeapMemoryMax(rs.getLong("heap_memory_max"));
  178 + po.setHeapMemoryUsed(rs.getLong("heap_memory_used"));
  179 + po.setNonHeapMemoryCommitted(rs.getLong("non_heap_memory_committed"));
  180 + po.setNonHeapMemoryInit(rs.getLong("non_heap_memory_init"));
  181 + po.setNonHeapMemoryMax(rs.getLong("non_heap_memory_max"));
  182 + po.setNonHeapMemoryUsed(rs.getLong("non_heap_memory_used"));
  183 + po.setPermGenCommitted(rs.getLong("perm_gen_committed"));
  184 + po.setPermGenInit(rs.getLong("perm_gen_init"));
  185 + po.setPermGenMax(rs.getLong("perm_gen_max"));
  186 + po.setPermGenUsed(rs.getLong("perm_gen_used"));
  187 + po.setOldGenCommitted(rs.getLong("old_gen_committed"));
  188 + po.setOldGenInit(rs.getLong("old_gen_init"));
  189 + po.setOldGenMax(rs.getLong("old_gen_max"));
  190 + po.setOldGenUsed(rs.getLong("old_gen_used"));
  191 + po.setEdenSpaceCommitted(rs.getLong("eden_space_committed"));
  192 + po.setEdenSpaceInit(rs.getLong("eden_space_init"));
  193 + po.setEdenSpaceMax(rs.getLong("eden_space_max"));
  194 + po.setEdenSpaceUsed(rs.getLong("eden_space_used"));
  195 + po.setSurvivorCommitted(rs.getLong("survivor_committed"));
  196 + po.setSurvivorInit(rs.getLong("survivor_init"));
  197 + po.setSurvivorMax(rs.getLong("survivor_max"));
  198 + po.setSurvivorUsed(rs.getLong("survivor_used"));
  199 +
  200 + list.add(po);
  201 + }
  202 + return list;
  203 + }
  204 + };
  205 +
  206 + public static final ResultSetHandler<List<JVMGCDataPo>> JVM_GC_SUM_M_DATA_RSH = new ResultSetHandler<List<JVMGCDataPo>>() {
  207 + @Override
  208 + public List<JVMGCDataPo> handle(ResultSet rs) throws SQLException {
  209 + List<JVMGCDataPo> list = new ArrayList<JVMGCDataPo>();
  210 +
  211 + while (rs.next()) {
  212 + JVMGCDataPo po = new JVMGCDataPo();
  213 + po.setTimestamp(rs.getLong("timestamp"));
  214 +
  215 + po.setYoungGCCollectionCount(rs.getLong("young_gc_collection_count"));
  216 + po.setYoungGCCollectionTime(rs.getLong("young_gc_collection_time"));
  217 + po.setFullGCCollectionCount(rs.getLong("full_gc_collection_count"));
  218 + po.setFullGCCollectionTime(rs.getLong("full_gc_collection_time"));
  219 + po.setSpanYoungGCCollectionCount(rs.getLong("span_young_gc_collection_count"));
  220 + po.setSpanYoungGCCollectionTime(rs.getLong("span_young_gc_collection_time"));
  221 + po.setSpanFullGCCollectionCount(rs.getLong("span_full_gc_collection_count"));
  222 + po.setSpanFullGCCollectionTime(rs.getLong("span_full_gc_collection_time"));
  223 +
  224 + list.add(po);
  225 + }
  226 + return list;
  227 + }
  228 + };
  229 +
  230 + public static final ResultSetHandler<List<JVMThreadDataPo>> JVM_THREAD_SUM_M_DATA_RSH = new ResultSetHandler<List<JVMThreadDataPo>>() {
  231 + @Override
  232 + public List<JVMThreadDataPo> handle(ResultSet rs) throws SQLException {
  233 + List<JVMThreadDataPo> list = new ArrayList<JVMThreadDataPo>();
  234 +
  235 + while (rs.next()) {
  236 + JVMThreadDataPo po = new JVMThreadDataPo();
  237 + po.setTimestamp(rs.getLong("timestamp"));
  238 +
  239 + po.setDaemonThreadCount(rs.getInt("daemon_thread_count"));
  240 + po.setThreadCount(rs.getInt("thread_count"));
  241 + po.setTotalStartedThreadCount(rs.getLong("total_started_thread_count"));
  242 + po.setDeadLockedThreadCount(rs.getInt("dead_locked_thread_count"));
  243 + po.setProcessCpuTimeRate(rs.getDouble("process_cpu_time_rate"));
  244 + list.add(po);
  245 + }
  246 + return list;
  247 + }
  248 + };
  249 +}
... ...
  1 +package com.github.ltsopensource.admin.access.domain;
  2 +
  3 +import com.github.ltsopensource.core.cluster.NodeType;
  4 +
  5 +import java.util.Date;
  6 +
  7 +/**
  8 + * 用来记录节点的上下线
  9 + *
  10 + * @author Robert HG (254963746@qq.com) on 9/26/15.
  11 + */
  12 +public class NodeOnOfflineLog {
  13 +
  14 + // 日志时间
  15 + private Date logTime;
  16 + // 取值 ONLINE(上线) OFFLINE(离线)
  17 + private String event;
  18 +
  19 + /**
  20 + * 下面属性来自
  21 + * {@link com.github.ltsopensource.core.cluster.Node}
  22 + */
  23 + private String clusterName;
  24 + private String ip;
  25 + private Integer port;
  26 + private String hostName;
  27 + private String group;
  28 + private Long createTime;
  29 + private Integer threads;
  30 + private String identity;
  31 + private NodeType nodeType;
  32 + private Integer httpCmdPort;
  33 +
  34 + public NodeType getNodeType() {
  35 + return nodeType;
  36 + }
  37 +
  38 + public void setNodeType(NodeType nodeType) {
  39 + this.nodeType = nodeType;
  40 + }
  41 +
  42 + public Date getLogTime() {
  43 + return logTime;
  44 + }
  45 +
  46 + public void setLogTime(Date logTime) {
  47 + this.logTime = logTime;
  48 + }
  49 +
  50 + public String getEvent() {
  51 + return event;
  52 + }
  53 +
  54 + public void setEvent(String event) {
  55 + this.event = event;
  56 + }
  57 +
  58 + public String getClusterName() {
  59 + return clusterName;
  60 + }
  61 +
  62 + public void setClusterName(String clusterName) {
  63 + this.clusterName = clusterName;
  64 + }
  65 +
  66 + public String getIp() {
  67 + return ip;
  68 + }
  69 +
  70 + public void setIp(String ip) {
  71 + this.ip = ip;
  72 + }
  73 +
  74 + public Integer getPort() {
  75 + return port;
  76 + }
  77 +
  78 + public void setPort(Integer port) {
  79 + this.port = port;
  80 + }
  81 +
  82 + public String getHostName() {
  83 + return hostName;
  84 + }
  85 +
  86 + public void setHostName(String hostName) {
  87 + this.hostName = hostName;
  88 + }
  89 +
  90 + public String getGroup() {
  91 + return group;
  92 + }
  93 +
  94 + public void setGroup(String group) {
  95 + this.group = group;
  96 + }
  97 +
  98 + public Long getCreateTime() {
  99 + return createTime;
  100 + }
  101 +
  102 + public void setCreateTime(Long createTime) {
  103 + this.createTime = createTime;
  104 + }
  105 +
  106 + public Integer getThreads() {
  107 + return threads;
  108 + }
  109 +
  110 + public void setThreads(Integer threads) {
  111 + this.threads = threads;
  112 + }
  113 +
  114 + public String getIdentity() {
  115 + return identity;
  116 + }
  117 +
  118 + public void setIdentity(String identity) {
  119 + this.identity = identity;
  120 + }
  121 +
  122 + public Integer getHttpCmdPort() {
  123 + return httpCmdPort;
  124 + }
  125 +
  126 + public void setHttpCmdPort(Integer httpCmdPort) {
  127 + this.httpCmdPort = httpCmdPort;
  128 + }
  129 +}
... ...
  1 +package com.github.ltsopensource.admin.access.face;
  2 +
  3 +import com.github.ltsopensource.admin.request.JvmDataReq;
  4 +import com.github.ltsopensource.admin.request.MDataPaginationReq;
  5 +import com.github.ltsopensource.monitor.access.domain.JVMGCDataPo;
  6 +import com.github.ltsopensource.monitor.access.face.JVMGCAccess;
  7 +
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * @author Robert HG (254963746@qq.com) on 9/28/15.
  12 + */
  13 +public interface BackendJVMGCAccess extends JVMGCAccess {
  14 +
  15 + void delete(JvmDataReq request);
  16 +
  17 + List<JVMGCDataPo> queryAvg(MDataPaginationReq request);
  18 +}
... ...
  1 +package com.github.ltsopensource.admin.access.face;
  2 +
  3 +import com.github.ltsopensource.admin.request.JvmDataReq;
  4 +import com.github.ltsopensource.admin.request.MDataPaginationReq;
  5 +import com.github.ltsopensource.monitor.access.domain.JVMMemoryDataPo;
  6 +import com.github.ltsopensource.monitor.access.face.JVMMemoryAccess;
  7 +
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * @author Robert HG (254963746@qq.com) on 9/28/15.
  12 + */
  13 +public interface BackendJVMMemoryAccess extends JVMMemoryAccess{
  14 +
  15 + void delete(JvmDataReq request);
  16 +
  17 + List<JVMMemoryDataPo> queryAvg(MDataPaginationReq request);
  18 +}
... ...
  1 +package com.github.ltsopensource.admin.access.face;
  2 +
  3 +import com.github.ltsopensource.admin.request.JvmDataReq;
  4 +import com.github.ltsopensource.admin.request.MDataPaginationReq;
  5 +import com.github.ltsopensource.monitor.access.domain.JVMThreadDataPo;
  6 +import com.github.ltsopensource.monitor.access.face.JVMThreadAccess;
  7 +
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * @author Robert HG (254963746@qq.com) on 9/28/15.
  12 + */
  13 +public interface BackendJVMThreadAccess extends JVMThreadAccess {
  14 +
  15 + void delete(JvmDataReq request);
  16 +
  17 + List<JVMThreadDataPo> queryAvg(MDataPaginationReq request);
  18 +
  19 +}
... ...
  1 +package com.github.ltsopensource.admin.access.face;
  2 +
  3 +import com.github.ltsopensource.admin.request.MDataPaginationReq;
  4 +import com.github.ltsopensource.admin.web.vo.NodeInfo;
  5 +import com.github.ltsopensource.monitor.access.domain.JobClientMDataPo;
  6 +import com.github.ltsopensource.monitor.access.face.JobClientMAccess;
  7 +
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * @author Robert HG (254963746@qq.com) on 3/12/16.
  12 + */
  13 +public interface BackendJobClientMAccess extends JobClientMAccess {
  14 +
  15 + void delete(MDataPaginationReq request);
  16 +
  17 + List<JobClientMDataPo> querySum(MDataPaginationReq request);
  18 +
  19 + List<NodeInfo> getJobClients();
  20 +}
... ...
  1 +package com.github.ltsopensource.admin.access.face;
  2 +
  3 +import com.github.ltsopensource.admin.request.MDataPaginationReq;
  4 +import com.github.ltsopensource.monitor.access.domain.JobTrackerMDataPo;
  5 +import com.github.ltsopensource.monitor.access.face.JobTrackerMAccess;
  6 +
  7 +import java.util.List;
  8 +
  9 +/**
  10 + * @author Robert HG (254963746@qq.com) on 9/22/15.
  11 + */
  12 +public interface BackendJobTrackerMAccess extends JobTrackerMAccess {
  13 +
  14 + List<JobTrackerMDataPo> querySum(MDataPaginationReq request);
  15 +
  16 + void delete(MDataPaginationReq request);
  17 +
  18 + List<String> getJobTrackers();
  19 +}
... ...
  1 +package com.github.ltsopensource.admin.access.face;
  2 +
  3 +import com.github.ltsopensource.admin.access.domain.NodeOnOfflineLog;
  4 +import com.github.ltsopensource.admin.request.NodeOnOfflineLogPaginationReq;
  5 +
  6 +import java.util.List;
  7 +
  8 +/**
  9 + * @author Robert HG (254963746@qq.com) on 9/26/15.
  10 + */
  11 +public interface BackendNodeOnOfflineLogAccess {
  12 +
  13 + void insert(List<NodeOnOfflineLog> nodeOnOfflineLogs);
  14 +
  15 + List<NodeOnOfflineLog> select(NodeOnOfflineLogPaginationReq request);
  16 +
  17 + Long count(NodeOnOfflineLogPaginationReq request);
  18 +
  19 + void delete(NodeOnOfflineLogPaginationReq request);
  20 +
  21 +}
... ...
  1 +package com.github.ltsopensource.admin.access.face;
  2 +
  3 +import com.github.ltsopensource.admin.request.MDataPaginationReq;
  4 +import com.github.ltsopensource.admin.web.vo.NodeInfo;
  5 +import com.github.ltsopensource.monitor.access.domain.TaskTrackerMDataPo;
  6 +import com.github.ltsopensource.monitor.access.face.TaskTrackerMAccess;
  7 +
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * @author Robert HG (254963746@qq.com) on 9/22/15.
  12 + */
  13 +public interface BackendTaskTrackerMAccess extends TaskTrackerMAccess{
  14 +
  15 + List<TaskTrackerMDataPo> querySum(MDataPaginationReq request);
  16 +
  17 + void delete(MDataPaginationReq request);
  18 +
  19 + List<NodeInfo> getTaskTrackers();
  20 +}
... ...
  1 +package com.github.ltsopensource.admin.access.memory;
  2 +
  3 +import com.github.ltsopensource.core.cluster.Config;
  4 +import com.github.ltsopensource.core.commons.file.FileUtils;
  5 +import com.github.ltsopensource.core.commons.utils.StringUtils;
  6 +import com.github.ltsopensource.core.constant.Constants;
  7 +import com.github.ltsopensource.core.exception.LtsRuntimeException;
  8 +import com.github.ltsopensource.store.jdbc.SqlTemplate;
  9 +import com.github.ltsopensource.store.jdbc.SqlTemplateFactory;
  10 +import com.github.ltsopensource.store.jdbc.exception.JdbcException;
  11 +
  12 +import java.io.IOException;
  13 +import java.io.InputStream;
  14 +
  15 +/**
  16 + * Memory-Only Databases , HSQLDB
  17 + *
  18 + * @author Robert HG (254963746@qq.com) on 6/6/15.
  19 + */
  20 +public abstract class MemoryAccess {
  21 +
  22 + private SqlTemplate sqlTemplate;
  23 +
  24 + public MemoryAccess() {
  25 + Config config = new Config();
  26 + config.setIdentity(StringUtils.generateUUID());
  27 + config.setParameter("jdbc.datasource.provider", "h2");
  28 + // see http://www.h2database.com/html/features.html#in_memory_databases
  29 + config.setParameter("jdbc.url", "jdbc:h2:mem:lts_admin;DB_CLOSE_DELAY=-1");
  30 + config.setParameter("jdbc.username", "lts");
  31 + config.setParameter("jdbc.password", "lts");
  32 + sqlTemplate = SqlTemplateFactory.create(config);
  33 + }
  34 +
  35 + protected SqlTemplate getSqlTemplate() {
  36 + return sqlTemplate;
  37 + }
  38 +
  39 + protected String readSqlFile(String path) {
  40 + InputStream is = this.getClass().getClassLoader().getResourceAsStream(path);
  41 + try {
  42 + return FileUtils.read(is, Constants.CHARSET);
  43 + } catch (IOException e) {
  44 + throw new LtsRuntimeException("Read sql file : [" + path + "] error ", e);
  45 + }
  46 + }
  47 +
  48 + protected void createTable(String sql) throws JdbcException {
  49 + try {
  50 + getSqlTemplate().createTable(sql);
  51 + } catch (Exception e) {
  52 + throw new JdbcException("Create table error, sql=" + sql, e);
  53 + }
  54 + }
  55 +}
... ...
  1 +package com.github.ltsopensource.admin.access.memory;
  2 +
  3 +import com.github.ltsopensource.admin.access.RshHandler;
  4 +import com.github.ltsopensource.admin.request.NodePaginationReq;
  5 +import com.github.ltsopensource.admin.response.PaginationRsp;
  6 +import com.github.ltsopensource.core.cluster.Node;
  7 +import com.github.ltsopensource.core.cluster.NodeType;
  8 +import com.github.ltsopensource.core.commons.utils.CharacterUtils;
  9 +import com.github.ltsopensource.core.commons.utils.CollectionUtils;
  10 +import com.github.ltsopensource.core.commons.utils.StringUtils;
  11 +import com.github.ltsopensource.core.logger.Logger;
  12 +import com.github.ltsopensource.core.logger.LoggerFactory;
  13 +import com.github.ltsopensource.store.jdbc.builder.*;
  14 +import com.github.ltsopensource.store.jdbc.dbutils.JdbcTypeUtils;
  15 +
  16 +import java.util.List;
  17 +
  18 +/**
  19 + * @author Robert HG (254963746@qq.com) on 6/6/15.
  20 + */
  21 +public class NodeMemCacheAccess extends MemoryAccess {
  22 +
  23 + private static final Logger LOGGER = LoggerFactory.getLogger(NodeMemCacheAccess.class);
  24 +
  25 + public NodeMemCacheAccess() {
  26 + createTable(readSqlFile("sql/h2/lts_node.sql"));
  27 + }
  28 +
  29 + private String getTableName() {
  30 + return "lts_node";
  31 + }
  32 +
  33 + public void addNode(List<Node> nodes) {
  34 + for (Node node : nodes) {
  35 + try {
  36 + NodePaginationReq request = new NodePaginationReq();
  37 + request.setIdentity(node.getIdentity());
  38 + List<Node> existNodes = search(request);
  39 + if (CollectionUtils.isNotEmpty(existNodes)) {
  40 + // 如果存在,那么先删除
  41 + removeNode(existNodes);
  42 + }
  43 +
  44 + new InsertSql(getSqlTemplate())
  45 + .insert(getTableName())
  46 + .columns("identity",
  47 + "available",
  48 + "cluster_name",
  49 + "node_type",
  50 + "ip",
  51 + "port",
  52 + "node_group",
  53 + "create_time",
  54 + "threads",
  55 + "host_name",
  56 + "http_cmd_port"
  57 + )
  58 + .values(node.getIdentity(),
  59 + node.isAvailable() ? 1 : 0,
  60 + node.getClusterName(),
  61 + node.getNodeType().name(),
  62 + node.getIp(),
  63 + node.getPort(),
  64 + node.getGroup(),
  65 + node.getCreateTime(),
  66 + node.getThreads(),
  67 + node.getHostName(),
  68 + node.getHttpCmdPort())
  69 + .doInsert();
  70 + } catch (Exception e) {
  71 + LOGGER.error("Insert {} error!", node, e);
  72 + }
  73 + }
  74 + }
  75 +
  76 + public void clear() {
  77 + new DeleteSql(getSqlTemplate())
  78 + .delete()
  79 + .from()
  80 + .table(getTableName())
  81 + .doDelete();
  82 + }
  83 +
  84 + public void removeNode(List<Node> nodes) {
  85 + for (Node node : nodes) {
  86 + try {
  87 + new DeleteSql(getSqlTemplate())
  88 + .delete()
  89 + .from()
  90 + .table(getTableName())
  91 + .where("identity = ?", node.getIdentity())
  92 + .doDelete();
  93 + } catch (Exception e) {
  94 + LOGGER.error("Delete {} error!", node, e);
  95 + }
  96 + }
  97 + }
  98 +
  99 + public Node getNodeByIdentity(String identity) {
  100 + return new SelectSql(getSqlTemplate())
  101 + .select()
  102 + .all()
  103 + .from()
  104 + .table(getTableName())
  105 + .where("identity = ?", identity)
  106 + .single(RshHandler.NODE_RSH);
  107 + }
  108 +
  109 + public List<Node> getNodeByNodeType(NodeType nodeType) {
  110 + NodePaginationReq nodePaginationReq = new NodePaginationReq();
  111 + nodePaginationReq.setNodeType(nodeType);
  112 + nodePaginationReq.setLimit(Integer.MAX_VALUE);
  113 + return search(nodePaginationReq);
  114 + }
  115 +
  116 + public List<Node> search(NodePaginationReq request) {
  117 +
  118 + SelectSql selectSql = new SelectSql(getSqlTemplate())
  119 + .select()
  120 + .all()
  121 + .from()
  122 + .table(getTableName())
  123 + .whereSql(buildWhereSql(request));
  124 + if (StringUtils.isNotEmpty(request.getField())) {
  125 + selectSql.orderBy()
  126 + .column(CharacterUtils.camelCase2Underscore(request.getField()), OrderByType.convert(request.getDirection()));
  127 + }
  128 + return selectSql.limit(request.getStart(), request.getLimit())
  129 + .list(RshHandler.NODE_LIST_RSH);
  130 + }
  131 +
  132 + private WhereSql buildWhereSql(NodePaginationReq request) {
  133 + return new WhereSql()
  134 + .andOnNotEmpty("identity = ?", request.getIdentity())
  135 + .andOnNotEmpty("node_group = ?", request.getNodeGroup())
  136 + .andOnNotNull("node_type = ?", request.getNodeType() == null ? null : request.getNodeType().name())
  137 + .andOnNotEmpty("ip = ?", request.getIp())
  138 + .andOnNotNull("available = ?", request.getAvailable())
  139 + .andBetween("create_time", JdbcTypeUtils.toTimestamp(request.getStartDate()), JdbcTypeUtils.toTimestamp(request.getEndDate()));
  140 + }
  141 +
  142 + public PaginationRsp<Node> pageSelect(NodePaginationReq request) {
  143 + PaginationRsp<Node> response = new PaginationRsp<Node>();
  144 +
  145 + Long results = new SelectSql(getSqlTemplate())
  146 + .select()
  147 + .columns("count(1)")
  148 + .from()
  149 + .table(getTableName())
  150 + .whereSql(buildWhereSql(request))
  151 + .single();
  152 + response.setResults(results.intValue());
  153 +
  154 + if (results > 0) {
  155 + List<Node> nodes = search(request);
  156 + response.setRows(nodes);
  157 + }
  158 + return response;
  159 + }
  160 +}
... ...
  1 +package com.github.ltsopensource.admin.access.mysql;
  2 +
  3 +import com.github.ltsopensource.admin.access.BackendAccessFactory;
  4 +import com.github.ltsopensource.admin.access.face.*;
  5 +import com.github.ltsopensource.core.cluster.Config;
  6 +
  7 +/**
  8 + * @author Robert HG (254963746@qq.com) on 3/9/16.
  9 + */
  10 +public class MysqlBackendAccessFactory implements BackendAccessFactory {
  11 + @Override
  12 + public BackendJobTrackerMAccess getJobTrackerMAccess(Config config) {
  13 + return new MysqlBackendJobTrackerMAccess(config);
  14 + }
  15 +
  16 + @Override
  17 + public BackendJobClientMAccess getBackendJobClientMAccess(Config config) {
  18 + return new MysqlBackendJobClientMAccess(config);
  19 + }
  20 +
  21 + @Override
  22 + public BackendJVMGCAccess getBackendJVMGCAccess(Config config) {
  23 + return new MysqlBackendJVMGCAccess(config);
  24 + }
  25 +
  26 + @Override
  27 + public BackendJVMMemoryAccess getBackendJVMMemoryAccess(Config config) {
  28 + return new MysqlBackendJVMMemoryAccess(config);
  29 + }
  30 +
  31 + @Override
  32 + public BackendJVMThreadAccess getBackendJVMThreadAccess(Config config) {
  33 + return new MysqlBackendJVMThreadAccess(config);
  34 + }
  35 +
  36 + @Override
  37 + public BackendNodeOnOfflineLogAccess getBackendNodeOnOfflineLogAccess(Config config) {
  38 + return new MysqlBackendNodeOnOfflineLogAccess(config);
  39 + }
  40 +
  41 + @Override
  42 + public BackendTaskTrackerMAccess getBackendTaskTrackerMAccess(Config config) {
  43 + return new MysqlBackendTaskTrackerMAccess(config);
  44 + }
  45 +}
... ...
  1 +package com.github.ltsopensource.admin.access.mysql;
  2 +
  3 +import com.github.ltsopensource.admin.access.RshHandler;
  4 +import com.github.ltsopensource.admin.access.face.BackendJVMGCAccess;
  5 +import com.github.ltsopensource.admin.request.JvmDataReq;
  6 +import com.github.ltsopensource.admin.request.MDataPaginationReq;
  7 +import com.github.ltsopensource.core.cluster.Config;
  8 +import com.github.ltsopensource.monitor.access.domain.JVMGCDataPo;
  9 +import com.github.ltsopensource.monitor.access.mysql.MysqlJVMGCAccess;
  10 +import com.github.ltsopensource.store.jdbc.builder.DeleteSql;
  11 +import com.github.ltsopensource.store.jdbc.builder.SelectSql;
  12 +import com.github.ltsopensource.store.jdbc.builder.WhereSql;
  13 +
  14 +import java.util.List;
  15 +
  16 +/**
  17 + * @author Robert HG (254963746@qq.com) on 3/10/16.
  18 + */
  19 +public class MysqlBackendJVMGCAccess extends MysqlJVMGCAccess implements BackendJVMGCAccess {
  20 +
  21 + public MysqlBackendJVMGCAccess(Config config) {
  22 + super(config);
  23 + }
  24 +
  25 + @Override
  26 + public void delete(JvmDataReq request) {
  27 + new DeleteSql(getSqlTemplate())
  28 + .delete()
  29 + .from()
  30 + .table(getTableName())
  31 + .whereSql(buildWhereSql(request))
  32 + .doDelete();
  33 + }
  34 +
  35 + @Override
  36 + public List<JVMGCDataPo> queryAvg(MDataPaginationReq request) {
  37 + return new SelectSql(getSqlTemplate())
  38 + .select()
  39 + .columns("timestamp",
  40 + "AVG(young_gc_collection_count) AS young_gc_collection_count",
  41 + "AVG(young_gc_collection_time) AS young_gc_collection_time",
  42 + "AVG(full_gc_collection_count) AS full_gc_collection_count",
  43 + "AVG(full_gc_collection_time) AS full_gc_collection_time",
  44 + "AVG(span_young_gc_collection_count) AS span_young_gc_collection_count",
  45 + "AVG(span_young_gc_collection_time) AS span_young_gc_collection_time",
  46 + "AVG(span_full_gc_collection_count) span_full_gc_collection_count",
  47 + "AVG(span_full_gc_collection_time) span_full_gc_collection_time")
  48 + .from()
  49 + .table(getTableName())
  50 + .whereSql(buildWhereSql(request))
  51 + .groupBy(" timestamp ASC ")
  52 + .limit(request.getStart(), request.getLimit())
  53 + .list(RshHandler.JVM_GC_SUM_M_DATA_RSH);
  54 + }
  55 +
  56 + public WhereSql buildWhereSql(JvmDataReq req) {
  57 + return new WhereSql()
  58 + .andOnNotEmpty("identity = ?", req.getIdentity())
  59 + .andBetween("timestamp", req.getStartTime(), req.getEndTime());
  60 +
  61 + }
  62 +
  63 + public WhereSql buildWhereSql(MDataPaginationReq request) {
  64 + return new WhereSql()
  65 + .andOnNotNull("id = ?", request.getId())
  66 + .andOnNotEmpty("identity = ?", request.getIdentity())
  67 + .andOnNotEmpty("node_group = ?", request.getNodeGroup())
  68 + .andBetween("timestamp", request.getStartTime(), request.getEndTime());
  69 + }
  70 +}
... ...
  1 +package com.github.ltsopensource.admin.access.mysql;
  2 +
  3 +import com.github.ltsopensource.admin.access.RshHandler;
  4 +import com.github.ltsopensource.admin.access.face.BackendJVMMemoryAccess;
  5 +import com.github.ltsopensource.admin.request.JvmDataReq;
  6 +import com.github.ltsopensource.admin.request.MDataPaginationReq;
  7 +import com.github.ltsopensource.core.cluster.Config;
  8 +import com.github.ltsopensource.monitor.access.domain.JVMMemoryDataPo;
  9 +import com.github.ltsopensource.monitor.access.mysql.MysqlJVMMemoryAccess;
  10 +import com.github.ltsopensource.store.jdbc.builder.DeleteSql;
  11 +import com.github.ltsopensource.store.jdbc.builder.SelectSql;
  12 +import com.github.ltsopensource.store.jdbc.builder.WhereSql;
  13 +
  14 +import java.util.List;
  15 +
  16 +/**
  17 + * @author Robert HG (254963746@qq.com) on 3/9/16.
  18 + */
  19 +public class MysqlBackendJVMMemoryAccess extends MysqlJVMMemoryAccess implements BackendJVMMemoryAccess {
  20 +
  21 + public MysqlBackendJVMMemoryAccess(Config config) {
  22 + super(config);
  23 + }
  24 +
  25 + @Override
  26 + public void delete(JvmDataReq request) {
  27 + new DeleteSql(getSqlTemplate())
  28 + .delete()
  29 + .from()
  30 + .table(getTableName())
  31 + .whereSql(buildWhereSql(request))
  32 + .doDelete();
  33 + }
  34 +
  35 + @Override
  36 + public List<JVMMemoryDataPo> queryAvg(MDataPaginationReq request) {
  37 + return new SelectSql(getSqlTemplate())
  38 + .select()
  39 + .columns("timestamp",
  40 + "AVG(heap_memory_committed) AS heap_memory_committed",
  41 + "AVG(heap_memory_init) AS heap_memory_init",
  42 + "AVG(heap_memory_max) AS heap_memory_max",
  43 + "AVG(heap_memory_used) AS heap_memory_used",
  44 + "AVG(non_heap_memory_committed) AS non_heap_memory_committed",
  45 + "AVG(non_heap_memory_init) AS non_heap_memory_init",
  46 + "AVG(non_heap_memory_max) AS non_heap_memory_max",
  47 + "AVG(non_heap_memory_used) AS non_heap_memory_used",
  48 + "AVG(perm_gen_committed) AS perm_gen_committed",
  49 + "AVG(perm_gen_init) AS perm_gen_init",
  50 + "AVG(perm_gen_max) AS perm_gen_max",
  51 + "AVG(perm_gen_used) AS perm_gen_used",
  52 + "AVG(old_gen_committed) AS old_gen_committed",
  53 + "AVG(old_gen_init) AS old_gen_init",
  54 + "AVG(old_gen_max) AS old_gen_max",
  55 + "AVG(old_gen_used) AS old_gen_used",
  56 + "AVG(eden_space_committed) AS eden_space_committed",
  57 + "AVG(eden_space_init) AS eden_space_init",
  58 + "AVG(eden_space_max) AS eden_space_max",
  59 + "AVG(eden_space_used) AS eden_space_used",
  60 + "AVG(survivor_committed) AS survivor_committed",
  61 + "AVG(survivor_init) AS survivor_init",
  62 + "AVG(survivor_max) AS survivor_max",
  63 + "AVG(survivor_used) AS survivor_used")
  64 + .from()
  65 + .table(getTableName())
  66 + .whereSql(buildWhereSql(request))
  67 + .groupBy(" timestamp ASC ")
  68 + .limit(request.getStart(), request.getLimit())
  69 + .list(RshHandler.JVM_MEMORY_SUM_M_DATA_RSH);
  70 + }
  71 +
  72 + public WhereSql buildWhereSql(JvmDataReq req) {
  73 + return new WhereSql()
  74 + .andOnNotEmpty("identity = ?", req.getIdentity())
  75 + .andBetween("timestamp", req.getStartTime(), req.getEndTime());
  76 +
  77 + }
  78 +
  79 + public WhereSql buildWhereSql(MDataPaginationReq request) {
  80 + return new WhereSql()
  81 + .andOnNotNull("id = ?", request.getId())
  82 + .andOnNotEmpty("identity = ?", request.getIdentity())
  83 + .andOnNotEmpty("node_group = ?", request.getNodeGroup())
  84 + .andBetween("timestamp", request.getStartTime(), request.getEndTime());
  85 + }
  86 +}
... ...
  1 +package com.github.ltsopensource.admin.access.mysql;
  2 +
  3 +import com.github.ltsopensource.admin.access.RshHandler;
  4 +import com.github.ltsopensource.admin.access.face.BackendJVMThreadAccess;
  5 +import com.github.ltsopensource.admin.request.JvmDataReq;
  6 +import com.github.ltsopensource.admin.request.MDataPaginationReq;
  7 +import com.github.ltsopensource.core.cluster.Config;
  8 +import com.github.ltsopensource.monitor.access.domain.JVMThreadDataPo;
  9 +import com.github.ltsopensource.monitor.access.mysql.MysqlJVMThreadAccess;
  10 +import com.github.ltsopensource.store.jdbc.builder.DeleteSql;
  11 +import com.github.ltsopensource.store.jdbc.builder.SelectSql;
  12 +import com.github.ltsopensource.store.jdbc.builder.WhereSql;
  13 +
  14 +import java.util.List;
  15 +
  16 +/**
  17 + * @author Robert HG (254963746@qq.com) on 3/9/16.
  18 + */
  19 +public class MysqlBackendJVMThreadAccess extends MysqlJVMThreadAccess implements BackendJVMThreadAccess {
  20 +
  21 + public MysqlBackendJVMThreadAccess(Config config) {
  22 + super(config);
  23 + }
  24 +
  25 + @Override
  26 + public void delete(JvmDataReq request) {
  27 + new DeleteSql(getSqlTemplate())
  28 + .delete()
  29 + .from()
  30 + .table(getTableName())
  31 + .whereSql(buildWhereSql(request))
  32 + .doDelete();
  33 + }
  34 +
  35 + @Override
  36 + public List<JVMThreadDataPo> queryAvg(MDataPaginationReq request) {
  37 + return new SelectSql(getSqlTemplate())
  38 + .select()
  39 + .columns("timestamp",
  40 + "AVG(daemon_thread_count) AS daemon_thread_count",
  41 + "AVG(thread_count) AS thread_count",
  42 + "AVG(total_started_thread_count) AS total_started_thread_count",
  43 + "AVG(dead_locked_thread_count) AS dead_locked_thread_count",
  44 + "AVG(process_cpu_time_rate) AS process_cpu_time_rate")
  45 + .from()
  46 + .table(getTableName())
  47 + .whereSql(buildWhereSql(request))
  48 + .groupBy(" timestamp ASC ")
  49 + .limit(request.getStart(), request.getLimit())
  50 + .list(RshHandler.JVM_THREAD_SUM_M_DATA_RSH);
  51 + }
  52 +
  53 + public WhereSql buildWhereSql(JvmDataReq req) {
  54 + return new WhereSql()
  55 + .andOnNotEmpty("identity = ?", req.getIdentity())
  56 + .andBetween("timestamp", req.getStartTime(), req.getEndTime());
  57 +
  58 + }
  59 +
  60 + public WhereSql buildWhereSql(MDataPaginationReq request) {
  61 + return new WhereSql()
  62 + .andOnNotNull("id = ?", request.getId())
  63 + .andOnNotEmpty("identity = ?", request.getIdentity())
  64 + .andOnNotEmpty("node_group = ?", request.getNodeGroup())
  65 + .andBetween("timestamp", request.getStartTime(), request.getEndTime());
  66 + }
  67 +}
... ...
  1 +package com.github.ltsopensource.admin.access.mysql;
  2 +
  3 +import com.github.ltsopensource.admin.access.RshHandler;
  4 +import com.github.ltsopensource.admin.access.face.BackendJobClientMAccess;
  5 +import com.github.ltsopensource.admin.request.MDataPaginationReq;
  6 +import com.github.ltsopensource.admin.web.vo.NodeInfo;
  7 +import com.github.ltsopensource.core.cluster.Config;
  8 +import com.github.ltsopensource.monitor.access.domain.JobClientMDataPo;
  9 +import com.github.ltsopensource.monitor.access.mysql.MysqlJobClientMAccess;
  10 +import com.github.ltsopensource.store.jdbc.builder.DeleteSql;
  11 +import com.github.ltsopensource.store.jdbc.builder.SelectSql;
  12 +import com.github.ltsopensource.store.jdbc.builder.WhereSql;
  13 +
  14 +import java.util.List;
  15 +
  16 +/**
  17 + * @author Robert HG (254963746@qq.com) on 3/12/16.
  18 + */
  19 +public class MysqlBackendJobClientMAccess extends MysqlJobClientMAccess implements BackendJobClientMAccess {
  20 +
  21 + public MysqlBackendJobClientMAccess(Config config) {
  22 + super(config);
  23 + }
  24 +
  25 + @Override
  26 + public void delete(MDataPaginationReq request) {
  27 +
  28 + new DeleteSql(getSqlTemplate())
  29 + .delete()
  30 + .from()
  31 + .table(getTableName())
  32 + .whereSql(buildWhereSql(request))
  33 + .doDelete();
  34 + }
  35 +
  36 + @Override
  37 + public List<JobClientMDataPo> querySum(MDataPaginationReq request) {
  38 + return new SelectSql(getSqlTemplate())
  39 + .select()
  40 + .columns("timestamp",
  41 + "SUM(submit_success_num) AS submit_success_num",
  42 + "SUM(submit_failed_num) AS submit_failed_num",
  43 + "SUM(fail_store_num) AS fail_store_num",
  44 + "SUM(submit_fail_store_num) AS submit_fail_store_num",
  45 + "SUM(handle_feedback_num) AS handle_feedback_num")
  46 + .from()
  47 + .table(getTableName())
  48 + .whereSql(buildWhereSql(request))
  49 + .groupBy(" timestamp ASC ")
  50 + .limit(request.getStart(), request.getLimit())
  51 + .list(RshHandler.JOB_CLIENT_SUM_M_DATA_RSH);
  52 + }
  53 +
  54 + @Override
  55 + public List<NodeInfo> getJobClients() {
  56 + return new SelectSql(getSqlTemplate())
  57 + .select()
  58 + .columns("DISTINCT identity AS identity", "node_group")
  59 + .from()
  60 + .table(getTableName())
  61 + .list(RshHandler.NODE_INFO_LIST_RSH);
  62 + }
  63 +
  64 + public WhereSql buildWhereSql(MDataPaginationReq request) {
  65 + return new WhereSql()
  66 + .andOnNotNull("id = ?", request.getId())
  67 + .andOnNotEmpty("identity = ?", request.getIdentity())
  68 + .andOnNotEmpty("node_group = ?", request.getNodeGroup())
  69 + .andBetween("timestamp", request.getStartTime(), request.getEndTime());
  70 + }
  71 +}
... ...
  1 +package com.github.ltsopensource.admin.access.mysql;
  2 +
  3 +import com.github.ltsopensource.admin.access.RshHandler;
  4 +import com.github.ltsopensource.admin.access.face.BackendJobTrackerMAccess;
  5 +import com.github.ltsopensource.admin.request.MDataPaginationReq;
  6 +import com.github.ltsopensource.core.cluster.Config;
  7 +import com.github.ltsopensource.monitor.access.domain.JobTrackerMDataPo;
  8 +import com.github.ltsopensource.monitor.access.mysql.MysqlJobTrackerMAccess;
  9 +import com.github.ltsopensource.store.jdbc.builder.DeleteSql;
  10 +import com.github.ltsopensource.store.jdbc.builder.SelectSql;
  11 +import com.github.ltsopensource.store.jdbc.builder.WhereSql;
  12 +import com.github.ltsopensource.store.jdbc.dbutils.ResultSetHandler;
  13 +
  14 +import java.sql.ResultSet;
  15 +import java.sql.SQLException;
  16 +import java.util.ArrayList;
  17 +import java.util.List;
  18 +
  19 +/**
  20 + * @author Robert HG (254963746@qq.com) on 3/9/16.
  21 + */
  22 +public class MysqlBackendJobTrackerMAccess extends MysqlJobTrackerMAccess implements BackendJobTrackerMAccess {
  23 +
  24 + public MysqlBackendJobTrackerMAccess(Config config) {
  25 + super(config);
  26 + }
  27 +
  28 + @Override
  29 + public List<JobTrackerMDataPo> querySum(MDataPaginationReq request) {
  30 +
  31 + return new SelectSql(getSqlTemplate())
  32 + .select()
  33 + .columns("timestamp",
  34 + "SUM(receive_job_num) AS receive_job_num",
  35 + "SUM(push_job_num) AS push_job_num" ,
  36 + "SUM(exe_success_num) AS exe_success_num" ,
  37 + "SUM(exe_failed_num) AS exe_failed_num" ,
  38 + "SUM(exe_later_num) AS exe_later_num" ,
  39 + "SUM(exe_exception_num) AS exe_exception_num" ,
  40 + "SUM(fix_executing_job_num) AS fix_executing_job_num")
  41 + .from()
  42 + .table(getTableName())
  43 + .whereSql(buildWhereSql(request))
  44 + .groupBy(" timestamp ASC ")
  45 + .limit(request.getStart(), request.getLimit())
  46 + .list(RshHandler.JOB_TRACKER_SUM_M_DATA_RSH);
  47 + }
  48 +
  49 + private WhereSql buildWhereSql(MDataPaginationReq request) {
  50 + return new WhereSql()
  51 + .andOnNotEmpty("id = ? ", request.getId())
  52 + .andOnNotEmpty("identity = ?", request.getIdentity())
  53 + .andBetween("timestamp", request.getStartTime(), request.getEndTime());
  54 + }
  55 +
  56 + @Override
  57 + public void delete(MDataPaginationReq request) {
  58 +
  59 + new DeleteSql(getSqlTemplate())
  60 + .delete()
  61 + .from()
  62 + .table(getTableName())
  63 + .whereSql(buildWhereSql(request))
  64 + .doDelete();
  65 + }
  66 +
  67 + @Override
  68 + public List<String> getJobTrackers() {
  69 + return new SelectSql(getSqlTemplate())
  70 + .select()
  71 + .columns("DISTINCT identity AS `identity` ")
  72 + .from()
  73 + .table(getTableName())
  74 + .list(new ResultSetHandler<List<String>>() {
  75 + @Override
  76 + public List<String> handle(ResultSet rs) throws SQLException {
  77 + List<String> list = new ArrayList<String>();
  78 + while (rs.next()) {
  79 + list.add(rs.getString("identity"));
  80 + }
  81 + return list;
  82 + }
  83 + });
  84 + }
  85 +
  86 +}
... ...
  1 +package com.github.ltsopensource.admin.access.mysql;
  2 +
  3 +import com.github.ltsopensource.admin.access.RshHandler;
  4 +import com.github.ltsopensource.admin.access.domain.NodeOnOfflineLog;
  5 +import com.github.ltsopensource.admin.access.face.BackendNodeOnOfflineLogAccess;
  6 +import com.github.ltsopensource.admin.request.NodeOnOfflineLogPaginationReq;
  7 +import com.github.ltsopensource.core.cluster.Config;
  8 +import com.github.ltsopensource.monitor.access.mysql.MysqlAbstractJdbcAccess;
  9 +import com.github.ltsopensource.store.jdbc.builder.*;
  10 +
  11 +import java.util.List;
  12 +
  13 +/**
  14 + * @author Robert HG (254963746@qq.com) on 3/9/16.
  15 + */
  16 +public class MysqlBackendNodeOnOfflineLogAccess extends MysqlAbstractJdbcAccess implements BackendNodeOnOfflineLogAccess {
  17 +
  18 + public MysqlBackendNodeOnOfflineLogAccess(Config config) {
  19 + super(config);
  20 + }
  21 +
  22 + @Override
  23 + protected String getTableName() {
  24 + return "lts_admin_node_onoffline_log";
  25 + }
  26 +
  27 + @Override
  28 + public void insert(List<NodeOnOfflineLog> nodeOnOfflineLogs) {
  29 + InsertSql insertSql = new InsertSql(getSqlTemplate())
  30 + .insert(getTableName())
  31 + .columns("log_time",
  32 + "event",
  33 + "node_type",
  34 + "cluster_name",
  35 + "ip",
  36 + "port",
  37 + "host_name",
  38 + "group",
  39 + "create_time",
  40 + "threads",
  41 + "identity",
  42 + "http_cmd_port");
  43 + for (NodeOnOfflineLog nodeOnOfflineLog : nodeOnOfflineLogs) {
  44 + insertSql.values(nodeOnOfflineLog.getLogTime(),
  45 + nodeOnOfflineLog.getEvent(),
  46 + nodeOnOfflineLog.getNodeType().name(),
  47 + nodeOnOfflineLog.getClusterName(),
  48 + nodeOnOfflineLog.getIp(),
  49 + nodeOnOfflineLog.getPort(),
  50 + nodeOnOfflineLog.getHostName(),
  51 + nodeOnOfflineLog.getGroup(),
  52 + nodeOnOfflineLog.getCreateTime(),
  53 + nodeOnOfflineLog.getThreads(),
  54 + nodeOnOfflineLog.getIdentity(),
  55 + nodeOnOfflineLog.getHttpCmdPort()
  56 + );
  57 + }
  58 + insertSql.doBatchInsert();
  59 + }
  60 +
  61 + @Override
  62 + public List<NodeOnOfflineLog> select(NodeOnOfflineLogPaginationReq request) {
  63 + return new SelectSql(getSqlTemplate())
  64 + .select()
  65 + .all()
  66 + .from()
  67 + .table(getTableName())
  68 + .whereSql(buildWhereSql(request))
  69 + .orderBy()
  70 + .column("log_time", OrderByType.DESC)
  71 + .limit(request.getStart(), request.getLimit())
  72 + .list(RshHandler.NODE_ON_OFFLINE_LOG_LIST_RSH);
  73 + }
  74 +
  75 + @Override
  76 + public Long count(NodeOnOfflineLogPaginationReq request) {
  77 + return new SelectSql(getSqlTemplate())
  78 + .select()
  79 + .columns("count(1)")
  80 + .from()
  81 + .table(getTableName())
  82 + .whereSql(buildWhereSql(request))
  83 + .single();
  84 + }
  85 +
  86 + @Override
  87 + public void delete(NodeOnOfflineLogPaginationReq request) {
  88 + new DeleteSql(getSqlTemplate())
  89 + .delete()
  90 + .from()
  91 + .table(getTableName())
  92 + .whereSql(buildWhereSql(request))
  93 + .doDelete();
  94 + }
  95 +
  96 + private WhereSql buildWhereSql(NodeOnOfflineLogPaginationReq request){
  97 + return new WhereSql()
  98 + .andOnNotEmpty("identity = ?", request.getIdentity())
  99 + .andOnNotEmpty("group = ?", request.getGroup())
  100 + .andOnNotEmpty("event = ?", request.getEvent())
  101 + .andBetween("log_time", request.getStartLogTime(), request.getEndLogTime());
  102 + }
  103 +}
... ...
  1 +package com.github.ltsopensource.admin.access.mysql;
  2 +
  3 +import com.github.ltsopensource.admin.access.RshHandler;
  4 +import com.github.ltsopensource.admin.access.face.BackendTaskTrackerMAccess;
  5 +import com.github.ltsopensource.admin.request.MDataPaginationReq;
  6 +import com.github.ltsopensource.admin.web.vo.NodeInfo;
  7 +import com.github.ltsopensource.core.cluster.Config;
  8 +import com.github.ltsopensource.monitor.access.domain.TaskTrackerMDataPo;
  9 +import com.github.ltsopensource.monitor.access.mysql.MysqlTaskTrackerMAccess;
  10 +import com.github.ltsopensource.store.jdbc.builder.DeleteSql;
  11 +import com.github.ltsopensource.store.jdbc.builder.SelectSql;
  12 +import com.github.ltsopensource.store.jdbc.builder.WhereSql;
  13 +
  14 +import java.util.List;
  15 +
  16 +/**
  17 + * @author Robert HG (254963746@qq.com) on 3/9/16.
  18 + */
  19 +public class MysqlBackendTaskTrackerMAccess extends MysqlTaskTrackerMAccess implements BackendTaskTrackerMAccess {
  20 +
  21 + public MysqlBackendTaskTrackerMAccess(Config config) {
  22 + super(config);
  23 + }
  24 +
  25 + @Override
  26 + public List<TaskTrackerMDataPo> querySum(MDataPaginationReq request) {
  27 +
  28 + return new SelectSql(getSqlTemplate())
  29 + .select()
  30 + .columns("timestamp",
  31 + "SUM(exe_success_num) AS exe_success_num",
  32 + "SUM(exe_failed_num) AS exe_failed_num",
  33 + "SUM(exe_later_num) AS exe_later_num",
  34 + "SUM(exe_exception_num) AS exe_exception_num",
  35 + "SUM(total_running_time) AS total_running_time")
  36 + .from()
  37 + .table(getTableName())
  38 + .whereSql(buildWhereSql(request))
  39 + .groupBy(" timestamp ASC ")
  40 + .limit(request.getStart(), request.getLimit())
  41 + .list(RshHandler.TASK_TRACKER_SUM_M_DATA_RSH);
  42 + }
  43 +
  44 + @Override
  45 + public void delete(MDataPaginationReq request) {
  46 +
  47 + new DeleteSql(getSqlTemplate())
  48 + .delete()
  49 + .from()
  50 + .table(getTableName())
  51 + .whereSql(buildWhereSql(request))
  52 + .doDelete();
  53 + }
  54 +
  55 + @Override
  56 + public List<NodeInfo> getTaskTrackers() {
  57 + return new SelectSql(getSqlTemplate())
  58 + .select()
  59 + .columns("DISTINCT identity", "node_group")
  60 + .from()
  61 + .table(getTableName())
  62 + .list(RshHandler.NODE_INFO_LIST_RSH);
  63 + }
  64 +
  65 + public WhereSql buildWhereSql(MDataPaginationReq request) {
  66 + return new WhereSql()
  67 + .andOnNotNull("id = ?", request.getId())
  68 + .andOnNotEmpty("identity = ?", request.getIdentity())
  69 + .andOnNotEmpty("node_group = ?", request.getNodeGroup())
  70 + .andBetween("timestamp", request.getStartTime(), request.getEndTime());
  71 + }
  72 +}
... ...
  1 +package com.github.ltsopensource.admin.cluster;
  2 +
  3 +import com.github.ltsopensource.admin.access.face.*;
  4 +import com.github.ltsopensource.admin.access.memory.NodeMemCacheAccess;
  5 +import com.github.ltsopensource.admin.web.support.NoRelyJobGenerator;
  6 +import com.github.ltsopensource.biz.logger.JobLogger;
  7 +import com.github.ltsopensource.core.AppContext;
  8 +import com.github.ltsopensource.core.cluster.Node;
  9 +import com.github.ltsopensource.queue.*;
  10 +
  11 +/**
  12 + * Robert HG (254963746@qq.com) on 6/5/15.
  13 + */
  14 +public class BackendAppContext extends AppContext {
  15 +
  16 + private CronJobQueue cronJobQueue;
  17 + private RepeatJobQueue repeatJobQueue;
  18 + private ExecutableJobQueue executableJobQueue;
  19 + private ExecutingJobQueue executingJobQueue;
  20 + private JobFeedbackQueue jobFeedbackQueue;
  21 + private SuspendJobQueue suspendJobQueue;
  22 + private NodeGroupStore nodeGroupStore;
  23 + private JobLogger jobLogger;
  24 + private Node node;
  25 +
  26 + private BackendJobClientMAccess backendJobClientMAccess;
  27 + private BackendJobTrackerMAccess backendJobTrackerMAccess;
  28 + private BackendTaskTrackerMAccess backendTaskTrackerMAccess;
  29 + private BackendJVMGCAccess backendJVMGCAccess;
  30 + private BackendJVMMemoryAccess backendJVMMemoryAccess;
  31 + private BackendJVMThreadAccess backendJVMThreadAccess;
  32 + private BackendNodeOnOfflineLogAccess backendNodeOnOfflineLogAccess;
  33 +
  34 + private NodeMemCacheAccess nodeMemCacheAccess;
  35 +
  36 + private NoRelyJobGenerator noRelyJobGenerator;
  37 +
  38 + private BackendRegistrySrv backendRegistrySrv;
  39 +
  40 + public Node getNode() {
  41 + return node;
  42 + }
  43 +
  44 + public void setNode(Node node) {
  45 + this.node = node;
  46 + }
  47 +
  48 + public CronJobQueue getCronJobQueue() {
  49 + return cronJobQueue;
  50 + }
  51 +
  52 + public void setCronJobQueue(CronJobQueue cronJobQueue) {
  53 + this.cronJobQueue = cronJobQueue;
  54 + }
  55 +
  56 + public RepeatJobQueue getRepeatJobQueue() {
  57 + return repeatJobQueue;
  58 + }
  59 +
  60 + public void setRepeatJobQueue(RepeatJobQueue repeatJobQueue) {
  61 + this.repeatJobQueue = repeatJobQueue;
  62 + }
  63 +
  64 + public ExecutableJobQueue getExecutableJobQueue() {
  65 + return executableJobQueue;
  66 + }
  67 +
  68 + public void setExecutableJobQueue(ExecutableJobQueue executableJobQueue) {
  69 + this.executableJobQueue = executableJobQueue;
  70 + }
  71 +
  72 + public ExecutingJobQueue getExecutingJobQueue() {
  73 + return executingJobQueue;
  74 + }
  75 +
  76 + public void setExecutingJobQueue(ExecutingJobQueue executingJobQueue) {
  77 + this.executingJobQueue = executingJobQueue;
  78 + }
  79 +
  80 + public SuspendJobQueue getSuspendJobQueue() {
  81 + return suspendJobQueue;
  82 + }
  83 +
  84 + public void setSuspendJobQueue(SuspendJobQueue suspendJobQueue) {
  85 + this.suspendJobQueue = suspendJobQueue;
  86 + }
  87 +
  88 + public NodeGroupStore getNodeGroupStore() {
  89 + return nodeGroupStore;
  90 + }
  91 +
  92 + public void setNodeGroupStore(NodeGroupStore nodeGroupStore) {
  93 + this.nodeGroupStore = nodeGroupStore;
  94 + }
  95 +
  96 + public JobFeedbackQueue getJobFeedbackQueue() {
  97 + return jobFeedbackQueue;
  98 + }
  99 +
  100 + public void setJobFeedbackQueue(JobFeedbackQueue jobFeedbackQueue) {
  101 + this.jobFeedbackQueue = jobFeedbackQueue;
  102 + }
  103 +
  104 + public JobLogger getJobLogger() {
  105 + return jobLogger;
  106 + }
  107 +
  108 + public void setJobLogger(JobLogger jobLogger) {
  109 + this.jobLogger = jobLogger;
  110 + }
  111 +
  112 + public BackendJobClientMAccess getBackendJobClientMAccess() {
  113 + return backendJobClientMAccess;
  114 + }
  115 +
  116 + public void setBackendJobClientMAccess(BackendJobClientMAccess backendJobClientMAccess) {
  117 + this.backendJobClientMAccess = backendJobClientMAccess;
  118 + }
  119 +
  120 + public BackendJobTrackerMAccess getBackendJobTrackerMAccess() {
  121 + return backendJobTrackerMAccess;
  122 + }
  123 +
  124 + public void setBackendJobTrackerMAccess(BackendJobTrackerMAccess backendJobTrackerMAccess) {
  125 + this.backendJobTrackerMAccess = backendJobTrackerMAccess;
  126 + }
  127 +
  128 + public BackendTaskTrackerMAccess getBackendTaskTrackerMAccess() {
  129 + return backendTaskTrackerMAccess;
  130 + }
  131 +
  132 + public void setBackendTaskTrackerMAccess(BackendTaskTrackerMAccess backendTaskTrackerMAccess) {
  133 + this.backendTaskTrackerMAccess = backendTaskTrackerMAccess;
  134 + }
  135 +
  136 + public BackendJVMGCAccess getBackendJVMGCAccess() {
  137 + return backendJVMGCAccess;
  138 + }
  139 +
  140 + public void setBackendJVMGCAccess(BackendJVMGCAccess backendJVMGCAccess) {
  141 + this.backendJVMGCAccess = backendJVMGCAccess;
  142 + }
  143 +
  144 + public BackendJVMMemoryAccess getBackendJVMMemoryAccess() {
  145 + return backendJVMMemoryAccess;
  146 + }
  147 +
  148 + public void setBackendJVMMemoryAccess(BackendJVMMemoryAccess backendJVMMemoryAccess) {
  149 + this.backendJVMMemoryAccess = backendJVMMemoryAccess;
  150 + }
  151 +
  152 + public BackendJVMThreadAccess getBackendJVMThreadAccess() {
  153 + return backendJVMThreadAccess;
  154 + }
  155 +
  156 + public void setBackendJVMThreadAccess(BackendJVMThreadAccess backendJVMThreadAccess) {
  157 + this.backendJVMThreadAccess = backendJVMThreadAccess;
  158 + }
  159 +
  160 + public BackendNodeOnOfflineLogAccess getBackendNodeOnOfflineLogAccess() {
  161 + return backendNodeOnOfflineLogAccess;
  162 + }
  163 +
  164 + public void setBackendNodeOnOfflineLogAccess(BackendNodeOnOfflineLogAccess backendNodeOnOfflineLogAccess) {
  165 + this.backendNodeOnOfflineLogAccess = backendNodeOnOfflineLogAccess;
  166 + }
  167 +
  168 + public NodeMemCacheAccess getNodeMemCacheAccess() {
  169 + return nodeMemCacheAccess;
  170 + }
  171 +
  172 + public void setNodeMemCacheAccess(NodeMemCacheAccess nodeMemCacheAccess) {
  173 + this.nodeMemCacheAccess = nodeMemCacheAccess;
  174 + }
  175 +
  176 + public NoRelyJobGenerator getNoRelyJobGenerator() {
  177 + return noRelyJobGenerator;
  178 + }
  179 +
  180 + public void setNoRelyJobGenerator(NoRelyJobGenerator noRelyJobGenerator) {
  181 + this.noRelyJobGenerator = noRelyJobGenerator;
  182 + }
  183 +
  184 + public BackendRegistrySrv getBackendRegistrySrv() {
  185 + return backendRegistrySrv;
  186 + }
  187 +
  188 + public void setBackendRegistrySrv(BackendRegistrySrv backendRegistrySrv) {
  189 + this.backendRegistrySrv = backendRegistrySrv;
  190 + }
  191 +}
... ...
  1 +package com.github.ltsopensource.admin.cluster;
  2 +
  3 +import com.github.ltsopensource.core.cluster.Node;
  4 +import com.github.ltsopensource.core.cluster.NodeType;
  5 +
  6 +/**
  7 + * @author Robert HG (254963746@qq.com) on 3/12/16.
  8 + */
  9 +public class BackendNode extends Node {
  10 +
  11 + public BackendNode() {
  12 + this.setNodeType(NodeType.JOB_TRACKER);
  13 + this.addListenNodeType(NodeType.JOB_CLIENT);
  14 + this.addListenNodeType(NodeType.TASK_TRACKER);
  15 + this.addListenNodeType(NodeType.JOB_TRACKER);
  16 + this.addListenNodeType(NodeType.MONITOR);
  17 + }
  18 +}
... ...
  1 +package com.github.ltsopensource.admin.cluster;
  2 +
  3 +import com.github.ltsopensource.admin.access.domain.NodeOnOfflineLog;
  4 +import com.github.ltsopensource.admin.request.NodePaginationReq;
  5 +import com.github.ltsopensource.admin.response.PaginationRsp;
  6 +import com.github.ltsopensource.core.cluster.Node;
  7 +import com.github.ltsopensource.core.commons.utils.CollectionUtils;
  8 +import com.github.ltsopensource.core.logger.Logger;
  9 +import com.github.ltsopensource.core.logger.LoggerFactory;
  10 +import com.github.ltsopensource.core.registry.*;
  11 +
  12 +import java.util.ArrayList;
  13 +import java.util.Date;
  14 +import java.util.List;
  15 +
  16 +/**
  17 + * Robert HG (254963746@qq.com) on 6/5/15.
  18 + */
  19 +public class BackendRegistrySrv {
  20 +
  21 + private static final Logger LOGGER = LoggerFactory.getLogger(BackendRegistrySrv.class);
  22 + private BackendAppContext appContext;
  23 + private Registry registry;
  24 + private NotifyListener notifyListener;
  25 +
  26 + public BackendRegistrySrv(BackendAppContext appContext) {
  27 + this.appContext = appContext;
  28 + }
  29 +
  30 + private void subscribe() {
  31 +
  32 + if (registry instanceof AbstractRegistry) {
  33 + ((AbstractRegistry) registry).setNode(appContext.getNode());
  34 + }
  35 + registry.subscribe(appContext.getNode(), notifyListener);
  36 + }
  37 +
  38 + public void reSubscribe() {
  39 + // 取消订阅
  40 + registry.unsubscribe(appContext.getNode(), notifyListener);
  41 + // 清空内存数据
  42 + appContext.getNodeMemCacheAccess().clear();
  43 + // 重新订阅
  44 + subscribe();
  45 + }
  46 +
  47 + public PaginationRsp<Node> getOnlineNodes(NodePaginationReq request) {
  48 + return appContext.getNodeMemCacheAccess().pageSelect(request);
  49 + }
  50 +
  51 + /**
  52 + * 记录节点上下线日志
  53 + */
  54 + private void addLog(NotifyEvent event, List<Node> nodes) {
  55 + List<NodeOnOfflineLog> logs = new ArrayList<NodeOnOfflineLog>(nodes.size());
  56 +
  57 + for (Node node : nodes) {
  58 + NodeOnOfflineLog log = new NodeOnOfflineLog();
  59 + log.setLogTime(new Date());
  60 + log.setEvent(event == NotifyEvent.ADD ? "ONLINE" : "OFFLINE");
  61 +
  62 + log.setClusterName(node.getClusterName());
  63 + log.setCreateTime(node.getCreateTime());
  64 + log.setGroup(node.getGroup());
  65 + log.setHostName(node.getHostName());
  66 + log.setIdentity(node.getIdentity());
  67 + log.setIp(node.getIp());
  68 + log.setPort(node.getPort());
  69 + log.setThreads(node.getThreads());
  70 + log.setNodeType(node.getNodeType());
  71 + log.setHttpCmdPort(node.getHttpCmdPort());
  72 +
  73 + logs.add(log);
  74 + }
  75 +
  76 + appContext.getBackendNodeOnOfflineLogAccess().insert(logs);
  77 + }
  78 +
  79 + public void start() throws Exception {
  80 +
  81 + registry = RegistryFactory.getRegistry(appContext);
  82 +
  83 + notifyListener = new NotifyListener() {
  84 + @Override
  85 + public void notify(NotifyEvent event, List<Node> nodes) {
  86 + if (CollectionUtils.isEmpty(nodes)) {
  87 + return;
  88 + }
  89 + switch (event) {
  90 + case ADD:
  91 + appContext.getNodeMemCacheAccess().addNode(nodes);
  92 + LOGGER.info("ADD NODE " + nodes);
  93 + break;
  94 + case REMOVE:
  95 + appContext.getNodeMemCacheAccess().removeNode(nodes);
  96 + LOGGER.info("REMOVE NODE " + nodes);
  97 + break;
  98 + }
  99 + // 记录日志
  100 + addLog(event, nodes);
  101 + }
  102 + };
  103 +
  104 + subscribe();
  105 + }
  106 +}
... ...
  1 +package com.github.ltsopensource.admin.request;
  2 +
  3 +/**
  4 + * @author Robert HG (254963746@qq.com) on 3/13/16.
  5 + */
  6 +public enum JVMType {
  7 +
  8 + GC,
  9 + MEMORY,
  10 + THREAD
  11 +
  12 +}
... ...
  1 +package com.github.ltsopensource.admin.request;
  2 +
  3 +/**
  4 + * @author Robert HG (254963746@qq.com) on 9/28/15.
  5 + */
  6 +public class JvmDataReq {
  7 +
  8 + private String identity;
  9 +
  10 + private Long startTime;
  11 +
  12 + private Long endTime;
  13 +
  14 + public String getIdentity() {
  15 + return identity;
  16 + }
  17 +
  18 + public void setIdentity(String identity) {
  19 + this.identity = identity;
  20 + }
  21 +
  22 + public Long getStartTime() {
  23 + return startTime;
  24 + }
  25 +
  26 + public void setStartTime(Long startTime) {
  27 + this.startTime = startTime;
  28 + }
  29 +
  30 + public Long getEndTime() {
  31 + return endTime;
  32 + }
  33 +
  34 + public void setEndTime(Long endTime) {
  35 + this.endTime = endTime;
  36 + }
  37 +}
... ...
  1 +package com.github.ltsopensource.admin.request;
  2 +
  3 +import com.github.ltsopensource.core.cluster.NodeType;
  4 +
  5 +/**
  6 + * @author Robert HG (254963746@qq.com) on 8/22/15.
  7 + */
  8 +public class MDataPaginationReq extends PaginationReq {
  9 +
  10 + private NodeType nodeType;
  11 +
  12 + private String id;
  13 +
  14 + private String nodeGroup;
  15 +
  16 + private String identity;
  17 +
  18 + private Long startTime;
  19 +
  20 + private Long endTime;
  21 +
  22 + private JVMType jvmType;
  23 +
  24 + public String getId() {
  25 + return id;
  26 + }
  27 +
  28 + public void setId(String id) {
  29 + this.id = id;
  30 + }
  31 +
  32 + public String getNodeGroup() {
  33 + return nodeGroup;
  34 + }
  35 +
  36 + public void setNodeGroup(String nodeGroup) {
  37 + this.nodeGroup = nodeGroup;
  38 + }
  39 +
  40 + public String getIdentity() {
  41 + return identity;
  42 + }
  43 +
  44 + public void setIdentity(String identity) {
  45 + this.identity = identity;
  46 + }
  47 +
  48 + public Long getStartTime() {
  49 + return startTime;
  50 + }
  51 +
  52 + public void setStartTime(Long startTime) {
  53 + this.startTime = startTime;
  54 + }
  55 +
  56 + public Long getEndTime() {
  57 + return endTime;
  58 + }
  59 +
  60 + public void setEndTime(Long endTime) {
  61 + this.endTime = endTime;
  62 + }
  63 +
  64 + public NodeType getNodeType() {
  65 + return nodeType;
  66 + }
  67 +
  68 + public void setNodeType(NodeType nodeType) {
  69 + this.nodeType = nodeType;
  70 + }
  71 +
  72 + public JVMType getJvmType() {
  73 + return jvmType;
  74 + }
  75 +
  76 + public void setJvmType(JVMType jvmType) {
  77 + this.jvmType = jvmType;
  78 + }
  79 +}
... ...
  1 +package com.github.ltsopensource.admin.request;
  2 +
  3 +import com.github.ltsopensource.core.cluster.NodeType;
  4 +
  5 +/**
  6 + * @author Robert HG (254963746@qq.com) on 9/5/15.
  7 + */
  8 +public class NodeGroupRequest {
  9 +
  10 + private NodeType nodeType;
  11 +
  12 + private String nodeGroup;
  13 +
  14 + public NodeType getNodeType() {
  15 + return nodeType;
  16 + }
  17 +
  18 + public void setNodeType(NodeType nodeType) {
  19 + this.nodeType = nodeType;
  20 + }
  21 +
  22 + public String getNodeGroup() {
  23 + return nodeGroup;
  24 + }
  25 +
  26 + public void setNodeGroup(String nodeGroup) {
  27 + this.nodeGroup = nodeGroup;
  28 + }
  29 +}
... ...
  1 +package com.github.ltsopensource.admin.request;
  2 +
  3 +import java.util.Date;
  4 +
  5 +/**
  6 + * @author Robert HG (254963746@qq.com) on 9/26/15.
  7 + */
  8 +public class NodeOnOfflineLogPaginationReq extends PaginationReq {
  9 +
  10 + private Date startLogTime;
  11 +
  12 + private Date endLogTime;
  13 +
  14 + private String group;
  15 +
  16 + private String identity;
  17 +
  18 + private String event;
  19 +
  20 + public String getIdentity() {
  21 + return identity;
  22 + }
  23 +
  24 + public void setIdentity(String identity) {
  25 + this.identity = identity;
  26 + }
  27 +
  28 + public String getEvent() {
  29 + return event;
  30 + }
  31 +
  32 + public void setEvent(String event) {
  33 + this.event = event;
  34 + }
  35 +
  36 + public String getGroup() {
  37 + return group;
  38 + }
  39 +
  40 + public void setGroup(String group) {
  41 + this.group = group;
  42 + }
  43 +
  44 + public Date getStartLogTime() {
  45 + return startLogTime;
  46 + }
  47 +
  48 + public void setStartLogTime(Date startLogTime) {
  49 + this.startLogTime = startLogTime;
  50 + }
  51 +
  52 + public Date getEndLogTime() {
  53 + return endLogTime;
  54 + }
  55 +
  56 + public void setEndLogTime(Date endLogTime) {
  57 + this.endLogTime = endLogTime;
  58 + }
  59 +}
... ...
  1 +package com.github.ltsopensource.admin.request;
  2 +
  3 +import com.github.ltsopensource.core.cluster.NodeType;
  4 +
  5 +import java.util.Date;
  6 +
  7 +/**
  8 + * @author Robert HG (254963746@qq.com) on 6/6/15.
  9 + */
  10 +public class NodePaginationReq extends PaginationReq {
  11 +
  12 + private String identity;
  13 + private String ip;
  14 + private String nodeGroup;
  15 + private NodeType nodeType;
  16 + private Boolean available;
  17 + private Date startDate;
  18 + private Date endDate;
  19 +
  20 + public NodePaginationReq() {
  21 + // 默认不分页
  22 + setLimit(Integer.MAX_VALUE);
  23 + }
  24 +
  25 + public String getNodeGroup() {
  26 + return nodeGroup;
  27 + }
  28 +
  29 + public void setNodeGroup(String nodeGroup) {
  30 + this.nodeGroup = nodeGroup;
  31 + }
  32 +
  33 + public String getIdentity() {
  34 + return identity;
  35 + }
  36 +
  37 + public void setIdentity(String identity) {
  38 + this.identity = identity;
  39 + }
  40 +
  41 + public String getIp() {
  42 + return ip;
  43 + }
  44 +
  45 + public void setIp(String ip) {
  46 + this.ip = ip;
  47 + }
  48 +
  49 + public NodeType getNodeType() {
  50 + return nodeType;
  51 + }
  52 +
  53 + public void setNodeType(NodeType nodeType) {
  54 + this.nodeType = nodeType;
  55 + }
  56 +
  57 + public Boolean getAvailable() {
  58 + return available;
  59 + }
  60 +
  61 + public void setAvailable(Boolean available) {
  62 + this.available = available;
  63 + }
  64 +
  65 + public Date getStartDate() {
  66 + return startDate;
  67 + }
  68 +
  69 + public void setStartDate(Date startDate) {
  70 + this.startDate = startDate;
  71 + }
  72 +
  73 + public Date getEndDate() {
  74 + return endDate;
  75 + }
  76 +
  77 + public void setEndDate(Date endDate) {
  78 + this.endDate = endDate;
  79 + }
  80 +}
... ...
  1 +package com.github.ltsopensource.admin.support;
  2 +
  3 +import com.github.ltsopensource.core.commons.utils.StringUtils;
  4 +
  5 +import java.io.File;
  6 +import java.io.FileInputStream;
  7 +import java.io.InputStream;
  8 +import java.util.HashMap;
  9 +import java.util.Map;
  10 +import java.util.Properties;
  11 +import java.util.concurrent.atomic.AtomicBoolean;
  12 +
  13 +/**
  14 + * 系统的配置信息(lts-admin.cfg)
  15 + *
  16 + * @author Robert HG (254963746@qq.com) on 5/11/15.
  17 + */
  18 +public class AppConfigurer {
  19 +
  20 + private static final Map<String, String> CONFIG = new HashMap<String, String>();
  21 + private static final String CONF_NAME = "lts-admin.cfg";
  22 +
  23 + private static AtomicBoolean load = new AtomicBoolean(false);
  24 +
  25 + public static void load(String confPath) {
  26 + String path = "";
  27 + try {
  28 + if (load.compareAndSet(false, true)) {
  29 + Properties conf = new Properties();
  30 +
  31 + if (StringUtils.isNotEmpty(confPath)) {
  32 + path = confPath + "/" + CONF_NAME;
  33 + InputStream is = new FileInputStream(new File(path));
  34 + conf.load(is);
  35 + } else {
  36 + path = CONF_NAME;
  37 + InputStream is = AppConfigurer.class.getClassLoader().getResourceAsStream(path);
  38 + conf.load(is);
  39 + }
  40 +
  41 + for (Map.Entry<Object, Object> entry : conf.entrySet()) {
  42 + String key = entry.getKey().toString();
  43 + String value = entry.getValue() == null ? null : entry.getValue().toString();
  44 + CONFIG.put(key, value);
  45 + }
  46 + }
  47 + } catch (Exception e) {
  48 + throw new RuntimeException("Load config[" + path + "] error ", e);
  49 + }
  50 + }
  51 +
  52 + public static Map<String, String> allConfig() {
  53 + return CONFIG;
  54 + }
  55 +
  56 + public static String getProperty(String name) {
  57 + return CONFIG.get(name);
  58 + }
  59 +
  60 + public static String getProperty(String name, String defaultValue) {
  61 + String returnValue = CONFIG.get(name);
  62 + if (returnValue == null || returnValue.equals("")) {
  63 + returnValue = defaultValue;
  64 + }
  65 + return returnValue;
  66 + }
  67 +}
... ...
  1 +package com.github.ltsopensource.admin.support;
  2 +
  3 +import com.github.ltsopensource.admin.access.BackendAccessFactory;
  4 +import com.github.ltsopensource.admin.access.memory.NodeMemCacheAccess;
  5 +import com.github.ltsopensource.admin.cluster.BackendAppContext;
  6 +import com.github.ltsopensource.admin.cluster.BackendNode;
  7 +import com.github.ltsopensource.admin.cluster.BackendRegistrySrv;
  8 +import com.github.ltsopensource.admin.web.support.NoRelyJobGenerator;
  9 +import com.github.ltsopensource.biz.logger.SmartJobLogger;
  10 +import com.github.ltsopensource.core.cluster.Config;
  11 +import com.github.ltsopensource.core.cluster.Node;
  12 +import com.github.ltsopensource.core.commons.utils.BeanUtils;
  13 +import com.github.ltsopensource.core.commons.utils.NetUtils;
  14 +import com.github.ltsopensource.core.commons.utils.StringUtils;
  15 +import com.github.ltsopensource.core.constant.Constants;
  16 +import com.github.ltsopensource.core.registry.RegistryStatMonitor;
  17 +import com.github.ltsopensource.core.spi.ServiceLoader;
  18 +import com.github.ltsopensource.core.support.SystemClock;
  19 +import com.github.ltsopensource.ec.EventCenter;
  20 +import com.github.ltsopensource.queue.JobQueueFactory;
  21 +import org.springframework.beans.factory.FactoryBean;
  22 +import org.springframework.beans.factory.InitializingBean;
  23 +
  24 +import java.util.Map;
  25 +
  26 +/**
  27 + * @author Robert HG (254963746@qq.com) on 6/6/15.
  28 + */
  29 +public class BackendAppContextFactoryBean implements FactoryBean<BackendAppContext>, InitializingBean {
  30 +
  31 + private BackendAppContext appContext;
  32 +
  33 + @Override
  34 + public BackendAppContext getObject() throws Exception {
  35 + return appContext;
  36 + }
  37 +
  38 + @Override
  39 + public Class<?> getObjectType() {
  40 + return BackendAppContext.class;
  41 + }
  42 +
  43 + @Override
  44 + public boolean isSingleton() {
  45 + return true;
  46 + }
  47 +
  48 + @Override
  49 + public void afterPropertiesSet() throws Exception {
  50 + final Node node = new BackendNode();
  51 + node.setCreateTime(SystemClock.now());
  52 + node.setIp(NetUtils.getLocalHost());
  53 + node.setHostName(NetUtils.getLocalHostName());
  54 + node.setIdentity(Constants.ADMIN_ID_PREFIX + StringUtils.generateUUID());
  55 +
  56 + Config config = new Config();
  57 + config.setIdentity(node.getIdentity());
  58 + config.setNodeType(node.getNodeType());
  59 + config.setRegistryAddress(AppConfigurer.getProperty("registryAddress"));
  60 + String clusterName = AppConfigurer.getProperty("clusterName");
  61 + if (StringUtils.isEmpty(clusterName)) {
  62 + throw new IllegalArgumentException("clusterName in lts-admin.cfg can not be null.");
  63 + }
  64 + config.setClusterName(clusterName);
  65 +
  66 + for (Map.Entry<String, String> entry : AppConfigurer.allConfig().entrySet()) {
  67 + // 将 config. 开头的配置都加入到config中
  68 + if (entry.getKey().startsWith("configs.")) {
  69 + config.setParameter(entry.getKey().replaceFirst("configs.", ""), entry.getValue());
  70 + }
  71 + }
  72 +
  73 + appContext = new BackendAppContext();
  74 + appContext.setConfig(config);
  75 + appContext.setNode(node);
  76 + appContext.setEventCenter(ServiceLoader.load(EventCenter.class, config));
  77 + appContext.setRegistryStatMonitor(new RegistryStatMonitor(appContext));
  78 + appContext.setBackendRegistrySrv(new BackendRegistrySrv(appContext));
  79 +
  80 + initAccess(config);
  81 +
  82 + // ----------------------下面是JobQueue的配置---------------------------
  83 + Config jobTConfig = (Config) BeanUtils.deepClone(config);
  84 + for (Map.Entry<String, String> entry : AppConfigurer.allConfig().entrySet()) {
  85 + // 将 jobT. 开头的配置都加入到jobTConfig中
  86 + if (entry.getKey().startsWith("jobT.")) {
  87 + String key = entry.getKey().replace("jobT.", "");
  88 + String value = entry.getValue();
  89 + jobTConfig.setParameter(key, value);
  90 + }
  91 + }
  92 + initJobQueue(jobTConfig);
  93 +
  94 + appContext.getBackendRegistrySrv().start();
  95 + }
  96 +
  97 + private void initJobQueue(Config config) {
  98 + JobQueueFactory factory = ServiceLoader.load(JobQueueFactory.class, config);
  99 + appContext.setExecutableJobQueue(factory.getExecutableJobQueue(config));
  100 + appContext.setExecutingJobQueue(factory.getExecutingJobQueue(config));
  101 + appContext.setCronJobQueue(factory.getCronJobQueue(config));
  102 + appContext.setRepeatJobQueue(factory.getRepeatJobQueue(config));
  103 + appContext.setSuspendJobQueue(factory.getSuspendJobQueue(config));
  104 + appContext.setJobFeedbackQueue(factory.getJobFeedbackQueue(config));
  105 + appContext.setNodeGroupStore(factory.getNodeGroupStore(config));
  106 + appContext.setJobLogger(new SmartJobLogger(appContext));
  107 + appContext.setNoRelyJobGenerator(new NoRelyJobGenerator(appContext));
  108 + }
  109 +
  110 + private void initAccess(Config config) {
  111 + BackendAccessFactory factory = ServiceLoader.load(BackendAccessFactory.class, config);
  112 + appContext.setBackendJobClientMAccess(factory.getBackendJobClientMAccess(config));
  113 + appContext.setBackendJobTrackerMAccess(factory.getJobTrackerMAccess(config));
  114 + appContext.setBackendTaskTrackerMAccess(factory.getBackendTaskTrackerMAccess(config));
  115 + appContext.setBackendJVMGCAccess(factory.getBackendJVMGCAccess(config));
  116 + appContext.setBackendJVMMemoryAccess(factory.getBackendJVMMemoryAccess(config));
  117 + appContext.setBackendJVMThreadAccess(factory.getBackendJVMThreadAccess(config));
  118 + appContext.setBackendNodeOnOfflineLogAccess(factory.getBackendNodeOnOfflineLogAccess(config));
  119 + appContext.setNodeMemCacheAccess(new NodeMemCacheAccess());
  120 + }
  121 +
  122 +}
... ...
  1 +package com.github.ltsopensource.admin.support;
  2 +
  3 +import org.slf4j.Logger;
  4 +import org.slf4j.LoggerFactory;
  5 +import org.springframework.beans.factory.annotation.Autowired;
  6 +import org.springframework.context.MessageSource;
  7 +
  8 +import java.util.Locale;
  9 +
  10 +/**
  11 + * @author Robert HG (254963746@qq.com) on 3/9/16.
  12 + */
  13 +public class I18nManager {
  14 +
  15 + private static final Logger logger = LoggerFactory.getLogger(I18nManager.class);
  16 +
  17 + private static MessageSource messageSource;
  18 +
  19 + @Autowired
  20 + public I18nManager(MessageSource messageSource) {
  21 + I18nManager.messageSource = messageSource;
  22 + }
  23 +
  24 + public static String getMessage(String messageKey) {
  25 + return resolveMessage(null, messageKey, null);
  26 + }
  27 +
  28 + public static String getMessage(String messageKey, Object... args) {
  29 + return resolveMessage(null, messageKey, args);
  30 + }
  31 +
  32 + public static String getMessage(Locale locale, String messageKey, Object... args) {
  33 + return resolveMessage(locale, messageKey, args);
  34 + }
  35 +
  36 + private static String resolveMessage(Locale locale, String key, Object[] args) {
  37 + if (locale == null) {
  38 + locale = new Locale("zh_CN");
  39 + }
  40 + try {
  41 + return messageSource.getMessage(key, args, locale);
  42 + } catch (Throwable t) {
  43 + logger.error("i18n error, message not found by key :" + key, t);
  44 + return key;
  45 + }
  46 + }
  47 +}
... ...
  1 +package com.github.ltsopensource.admin.support;
  2 +
  3 +import com.github.ltsopensource.admin.cluster.BackendAppContext;
  4 +import com.github.ltsopensource.admin.request.JvmDataReq;
  5 +import com.github.ltsopensource.admin.request.MDataPaginationReq;
  6 +import com.github.ltsopensource.admin.request.NodeOnOfflineLogPaginationReq;
  7 +import com.github.ltsopensource.core.commons.utils.Callable;
  8 +import com.github.ltsopensource.core.commons.utils.DateUtils;
  9 +import com.github.ltsopensource.core.commons.utils.QuietUtils;
  10 +import com.github.ltsopensource.core.factory.NamedThreadFactory;
  11 +import com.github.ltsopensource.core.logger.Logger;
  12 +import com.github.ltsopensource.core.logger.LoggerFactory;
  13 +import org.springframework.beans.factory.InitializingBean;
  14 +import org.springframework.beans.factory.annotation.Autowired;
  15 +
  16 +import java.util.Date;
  17 +import java.util.concurrent.Executors;
  18 +import java.util.concurrent.ScheduledExecutorService;
  19 +import java.util.concurrent.TimeUnit;
  20 +import java.util.concurrent.atomic.AtomicBoolean;
  21 +
  22 +/**
  23 + * 定时清除 monitor 数据
  24 + *
  25 + * @author Robert HG (254963746@qq.com) on 8/23/15.
  26 + */
  27 +public class LtsAdminDataCleaner implements InitializingBean {
  28 +
  29 + private static final Logger LOGGER = LoggerFactory.getLogger(LtsAdminDataCleaner.class);
  30 +
  31 + @Autowired
  32 + private BackendAppContext appContext;
  33 +
  34 + private ScheduledExecutorService cleanExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("LTS-Admin-Clean", true));
  35 +
  36 + private AtomicBoolean start = new AtomicBoolean(false);
  37 +
  38 + public void start() {
  39 + if (start.compareAndSet(false, true)) {
  40 + cleanExecutor.scheduleAtFixedRate(new Runnable() {
  41 + @Override
  42 + public void run() {
  43 + try {
  44 + clean();
  45 + } catch (Throwable t) {
  46 + LOGGER.error("Clean monitor data error ", t);
  47 + }
  48 + }
  49 + }, 1, 24, TimeUnit.HOURS);
  50 + LOGGER.info("LtsAdminDataCleaner start succeed ");
  51 + }
  52 + }
  53 +
  54 + private void clean() {
  55 + // 1. 清除TaskTracker JobTracker, JobClient的统计数据(3天之前的)
  56 + final MDataPaginationReq request = new MDataPaginationReq();
  57 + request.setEndTime(DateUtils.addDay(new Date(), -3).getTime());
  58 +
  59 + QuietUtils.doWithWarn(new Callable() {
  60 + @Override
  61 + public void call() throws Exception {
  62 + appContext.getBackendTaskTrackerMAccess().delete(request);
  63 + }
  64 + });
  65 + QuietUtils.doWithWarn(new Callable() {
  66 + @Override
  67 + public void call() throws Exception {
  68 + appContext.getBackendJobTrackerMAccess().delete(request);
  69 + }
  70 + });
  71 + QuietUtils.doWithWarn(new Callable() {
  72 + @Override
  73 + public void call() throws Exception {
  74 + appContext.getBackendJobClientMAccess().delete(request);
  75 + }
  76 + });
  77 +
  78 + // 2. 清除30天以前的节点上下线日志
  79 + final NodeOnOfflineLogPaginationReq nodeOnOfflineLogPaginationReq = new NodeOnOfflineLogPaginationReq();
  80 + nodeOnOfflineLogPaginationReq.setEndLogTime(DateUtils.addDay(new Date(), -30));
  81 +
  82 + QuietUtils.doWithWarn(new Callable() {
  83 + @Override
  84 + public void call() throws Exception {
  85 + appContext.getBackendNodeOnOfflineLogAccess().delete(nodeOnOfflineLogPaginationReq);
  86 + }
  87 + });
  88 +
  89 + // 3. 清除3天前的JVM监控信息
  90 + final JvmDataReq jvmDataReq = new JvmDataReq();
  91 + jvmDataReq.setEndTime(DateUtils.addDay(new Date(), -3).getTime());
  92 + QuietUtils.doWithWarn(new Callable() {
  93 + @Override
  94 + public void call() throws Exception {
  95 + appContext.getBackendJVMGCAccess().delete(jvmDataReq);
  96 + }
  97 + });
  98 + QuietUtils.doWithWarn(new Callable() {
  99 + @Override
  100 + public void call() throws Exception {
  101 + appContext.getBackendJVMThreadAccess().delete(jvmDataReq);
  102 + }
  103 + });
  104 + QuietUtils.doWithWarn(new Callable() {
  105 + @Override
  106 + public void call() throws Exception {
  107 + appContext.getBackendJVMMemoryAccess().delete(jvmDataReq);
  108 + }
  109 + });
  110 +
  111 + LOGGER.info("Clean monitor data succeed ");
  112 + }
  113 +
  114 + @Override
  115 + public void afterPropertiesSet() throws Exception {
  116 + start();
  117 + }
  118 +}
... ...
  1 +package com.github.ltsopensource.admin.support;
  2 +
  3 +import com.github.ltsopensource.core.commons.file.FileUtils;
  4 +import com.github.ltsopensource.core.commons.utils.PlatformUtils;
  5 +import com.github.ltsopensource.core.commons.utils.StringUtils;
  6 +import com.github.ltsopensource.core.compiler.AbstractCompiler;
  7 +import com.github.ltsopensource.core.constant.ExtConfig;
  8 +import com.github.ltsopensource.core.json.JSONFactory;
  9 +import com.github.ltsopensource.core.logger.LoggerFactory;
  10 +import com.github.ltsopensource.monitor.MonitorAgentStartup;
  11 +import org.apache.log4j.PropertyConfigurator;
  12 +
  13 +import javax.servlet.ServletContextEvent;
  14 +import javax.servlet.ServletContextListener;
  15 +
  16 +/**
  17 + * @author Robert HG (254963746@qq.com) on 9/2/15.
  18 + */
  19 +public class SystemInitListener implements ServletContextListener {
  20 +
  21 + @Override
  22 + public void contextInitialized(ServletContextEvent servletContextEvent) {
  23 +
  24 + String confPath = servletContextEvent.getServletContext().getInitParameter("lts.admin.config.path");
  25 + if (StringUtils.isNotEmpty(confPath)) {
  26 + System.out.println("lts.admin.config.path : " + confPath);
  27 + }
  28 + AppConfigurer.load(confPath);
  29 +
  30 + String compiler = AppConfigurer.getProperty("configs." + ExtConfig.COMPILER);
  31 + if (StringUtils.isNotEmpty(compiler)) {
  32 + AbstractCompiler.setCompiler(compiler);
  33 + }
  34 +
  35 + String jsonAdapter = AppConfigurer.getProperty("configs." + ExtConfig.LTS_JSON);
  36 + if (StringUtils.isNotEmpty(jsonAdapter)) {
  37 + JSONFactory.setJSONAdapter(jsonAdapter);
  38 + }
  39 +
  40 + String loggerAdapter = AppConfigurer.getProperty("configs." + ExtConfig.LTS_LOGGER);
  41 + if (StringUtils.isNotEmpty(loggerAdapter)) {
  42 + LoggerFactory.setLoggerAdapter(loggerAdapter);
  43 + }
  44 +
  45 + String log4jPath = confPath + "/log4j.properties";
  46 + if (FileUtils.exist(log4jPath)) {
  47 + // log4j 配置文件路径
  48 + PropertyConfigurator.configure(log4jPath);
  49 + }
  50 +
  51 + boolean monitorAgentEnable = Boolean.valueOf(AppConfigurer.getProperty("lts.monitorAgent.enable", "true"));
  52 + if (monitorAgentEnable) {
  53 + String ltsMonitorCfgPath = confPath;
  54 + if (StringUtils.isEmpty(ltsMonitorCfgPath)) {
  55 + ltsMonitorCfgPath = this.getClass().getResource("/").getPath();
  56 + if (PlatformUtils.isWindows()) {
  57 + // 替换window下空格问题
  58 + ltsMonitorCfgPath = ltsMonitorCfgPath.replaceAll("%20", " ");
  59 + }
  60 + }
  61 + MonitorAgentStartup.start(ltsMonitorCfgPath);
  62 + }
  63 + }
  64 +
  65 + @Override
  66 + public void contextDestroyed(ServletContextEvent servletContextEvent) {
  67 + MonitorAgentStartup.stop();
  68 + }
  69 +}
... ...
  1 +package com.github.ltsopensource.admin.web;
  2 +
  3 +import com.github.ltsopensource.admin.web.support.DateEditor;
  4 +import com.github.ltsopensource.admin.web.support.MapEditor;
  5 +import org.springframework.web.bind.ServletRequestDataBinder;
  6 +import org.springframework.web.bind.annotation.InitBinder;
  7 +
  8 +import java.util.Date;
  9 +import java.util.Map;
  10 +
  11 +/**
  12 + * @author Robert HG (254963746@qq.com) on 5/9/15.
  13 + */
  14 +public class AbstractMVC {
  15 +
  16 + @InitBinder
  17 + protected void initBinder(ServletRequestDataBinder binder) throws Exception {
  18 + //对于需要转换为Date类型的属性,使用DateEditor进行处理
  19 + binder.registerCustomEditor(Date.class, new DateEditor());
  20 + binder.registerCustomEditor(Map.class, "extParams", new MapEditor());
  21 + }
  22 +
  23 +}
... ...
  1 +package com.github.ltsopensource.admin.web.api;
  2 +
  3 +import com.github.ltsopensource.admin.cluster.BackendAppContext;
  4 +import com.github.ltsopensource.admin.request.JobQueueReq;
  5 +import com.github.ltsopensource.admin.response.PaginationRsp;
  6 +import com.github.ltsopensource.admin.web.AbstractMVC;
  7 +import com.github.ltsopensource.admin.web.support.Builder;
  8 +import com.github.ltsopensource.admin.web.vo.RestfulResponse;
  9 +import com.github.ltsopensource.biz.logger.JobLogUtils;
  10 +import com.github.ltsopensource.biz.logger.domain.LogType;
  11 +import com.github.ltsopensource.core.commons.utils.Assert;
  12 +import com.github.ltsopensource.core.commons.utils.StringUtils;
  13 +import com.github.ltsopensource.core.constant.Constants;
  14 +import com.github.ltsopensource.core.logger.Logger;
  15 +import com.github.ltsopensource.core.logger.LoggerFactory;
  16 +import com.github.ltsopensource.core.support.CronExpression;
  17 +import com.github.ltsopensource.core.support.JobUtils;
  18 +import com.github.ltsopensource.core.support.SystemClock;
  19 +import com.github.ltsopensource.queue.domain.JobPo;
  20 +import com.github.ltsopensource.store.jdbc.exception.DupEntryException;
  21 +import org.springframework.beans.factory.annotation.Autowired;
  22 +import org.springframework.web.bind.annotation.RequestMapping;
  23 +import org.springframework.web.bind.annotation.RestController;
  24 +
  25 +import java.text.ParseException;
  26 +import java.util.Date;
  27 +
  28 +/**
  29 + * @author Robert HG (254963746@qq.com) on 3/26/16.
  30 + */
  31 +@RestController
  32 +public class CronJobQueueApi extends AbstractMVC {
  33 +
  34 + private static final Logger LOGGER = LoggerFactory.getLogger(CronJobQueueApi.class);
  35 + @Autowired
  36 + private BackendAppContext appContext;
  37 +
  38 + @RequestMapping("/job-queue/cron-job-get")
  39 + public RestfulResponse cronJobGet(JobQueueReq request) {
  40 + PaginationRsp<JobPo> paginationRsp = appContext.getCronJobQueue().pageSelect(request);
  41 + RestfulResponse response = new RestfulResponse();
  42 + response.setSuccess(true);
  43 + response.setResults(paginationRsp.getResults());
  44 + response.setRows(paginationRsp.getRows());
  45 + return response;
  46 + }
  47 +
  48 + @RequestMapping("/job-queue/cron-job-update")
  49 + public RestfulResponse cronJobUpdate(JobQueueReq request) {
  50 + RestfulResponse response = new RestfulResponse();
  51 + // 检查参数
  52 + try {
  53 + Assert.hasLength(request.getJobId(), "jobId不能为空!");
  54 + Assert.hasLength(request.getCronExpression(), "cronExpression不能为空!");
  55 + } catch (IllegalArgumentException e) {
  56 + return Builder.build(false, e.getMessage());
  57 + }
  58 + try {
  59 + // 1. 检测 cronExpression是否是正确的
  60 + CronExpression expression = new CronExpression(request.getCronExpression());
  61 + Date nextTriggerTime = expression.getTimeAfter(new Date());
  62 + if (nextTriggerTime == null) {
  63 + return Builder.build(false, StringUtils.format("该CronExpression={} 已经没有执行时间点! 请重新设置或者直接删除。", request.getCronExpression()));
  64 + }
  65 + JobPo oldJobPo = appContext.getCronJobQueue().getJob(request.getJobId());
  66 + boolean success = appContext.getCronJobQueue().selectiveUpdateByJobId(request);
  67 + if (success) {
  68 + JobPo newJobPo = appContext.getCronJobQueue().getJob(request.getJobId());
  69 + try {
  70 + // 判断是否有relyOnPrevCycle变更
  71 + boolean relyOnPrevCycleChanged = !newJobPo.getRelyOnPrevCycle().equals(oldJobPo.getRelyOnPrevCycle());
  72 + boolean cronExpressionChanged = !newJobPo.getCronExpression().equals(oldJobPo.getCronExpression());
  73 +
  74 + // 1. 修改前relyOnPrevCycle=true,并且修改后也是true
  75 + if (oldJobPo.getRelyOnPrevCycle() && !relyOnPrevCycleChanged) {
  76 + // 看CronExpression是否有修改,如果有修改,需要更新triggerTime
  77 + if (cronExpressionChanged) {
  78 + request.setTriggerTime(nextTriggerTime);
  79 + }
  80 + appContext.getExecutableJobQueue().selectiveUpdateByJobId(request);
  81 + } else {
  82 + // 2. 需要对批量任务做处理
  83 + if (relyOnPrevCycleChanged) {
  84 + // 如果relyOnPrevCycle 修改过
  85 + if (oldJobPo.getRelyOnPrevCycle()) {
  86 + // 之前是依赖的,现在不依赖,需要生成批量任务
  87 + appContext.getExecutableJobQueue().remove(oldJobPo.getTaskTrackerNodeGroup(), oldJobPo.getJobId());
  88 + appContext.getNoRelyJobGenerator().generateCronJobForInterval(newJobPo, new Date());
  89 + } else {
  90 + // 之前不依赖,现在依赖,需要删除批量任务
  91 + appContext.getExecutableJobQueue().removeBatch(oldJobPo.getRealTaskId(), oldJobPo.getTaskTrackerNodeGroup());
  92 + // 添加新的任务
  93 + newJobPo.setTriggerTime(nextTriggerTime.getTime());
  94 + try {
  95 + newJobPo.setInternalExtParam(Constants.EXE_SEQ_ID, JobUtils.generateExeSeqId(newJobPo));
  96 + appContext.getExecutableJobQueue().add(newJobPo);
  97 + } catch (DupEntryException ignored) {
  98 + }
  99 + }
  100 + } else {
  101 + // 如果relyOnPrevCycle 没有修改过, 表示relyOnPrevCycle=false, 那么要看cronExpression是否修改过,如果修改过,需要删除重新生成
  102 + if (cronExpressionChanged) {
  103 + appContext.getExecutableJobQueue().removeBatch(oldJobPo.getRealTaskId(), oldJobPo.getTaskTrackerNodeGroup());
  104 + appContext.getNoRelyJobGenerator().generateCronJobForInterval(newJobPo, new Date());
  105 + } else {
  106 + appContext.getExecutableJobQueue().selectiveUpdateByTaskId(request);
  107 + }
  108 + }
  109 + }
  110 + } catch (Exception e) {
  111 + LOGGER.error(e.getMessage(), e);
  112 + return Builder.build(false, "更新等待执行的任务失败,请手动更新! error:" + e.getMessage());
  113 + }
  114 + response.setSuccess(true);
  115 + } else {
  116 + return Builder.build(false, "该任务已经被删除或者执行完成");
  117 + }
  118 + JobLogUtils.log(LogType.UPDATE, oldJobPo, appContext.getJobLogger());
  119 + return response;
  120 + } catch (ParseException e) {
  121 + LOGGER.error(e.getMessage(), e);
  122 + return Builder.build(false, "请输入正确的 CronExpression!" + e.getMessage());
  123 + }
  124 + }
  125 +
  126 + @RequestMapping("/job-queue/cron-job-delete")
  127 + public RestfulResponse cronJobDelete(JobQueueReq request) {
  128 + if (StringUtils.isEmpty(request.getJobId())) {
  129 + return Builder.build(false, "JobId 必须传!");
  130 + }
  131 + JobPo jobPo = appContext.getCronJobQueue().getJob(request.getJobId());
  132 + if (jobPo == null) {
  133 + return Builder.build(true, "已经删除");
  134 + }
  135 + boolean success = appContext.getCronJobQueue().remove(request.getJobId());
  136 + if (success) {
  137 + try {
  138 + appContext.getExecutableJobQueue().removeBatch(jobPo.getRealTaskId(), jobPo.getTaskTrackerNodeGroup());
  139 + } catch (Exception e) {
  140 + LOGGER.error(e.getMessage(), e);
  141 + return Builder.build(false, "删除等待执行的任务失败,请手动删除! error:{}" + e.getMessage());
  142 + }
  143 + }
  144 + JobLogUtils.log(LogType.DEL, jobPo, appContext.getJobLogger());
  145 +
  146 + return Builder.build(true, "ok");
  147 + }
  148 +
  149 + @RequestMapping("/job-queue/cron-job-suspend")
  150 + public RestfulResponse cronJobSuspend(JobQueueReq request) {
  151 + if (StringUtils.isEmpty(request.getJobId())) {
  152 + return Builder.build(false, "JobId 必须传!");
  153 + }
  154 + JobPo jobPo = appContext.getCronJobQueue().getJob(request.getJobId());
  155 + if (jobPo == null) {
  156 + return Builder.build(false, "任务不存在,或者已经删除");
  157 + }
  158 + try {
  159 + jobPo.setGmtModified(SystemClock.now());
  160 + appContext.getSuspendJobQueue().add(jobPo);
  161 + } catch (DupEntryException e) {
  162 + LOGGER.error(e.getMessage(), e);
  163 + return Builder.build(false, "该任务已经被暂停, 请检查暂停队列");
  164 + } catch (Exception e) {
  165 + LOGGER.error(e.getMessage(), e);
  166 + return Builder.build(false, "移动任务到暂停队列失败, error:" + e.getMessage());
  167 + }
  168 + try {
  169 + appContext.getCronJobQueue().remove(request.getJobId());
  170 + } catch (Exception e) {
  171 + LOGGER.error(e.getMessage(), e);
  172 + return Builder.build(false, "删除Cron任务失败,请手动删除! error:" + e.getMessage());
  173 + }
  174 + try {
  175 + if (!jobPo.getRelyOnPrevCycle()) {
  176 + appContext.getCronJobQueue().updateLastGenerateTriggerTime(jobPo.getJobId(), new Date().getTime());
  177 + appContext.getExecutableJobQueue().removeBatch(jobPo.getRealTaskId(), jobPo.getTaskTrackerNodeGroup());
  178 + } else {
  179 + appContext.getExecutableJobQueue().remove(request.getTaskTrackerNodeGroup(), request.getJobId());
  180 + }
  181 + } catch (Exception e) {
  182 + LOGGER.error(e.getMessage(), e);
  183 + return Builder.build(false, "删除等待执行的任务失败,请手动删除! error:" + e.getMessage());
  184 + }
  185 +
  186 + // 记录日志
  187 + JobLogUtils.log(LogType.SUSPEND, jobPo, appContext.getJobLogger());
  188 +
  189 + return Builder.build(true, "ok");
  190 + }
  191 +}
... ...
  1 +package com.github.ltsopensource.admin.web.api;
  2 +
  3 +import com.github.ltsopensource.admin.cluster.BackendAppContext;
  4 +import com.github.ltsopensource.admin.request.JobQueueReq;
  5 +import com.github.ltsopensource.admin.response.PaginationRsp;
  6 +import com.github.ltsopensource.admin.support.AppConfigurer;
  7 +import com.github.ltsopensource.admin.support.I18nManager;
  8 +import com.github.ltsopensource.admin.web.AbstractMVC;
  9 +import com.github.ltsopensource.admin.web.support.Builder;
  10 +import com.github.ltsopensource.admin.web.vo.RestfulResponse;
  11 +import com.github.ltsopensource.biz.logger.domain.JobLogPo;
  12 +import com.github.ltsopensource.biz.logger.domain.JobLoggerRequest;
  13 +import com.github.ltsopensource.cmd.DefaultHttpCmd;
  14 +import com.github.ltsopensource.cmd.HttpCmd;
  15 +import com.github.ltsopensource.cmd.HttpCmdClient;
  16 +import com.github.ltsopensource.cmd.HttpCmdResponse;
  17 +import com.github.ltsopensource.core.cluster.Node;
  18 +import com.github.ltsopensource.core.cluster.NodeType;
  19 +import com.github.ltsopensource.core.cmd.HttpCmdNames;
  20 +import com.github.ltsopensource.core.commons.utils.Assert;
  21 +import com.github.ltsopensource.core.commons.utils.CollectionUtils;
  22 +import com.github.ltsopensource.core.commons.utils.StringUtils;
  23 +import com.github.ltsopensource.core.domain.Job;
  24 +import com.github.ltsopensource.core.domain.Pair;
  25 +import com.github.ltsopensource.core.json.JSON;
  26 +import com.github.ltsopensource.core.support.CronExpression;
  27 +import com.github.ltsopensource.queue.domain.JobPo;
  28 +import org.springframework.beans.factory.annotation.Autowired;
  29 +import org.springframework.web.bind.annotation.RequestMapping;
  30 +import org.springframework.web.bind.annotation.RestController;
  31 +
  32 +import java.text.ParseException;
  33 +import java.util.ArrayList;
  34 +import java.util.Date;
  35 +import java.util.List;
  36 +import java.util.Map;
  37 +
  38 +/**
  39 + * @author Robert HG (254963746@qq.com) on 6/6/15.
  40 + */
  41 +@RestController
  42 +public class JobQueueApi extends AbstractMVC {
  43 +
  44 + @Autowired
  45 + private BackendAppContext appContext;
  46 +
  47 + @RequestMapping("/job-queue/executable-job-get")
  48 + public RestfulResponse executableJobGet(JobQueueReq request) {
  49 + PaginationRsp<JobPo> paginationRsp = appContext.getExecutableJobQueue().pageSelect(request);
  50 +
  51 + boolean needClear = Boolean.valueOf(AppConfigurer.getProperty("lts.admin.remove.running.job.on.executable.search", "false"));
  52 + if (needClear) {
  53 + paginationRsp = clearRunningJob(paginationRsp);
  54 + }
  55 + RestfulResponse response = new RestfulResponse();
  56 + response.setSuccess(true);
  57 + response.setResults(paginationRsp.getResults());
  58 + response.setRows(paginationRsp.getRows());
  59 + return response;
  60 + }
  61 +
  62 + /**
  63 + * 比较恶心的逻辑,当等待执行队列的任务同时也在执行中队列, 则不展示
  64 + */
  65 + private PaginationRsp<JobPo> clearRunningJob(PaginationRsp<JobPo> paginationRsp) {
  66 + if (paginationRsp == null || paginationRsp.getResults() == 0) {
  67 + return paginationRsp;
  68 + }
  69 + PaginationRsp<JobPo> rsp = new PaginationRsp<JobPo>();
  70 + List<JobPo> rows = new ArrayList<JobPo>();
  71 + for (JobPo jobPo : paginationRsp.getRows()) {
  72 + if (appContext.getExecutingJobQueue().getJob(jobPo.getTaskTrackerNodeGroup(), jobPo.getTaskId()) == null) {
  73 + // 没有正在执行, 则显示在等待执行列表中
  74 + rows.add(jobPo);
  75 + }
  76 + }
  77 + rsp.setRows(rows);
  78 + rsp.setResults(paginationRsp.getResults() - paginationRsp.getRows().size() - rows.size());
  79 + return rsp;
  80 + }
  81 +
  82 + @RequestMapping("/job-queue/executing-job-trigger")
  83 + public RestfulResponse triggerJobManually(JobQueueReq request) {
  84 +
  85 + try {
  86 + Assert.hasLength(request.getJobId(), "jobId不能为空!");
  87 + Assert.hasLength(request.getTaskTrackerNodeGroup(), "taskTrackerNodeGroup不能为空!");
  88 + } catch (IllegalArgumentException e) {
  89 + return Builder.build(false, e.getMessage());
  90 + }
  91 +
  92 + HttpCmd httpCmd = new DefaultHttpCmd();
  93 + httpCmd.setCommand(HttpCmdNames.HTTP_CMD_TRIGGER_JOB_MANUALLY);
  94 + httpCmd.addParam("jobId", request.getJobId());
  95 + httpCmd.addParam("nodeGroup", request.getTaskTrackerNodeGroup());
  96 +
  97 + List<Node> jobTrackerNodeList = appContext.getNodeMemCacheAccess().getNodeByNodeType(NodeType.JOB_TRACKER);
  98 + if (CollectionUtils.isEmpty(jobTrackerNodeList)) {
  99 + return Builder.build(false, I18nManager.getMessage("job.tracker.not.found"));
  100 + }
  101 +
  102 + HttpCmdResponse response = null;
  103 + for (Node node : jobTrackerNodeList) {
  104 + httpCmd.setNodeIdentity(node.getIdentity());
  105 + response = HttpCmdClient.doGet(node.getIp(), node.getHttpCmdPort(), httpCmd);
  106 + if (response.isSuccess()) {
  107 + return Builder.build(true);
  108 + }
  109 + }
  110 + if (response != null) {
  111 + return Builder.build(false, response.getMsg());
  112 + } else {
  113 + return Builder.build(false, "TriggerFailed failed");
  114 + }
  115 + }
  116 +
  117 + @RequestMapping("/job-queue/executing-job-get")
  118 + public RestfulResponse executingJobGet(JobQueueReq request) {
  119 + PaginationRsp<JobPo> paginationRsp = appContext.getExecutingJobQueue().pageSelect(request);
  120 + RestfulResponse response = new RestfulResponse();
  121 + response.setSuccess(true);
  122 + response.setResults(paginationRsp.getResults());
  123 + response.setRows(paginationRsp.getRows());
  124 + return response;
  125 + }
  126 +
  127 + @RequestMapping("/job-queue/executable-job-update")
  128 + public RestfulResponse executableJobUpdate(JobQueueReq request) {
  129 + // 检查参数
  130 + // 1. 检测 cronExpression是否是正确的
  131 + if (StringUtils.isNotEmpty(request.getCronExpression())) {
  132 + try {
  133 + CronExpression expression = new CronExpression(request.getCronExpression());
  134 + if (expression.getTimeAfter(new Date()) == null) {
  135 + return Builder.build(false, StringUtils.format("该CronExpression={} 已经没有执行时间点!", request.getCronExpression()));
  136 + }
  137 + } catch (ParseException e) {
  138 + return Builder.build(false, "请输入正确的 CronExpression!");
  139 + }
  140 + }
  141 + try {
  142 + Assert.hasLength(request.getJobId(), "jobId不能为空!");
  143 + Assert.hasLength(request.getTaskTrackerNodeGroup(), "taskTrackerNodeGroup不能为空!");
  144 + } catch (IllegalArgumentException e) {
  145 + return Builder.build(false, e.getMessage());
  146 + }
  147 + boolean success = appContext.getExecutableJobQueue().selectiveUpdateByJobId(request);
  148 + RestfulResponse response = new RestfulResponse();
  149 + if (success) {
  150 + response.setSuccess(true);
  151 + } else {
  152 + response.setSuccess(false);
  153 + response.setCode("DELETE_OR_RUNNING");
  154 + }
  155 + return response;
  156 + }
  157 +
  158 + @RequestMapping("/job-queue/executable-job-delete")
  159 + public RestfulResponse executableJobDelete(JobQueueReq request) {
  160 + try {
  161 + Assert.hasLength(request.getJobId(), "jobId不能为空!");
  162 + Assert.hasLength(request.getTaskTrackerNodeGroup(), "taskTrackerNodeGroup不能为空!");
  163 + } catch (IllegalArgumentException e) {
  164 + return Builder.build(false, e.getMessage());
  165 + }
  166 +
  167 + boolean success = appContext.getExecutableJobQueue().remove(request.getTaskTrackerNodeGroup(), request.getJobId());
  168 + if (success) {
  169 + if (StringUtils.isNotEmpty(request.getCronExpression()) && !"null".equals(request.getCronExpression())) {
  170 + // 是Cron任务, Cron任务队列的也要被删除
  171 + try {
  172 + appContext.getCronJobQueue().remove(request.getJobId());
  173 + } catch (Exception e) {
  174 + return Builder.build(false, "在Cron任务队列中删除该任务失败,请手动更新! error:" + e.getMessage());
  175 + }
  176 + }
  177 + return Builder.build(true);
  178 + } else {
  179 + return Builder.build(false, "更新失败,该条任务可能已经删除.");
  180 + }
  181 + }
  182 +
  183 + @RequestMapping("/job-logger/job-logger-get")
  184 + public RestfulResponse jobLoggerGet(JobLoggerRequest request) {
  185 + RestfulResponse response = new RestfulResponse();
  186 +
  187 + PaginationRsp<JobLogPo> paginationRsp = appContext.getJobLogger().search(request);
  188 + response.setResults(paginationRsp.getResults());
  189 + response.setRows(paginationRsp.getRows());
  190 +
  191 + response.setSuccess(true);
  192 + return response;
  193 + }
  194 +
  195 + /**
  196 + * 给JobTracker发消息 加载任务到内存
  197 + */
  198 + @RequestMapping("/job-queue/load-add")
  199 + public RestfulResponse loadJob(JobQueueReq request) {
  200 + RestfulResponse response = new RestfulResponse();
  201 +
  202 + String nodeGroup = request.getTaskTrackerNodeGroup();
  203 +
  204 + HttpCmd httpCmd = new DefaultHttpCmd();
  205 + httpCmd.setCommand(HttpCmdNames.HTTP_CMD_LOAD_JOB);
  206 + httpCmd.addParam("nodeGroup", nodeGroup);
  207 +
  208 + List<Node> jobTrackerNodeList = appContext.getNodeMemCacheAccess().getNodeByNodeType(NodeType.JOB_TRACKER);
  209 + if (CollectionUtils.isEmpty(jobTrackerNodeList)) {
  210 + response.setMsg(I18nManager.getMessage("job.tracker.not.found"));
  211 + response.setSuccess(false);
  212 + return response;
  213 + }
  214 +
  215 + boolean success = false;
  216 + HttpCmdResponse cmdResponse = null;
  217 + for (Node node : jobTrackerNodeList) {
  218 + // 所有的JobTracker都load一遍
  219 + httpCmd.setNodeIdentity(node.getIdentity());
  220 + cmdResponse = HttpCmdClient.doGet(node.getIp(), node.getHttpCmdPort(), httpCmd);
  221 + if (cmdResponse.isSuccess()) {
  222 + success = true;
  223 + }
  224 + }
  225 + if (success) {
  226 + response.setMsg("Load success");
  227 + } else {
  228 + response.setMsg("Load failed");
  229 + }
  230 + response.setSuccess(success);
  231 + return response;
  232 + }
  233 +
  234 + @RequestMapping("/job-queue/job-add")
  235 + public RestfulResponse jobAdd(String jobType, JobQueueReq request) {
  236 + // 表单check
  237 +
  238 + try {
  239 + Assert.hasLength(request.getTaskId(), I18nManager.getMessage("taskId.not.null"));
  240 + Assert.hasLength(request.getTaskTrackerNodeGroup(), "taskTrackerNodeGroup不能为空!");
  241 + if (request.getNeedFeedback()) {
  242 + Assert.hasLength(request.getSubmitNodeGroup(), "submitNodeGroup不能为空!");
  243 + }
  244 +
  245 + if (StringUtils.isNotEmpty(request.getCronExpression())) {
  246 + try {
  247 + CronExpression expression = new CronExpression(request.getCronExpression());
  248 + Date nextTime = expression.getTimeAfter(new Date());
  249 + if (nextTime == null) {
  250 + return Builder.build(false, StringUtils.format("该CronExpression={} 已经没有执行时间点!", request.getCronExpression()));
  251 + } else {
  252 + request.setTriggerTime(nextTime);
  253 + }
  254 + } catch (ParseException e) {
  255 + return Builder.build(false, "请输入正确的 CronExpression!");
  256 + }
  257 + }
  258 +
  259 + } catch (IllegalArgumentException e) {
  260 + return Builder.build(false, e.getMessage());
  261 + }
  262 +
  263 + Pair<Boolean, String> pair = addJob(jobType, request);
  264 + return Builder.build(pair.getKey(), pair.getValue());
  265 + }
  266 +
  267 + private Pair<Boolean, String> addJob(String jobType, JobQueueReq request) {
  268 +
  269 + Job job = new Job();
  270 + job.setTaskId(request.getTaskId());
  271 + if (CollectionUtils.isNotEmpty(request.getExtParams())) {
  272 + for (Map.Entry<String, String> entry : request.getExtParams().entrySet()) {
  273 + job.setParam(entry.getKey(), entry.getValue());
  274 + }
  275 + }
  276 + // 执行节点的group名称
  277 + job.setTaskTrackerNodeGroup(request.getTaskTrackerNodeGroup());
  278 + job.setSubmitNodeGroup(request.getSubmitNodeGroup());
  279 +
  280 + job.setNeedFeedback(request.getNeedFeedback());
  281 + job.setReplaceOnExist(true);
  282 +
  283 + // 这个是 cron expression 和 quartz 一样,可选
  284 + job.setCronExpression(request.getCronExpression());
  285 + if (request.getTriggerTime() != null) {
  286 + job.setTriggerTime(request.getTriggerTime().getTime());
  287 + }
  288 + job.setRepeatCount(request.getRepeatCount() == null ? 0 : request.getRepeatCount());
  289 + job.setRepeatInterval(request.getRepeatInterval());
  290 +
  291 + job.setPriority(request.getPriority());
  292 + job.setMaxRetryTimes(request.getMaxRetryTimes() == null ? 0 : request.getMaxRetryTimes());
  293 + job.setRelyOnPrevCycle(request.getRelyOnPrevCycle() == null ? true : request.getRelyOnPrevCycle());
  294 +
  295 + if ("REAL_TIME_JOB".equals(jobType)) {
  296 + job.setCronExpression(null);
  297 + job.setTriggerTime(null);
  298 + job.setRepeatInterval(null);
  299 + job.setRepeatCount(0);
  300 + job.setRelyOnPrevCycle(true);
  301 + } else if ("TRIGGER_TIME_JOB".equals(jobType)) {
  302 + job.setCronExpression(null);
  303 + job.setRepeatInterval(null);
  304 + job.setRepeatCount(0);
  305 + job.setRelyOnPrevCycle(true);
  306 + } else if ("CRON_JOB".equals(jobType)) {
  307 + job.setRepeatInterval(null);
  308 + job.setRepeatCount(0);
  309 + } else if ("REPEAT_JOB".equals(jobType)) {
  310 + job.setCronExpression(null);
  311 + }
  312 + return addJob(job);
  313 + }
  314 +
  315 + private Pair<Boolean, String> addJob(Job job) {
  316 + HttpCmd httpCmd = new DefaultHttpCmd();
  317 + httpCmd.setCommand(HttpCmdNames.HTTP_CMD_ADD_JOB);
  318 + httpCmd.addParam("job", JSON.toJSONString(job));
  319 +
  320 + List<Node> jobTrackerNodeList = appContext.getNodeMemCacheAccess().getNodeByNodeType(NodeType.JOB_TRACKER);
  321 + if (CollectionUtils.isEmpty(jobTrackerNodeList)) {
  322 + return new Pair<Boolean, String>(false, I18nManager.getMessage("job.tracker.not.found"));
  323 + }
  324 +
  325 + HttpCmdResponse response = null;
  326 + for (Node node : jobTrackerNodeList) {
  327 + httpCmd.setNodeIdentity(node.getIdentity());
  328 + response = HttpCmdClient.doGet(node.getIp(), node.getHttpCmdPort(), httpCmd);
  329 + if (response.isSuccess()) {
  330 + return new Pair<Boolean, String>(true, "Add success");
  331 + }
  332 + }
  333 + if (response != null) {
  334 + return new Pair<Boolean, String>(false, response.getMsg());
  335 + } else {
  336 + return new Pair<Boolean, String>(false, "Add failed");
  337 + }
  338 + }
  339 +
  340 + @RequestMapping("/job-queue/executing-job-terminate")
  341 + public RestfulResponse jobTerminate(String jobId) {
  342 +
  343 + JobPo jobPo = appContext.getExecutingJobQueue().getJob(jobId);
  344 + if (jobPo == null) {
  345 + return Builder.build(false, "该任务已经执行完成或者被删除");
  346 + }
  347 +
  348 + String taskTrackerIdentity = jobPo.getTaskTrackerIdentity();
  349 +
  350 + Node node = appContext.getNodeMemCacheAccess().getNodeByIdentity(taskTrackerIdentity);
  351 + if (node == null) {
  352 + return Builder.build(false, "执行该任务的TaskTracker已经离线");
  353 + }
  354 +
  355 + HttpCmd cmd = new DefaultHttpCmd();
  356 + cmd.setCommand(HttpCmdNames.HTTP_CMD_JOB_TERMINATE);
  357 + cmd.setNodeIdentity(taskTrackerIdentity);
  358 + cmd.addParam("jobId", jobId);
  359 + HttpCmdResponse response = HttpCmdClient.doPost(node.getIp(), node.getHttpCmdPort(), cmd);
  360 + if (response.isSuccess()) {
  361 + return Builder.build(true);
  362 + } else {
  363 + return Builder.build(false, response.getMsg());
  364 + }
  365 + }
  366 +}
... ...
  1 +package com.github.ltsopensource.admin.web.api;
  2 +
  3 +import com.github.ltsopensource.admin.cluster.BackendAppContext;
  4 +import com.github.ltsopensource.admin.support.I18nManager;
  5 +import com.github.ltsopensource.admin.web.AbstractMVC;
  6 +import com.github.ltsopensource.admin.web.support.Builder;
  7 +import com.github.ltsopensource.admin.web.vo.RestfulResponse;
  8 +import com.github.ltsopensource.cmd.DefaultHttpCmd;
  9 +import com.github.ltsopensource.cmd.HttpCmd;
  10 +import com.github.ltsopensource.cmd.HttpCmdClient;
  11 +import com.github.ltsopensource.cmd.HttpCmdResponse;
  12 +import com.github.ltsopensource.core.cluster.Node;
  13 +import com.github.ltsopensource.core.cmd.HttpCmdNames;
  14 +import org.springframework.beans.factory.annotation.Autowired;
  15 +import org.springframework.web.bind.annotation.RequestMapping;
  16 +import org.springframework.web.bind.annotation.RestController;
  17 +
  18 +import java.util.Collections;
  19 +
  20 +/**
  21 + * @author Robert HG (254963746@qq.com) on 9/28/15.
  22 + */
  23 +@RestController
  24 +@RequestMapping("/jvm")
  25 +public class JvmDataApi extends AbstractMVC {
  26 +
  27 + @Autowired
  28 + private BackendAppContext appContext;
  29 +
  30 + @RequestMapping("node-jvm-info-get")
  31 + public RestfulResponse getNodeList(String identity) {
  32 +
  33 + RestfulResponse restfulResponse = new RestfulResponse();
  34 +
  35 + Node node = appContext.getNodeMemCacheAccess().getNodeByIdentity(identity);
  36 +
  37 + if (node == null) {
  38 + return Builder.build(false, I18nManager.getMessage("node.dose.not.alive"));
  39 + }
  40 +
  41 + HttpCmd cmd = new DefaultHttpCmd();
  42 + cmd.setCommand(HttpCmdNames.HTTP_CMD_JVM_INFO_GET);
  43 + cmd.setNodeIdentity(identity);
  44 +
  45 + HttpCmdResponse response = HttpCmdClient.doGet(node.getIp(), node.getHttpCmdPort(), cmd);
  46 + if (response.isSuccess()) {
  47 + restfulResponse.setSuccess(true);
  48 + restfulResponse.setResults(1);
  49 + restfulResponse.setRows(Collections.singletonList(response.getObj()));
  50 + } else {
  51 + restfulResponse.setSuccess(false);
  52 + restfulResponse.setMsg(response.getMsg());
  53 + }
  54 +
  55 + return restfulResponse;
  56 + }
  57 +
  58 +}
... ...