CAT中实现异步请求的调用链查看
CAT简介
CAT(Central Application Tracking),是美团点评基于 Java 开发的一套开源的分布式实时监控系统。美团点评基础架构部希望在基础存储、高性能通信、大规模在线访问、服务治理、实时监控、容器化及集群智能调度等领域提供业界领先的、统一的解决方案,CAT 目前在美团点评的产品定位是应用层的统一监控组件,在中间件(RPC、数据库、缓存、MQ 等)框架中得到广泛应用,为各业务线提供系统的性能指标、健康状况、实时告警等服务。
准备工作
对于同步请求API,CAT服务端自然是可以看到的。同步请求API的实例可以参考之前的文章《五分钟后,你将学会在SpringBoot项目中如何集成CAT调用链》。但对于异步请求API,因为不在同一线程中,在子线程中无法获取到父线程消息树,所以在CAT服务端是无法看到的对应请求。
首先,写一个类实现Cat.Context接口,用于存放消息树的上下文信息:
public class CatContext implements Cat.Context {private Map<String, String> properties = new HashMap<>();@Overridepublic void addProperty(String key, String value) {properties.put(key, value);}@Overridepublic String getProperty(String key) {return properties.get(key);}@Overridepublic String toString() {return "CatContext{"+ "properties=" + properties + '}';}
}
我们可以先父线程消息树的上下文信息保存下来,然后在子线程使用。先写一个存放上下文信息的地方:
public class ContextWarehouse {private static ThreadLocal<CatContext> contextThreadLocal = new ThreadLocal();public static void setContext(final CatContext context) {contextThreadLocal.set(context);}public static CatContext getContext() {//先从ContextWarehouse中获取上下文信息CatContext context = contextThreadLocal.get();if (context == null) {context = new CatContext();Cat.logRemoteCallClient(context);}return context;}
}
实现Callable接口,创建一个自定义的类,实现了在子线程中存放父线程的上下文信息的功能:
public class OneMoreCallable<V> implements Callable<V> {private CatContext catContext;private Callable<V> callable;public DdCallable(final Callable<V> callable) {this.callable = callable;this.catContext = new CatContext();//获取父线程消息树的上下文信息Cat.logRemoteCallClient(this.catContext);}@Overridepublic V call() throws Exception {//保存父线程消息树的上下文信息到子线程ContextWarehouse.setContext(this.catContext);return callable.call();}
}
定义一些常量,在调用API时作为header中的key:
public class CatHttpConstants {public static final String CAT_HTTP_HEADER_CHILD_MESSAGE_ID = "DD-CAT-CHILD-MESSAGE-ID";public static final String CAT_HTTP_HEADER_PARENT_MESSAGE_ID = "DD-CAT-PARENT-MESSAGE-ID";public static final String CAT_HTTP_HEADER_ROOT_MESSAGE_ID = "DD-CAT-ROOT-MESSAGE-ID";
}
埋点时,在调用API的HttpClient工具类中统一增加代码,以GET方式为例:
public class HttpClientUtil {public static String doGet(String url) throws IOException {HttpGet httpGet = new HttpGet(url);CloseableHttpResponse response = null;CloseableHttpClient httpClient = HttpClientBuilder.create().build();String content = null;Transaction t = Cat.newTransaction(CatConstants.TYPE_CALL, url);try {CatContext context = ContextWarehouse.getContext();httpGet.setHeader(CatHttpConstants.CAT_HTTP_HEADER_ROOT_MESSAGE_ID, context.getProperty(Cat.Context.ROOT));httpGet.setHeader(CatHttpConstants.CAT_HTTP_HEADER_PARENT_MESSAGE_ID, context.getProperty(Cat.Context.PARENT));httpGet.setHeader(CatHttpConstants.CAT_HTTP_HEADER_CHILD_MESSAGE_ID, context.getProperty(Cat.Context.CHILD));response = httpClient.execute(httpGet);if (response.getStatusLine().getStatusCode() == 200) {content = EntityUtils.toString(response.getEntity(), "UTF-8");t.setStatus(Transaction.SUCCESS);}} catch (Exception e) {Cat.logError(e);t.setStatus(e);throw e;} finally {if (response != null) {response.close();}if (httpClient != null) {httpClient.close();}t.complete();}return content;}
}
异步请求实例
下面写一个异步请求的实例,通过多个商品ID异步获取对应的商品详细信息:
public class ProductService {/*** 声明一个大小固定为10的线程池*/private static ExecutorService executor = Executors.newFixedThreadPool(10);/*** 通过商品ID列表异步获取对应的商品详细信息** @param productIds 商品ID列表* @return 对应的商品详细信息*/public List<String> findProductInfo(List<Long> productIds) {List<Future<String>> futures = new ArrayList<>();for (Long productId : productIds) {futures.add(executor.submit(new DdCallable(() -> {try {//调用获取商品详细信息的APIreturn HttpClientUtil.doGet("http://api.product/get?id=" + productId);} catch (Exception e) {return "";}})));}List<String> productInfos = new ArrayList<>();for (Future<String> future : futures) {try {//异步获取对应商品详细信息productInfos.add(future.get());} catch (Exception e) {productInfos.add("");}}return productInfos;}
}
这样写以后,在CAT服务端的Transaction报表中就可以查看到异步请求了。
CAT中实现异步请求的调用链查看相关推荐
- PHP guzzle异步请求数据,Guzzle中的异步请求
Guzzle中的异步请求 使用Guzzle发起异步请求 Guzzle是一个PHP的HTTP客户端,它在发起http请求时不仅可以同步发起,还可以异步发起. $client = new Client() ...
- php中jquery ajax请求参数,浅谈Jquery中Ajax异步请求中的async参数的作用
之前不知道这个参数的作用,上网找了前辈的博客,在此收录到自己的博客,希望能帮到更多的朋友: test.html asy.js function testAsync{ var temp; $.ajax( ...
- react中实现异步请求的方法一,react-thunk
写在前面: 在react中,dispatch是同步执行reducers生成新状态的,对于页面的操作没有问题:但是如果点击事件是请求了某个结果,需要等待结果响应后再更新视图呢?应该如何处理?这里就用到了 ...
- SpringMVC中的异步请求-跨域访问
发送异步请求: <%@page pageEncoding="UTF-8" language="java" contentType="text/h ...
- @async 没有异步_扒一扒VueCLI3.0中Axios异步请求同步化
前台经常会遇到请求同步和异步的问题,今天咱们来聊一聊vue中同步请求和异步请求那些事儿. 说到接口的请求同步和异步问题,最早接触Ajax中就存在,Ajax传递的参数有一个async,默认情况下是fal ...
- html中的异步请求数据格式,解决layui中table异步数据请求不支持自定义返回数据格式的问题...
使用版本 layui-v2.3.0 修改: 打开layui中table.js源码 在 Class.prototype.pullData 这个方法定义内部 //获得数据 Class.prototype. ...
- jax-rs jax-ws_在JAX-RS中处理异步请求中的超时
jax-rs jax-ws JAX-RS 2.0在客户端和服务器端都支持异步编程范例. 这篇文章重点介绍了使用JAX-RS(2.0)API在服务器端执行异步REST请求时的超时功能 无需过多介绍,这里 ...
- 在JAX-RS中处理异步请求中的超时
JAX-RS 2.0在客户端和服务器端都支持异步编程范例. 这篇文章重点介绍了使用JAX-RS(2.0)API在服务器端执行异步REST请求时的超时功能 无需过多介绍,这里是一个快速概述. 为了以异步 ...
- 异步请求中jetty处理ServletRequestListener的坑
标题起得比较诡异,其实并不是坑,而是jetty似乎压根就没做对异步request的ServletRequestListener的特殊处理,如果文中有错误欢迎提出,可能自己有所疏漏了. 之前遇到了一个b ...
最新文章
- JSP第二次作业_5小题
- html5主要是针对哪方面行优化,前端知识点总结(HTML篇)
- YIFullScreenScroll
- 九种破解Xp登录密码方法
- [转载] 深入剖析 redis 主从复制
- 一些debug常用的魔法数值
- 调用cmd不显示黑框的方法
- 40.QT-QPropertyAnimationdong和QParallelAnimationGroup动画实现
- praying,blessing,wishing
- 《PostgreSQL 指南:内幕探索》之基础备份与时间点恢复(上)
- 95-40-014-生产者-KafkaProducer
- JSON-RPC轻量级远程调用协议介绍及使用
- java接口中有效的方法声明_在Java接口中,下列选顶中有效的方法声明是
- echarts 折线图y轴自定义 使用icon
- 【VS】错误1error LNK1168: 无法打开 F:\C++6\prob\ConsoleApplication1\Debug\ConsoleApplication1.exe 进行写入
- Python常用标准库、模块
- 数据结构算法—非递归算法求二叉树的叶子结点(C语言)
- css中自适应字体问题等
- 软件工程的完整生命周期
- 拆解1968年的美国军用电脑,真的怀疑是“穿越”啊!