买买买结算零碎


一年一度的双十一购物狂欢节就要到了,又到剁手党们开始表演的时刻了。当咱们把种草很久的商品放入购物车当前,点击“结算”按钮时,就来到了买买买必不可少的结算页面了。让咱们虚构一个买买买结算零碎,为结算页面提供商品、促销、库存等结算信息,就此零碎开展如何在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 + '}'; }}
  2. 第二个类中定义一些常量,在调用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中:

@Configurationpublic 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_URL, 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还有很多丰盛的性能,可参见官网。