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. 十七、存储过程&自定义函数详解

    代码中被[]包含的表示可选,|符号分开的表示可选其一. 需求背景介绍 线上程序有时候出现问题导致数据错误的时候,如果比较紧急,我们可以写一个存储来快速修复这块的数据,然后再去修复程序,这种方式我们用到 ...

  2. Ceph FS 挂载

    Cephfs使用挂载方式有两种 1.使用linux kernel挂载 mount 2.使用ceph-fuse挂载. 1.下图为mount挂载 mount -t ceph 10.110.180.112: ...

  3. [https][tls] 如何使用wireshark查看tls/https加密消息--使用keylog

    姊妹篇: [ipsec][strongswan] 使用wireshark查看strongswan ipsec esp ikev1 ikev2的加密内容 [https][tls] 如何使用wiresha ...

  4. IP详解

    现在的IP网络使用32位地址,以点分十进制表示,如172.16.0.0.地址格式为:IP地址=网络地址+主机地址 或 IP地址=主机地址+子网地址+主机地址. IP地址类型  最初设计互联网络时,为了 ...

  5. Java精通并发-透过openjdk源码分析wait与notify方法的本地实现

    上一次https://www.cnblogs.com/webor2006/p/11442551.html中通过openjdk从c++的底层来审视了ObjectMonitor的底层实现,这次继续来探究底 ...

  6. 《Exceptioning团队》第四次作业:项目需求调研与分析

    一.项目基本介绍 项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 作业链接地址 团队名称 Exception 作业学习目标 1.探索团队软件项目需求获取技巧与方法2.学会 ...

  7. stm32中使用cubemx配置freertos的信号量大小

    在配置freertos的情况下,cubemx会自动计算每个任务.信号,队列和软件定时器的使用堆栈大小,因此要合理规划 信号量默认是88byte 任务根据设定来计算,我默认配置是128,则最终是624b ...

  8. ubuntu下subversion1.7的安装

    环境: ubuntu11.10 subversion1.7 1.用synaptic安装的svn都是1.6版,根本于现在的主流svn服务器无法通信.需要升级为1.7. 1.1 apt-add-repos ...

  9. [Javascript] Avoid Accidental Returns of New State by using the void Keyword

    For example we have a 'useState' function, which takes a state and a function to update the state: c ...

  10. 如何轻松愉快地理解条件随机场(CRF)

    https://blog.csdn.net/DCX_abc/article/details/78319246 机器学习之条件随机场(CRF): https://blog.csdn.net/wangya ...