Skip to content

Commit dbda99d

Browse files
committed
README
1 parent 0125081 commit dbda99d

File tree

1 file changed

+123
-40
lines changed

1 file changed

+123
-40
lines changed

README.md

Lines changed: 123 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,96 @@
1-
### javaagent 技术
1+
### 项目介绍
22

3-
#### 1、技术点
3+
#### 1、抛出问题
4+
5+
- 在基于 JAVA (SpringBoot)开发定时任务时,一般的情况下会使用以下几种进行实现
6+
- Xxl
7+
- Quartz
8+
- Spring 注解 @Scheduled
9+
- 定时任务开发完成后,需要针对定时任务进行测试,一般的测试思路
10+
1. 写 http 接口对外暴露进行测试,可能需要给每一个定时任务都需要写一个接口
11+
2. 一般定时任务是基于 Cron 表达式写在配置文件中,通过修改定配合重启服务进行测试
12+
13+
> 以上发现基于上面的测试方式很麻烦且很费时,浪费大量开发和测试时间
14+
15+
#### 2、解决思路
16+
17+
- 分析常见的定时任务实现原理,找到存储定时任务的地方(源码阅读): 针对 Xxl、Quartz、Spring 注解 @Scheduled 进行源码分析
18+
- 针对不同实现的定时任务暴露2个 http 接口,可对其进行立即执行和CRUD操作(接口定义): 约定对外暴露 http 接口的入参出参
19+
- 暴露的 http 接口可针对定时任务进行传参测试(可先写死): 在 controller 中写死逻辑
20+
- 做到代码无侵入(最终目标): 使用 javaagent 技术进行代理实现
21+
22+
#### 4、实现技术
423

524
- javaagent
6-
- javassist
7-
- xxl job
8-
- quartz job
9-
- spring job
10-
- simple 自定义 job
25+
- Javassist、ASM、ByteBuddy
26+
- Xxl、Spring、Quartz、Simple(基于Spring) 定时任务
27+
28+
#### 5、使用说明
29+
30+
1. git 拉取项目
31+
32+
```sh
33+
git clone [email protected]:wangchirl/javaagent.git
34+
```
35+
36+
2. 进入项目使用 maven 打包
37+
38+
```sh
39+
cd javaagent
40+
mvn clean package -Dmaven.test.skip=true
41+
```
42+
43+
3. git 拉取测试项目
44+
45+
```sh
46+
git clone [email protected]:wangchirl/scheduler.git
47+
```
48+
49+
4. 进入项目使用 maven 打包
50+
51+
```sh
52+
cd scheduler
53+
mvn clean package -Dmaven.test.skip=true
54+
```
1155

12-
#### 2、说明
56+
5. 进入测试项目target目录下,执行脚本
1357

14-
- 定时任务开发完成后,如果要进行测试时,需要修改定时任务时间,不能立即执行,测试不方便
15-
- 项目针对以上问题做了针对以上定时任务实现方式的代理实现,利用 javaagent 技术,无侵入
16-
- 此项目可直接打包为 jar 包
17-
- 可结合测试仓库进行测试,测试仓库地址 :https://github.com/wangchirl/scheduler.git
18-
- 源码以开源,可根据自己需求进行改造
19-
- 后续版本将使用 ASM 、Byte buddy 来对项目进行改造
20-
- 目前实现了 load time 、dynamic 的 javassist 实现方式,其他方式将在后续进行实现
58+
```sh
59+
java -javaagent:本地路径(替换为自己的)\javaagent\target\SuperAgent-jar-with-dependencies.jar=ctlClass=com.shadow.controller.AgentBaseController,tlClass=com.shadow.supports.framework.ScheduleService,tlFieldName=JOB_PARAMETERS_THREAD_LOCAL,debug=true,logger=true,crudFieldName=xxxx,crud=true,proxyType=asm,jobType=spring -jar shadow.jar
60+
```
2161

22-
#### 3、针对测试仓库进行测试的相关说明
62+
6. 测试定时任务立即执行及CRUD
2363

64+
```sh
65+
# 执行定时任务 [spring2] 为 spring 定时任务的方法名称
66+
# 立即执行 请求参数为 test Spring
67+
curl localhost:50084/shadow/api/system/agent/run/spring2?params=test%20Spring
68+
# 修改 cron 表达式为 0/3 * * * * ?
69+
curl localhost:50084/shadow/api/system/agent/crud/1/spring1?cron=0/3%20*%20*%20*%20*%20?
70+
```
71+
72+
7. 可在本地自行导入 [postman 测试文件](./javaagent+schedule项目POSTMAN测试.json) 进行测试
73+
74+
#### 6、特别说明
75+
76+
> 接口说明:
77+
>
78+
> - 立即执行路径:/agent/run/{taskKey}
79+
> - CRUD路径:/agent/crud/{operation}/{taskKey}
80+
>
81+
> > 动态参数说明:
82+
> >
83+
> > - taskKey(字符串)
84+
> >
85+
> > 定时任务名称
86+
> >
87+
> > - operation (数字)
88+
> >
89+
> > - 0 删除定时任务
90+
> > - 1 添加定时任务
91+
> > - 2 更新定时任务
92+
> > - 其他数字 查询定时任务
93+
>
2494
> 参数说明:
2595
>
2696
> ##### Load time 参数:
@@ -34,6 +104,7 @@
34104
> - methodBody :暴露 HTTP 请求的方法体,已提供以上四种定时任务实现方式【可选】
35105
> - httpUri :暴露 HTTP 请求的 URI 前缀,会拼接上 /{taskKey} ,默认 /agent/run【可选】
36106
> - debug :是否 debug 模式,次模式方便调试,可生成对应的增强的 controller 类信息文件【可选】
107+
> - logger :打印 agent 中的一些提示信息【可选】
37108
>
38109
> ##### Dynamic time 参数:
39110
>
@@ -49,17 +120,20 @@
49120
> > - methodName :暴露 HTTP 请求的方法的名称,有默认值【可选】
50121
> > - methodBody :暴露 HTTP 请求的方法体,已提供以上四种定时任务实现方式【可选】
51122
> > - debug :是否 debug 模式,此模式方便调试,可生成对应的增强的 controller 类信息文件【可选】
123+
> > - logger :打印 agent 中的一些提示信息【可选】
52124
53125
- xxl job 测试
54126

55127
```sh
56128
# 启动项目
57-
-javaagent:F:\source\javaagent\target\SuperAgent-jar-with-dependencies.jar=jobType=XXL&ctlClass=com.shadow.controller.AgentBaseController&debug=true&tlClass=com.shadow.supports.framework.ScheduleService&tlFieldName=JOB_PARAMETERS_THREAD_LOCAL
129+
java -javaagent:本地路径(替换为自己的)\javaagent\target\SuperAgent-jar-with-dependencies.jar=ctlClass=com.shadow.controller.AgentBaseController,tlClass=com.shadow.supports.framework.ScheduleService,tlFieldName=JOB_PARAMETERS_THREAD_LOCAL,debug=true,logger=true,crudFieldName=xxxx,crud=true,proxyType=asm,jobType=xxl -jar shadow.jar
58130
```
59131

60132
```sh
61133
# 执行定时任务 [xxl2] 为定时任务JOB NAME
62-
localhost:50084/shadow/api/system/agent/run/xxl2?params=王钦测试Xxl
134+
curl localhost:50084/shadow/api/system/agent/run/xxl2?params=testXxl
135+
# XXL 只有查询实现,因为其调度器和执行器是分离的
136+
curl localhost:50084/shadow/api/system/agent/crud/1/1
63137
```
64138

65139

@@ -68,12 +142,14 @@
68142

69143
```sh
70144
# 启动项目
71-
-javaagent:F:\source\javaagent\target\SuperAgent-jar-with-dependencies.jar=jobType=QUARTZ&ctlClass=com.shadow.controller.AgentBaseController&debug=true&tlClass=com.shadow.supports.framework.ScheduleService&tlFieldName=JOB_PARAMETERS_THREAD_LOCAL
145+
java -javaagent:本地路径(替换为自己的)\javaagent\target\SuperAgent-jar-with-dependencies.jar=ctlClass=com.shadow.controller.AgentBaseController,tlClass=com.shadow.supports.framework.ScheduleService,tlFieldName=JOB_PARAMETERS_THREAD_LOCAL,debug=true,logger=true,crudFieldName=xxxx,crud=true,proxyType=asm,jobType=quartz -jar shadow.jar
72146
```
73147

74148
```sh
75149
# 执行定时任务 [quartzTriggerKey] 为 Trigger Bean,[quartzJob]为 job detail ID
76-
localhost:50084/shadow/api/system/agent/run/quartzTriggerKey?params=quartzJob
150+
curl -H "Content-Type:application/json" -X POST --data "{\"name\":\"shadow\",\"age\":20}" localhost:50084/shadow/api/system/agent/run/quartzTriggerKey?params=quartzJob
151+
# 修改 cron 表达式为 0/3 * * * * ?
152+
curl localhost:50084/shadow/api/system/agent/crud/1/quartzTriggerKey@quartzJob?cron=0/3%20*%20*%20*%20*%20?
77153
```
78154

79155
> Quartz 定时任务存在特殊性:
@@ -85,12 +161,15 @@
85161

86162
```sh
87163
# 启动项目
88-
-javaagent:F:\source\javaagent\target\SuperAgent-jar-with-dependencies.jar=jobType=SPRING&ctlClass=com.shadow.controller.AgentBaseController&debug=true&tlClass=com.shadow.supports.framework.ScheduleService&tlFieldName=JOB_PARAMETERS_THREAD_LOCAL
164+
java -javaagent:本地路径(替换为自己的)\javaagent\target\SuperAgent-jar-with-dependencies.jar=ctlClass=com.shadow.controller.AgentBaseController,tlClass=com.shadow.supports.framework.ScheduleService,tlFieldName=JOB_PARAMETERS_THREAD_LOCAL,debug=true,logger=true,crudFieldName=xxxx,crud=true,proxyType=asm,jobType=spring -jar shadow.jar
89165
```
90166

91167
```sh
92168
# 执行定时任务 [spring2] 为 spring 定时任务的方法名称
93-
localhost:50084/shadow/api/system//agent/run/spring2?params=王钦测试Spring
169+
# 立即执行 请求参数为 test Spring
170+
curl localhost:50084/shadow/api/system/agent/run/spring2?params=test%20Spring
171+
# 修改 cron 表达式为 0/3 * * * * ?
172+
curl localhost:50084/shadow/api/system/agent/crud/1/spring1?cron=0/3%20*%20*%20*%20*%20?
94173
```
95174

96175

@@ -99,37 +178,41 @@
99178

100179
```sh
101180
# 启动项目
102-
-javaagent:F:\source\javaagent\target\SuperAgent-jar-with-dependencies.jar=jobType=SIMPLE&ctlClass=com.shadow.controller.AgentBaseController&debug=true&tlClass=com.shadow.supports.framework.ScheduleService&tlFieldName=JOB_PARAMETERS_THREAD_LOCAL
181+
java -javaagent:本地路径(替换为自己的)\javaagent\target\SuperAgent-jar-with-dependencies.jar=ctlClass=com.shadow.controller.AgentBaseController,tlClass=com.shadow.supports.framework.ScheduleService,tlFieldName=JOB_PARAMETERS_THREAD_LOCAL,debug=true,logger=true,crudFieldName=xxxx,crud=true,proxyType=asm,jobType=simple -jar shadow.jar
103182
```
104183

105184
```sh
106185
# 执行定时任务 [simple1] 为 spring 容器 Bean 名称
107-
localhost:50084/shadow/api/system//agent/run/simple1?王钦测试Simple
186+
curl localhost:50084/shadow/api/system//agent/run/simple1?testSimple
187+
# 修改 cron 表达式为 0/3 * * * * ?
188+
curl localhost:50084/shadow/api/system/agent/crud/1/simple2?cron=0/3%20*%20*%20*%20*%20?
108189
```
109190

110191

111-
#### 4、最全的 agent 请求参数传递
192+
#### 7、最全的 agent 请求参数传递
112193

113194
> ```sh
114-
> -javaagent:F:\source\javaagent\target\SuperAgent-jar-with-dependencies.jar=jobType=XXL&ctlClass=com.shadow.controller.AgentBaseController&tlClass=com.shadow.supports.framework.ScheduleService&tlFieldName=JOB_PARAMETERS_THREAD_LOCAL&methodName=testMethod&iocFieldName=ioc&httpUri=/test/run&debug=true
195+
> java -javaagent:本地路径(替换为自己的)\javaagent\target\SuperAgent-jar-with-dependencies.jar=ctlClass=com.shadow.controller.AgentBaseController,tlClass=com.shadow.supports.framework.ScheduleService,tlFieldName=JOB_PARAMETERS_THREAD_LOCAL,debug=true,logger=true,httpUri=/test/run,methodName=testMethod,iocFieldName=ioc,crudFieldName=xxxx,crud=true,proxyType=asm,jobType=simple -jar shadow.jar
115196
> ```
116197
>
117198
> 说明:
118199
>
119-
> - 定时任务类型为 XXL
120-
> - 暴露 HTTP 的 controller 是 com.shadow.controller.AgentBaseController
121-
> - ThreadLocal 参数传递的类是 com.shadow.supports.framework.ScheduleService
122-
> - ThreadLocal 对象的字段名称是 JOB_PARAMETERS_THREAD_LOCAL
123-
> - 暴露 HTTP 接口方法名称是 testMethod
124-
> - 注入到 controller 类中的 Spring IOC 容器字段名称是 ioc
125-
> - HTTP 请求路径是 当前 controller 的 path + /test/run/{taskKey}
126-
> - debug 是 true,会在当前位置生成所增强的 controller 的字节码文件
127-
128-
#### 5、postman 相关测试在同目录下的 `javaagent+schedule项目POSTMAN测试.json`
129-
130-
131-
132-
#### 6、Attach 机制 - 可动态替换定时任务类型
200+
> - jobType :定时任务类型为 XXL
201+
> - proxyType :asm 表示使用 ASM 代理,可选 buddy 和 javassist
202+
> - crud :true 表示暴露 CRUD 接口
203+
> - crudFieldName :crud 需要使用的字段名称,避免和代理类字段冲突使用 xxxx
204+
> - iocFieldName :spring ioc 的字段名称,避免和代理类中 spring ioc 名称的冲突使用 ioc
205+
> - methodName :立即执行接口的方法名称,避免和代理类方法名称冲突使用 testMethod
206+
> - httpUri :立即执行接口的路径,避免和代理类路径冲突使用 /test/run/{taskKey}
207+
> - logger :true 表示打印代理过程中的提示信息
208+
> - debug :true 表示生成代理后的 class 文件
209+
> - tlFieldName :定义的 ThreadLocal 的字段名称 JOB_PARAMETERS_THREAD_LOCAL
210+
> - tlClass :定义 ThreadLocal 的类名称 com.shadow.supports.framework.ScheduleService
211+
> - ctlClass :代理的 controller 类 com.shadow.controller.AgentBaseController
212+
213+
214+
215+
#### 8、Attach 机制 - 可动态替换定时任务类型 TODO
133216
134217
> 测试类:com.shadow.agent.AttachAgentTest
135218
>

0 commit comments

Comments
 (0)