当前位置: 首页 > news >正文

直播视频app合肥seo优化外包公司

直播视频app,合肥seo优化外包公司,悦然wordpress建站服务,公司网站客户案例SpringBoot项目使用slf4j的MDC日志打点功能 物料准备: 1.自定义1个线程MDC打点工具类 2.配置logback打印MDC打点的traceId 3.配置webMVC使用MDC打点 4.配置ThreadPoolTaskExecutor使用MDC打点 5.配置HttpClient使用MDC打点 6.测试MDC日志打点效果 线程mdc打…

SpringBoot项目使用slf4j的MDC日志打点功能

物料准备:

1.自定义1个线程MDC打点工具类

2.配置logback打印MDC打点的traceId

3.配置webMVC使用MDC打点

4.配置ThreadPoolTaskExecutor使用MDC打点

5.配置HttpClient使用MDC打点

6.测试MDC日志打点效果

线程mdc打点工具类代码

package cn.ath.knowwikibackend.mdc;import cn.hutool.core.lang.UUID;
import org.slf4j.MDC;import java.util.Map;
import java.util.concurrent.Callable;/*** 线程mdc打点工具类*/
public class ThreadMdcUtil {public static void setTRaceIdIfAbsent() {if (MDC.get("traceId") == null) {MDC.put("traceId", UUID.fastUUID().toString());}}public static <T> Callable<T> wrap(final Callable<T> callable, final Map<String, String> context) {return () -> {if (context == null) {MDC.clear();} else {MDC.setContextMap(context);}setTRaceIdIfAbsent();try {//最终通过 callable.call执行线程任务return callable.call();} finally {MDC.clear();}};}public static Runnable wrap(final Runnable runnable,final Map<String,String> context){return ()->{if (context==null){MDC.clear(); //mdc上下文为空 就清掉mdc}else {MDC.setContextMap(context);  // mdc上下文不为空,要设置上下文为 context}setTRaceIdIfAbsent(); //设置mdc 记录traceIdtry {//最终通过 runnable.run 执行线程任务runnable.run();}finally {MDC.clear();}};}
}

配置logback 输出的日志格式,要输出mdc里定义的traceId

logging:file:path: ${user.home}/.${spring.application.name}/log/logback:rollingpolicy:max-file-size: 15MBmax-history: 10pattern: # 注意这里配置的 [%X{traceId}] 即输出mdc打点的traceId值console: "%date  %level [%thread] [%X{traceId}] %logger{10} [%file : %line] %msg%n"file: "%date  %level [%thread] [%X{traceId}] %logger{10} [%file : %line] %msg%n"level:cn.ath.knowwikibackend.rest: info

配置webMVC使用MDC打点

定义MvcTraceInterceptor,来拦截http请求进行mdc打点

package cn.ath.knowwikibackend.mdc;import cn.hutool.core.lang.UUID;
import org.slf4j.MDC;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** mvc trace拦截器,作用是 实现trace打点*/
public class MvcTraceInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//在请求头里拿一个 traceId ,拿不到就创建1个 traceIdString traceId = request.getHeader("traceId");if (traceId==null){traceId = UUID.fastUUID().toString();}// traceId记录到mdc中MDC.put("traceId",traceId);return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {//1个http请求 后台处理完毕后 ,从mdc中移除 traceIdMDC.remove("traceId");}
}

使用自定义的MvcTraceInterceptor

package cn.ath.knowwikibackend.mdc;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcMdcConfig implements WebMvcConfigurer {/*** 配置spring mvc启用 mvc trace拦截器,实现trace打点* @param registry InterceptorRegistry*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MvcTraceInterceptor()).addPathPatterns("/**");}
}

配置ThreadPoolTaskExecutor使用MDC打点

package cn.ath.knowwikibackend.mdc;import org.slf4j.MDC;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.io.Serializable;
import java.util.concurrent.*;
/*** 异步线程池 的mdc 包装器,作用是 让 async 异步任务 实现trace打点*/
public class AsyncThreadPoolMdcWrapper extends ThreadPoolTaskExecutor implements Serializable {private static final long serialVersionUID = -1530245553055682935L;@Overridepublic void execute(Runnable task) {// Runnable 类型的线程运行时  进行 mdc 打点记录super.execute(ThreadMdcUtil.wrap(task, MDC.getCopyOfContextMap()));}@Overridepublic <T> Future<T> submit(Callable<T> task) {// Callable 类型的线程运行时  进行 mdc 打点记录return super.submit(ThreadMdcUtil.wrap(task,MDC.getCopyOfContextMap()));}@Overridepublic Future<?> submit(Runnable task) {//  Runnable 类型且返回Future的 线程运行时  进行 mdc 打点记录return super.submit(ThreadMdcUtil.wrap(task,MDC.getCopyOfContextMap()));}
}

配置ApacheHttpClient使用MDC打点

package cn.ath.knowwikibackend.mdc;import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.protocol.HttpContext;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import java.io.IOException;/*** 自定义 HttpRequestInterceptor,* 这里可以对外发的http请求 追加请求头/请求参数之类的配置** 这里 在 Header 里追加上本应用的traceId ,便于全局排查请求日志*/
@Component
@Slf4j
public class HttpClientTracedInterceptor implements HttpRequestInterceptor {@Overridepublic void process(HttpRequest httpRequest, HttpContext httpContext) throws HttpException, IOException {//从mdc 中取出traceId 然后追加到 外发的http请求头里String traceId = MDC.get("traceId");if (traceId != null){httpRequest.addHeader("traceId",traceId);}//打印出所有的http请求头for (Header header : httpRequest.getAllHeaders()) {log.info("req header item---->{}",header);}}
}

测试MDC日志打点效果

修改之前的异步线程池使用AsyncThreadPoolMdcWrapper 替换掉默认的ThreadPoolTaskExecutor

@Configuration
public class AsyncConfig {@Bean("asyncCountTestTaskExecutor")public AsyncThreadPoolMdcWrapper asyncCountTaskTest(){AsyncThreadPoolMdcWrapper executor = new AsyncThreadPoolMdcWrapper();//核心线程数5:线程池创建时候初始化的线程数executor.setCorePoolSize(5);//最大线程数10:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程executor.setMaxPoolSize(10);//缓冲队列100:用来缓冲执行任务的队列executor.setQueueCapacity(100);//允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁executor.setKeepAliveSeconds(60);//线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池executor.setThreadNamePrefix("countTestTaskAsync-");//线程池满了后新任务由 任务发起者的线程执行RejectedExecutionHandler callerRunsPolicy = new ThreadPoolExecutor.CallerRunsPolicy();executor.setRejectedExecutionHandler(callerRunsPolicy);executor.initialize();return executor;}@Bean("asyncVoidTestTaskExecutor")public AsyncThreadPoolMdcWrapper asyncVoidTaskTest(){AsyncThreadPoolMdcWrapper executor = new AsyncThreadPoolMdcWrapper();//核心线程数5:线程池创建时候初始化的线程数executor.setCorePoolSize(5);//最大线程数10:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程executor.setMaxPoolSize(10);//缓冲队列100:用来缓冲执行任务的队列executor.setQueueCapacity(100);//允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁executor.setKeepAliveSeconds(60);//线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池executor.setThreadNamePrefix("voidTestTaskAsync-");//线程池满了后新任务由 任务发起者的线程执行RejectedExecutionHandler callerRunsPolicy = new ThreadPoolExecutor.CallerRunsPolicy();executor.setRejectedExecutionHandler(callerRunsPolicy);executor.initialize();return executor;}
}

在API接口中测试

@Slf4j
@RestController
@RequestMapping("/third")
public class TestApi {@AutowiredHttpClientTracedInterceptor httpClientTracedInterceptor;@Autowiredprivate AsyncAllService asyncAllService@GetMapping("/t1")public String te() throws ExecutionException, InterruptedException, IOException {log.trace("trace---test!!!!!");log.info("info---test!!!!!");log.warn("warn---test!!!!!");log.debug("debug---test!!!!!");log.error("error---test!!!!!");//有返回值的async任务Future<Long> longFuture = asyncAllService.testCount1();//无返回值的async任务asyncAllService.testAsync2();//有返回值的async任务,需要future执行后,最后统一get返回值Long l605 = longFuture.get();log.info("async task res:{}",l605);//测试使用apache httpclient 外发1个http请求String content = "test.dhrth.xxx.zzzdfg.derferf.sregvreg.regetg.esrtg34gf3";String url = "http://10.1.5.212:8008/api/getresult";Map<String, String> mapData = new HashMap<String, String>();mapData.put("type", "NER_RE");mapData.put("text", content);Map<String, Object> map = new HashMap<String, Object>();map.put("sid", "re");map.put("data", mapData);String reqStr = JSON.toJSONString(map);// 获取httpclientCloseableHttpClient httpclient = HttpClients.custom().addInterceptorFirst(httpClientTracedInterceptor).build();//创建post请求HttpPost httpPost = new HttpPost(url);RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(20*1000).setConnectionRequestTimeout(1000).setConnectTimeout(1000).build();httpPost.setConfig(requestConfig);StringEntity entity = new StringEntity(reqStr, ContentType.APPLICATION_JSON);httpPost.setEntity(entity);CloseableHttpResponse response = httpclient.execute(httpPost);// 得到响应信息int statusCode = response.getStatusLine().getStatusCode();log.info("http-res-statusCode:{}",statusCode);String respStr = EntityUtils.toString(response.getEntity(), "utf-8");log.info("http-resp:{}",respStr);return "thirdTestApi测试!";}
}    

测试控制台输出的日志效果

2023-06-05 15:45:54,228  INFO [http-nio-8080-exec-1] [8e5e137d-1bb0-49bc-b7da-c8b9f6568ef4] c.a.k.s.l.ReqLogAspect [ReqLogAspect.java : 94] 请求URI:/kwb/third/t1
2023-06-05 15:45:54,251  INFO [http-nio-8080-exec-1] [8e5e137d-1bb0-49bc-b7da-c8b9f6568ef4] c.a.k.s.l.ReqLogAspect [ReqLogAspect.java : 107] 请求目标类:String cn.ath.knowwikibackend.rest.TestApi.te()
2023-06-05 15:45:54,254  INFO [http-nio-8080-exec-1] [8e5e137d-1bb0-49bc-b7da-c8b9f6568ef4] c.a.k.r.TestApi [TestApi.java : 60] info---test!!!!!
2023-06-05 15:45:54,254  WARN [http-nio-8080-exec-1] [8e5e137d-1bb0-49bc-b7da-c8b9f6568ef4] c.a.k.r.TestApi [TestApi.java : 61] warn---test!!!!!
2023-06-05 15:45:54,255  ERROR [http-nio-8080-exec-1] [8e5e137d-1bb0-49bc-b7da-c8b9f6568ef4] c.a.k.r.TestApi [TestApi.java : 63] error---test!!!!!
2023-06-05 15:45:54,299  INFO [countTestTaskAsync-1] [8e5e137d-1bb0-49bc-b7da-c8b9f6568ef4] c.a.k.a.b.AsyncAllService [AsyncAllService.java : 35] now:2023-06-05 15:45:54
2023-06-05 15:45:54,299  INFO [voidTestTaskAsync-1] [8e5e137d-1bb0-49bc-b7da-c8b9f6568ef4] c.a.k.a.b.AsyncAllService [AsyncAllService.java : 52] now:2023-06-05 15:45:54
2023-06-05 15:45:54,300  INFO [countTestTaskAsync-1] [8e5e137d-1bb0-49bc-b7da-c8b9f6568ef4] c.a.k.a.b.AsyncAllService [AsyncAllService.java : 36] ---exec testCount1------------
2023-06-05 15:45:54,300  INFO [voidTestTaskAsync-1] [8e5e137d-1bb0-49bc-b7da-c8b9f6568ef4] c.a.k.a.b.AsyncAllService [AsyncAllService.java : 53] ---exec testAsync2------------
2023-06-05 15:45:54,300  INFO [http-nio-8080-exec-1] [8e5e137d-1bb0-49bc-b7da-c8b9f6568ef4] c.a.k.r.TestApi [TestApi.java : 73] async task res:8
2023-06-05 15:45:54,352  INFO [http-nio-8080-exec-1] [8e5e137d-1bb0-49bc-b7da-c8b9f6568ef4] c.a.k.m.HttpClientTracedInterceptor [HttpClientTracedInterceptor.java : 36] req header item---->traceId: 8e5e137d-1bb0-49bc-b7da-c8b9f6568ef4
2023-06-05 15:45:55,429  INFO [http-nio-8080-exec-1] [8e5e137d-1bb0-49bc-b7da-c8b9f6568ef4] c.a.k.r.TestApi [TestApi.java : 109] http-res-statusCode:200
2023-06-05 15:45:55,431  INFO [http-nio-8080-exec-1] [8e5e137d-1bb0-49bc-b7da-c8b9f6568ef4] c.a.k.r.TestApi [TestApi.java : 121] http-resp:{"status": "OK","message": "提取成功","result": {}
}
2023-06-05 15:45:55,432  INFO [http-nio-8080-exec-1] [8e5e137d-1bb0-49bc-b7da-c8b9f6568ef4] c.a.k.s.l.ReqLogAspect [ReqLogAspect.java : 125] Around请求耗时:1227ms
从日志中可以看到,1次浏览器请求进到app后,从切面就开始mdc打点,之后的异步线程操作 和 外发http操作 的log日志中都显示出了本次浏览器请求对应的后台日志的打点traceId值为 8e5e137d-1bb0-49bc-b7da-c8b9f6568ef4

http://www.15wanjia.com/news/27116.html

相关文章:

  • 网站结构怎么做百度推广客户端电脑版
  • 网站建设与网页设计百度文库职业技能培训网上平台
  • 建设双语的网站百度seo排名报价
  • 比较好的网站公司汕头网站推广排名
  • 网站开发后台php技术今天宣布疫情最新消息
  • 广东省最新疫情防控信息seo基础知识培训视频
  • wordpress单本小说主题优化公司组织架构
  • 建设网站培训学校seo快排优化
  • 聊城网页设计公司seo结算系统
  • 潍坊智能建站模板运营培训班有用吗
  • 随州网站seo诊断软件培训机构哪家好
  • app开发需求文档模板什么是seo营销
  • 义乌购物网站建设多少钱一网信息一个简单便捷的新闻网站
  • 优推宝可以做自己网站吗深圳网站设计
  • 做二手房又做网站的广州百度推广电话
  • 做网站的相关术语推荐一个seo优化软件
  • 通州区住房和城乡建设部网站泰州seo推广
  • 企业网站的基本内容有哪些网页设计制作教程
  • 江西网站建设优化服务潍坊百度快速排名优化
  • 宁波比较好的外贸公司台州百度推广优化
  • 保定网站制作网页建网站的流程
  • WordPress 卡密购买插件seo建站工具
  • 手机wap网站模板 带后台深圳网络推广专员
  • 做网站用php还是html百度认证有什么用
  • 网站域名审核时间免费关键词排名优化
  • 深圳龙岗区吉华街道邮编宁波seo链接优化
  • 做棋牌网站多少钱seo外链在线提交工具
  • 小程序sdk开发seo新方法
  • 申请账号注册常用的seo查询工具
  • 做个卖车票的网站怎么做企业培训课程种类