CAT简介

CAT(Central Application Tracking),是美团点评基于 Java 开发的一套开源的分布式实时监控系统。美团点评基础架构部希望在基础存储、高性能通信、大规模在线访问、服务治理、实时监控、容器化及集群智能调度等领域提供业界领先的、统一的解决方案,CAT 目前在美团点评的产品定位是应用层的统一监控组件,在中间件(RPC、数据库、缓存、MQ 等)框架中得到广泛应用,为各业务线提供系统的性能指标、健康状况、实时告警等服务。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

准备工作

对于同步请求API,CAT服务端自然是可以看到的。同步请求API的实例可以参考之前的文章《五分钟后,你将学会在SpringBoot项目中如何集成CAT调用链》。但对于异步请求API,因为不在同一线程中,在子线程中无法获取到父线程消息树,所以在CAT服务端是无法看到的对应请求。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

首先,写一个类实现Cat.Context接口,用于存放消息树的上下文信息:

public class CatContext implements Cat.Context {

    private Map<String, String> properties = new HashMap<>();

    @Override
public void addProperty(String key, String value) {
properties.put(key, value);
} @Override
public String getProperty(String key) {
return properties.get(key);
} @Override
public 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);
} @Override
public V call() throws Exception {
//保存父线程消息树的上下文信息到子线程
ContextWarehouse.setContext(this.catContext);
return callable.call();
}
}

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

定义一些常量,在调用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;
}
}

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

异步请求实例

下面写一个异步请求的实例,通过多个商品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 {
//调用获取商品详细信息的API
return 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报表中就可以查看到异步请求了。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

CAT中实现异步请求的调用链查看的更多相关文章

  1. Springmvc中 同步/异步请求参数的传递以及数据的返回

    转载:http://blog.csdn.net/qh_java/article/details/44802287 注意: 这里的返回就是返回到jsp页面 **** controller接收前台数据的方 ...

  2. springmvc中同步/异步请求参数的传递以及数据的返回

    注意: 这里的返回就是返回到jsp页面 **** controller接收前台数据的方式,以及将处理后的model 传向前台***** 1.前台传递数据的接受:传的属性名和javabean的属性相同 ...

  3. iOS中POST异步请求

    POST异步请求(代理) 1.遵循<NSURLConnectionDataDelegate> @interface ViewController ()<NSURLConnection ...

  4. Jquery中Ajax异步请求中的async参数的作用

    之前不知道这个参数的作用,上网找了前辈的博客,在此收录到自己的博客,希望能帮到更多的朋友: test.html <a href="javascript:void(0)" on ...

  5. for循环中嵌套异步请求问题

    for循环中嵌套了异步请求会导致顺序错乱,用递归代替for循环,可以保证正常执行顺序:

  6. vue 中promise 异步请求数据

    export function getTypes(type) { return listDictItems({ code: type }).then((res) => { if (res.cod ...

  7. 在Mvc中进行异步请求是出现(没有为该对象定义无参数的构造函数)

    解决办法就是给相应的类添加无参数的构造函数:

  8. 五分钟后,你将学会在SpringBoot项目中如何集成CAT调用链

    买买买结算系统 一年一度的双十一购物狂欢节就要到了,又到剁手党们开始表演的时刻了.当我们把种草很久的商品放入购物车以后,点击"结算"按钮时,就来到了买买买必不可少的结算页面了.让我 ...

  9. 异步请求中jetty处理ServletRequestListener的坑

    标题起得比较诡异,其实并不是坑,而是jetty似乎压根就没做对异步request的ServletRequestListener的特殊处理,如果文中有错误欢迎提出,可能自己有所疏漏了. 之前遇到了一个b ...

随机推荐

  1. Tomcat启动超时设置

    Tomcat启动超时设置: 处理方法: 1. 在server中找到当前Tomcat双击. 2.在视图中进行修改.(如下图:)

  2. Python开发之路:目录篇

    第一部分:Python基础知识 本篇主要python基础知识的积累和学习,其中包括python的介绍.基本数据类型.函数.模块及面向对象等.  第一篇:Python简介  第二篇:Python基本知识 ...

  3. 【转】基于TMS320C6455的千兆以太网设计

    基于TI公司最新DSP芯片TMS320C6455.设计并实现了以太网通信软硬件接口.采用TMS320C6455片内以太网接口模块EMAC/MDIO,结合片外AR8031 PHY芯片,在嵌入式操作系统D ...

  4. [ipsec][crypto] ike/ipsec与tls的认证机制比较

    前言 接上篇:[ipsec][crypto] 有点不同的数字证书到底是什么 本篇内容主要是上一篇内容的延伸.抽象的从概念上理解了证书是什么之后,我们接下来 从实践的角度出发,以IKEv2和TLS两个协 ...

  5. 191010 python3分解质因数

    # 题目:将一个正整数分解质因数.例如:输入90,打印出90=2*3*3*5.# 程序分析:对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完成:# (1)如果这个质数恰等于n,则说明分解 ...

  6. WEB前端-搜索引擎工作原理与SEO优化

    一.搜索引擎工作原理 搜索引擎的工作分为三个阶段,即爬行,索引和检索 1.爬行  搜索引擎具有网络爬虫或蜘蛛来执行爬网,每次抓取工具访问网页时,它都会复制该网页并将其网址添加到索引中. 在“蜘蛛”抓取 ...

  7. 使用Python的turtle库实现六角形以及正方形螺旋线的绘制

    1.六角形的绘制 思路:一个六角形可以看作是两个等边三角形具有共同的中心且垂线互成60°角.所以只需实现一个等边三角形的绘制以及第二个三角形绘制起点的移动即可. 代码如下: import turtle ...

  8. 0027SpringMVC拦截器的编写和配置

    SpringMvc中想使用拦截器,主要分为两步: a.编写拦截器,需实现HandlerInterceptor接口 b.springmvc.xml中配置拦截器 逻辑图如下: 测试过程主要分为如下几步: ...

  9. LightOJ - 1354 - IP Checking(进制)

    链接: https://vjudge.net/problem/LightOJ-1354 题意: An IP address is a 32 bit address formatted in the f ...

  10. [React] Use the React Effect Hook in Function Components

    Similar to the State Hook, the Effect Hook is “first-class” in React and handy for performing side e ...