開発スキャフォールディングをゼロから構築して、非同期スレッド プールのシナリオで Trace 機能を強化する
序文
以下の 2 つの記事は、以前に書いたトレース機能の基礎と原則です。
ただし、ビジネスに非同期スレッドが存在するシナリオでは、トレース機能に少し問題があります。詳細については、次の説明を参照してください。
質問サンプルコード
// 有个业务线程池
ThreadPoolExecutor pool = new EasyAdminThreadPoolExecutor(10,10,"laker");
// 模拟业务代码
public void pageList(){
// 1.本地查询
xxxService.pageList();
// 2.模拟异步远程调用,耗时300ms
pool.submit(() -> {
TraceCodeBlock.trace("remoteService.call", value -> {
TimeUnit.MILLISECONDS.sleep(300);
});
}
// 3.本地插入记录
xxxService.insert();
}
結果ログ:
// 1 线程laker-9 丢掉了userId和traceId
20:21:35.534 INFO --- [ laker-9] [|] com.laker.admin.framework.aop.trace.Trace:86 `---
`---[302ms] Others-remoteService.call
// 2 tomcat线程 userId=16还有traceId
20:21:35.547 INFO --- [io-8080-exec-38] [16|497ef9d28d20452f84443c66c6f25354] com.laker.admin.framework.aop.trace.Trace:86 `---
`---[428ms] Controller-ExtLeaveController|pageAll
+---[max]:[414ms] Controller-ExtLeaveController.pageAll
| +---[32ms] Others-leaveService.page
| | +---[3ms] Mapper-com.laker.admin.module.ext.mapper.ExtLeaveMapper.selectPage_mpCount
| | `---[1ms] Mapper-com.laker.admin.module.ext.mapper.ExtLeaveMapper.selectPage
ログには 2 つの問題があります。
- 質問 1: 非同期性により、子スレッドは親スレッドの
userId
合計を失いますtraceId
。 - 質問 2: 非同期性により、子スレッドと親スレッドが Trace オブジェクトを使用しなくなります。つまり、上記のログのパート 1 とパート 2 が分割されます。
強化する
上記の問題を解決するのは実際には非常に簡単です。非同期で処理し、親スレッドのスレッドローカルの値を手動で子スレッドにコピーし、使用後にクリアするだけです。
疑似コード
// 父线程信息
userId/traceId/trace = LakerThreadlocal.get();
pool.submit(() -> {
// 传递到子线程
LakerThreadlocal.set(userId/traceId/trace);
// 业务处理
......
// 清空
LakerThreadlocal.clear();
}
上記の疑似コードは問題を解決するためのコア コードであり、このロジックをEasyAdminMDCThreadPoolExecutor.javaにカプセル化しました。
ユーザーは以前のスレッド プールを変更するだけで済みます。サンプル コードは次のとおりです。
ThreadPoolExecutor pool = new EasyAdminMDCThreadPoolExecutor(10,10,"laker");
この時のログ効果は以下の通り
20:21:35.547 INFO --- [io-8080-exec-38] [16|497ef9d28d20452f84443c66c6f25354] com.laker.admin.framework.aop.trace.Trace:86 `---
`---[428ms] Controller-ExtLeaveController|pageAll
+---[max]:[414ms] Controller-ExtLeaveController.pageAll
| +---[410ms] Others-leaveService.page
| | +---[3ms] Mapper-com.laker.admin.module.ext.mapper.ExtLeaveMapper.selectPage_mpCount
| | `---[1ms] Mapper-com.laker.admin.module.ext.mapper.ExtLeaveMapper.selectPage
| | +---[302ms] Others-remoteService.call // 这里是被修复处
完全なコード アドレス: https://gitee.com/lakernote/easy-admin