Recently, when using the asynchronous tasks that come with the COLA framework, I found that each execution of asynchronous tasks is executed twice. If some interfaces are not idempotent, there will be problems, such as warehousing operations, etc., will cause Data is repeatedly stored in the database, causing serious bugs.
With doubts, started the bug journey.
1 problem found
1. First check whether there are two execution entries, and only one is found;
2. The problem of calling the entrance? The handler was called directly through the controller, and it was called twice.
3. Simplify the code, delete all the content in the handler, and only have one logger print statement? The result was printed twice.
But this time, I found that the thread names of the logger are different, they are two threads.
2021-07-26 14:11:19.429 INFO 47294 --- [pool-4-thread-2] c.e.colademo.event.handler.TestHandler : >>>>>>>>>>>>> 0
2021-07-26 14:11:19.430 INFO 47294 --- [pool-4-thread-1] c.e.colademo.event.handler.TestHandler : >>>>>>>>>>>>> 0
2 Troubleshooting
Why are there two threads executing at the same time? View the COLA source code.
public void asyncFire(EventI event) {
this.eventHub.getEventHandler(event.getClass()).parallelStream().map((p) -> {
Response response = null;
try {
if (null != p.getExecutor()) {
p.getExecutor().submit(() -> {
return p.execute(event);
});
} else {
this.defaultExecutor.submit(() -> {
return p.execute(event);
});
}
} catch (Exception var5) {
response = this.handleException(p, response, var5);
}
return response;
}).collect(Collectors.toList());
}
Submit the asynchronous task, and finally go to the above code, and submit the task to the thread pool for execution. If there is no custom thread pool, it will be submitted to the default thread pool of defaultExecutor
Found that it was submitted twice, check the content in this object, == found that Event object and Handler object have two ==.
3 Cause of the problem
What causes duplicate objects?
Compared with the previous handler object, the only difference of this object is to use @RefreshScope
, check the annotation source code, and find that the object with the annotation == will use the code to create a new object, and cache it ==, debug source code, view the cached object Object.
Found that there is indeed a TestHandler object, the object is @12349.
Compared with the handler object in Figure 1, there is also a TestHandler object inside, which is also @12349.
It turns out that because the annotation @RefreshScope
, this annotation will create an object, so there will be two identical objects, causing repeated execution.
Conclusion: The use of annotation @RefreshScope
requires attention. It is best to put the content of the configuration obtained in a separate property object, and do not mix it with other codes.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。