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. RabbitMQ topic 交换器

    topic交换器:"."将路由键分为几个标识符,"*"匹配一个, "#"可以匹配多个 1:路由键为*或者#的时候 *:只能匹配单个的字符串 ...

  2. 学习python的日常7

    ---恢复内容开始--- 正则表达式: 在正则表达式中,用\d可以匹配一个数字,\w可以匹配一个字母或数字,'.'可以匹配任意字符,用*表示任意个字符,用+表示至少一个字符,用?表示0个货一个字符,用 ...

  3. golang基础归纳

    1. hello-world package main import "fmt" func main(){ fmt.Println("Hello world, Go Go ...

  4. QEMU简介

    参考:What Is the Difference between QEMU and KVM? 注意:上面参考文章有个错误,他把KVM算成类型一虚拟化,应该是类型2虚拟化. 关于类型一虚拟化和类型二虚 ...

  5. IAR为STM32创建工程模板(基于STM32f103zet6)

    今天给小伙伴分享一篇给stm32新建工程模版 1.首先打开IAR,就是这个样子 2.再建一个目录文件夹 3.建立一个工作空间,以及建好工作空间如右图所示 4.接下来建立工程,Project------ ...

  6. abp学习(二)

    翻译下首页截图的标签: DDD Base Classes 介绍: 应用程序代码库的分层是一种被广泛接受的技术,可帮助降低复杂性并提高代码重用性.为了实现分层架构,ASP.NET样板遵循域驱动设计的原则 ...

  7. Centos7.3云服务器上安装Nginx、MySQL、JDK、Tomcat环境

    安装的软件路径建议放到/usr/local目录下 Tomcat 首先从最简单的Tomcat开始,进入到Apache的官网:http://www.apache.org,下载合适的版本来装,一般建议8.0 ...

  8. markdown种嵌入html标签,实现自定义样式

    转:https://www.cnblogs.com/buwuliao/p/9578918.html -------------------------------------------------- ...

  9. ORM框架三种映射在Springboot上的使用

    ORM(对象/关系映射)是数据库层非常重要的一部分,有三种常用的映射关系 1.多对一 tbl_clazz clazz{ id name description grade_id charge_id } ...

  10. pytorch imagenet测试代码

    image_test.py import argparse import numpy as np import sys import os import csv from imagenet_test_ ...