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

做图骂人的图片网站大连网站建设选高和科技

做图骂人的图片网站,大连网站建设选高和科技,上海营销型网站开发,有什么建筑网站在微服务环境中#xff0c;我们经常使用 Skywalking、Spring Cloud Sleut 等去实现整体请求链路的追踪#xff0c;但是这个整体运维成本高#xff0c;架构复杂#xff0c;本次我们来使用 MDC 通过 Log 来实现一个轻量级的会话事务跟踪功能#xff0c;需要的朋友可以参考一…在微服务环境中我们经常使用 Skywalking、Spring Cloud Sleut 等去实现整体请求链路的追踪但是这个整体运维成本高架构复杂本次我们来使用 MDC 通过 Log 来实现一个轻量级的会话事务跟踪功能需要的朋友可以参考一下。 1.1 应用效果图 我们知道了 MDC 的好处后其实在用户从第一时间调用请求时候我们其实可以将请求增加 traceid 一并返回这样用户反馈时候我们直接用 traceid 就可以全链路追踪到所有请求的情况了做到信息的闭环。 请求效果图 LOGBOOK 效果图 2、关键思路 2.1 MDC 日志追踪目标是每次请求级别的也就是说同一个接口的每次请求都应该有不同的 traceId。每次接口请求都是一个单独的线程所以自然我们很容易考虑到通过 ThreadLocal 实现上述需求。考虑到 log4j 本身已经提供了类似的功能 MDC所以直接使用 MDC 进行实现。 关于 MDC 的简述 MDCMapped Diagnostic Context是一个映射用于存储运行上下文的特定线程的上下文数据。因此如果使用 log4j 进行日志记录则每个线程都可以拥有自己的 MDC该 MDC 对整个线程是全局的。属于该线程的任何代码都可以轻松访问线程的 MDC 中存在的值。 API 说明 clear()  移除所有 MDC get (String key)  获取当前线程 MDC 中指定 key 的值 getContext()  获取当前线程 MDC 的 MDC put(String key, Object o)  往当前线程的 MDC 中存入指定的键值对 remove(String key)  删除当前线程 MDC 中指定的键值对 3、目标 需要一个全服务唯一的 id即 traceId如何保证 traceId 如何在服务内部传递 traceId 如何在服务间传递 traceId 如何在多线程中传递 4、实现方式 4.1 需要一个全服务唯一的 id即 traceId如何保证 使用最简单的 uuid 即可。复杂的话可以配置 Redis、雪花算法等方式。本次分享选最简单 uuid 生成 traceId 的方式。 4.2 traceId 如何在服务间传递 1在 XML 的日志格式中添加 %X{traceId} 配置。 appender nameCONSOLE classorg.apache.log4j.ConsoleAppenderlayout classorg.apache.log4j.PatternLayoutparam nameConversionPattern value%d{yyyy-MM-dd HH:mm:ss} [%X{traceId}] [%p] %l[%t]%n%m%n //layout /appender2新增拦截器拦截所有请求从 header 中获取 traceId 然后放到 MDC 中如果没有获取到则直接用 UUID 生成一个。 Slf4j Component public class LogInterceptor implements HandlerInterceptor {private static final String TRACE_ID  traceId;Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,Exception arg3) throws Exception {}Overridepublic void postHandle(HttpServletRequest request,HttpServletResponse response, Object handler, ModelAndView arg3) throws Exception {}Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {String traceId  request.getHeader(TRACE_ID);if (StringUtils.isEmpty(traceId)) {MDC.put(TRACE_ID, UUID.randomUUID().toString());} else {MDC.put(TRACE_ID, traceId);}return true;} }3配置拦截器 Configuration public class WebConfig implements WebMvcConfigurer {Resourceprivate LogInterceptor logInterceptor;Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(logInterceptor).addPathPatterns(/**);} }4.3 traceId 如何在服务间传递 封装 HTTP 工具类把 traceId 加入头中带到下一个服务。 Slf4j public class HttpUtils {public static String get(String url) throws URISyntaxException {RestTemplate restTemplate  new RestTemplate();MultiValueMapString, String headers  new HttpHeaders();headers.add(traceId, MDC.get(traceId));URI uri  new URI(url);RequestEntity? requestEntity  new RequestEntity(headers, HttpMethod.GET, uri);ResponseEntity exchange  restTemplate.exchange(requestEntity, String.class);if (exchange.getStatusCode().equals(HttpStatus.OK)) {log.info(send http request success);}return exchange.getBody();} }4.4 traceId 如何在多线程中传递 Spring 项目也使用到了很多线程池比如 Async 异步调用Zookeeper 线程池、 Kafka 线程池等。不管是哪种线程池都大都支持传入指定的线程池实现拿 Async 举例 原理为 MDC 底层使用 ThreadLocal 来实现那根据 ThreadLocal 的特点它是可以让我们在同一个线程中共享数据的但是往往我们在业务方法中会开启多线程来执行程序这样的话 MDC 就无法传递到其他子线程了。这时我们需要使用额外的方法来传递存在 ThreadLocal 里的值。 MDC 提供了一个叫 getCopyOfContextMap 的方法很显然该方法就是把当前线程 ThreadLocal 绑定的Map获取出来之后就是把该 Map 绑定到子线程中的ThreadLocal 中了。 改造 Spring 的异步线程池包装提交的任务。 Slf4j Component public class TraceAsyncConfigurer implements AsyncConfigurer {Overridepublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor  new ThreadPoolTaskExecutor();executor.setCorePoolSize(8);executor.setMaxPoolSize(16);executor.setQueueCapacity(100);executor.setThreadNamePrefix(async-pool-);executor.setTaskDecorator(new MdcTaskDecorator());executor.setWaitForTasksToCompleteOnShutdown(true);executor.initialize();return executor;}Overridepublic AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {return (throwable, method, params) - log.error(asyc execute error, method{}, params{}, method.getName(),Arrays.toString(params));}public static class MdcTaskDecorator implements TaskDecorator {Overridepublic Runnable decorate(Runnable runnable) {MapString, String contextMap  MDC.getCopyOfContextMap();return () - {if (contextMap ! null) {MDC.setContextMap(contextMap);}try {runnable.run();} finally {MDC.clear();}};}} }public class MDCLogThreadPoolExecutor extends ThreadPoolExecutor {public MDCLogThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,BlockingQueue workQueue) {super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);}Overridepublic void execute(Runnable command) {super.execute(MDCLogThreadPoolExecutor.executeRunable(command, MDC.getCopyOfContextMap()));}Overridepublic Future? submit(Runnable task) {return super.submit(MDCLogThreadPoolExecutor.executeRunable(task, MDC.getCopyOfContextMap()));}Overridepublic Future submit(Callable callable) {return super.submit(MDCLogThreadPoolExecutor.submitCallable(callable, MDC.getCopyOfContextMap()));}public static Runnable executeRunable(Runnable runnable, MapString, String mdcContext) {return new Runnable() {Overridepublic void run() {if (mdcContext  null) {MDC.clear();} else {MDC.setContextMap(mdcContext);}try {runnable.run();} finally {MDC.clear();}}};}private static Callable submitCallable(Callable callable, MapString, String context) {return () - {if (context  null) {MDC.clear();} else {MDC.setContextMap(context);}try {return callable.call();} finally {MDC.clear();}};} }接下来需要对 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 {Overridepublic T FutureT submit(CallableT task) {log.info(mdc thread pool task executor submit);MapString, 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;});}Overridepublic void execute(Runnable task) {log.info(mdc thread pool task executor execute);MapString, 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 来实现线程池配置 /*** 线程池配置* * author wangbo* date 2021/5/13*/ Slf4j Configurationpublic class ThreadPoolConfig {/** * 异步任务线程池 * 用于执行普通的异步请求带有请求链路的MDC标志 */Beanpublic Executor commonThreadPool() {log.info(start init common thread pool); // ThreadPoolTaskExecutorexecutor  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* 和上面的线程池没啥区别只是名字不同*/Beanpublic 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;} }5、扩展点 5.1 JSF 接口日志追踪的应用 项目中也运用到了大量的 JSF 接口我们其实可以按照上述的思路进行服务间的传递。 调用端 // todo 不能在filter里面这么用 RpcContext.getContext().setAttachment(user, zhanggeng); RpcContext.getContext().setAttachment(.passwd, 11112222);  // .开头的对应上面的hidetruexxxService.yyy();// 再开始调用远程方法 // 重要:下一次调用要重新设置之前的属性会被删除 RpcContext.getContext().setAttachment(user, zhanggeng); RpcContext.getContext().setAttachment(.passwd, 11112222);  // .开头的对应上面的hidetruexxxService.zzz(); // 再开始调用远程方法Provider 端 1.filter 中直接获取包括标记为 hidden 的参数。通过 Rpccontext 无法获取。 String consumerToken  (String) invocation.getAttachment(.passwd);2.服务端业务代码中直接获取。 String user  RpcContext.getContext().getAttachment(user);提示调用链中的隐式传参。 ❝ 注意在调用链例如 A–B–CA和B都要隐私传参的时候由于是同一个线程会出现数据污染。例如 A 发参数 P1 给 BB 收到请求拿到 P1 同时要发参数 P2 给 C那么 C 会直接拿到 P1、P2。这种情况就要求 B 收到 P1然后设置 P2 调用 C 之前要求自己清空上下文数据RpcContext.getContext().clearAttachments(); ❞ 5.2 接口返回值应用 我们知道了 MDC 的好处后其实在用户从第一时间调用请求时候我们其实可以将有误的请求增加 traceid 一并返回。这样用户反馈时候我们直接用 traceid 就可以全链路追踪到所有请求的情况了做到信息的闭环。 效果图 6、备注 各位知道了日志追踪的原理其实很多应用场景可以继续补充例如 MQJD 的其他中间件也可以应用相同原理进行追踪。 其实当了解了底层的原理后我们其实就可以了解到 JD 监控中间件 PFinder 监控等中间件是如何做的了。 本次由于时间情况就不进行扩展了各位可以线下去了解 Skywalking 分布式链路追踪系统就可以知道万变不离其宗。 最后说一句(求关注!别白嫖) 如果这篇文章对您有所帮助或者有所启发的话求一键三连点赞、转发、在看。 关注公众号woniuxgg在公众号中回复笔记  就可以获得蜗牛为你精心准备的java实战语雀笔记回复面试、开发手册、有超赞的粉丝福利
http://www.sczhlp.com/news/234217/

相关文章:

  • 扶贫办网站建设百度搜索推广方案
  • 宁波网站建设费用学生个人网站建设方案书框架栏目
  • 昆山网站设计哪家好wordpress页面连接
  • 网站建设步骤 文档h5建站工具
  • 昆明电子商务网站建设如何重新运行wordpress
  • 营销型网站建设发难做公众号一般在哪个网站照片
  • 做3d图的网站有哪些软件wordpress安装网站吗
  • 网站做互动广东网站se0优化公司
  • 中小学网站建设排行2017软文广告经典案例
  • 天津网站建设信息科技有限公司9个常用的wordpress sql查询命令
  • 浙江建设长沙优化网站建设
  • 厦门建设银行招聘网站应用下载app排行榜
  • 住房和城乡建设局网站照片书制作软件
  • 公司网站建设手机端跟PC端网站建设 新闻
  • 主体负责人和网站负责人学校手机网站模板
  • 没有网站怎么做网推京鑫建设集团网站
  • 河南省建设监理协会网站会员小程序怎么做
  • 网站悬浮二维码集团网站建设哪家好
  • 建设厅网站上企业登录徐州app定制
  • 网站建设费用申请有哪些网站可以做任务返现
  • 专业建站公司提供详细的功能描述及报价网站访问量有什么用
  • 嘉兴网站seo公司肥城移动网站制作
  • 广东网站备案需要多久直播软件app开发制作
  • 架构师必备:限流方案选型(使用篇)
  • 10月第一篇
  • 2025 年青岛点焊机厂家最新推荐榜,聚焦技术实力与市场口碑深度解析螺母/自动/螺栓/储能/汽车零部件点焊机厂家推荐
  • 网站优化用什么软件广西建设协会网站首页
  • 线性表
  • 2025 年不锈钢护栏厂家最新推荐排行榜:含河道、桥梁防撞、201/316L 材质、景观灯光类产品,精选高性能优质品牌
  • 网站精神文明建设专栏网站优化主要优化哪些地方