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.
.gitattributes
0 → 100644
LICENSE
0 → 100644
| 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. | ... | ... |
README.md
0 → 100644
| 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 | + | |
| 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 | + | |
| 67 | + | |
| 68 | +## LTS-Admin新版界面预览 | |
| 69 | + | |
| 70 | + | |
| 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 欢迎投递 | ... | ... |
build.cmd
0 → 100644
| 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 ..\..\ | ... | ... |
build.sh
0 → 100644
| 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 | ... | ... |
docs/LTS 使用说明文档.pdf
0 → 100644
No preview for this file type
130 KB
docs/LTS-Admin/LTS-Admin-cron-job-queue.png
0 → 100644
115 KB
docs/LTS-Admin/LTS-Admin-job-add.png
0 → 100644
110 KB
docs/LTS_Spring全注解使用说明.md
0 → 100644
| 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 | +``` | ... | ... |
docs/LTS_architecture.png
0 → 100644
92.9 KB
docs/LTS_progress.png
0 → 100644
95.8 KB
docs/LTS一个TaskTracker执行多种任务.pdf
0 → 100644
No preview for this file type
docs/LTS业务场景说明.pdf
0 → 100644
No preview for this file type
docs/LTS文档.md
0 → 100644
| 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 | + | |
| 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 | + | |
| 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 | + | ... | ... |
docs/OLD_README.md
0 → 100644
| 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 | + | |
| 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 | + | |
| 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 | ... | ... |
docs/osc&github同时推送数据.txt
0 → 100644
| 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 | + | ... | ... |
docs/包引入说明.md
0 → 100644
| 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 | + | ... | ... |
lts-admin/pom.xml
0 → 100644
| 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 | +} | ... | ... |
lts-admin/src/main/java/com/github/ltsopensource/admin/access/domain/NodeOnOfflineLog.java
0 → 100644
| 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 | +} | ... | ... |
lts-admin/src/main/java/com/github/ltsopensource/admin/access/face/BackendJVMGCAccess.java
0 → 100644
| 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 | +} | ... | ... |
lts-admin/src/main/java/com/github/ltsopensource/admin/access/face/BackendJVMMemoryAccess.java
0 → 100644
| 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 | +} | ... | ... |
lts-admin/src/main/java/com/github/ltsopensource/admin/access/face/BackendJVMThreadAccess.java
0 → 100644
| 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 | +} | ... | ... |
lts-admin/src/main/java/com/github/ltsopensource/admin/access/face/BackendJobClientMAccess.java
0 → 100644
| 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 | +} | ... | ... |
lts-admin/src/main/java/com/github/ltsopensource/admin/access/face/BackendJobTrackerMAccess.java
0 → 100644
| 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 | +} | ... | ... |
lts-admin/src/main/java/com/github/ltsopensource/admin/access/face/BackendTaskTrackerMAccess.java
0 → 100644
| 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 | +} | ... | ... |
lts-admin/src/main/java/com/github/ltsopensource/admin/access/memory/NodeMemCacheAccess.java
0 → 100644
| 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 | +} | ... | ... |
lts-admin/src/main/java/com/github/ltsopensource/admin/access/mysql/MysqlBackendAccessFactory.java
0 → 100644
| 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 | +} | ... | ... |
lts-admin/src/main/java/com/github/ltsopensource/admin/access/mysql/MysqlBackendJVMGCAccess.java
0 → 100644
| 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 | +} | ... | ... |
lts-admin/src/main/java/com/github/ltsopensource/admin/access/mysql/MysqlBackendJVMMemoryAccess.java
0 → 100644
| 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 | +} | ... | ... |
lts-admin/src/main/java/com/github/ltsopensource/admin/access/mysql/MysqlBackendJVMThreadAccess.java
0 → 100644
| 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 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 | +} | ... | ... |
lts-admin/src/main/java/com/github/ltsopensource/admin/request/NodeOnOfflineLogPaginationReq.java
0 → 100644
| 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 | +} | ... | ... |
lts-admin/src/main/java/com/github/ltsopensource/admin/support/BackendAppContextFactoryBean.java
0 → 100644
| 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 | +} | ... | ... |