当前位置: 移动技术网 > IT编程>开发语言>Java > 五分钟后,你将学会在SpringBoot项目中如何集成CAT调用链

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

2019年10月31日  | 移动技术网IT编程  | 我要评论

买买买结算系统

一年一度的双十一购物狂欢节就要到了,又到剁手党们开始表演的时刻了。当我们把种草很久的商品放入购物车以后,点击“结算”按钮时,就来到了买买买必不可少的结算页面了。让我们虚拟一个买买买结算系统,为结算页面提供商品、促销、库存等结算信息,就此系统展开如何在springboot项目中集成cat调用链。买买买结算系统包含以下4个项目:

  1. 结算ui:为前端页面提供结算的基础数据。
  2. 购物车api:获取用户购物车中有哪些商品。
  3. 商品api:获取商品详细信息
  4. 商品促销api:获取商品的促销信息
  5. 商品库存api:获取商品的库存信息

时序图如下:

通过maven添加依赖

<dependency>
    <groupid>com.dianping.cat</groupid>
    <artifactid>cat-client</artifactid>
    <version>3.0.0</version>
</dependency>

配置client.xml

创建/data/appdatas/cat/目录,并创建client.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<config xmlns:xsi="http://www.w3.org/2001/xmlschema" xsi:nonamespaceschemalocation="config.xsd">
    <servers>
        <server ip="127.0.0.1" port="2280" http-port="8080" />
    </servers>
</config>

注意:把127.0.0.1替换成cat服务端的ip。

配置项目名称

买买买结算系统中一共有5个项目,每个项目都需要配置各自的项目名称。
首先,在每个项目中创建如下文件:
src/main/resources/meta-inf/app.properties
然后,在每个项目里添加如下内容:

  1. 结算ui:
    app.name=buy-buy-buy-checkout
  2. 购物车api:
    app.name=buy-buy-buy-cart
  3. 商品api:
    app.name=buy-buy-buy-product
  4. 商品促销api:
    app.name=buy-buy-buy-promotion
  5. 商品库存api:
    app.name=buy-buy-buy-store

注意:项目名称只能包含英文字母 (a-z, a-z)、数字 (0-9)、下划线 (_) 和中划线 (-)

准备埋点

在埋点之前,需要先写两个公共类,方便之后埋点时调用。

  1. 第一个类实现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 + '}';
    }
}
  1. 第二个类中定义一些常量,在调用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";
}

开始埋点

使用cat进行分布式调用链监控,需要修改项目中的代码进行埋点:

  1. 在刚刚接收到请求时进行埋点。
  2. 在准备调用api时进行埋点。

那么在买买买结算系统中需要做哪些代码修改呢?看一下时序图的变化就明白了:

第一个埋点,在刚刚接收到请求时,这里使用filter实现,代码如下:

public class catservletfilter implements filter {

    @override
    public void init(filterconfig filterconfig) throws servletexception {

    }

    @override
    public void dofilter(servletrequest servletrequest, servletresponse servletresponse, filterchain filterchain) throws ioexception, servletexception {

        httpservletrequest request = (httpservletrequest) servletrequest;

        catcontext catcontext = new catcontext();
        catcontext.addproperty(cat.context.root, request.getheader(cathttpconstants.cat_http_header_root_message_id));
        catcontext.addproperty(cat.context.parent, request.getheader(cathttpconstants.cat_http_header_parent_message_id));
        catcontext.addproperty(cat.context.child, request.getheader(cathttpconstants.cat_http_header_child_message_id));
        cat.logremotecallserver(catcontext);

        transaction t = cat.newtransaction(catconstants.type_url, request.getrequesturi());

        try {
            
            cat.logevent("service.method", request.getmethod(), message.success, request.getrequesturl().tostring());
            cat.logevent("service.client", request.getremotehost());

            filterchain.dofilter(servletrequest, servletresponse);

            t.setstatus(transaction.success);
        } catch (exception ex) {
            t.setstatus(ex);
            cat.logerror(ex);
            throw ex;
        } finally {
            t.complete();
        }
    }

    @override
    public void destroy() {

    }
}

filter已经写好了,接下来还需要把filter注册到springboot中:

@configuration
public class catconfiguration {
    @bean
    public filterregistrationbean catservletfilter() {
        filterregistrationbean registration = new filterregistrationbean();
        catservletfilter filter = new catservletfilter();
        registration.setfilter(filter);
        registration.addurlpatterns("/*");
        registration.setname("cat-servlet-filter");
        registration.setorder(1);
        return registration;
    }
}

第两个埋点,在调用api的httpclient工具类中统一增加代码,以get方式为例:

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 {
        context ctx = new catcontext();
        cat.logremotecallclient(ctx);
        httpget.setheader(cathttpconstants.cat_http_header_root_message_id, ctx.getproperty(cat.context.root));
        httpget.setheader(cathttpconstants.cat_http_header_parent_message_id, ctx.getproperty(cat.context.parent));
        httpget.setheader(cathttpconstants.cat_http_header_child_message_id, ctx.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;
}

结语

以上便是springboot集成cat调用链的整个实例了,可以灵活应用,更加优雅的集成到实际项目中。
另外,cat还有很多丰富的功能,可参见。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网