日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

SpringBoot 項目添加 MDC 日志鏈路追蹤的執行流程

瀏覽:119日期:2023-03-02 17:57:53
目錄1. 線程池配置2. 攔截器配置3. 日志文件配置4. 使用方法示例4.1. 異步使用4.2. 定時任務

日志鏈路追蹤的意思就是將一個標志跨線程進行傳遞,在一般的小項目中也就是在你新起一個線程的時候,或者使用線程池執行任務的時候會用到,比如追蹤一個用戶請求的完整執行流程。

這里用到MDC和ThreadLocal,分別由下面的包提供:

java.lang.ThreadLocalorg.slf4j.MDC

直接上代碼:

1. 線程池配置

如果你直接通過手動新建線程來執行異步任務,想要實現標志傳遞的話,需要自己去實現,其實和線程池一樣,也是調用MDC的相關方法,如下所示:

//取出父線程的MDCMap<String, String> context = MDC.getCopyOfContextMap();//將父線程的MDC內容傳給子線程MDC.setContextMap(context);

首先提供一個常量:

package com.example.demo.common.constant;/** * 常量 * * @author wangbo * @date 2021/5/13 */public class Constants { public static final String LOG_MDC_ID = 'trace_id';}

接下來需要對ThreadPoolTaskExecutor的方法進行重寫:

package com.example.demo.common.threadpool;import com.example.demo.common.constant.Constants;import lombok.extern.slf4j.Slf4j;import org.slf4j.MDC;import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.Map;import java.util.UUID;import java.util.concurrent.Callable;import java.util.concurrent.Future;/** * MDC線程池 * 實現內容傳遞 * * @author wangbo * @date 2021/5/13 */@Slf4jpublic class MdcTaskExecutor extends ThreadPoolTaskExecutor { @Override public <T> Future<T> submit(Callable<T> task) {log.info('mdc thread pool task executor submit');Map<String, String> context = MDC.getCopyOfContextMap();return super.submit(() -> { T result; if (context != null) {//將父線程的MDC內容傳給子線程MDC.setContextMap(context); } else {//直接給子線程設置MDCMDC.put(Constants.LOG_MDC_ID, UUID.randomUUID().toString().replace('-', '')); } try {//執行任務result = task.call(); } finally {try { MDC.clear();} catch (Exception e) { log.warn('MDC clear exception', e);} } return result;}); } @Override public void execute(Runnable task) {log.info('mdc thread pool task executor execute');Map<String, String> context = MDC.getCopyOfContextMap();super.execute(() -> { if (context != null) {//將父線程的MDC內容傳給子線程MDC.setContextMap(context); } else {//直接給子線程設置MDCMDC.put(Constants.LOG_MDC_ID, UUID.randomUUID().toString().replace('-', '')); } try {//執行任務task.run(); } finally {try { MDC.clear();} catch (Exception e) { log.warn('MDC clear exception', e);} }}); }}

然后使用自定義的重寫子類MdcTaskExecutor來實現線程池配置:

package com.example.demo.common.threadpool;import lombok.extern.slf4j.Slf4j;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import java.util.concurrent.Executor;import java.util.concurrent.ThreadPoolExecutor;/** * 線程池配置 * * @author wangbo * @date 2021/5/13 */@Slf4j@Configurationpublic class ThreadPoolConfig { /** * 異步任務線程池 * 用于執行普通的異步請求,帶有請求鏈路的MDC標志 */ @Bean public Executor commonThreadPool() {log.info('start init common thread pool');//ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();MdcTaskExecutor executor = new MdcTaskExecutor();//配置核心線程數executor.setCorePoolSize(10);//配置最大線程數executor.setMaxPoolSize(20);//配置隊列大小executor.setQueueCapacity(3000);//配置空閑線程存活時間executor.setKeepAliveSeconds(120);//配置線程池中的線程的名稱前綴executor.setThreadNamePrefix('common-thread-pool-');//當達到最大線程池的時候丟棄最老的任務executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());//執行初始化executor.initialize();return executor; } /** * 定時任務線程池 * 用于執行自啟動的任務執行,父線程不帶有MDC標志,不需要傳遞,直接設置新的MDC * 和上面的線程池沒啥區別,只是名字不同 */ @Bean public Executor scheduleThreadPool() {log.info('start init schedule thread pool');MdcTaskExecutor executor = new MdcTaskExecutor();executor.setCorePoolSize(10);executor.setMaxPoolSize(20);executor.setQueueCapacity(3000);executor.setKeepAliveSeconds(120);executor.setThreadNamePrefix('schedule-thread-pool-');executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());executor.initialize();return executor; }}2. 攔截器配置

package com.example.demo.common.interceptor;import com.example.demo.common.constant.Constants;import lombok.extern.slf4j.Slf4j;import org.slf4j.MDC;import org.springframework.stereotype.Component;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.util.UUID;/** * 日志攔截器 * * @author wangbo * @date 2021/5/13 */@Slf4j@Componentpublic class LogInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//log.info('進入 LogInterceptor');//添加MDC值MDC.put(Constants.LOG_MDC_ID, UUID.randomUUID().toString().replace('-', ''));//打印接口請求信息String method = request.getMethod();String uri = request.getRequestURI();log.info('[請求接口] : {} : {}', method, uri);//打印請求參數return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {//log.info('執行 LogInterceptor'); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {//log.info('退出 LogInterceptor');//打印請求結果//刪除MDC值MDC.remove(Constants.LOG_MDC_ID); }}

對攔截器進行注冊:

package com.example.demo.common.config;import com.example.demo.common.interceptor.LogInterceptor;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/** * MVC配置 * * @author wangbo * @date 2021/5/13 */@Configurationpublic class WebMvcConfig implements WebMvcConfigurer { @Autowired private LogInterceptor logInterceptor;/** * 攔截器注冊 */ @Override public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(logInterceptor); }}3. 日志文件配置

需要在logback-spring.xml文件中的日志打印格式里添加%X{trace_id},如下所示:

<!-- 控制臺打印日志的相關配置 --><appender name='console_out' class='ch.qos.logback.core.ConsoleAppender'> <!-- 日志格式 --> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{trace_id}] [%level] [%thread] [%class:%line] - %m%n</pattern> <charset>UTF-8</charset> </encoder> </appender>4. 使用方法示例4.1. 異步使用

這里注意,異步方法的調用不能直接調用當前類的方法,也就是說調用方法和異步方法不能在同一個類里,否則會變為同步執行。

/** * 異步方法 */ //@Async//這種寫法,當只有一個線程池時,會使用該線程池執行,有多個則會使用SimpleAsyncTaskExecutor @Async(value = 'commonThreadPool')//指定執行的線程池 @Override public void async() {log.info('測試異步線程池'); }4.2. 定時任務

package com.example.demo.generator.crontab;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Component;import java.time.LocalDateTime;/** * 定時任務 * * @author wangbo * @date 2021/5/14 */@Slf4j@Componentpublic class TestTimeTask { //基于注解@Scheduled默認為單線程,開啟多個任務時,任務的執行時機會受上一個任務執行時間的影響。 //使用的線程池是taskScheduler,線程ID為scheduling-x //添加@Async注解指定線程池,則可以多線程執行定時任務(原本是單線程的)。 /** * 兩次任務開始的時間間隔為2S * 不使用線程池,單線程間隔則為4S。單線程保證不了這個2S間隔,因為任務執行耗時超過了定時間隔,就會影響下一次任務的執行 * 使用線程池,多線程執行,時間間隔為2S */ //@Async(value = 'scheduleThreadPool') //@Scheduled(fixedRate = 2000) public void fixedRate() {log.info('定時間隔任務 fixedRate = {}', LocalDateTime.now());try { Thread.sleep(4_000);} catch (InterruptedException e) { e.printStackTrace();} } /** * 下次任務的開始時間距離上次任務的結束時間間隔為2S * 這種適合使用單線程,不適合使用線程池,單線程間隔則為6S。 * 用了線程池,和這個特性相背離了 */ //@Scheduled(fixedDelay = 2_000) public void fixedDelay() {log.info('延遲定時間隔任務 fixedDelay = {}', LocalDateTime.now());try { Thread.sleep(4_000);} catch (InterruptedException e) { e.printStackTrace();} } /** * 首次延遲10S后執行fixedDelay類型間隔任務,也可以配置為fixedDelay類型間隔任務 * 控件第一次執行之前要延遲的毫秒數 * {@link # fixeddrate} or {@link #fixedDelay} */ //@Scheduled(initialDelay = 10_000, fixedDelay = 1_000) public void initialDelay() {log.info('首次延遲定時間隔任務 initialDelay = {}', LocalDateTime.now()); } /** * 這里使用線程池也是為了防止任務執行耗時超過了定時間隔,就會影響下一次任務的執行 */ //@Async(value = 'scheduleThreadPool') //@Scheduled(cron = '0/2 * * * * *') public void testCron() {log.info('測試表達式定時任務 testCron = {}', LocalDateTime.now());try { Thread.sleep(4_000);} catch (InterruptedException e) { e.printStackTrace();} }}

到此這篇關于SpringBoot 項目添加 MDC 日志鏈路追蹤的文章就介紹到這了,更多相關SpringBoot MDC 日志鏈路追蹤內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Spring
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
精品一区二区三区中文字幕 | 99国产精品99久久久久久粉嫩| 国产激情综合| 午夜精品婷婷| 日韩亚洲精品在线观看| 精品国模一区二区三区| 四虎成人av| 天堂√中文最新版在线| 国产96在线亚洲| 国产suv精品一区| 国产精品腿扒开做爽爽爽挤奶网站| 蜜桃精品视频| 国产一区亚洲| 国产精品久久久久久av公交车 | 日本黄色精品| 日韩精品看片| 岛国精品一区| 日韩高清电影一区| 久久精品导航| 你懂的国产精品| 欧美日韩夜夜| 欧美天堂视频| 水蜜桃久久夜色精品一区的特点 | 宅男在线一区| 97视频热人人精品免费| 日韩国产欧美一区二区三区| 国产91精品对白在线播放| 美女久久99| 日本a级不卡| 奇米狠狠一区二区三区| 日韩av影院| 婷婷亚洲成人| 日韩欧美三区| 国产精品手机在线播放| 中文欧美日韩| 中文国产一区| 中文视频一区| 18国产精品| 日韩va亚洲va欧美va久久| 最新亚洲国产| 亚洲91网站| 四虎精品一区二区免费| 黄色亚洲大片免费在线观看| 免费在线成人网| 日韩和欧美一区二区| 欧美综合社区国产| 日本精品国产| 欧美91在线| 日韩欧美1区| 国产日韩中文在线中文字幕 | 亚洲欧美日韩国产一区| 激情视频一区二区三区| 视频在线观看一区二区三区| 日韩一区二区久久| 免费视频一区二区| 美女毛片一区二区三区四区最新中文字幕亚洲 | 欧美午夜三级| а√在线中文在线新版| 99视频精品| 亲子伦视频一区二区三区| 69堂免费精品视频在线播放| 成人免费一区| 亚洲毛片在线| 欧洲激情综合| 亚洲人成精品久久久| 亚洲婷婷免费| 精品三区视频| 国产一区二区三区网| 久久99伊人| 久久影院一区| 午夜亚洲福利| 久久美女精品| 国产精品亚洲综合色区韩国| 免费在线小视频| 91精品国产乱码久久久久久久| 麻豆精品91| 精品视频在线一区二区在线| 欧美日韩国产传媒| 国产伦理久久久久久妇女| 国产成人1区| 亚洲精品人人| 欧美13videosex性极品| 日韩精品a在线观看91| 婷婷综合社区| 亚洲精品在线二区| 国产精品高颜值在线观看| 国产亚洲一区二区手机在线观看| 免费观看在线色综合| 精品在线播放| 久久久久国产精品一区三寸 | 精品久久免费| 免费日韩av片| 波多视频一区| 国产精品久久久久久久久妇女| 中文字幕一区日韩精品| 99精品一区| 四虎国产精品免费久久| 日韩欧美高清一区二区三区| 久久精品播放| 久久男女视频| 欧美国产偷国产精品三区| 亚洲精品人人| 日韩精品欧美大片| 日本aⅴ亚洲精品中文乱码| 久久福利影视| 免费一级片91| 亚洲欧美视频| 色偷偷色偷偷色偷偷在线视频| 麻豆国产精品| 捆绑调教美女网站视频一区 | 欧美资源在线| 亚洲va中文在线播放免费| 日韩在线观看一区二区三区| 国产精品www994| 日韩一区二区三区免费| 亚洲在线国产日韩欧美| 欧美一区免费| 天堂中文av在线资源库| 好看的av在线不卡观看| 日韩不卡免费视频| 久久要要av| 国产午夜精品一区二区三区欧美 | 国产精品一区亚洲| 国产成年精品| 蜜桃av一区二区三区电影| 亚洲1区在线观看| 国产精品视频一区二区三区综合| 日本韩国欧美超级黄在线观看| 视频在线在亚洲| 狠狠久久伊人中文字幕| 天堂av在线一区| 亚洲精品少妇| 成人自拍av| 亚洲精品1区2区| 麻豆国产精品一区二区三区| 国产精品三上| 日本欧美不卡| 涩涩涩久久久成人精品| 黄色成人精品网站| 欧美黑人做爰爽爽爽| 中文一区一区三区免费在线观 | 日韩视频一区二区三区在线播放免费观看| 精品中文字幕一区二区三区av| 欧美永久精品| 性色一区二区| 国内自拍视频一区二区三区| 自拍自偷一区二区三区| 久久久一二三| а√在线中文在线新版| 国产精品毛片久久久| 亚洲深夜福利| 老司机精品视频网| 一区免费视频| 日韩一区二区免费看| 色在线视频观看| 国产福利电影在线播放| 国产福利一区二区精品秒拍| 日韩精品a在线观看91| 丝袜脚交一区二区| 欧美精选一区二区三区| 99视频精品全国免费| 亚洲二区免费| 国产一区日韩一区| 午夜日韩在线| 日韩精品专区| 精品五月天堂| 91伊人久久| 欧美亚洲专区| 免费一级欧美在线观看视频 | 1024精品久久久久久久久| 日韩一区自拍| 久久精品成人| 久久久久久久久久久妇女| 最近国产精品视频| 亚洲综合图色| 欧美日韩国产高清电影| 亚洲激情中文在线| 一本综合精品| 欧美jjzz| 国产一区一一区高清不卡| 国产精品久久久一区二区| 久久三级中文| 亚洲精品.com| 一区二区电影| 国产一二在线播放| 久久电影一区| 国产精品最新| 欧美aⅴ一区二区三区视频| 精品视频91| 尤物精品在线| 国产精品nxnn| 欧美粗暴jizz性欧美20| 91麻豆精品| 久久性天堂网| 欧美激情另类| 日韩国产在线一| 五月天综合网站| 激情综合五月| 黑丝一区二区三区| 久久国产欧美|