溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

調(diào)用鏈監(jiān)控 CAT 之 URL埋點(diǎn)實(shí)踐

發(fā)布時(shí)間:2020-07-28 04:43:04 來(lái)源:網(wǎng)絡(luò) 閱讀:442 作者:程序員果果 欄目:編程語(yǔ)言

URL監(jiān)控埋點(diǎn)作用

  • 一個(gè)http請(qǐng)求來(lái)了之后,會(huì)自動(dòng)打點(diǎn),能夠記錄每個(gè)url的訪問(wèn)情況,并將以此請(qǐng)求后續(xù)的調(diào)用鏈路串起來(lái),可以在cat上查看logview
  • 可以在cat Transaction及Event 頁(yè)面上都看到URL和URL.Forward(如果有Forward請(qǐng)求的話)兩類(lèi)數(shù)據(jù);Transaction數(shù)據(jù)中URL點(diǎn)進(jìn)去的數(shù)據(jù)就是被訪問(wèn)的具體URL(去掉參數(shù)的前綴部分)
  • 請(qǐng)將catFilter存放filter的第一個(gè),這樣可以保證最大可能性監(jiān)控所有的請(qǐng)求

實(shí)踐

工程說(shuō)明

工程名 端口 作用
cat-ui 8082 調(diào)用入口服務(wù)
cat-business-consumer 8083 業(yè)務(wù)消費(fèi)服務(wù)
cat-order-service 8084 訂單服務(wù)
cat-storage-service 8085 庫(kù)存服務(wù)

調(diào)用鏈監(jiān)控 CAT 之 URL埋點(diǎn)實(shí)踐

上圖是本節(jié)實(shí)例的埋點(diǎn)圖,首先 cat-ui 的入口 和 調(diào)用點(diǎn) 加入cat埋點(diǎn),cat-business-consumer的入口和調(diào)用點(diǎn)加入埋點(diǎn),cat-order-service 和 cat-storage-service 不再調(diào)用其他微服務(wù),所以只在入口加入埋點(diǎn)。通過(guò)這樣的埋點(diǎn),可以組成一條完整的調(diào)用鏈。

關(guān)鍵代碼

調(diào)用鏈上下文通用類(lèi)
CatContextImpl.java
/**
 * Cat.context接口實(shí)現(xiàn)類(lèi),用于context調(diào)用鏈傳遞,相關(guān)方法Cat.logRemoteCall()和Cat.logRemoteServer()
 */
public class CatContextImpl implements Cat.Context {

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

    @Override
    public void addProperty(String key, String value) {
        properties.put(key, value);
    }

    @Override
    public String getProperty(String key) {
        return properties.get(key);
    }
}
CatHttpConstants
/**
 * 添加header常量,用于http協(xié)議傳輸rootId、parentId、childId三個(gè)context屬性
 */
public class CatHttpConstants {

    /**
     * http header 常量
     */
    public static final String CAT_HTTP_HEADER_ROOT_MESSAGE_ID = "X-CAT-ROOT-MESSAGE-ID";
    public static final String CAT_HTTP_HEADER_PARENT_MESSAGE_ID = "X-CAT-ROOT-PARENT-ID";
    public static final String CAT_HTTP_HEADER_CHILD_MESSAGE_ID = "X-CAT-ROOT-CHILD-ID";

}
CatServletFilter
/**
 * http協(xié)議傳輸,遠(yuǎn)程調(diào)用鏈目標(biāo)端接收context的filter,
 * 通過(guò)header接收rootId、parentId、childId并放入CatContextImpl中,調(diào)用Cat.logRemoteCallServer()進(jìn)行調(diào)用鏈關(guān)聯(lián)
 * 注:若不涉及調(diào)用鏈,則直接使用cat-client.jar中提供的filter即可
 * 使用方法(視項(xiàng)目框架而定):
 *      1、web項(xiàng)目:在web.xml中引用此filter
 *      2、Springboot項(xiàng)目,通過(guò)注入bean的方式注入此filter
 */
public class CatServletFilter implements Filter {

    private String[] urlPatterns = new String[0];

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String patterns = filterConfig.getInitParameter("CatHttpModuleUrlPatterns");
        if (patterns != null) {
            patterns = patterns.trim();
            urlPatterns = patterns.split(",");
            for (int i = 0; i < urlPatterns.length; i++) {
                urlPatterns[i] = urlPatterns[i].trim();
            }
        }
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;

        String url = request.getRequestURL().toString();
        for (String urlPattern : urlPatterns) {
            if (url.startsWith(urlPattern)) {
                url = urlPattern;
            }
        }

        CatContextImpl catContext = new CatContextImpl();
        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, url);

        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() {

    }
}

本節(jié)實(shí)例中每個(gè)工程都會(huì)用到調(diào)用鏈上下文通用類(lèi)。

cat-ui 工程
CatRestInterceptor
@Component
public class CatRestInterceptor implements ClientHttpRequestInterceptor {

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        Transaction t = Cat.newTransaction(CatConstants.TYPE_REMOTE_CALL, request.getURI().toString());

        try {
            HttpHeaders headers = request.getHeaders();

            // 保存和傳遞CAT調(diào)用鏈上下文
            Cat.Context ctx = new CatContextImpl();
            Cat.logRemoteCallClient(ctx);
            headers.add(CatHttpConstants.CAT_HTTP_HEADER_ROOT_MESSAGE_ID, ctx.getProperty(Cat.Context.ROOT));
            headers.add(CatHttpConstants.CAT_HTTP_HEADER_PARENT_MESSAGE_ID, ctx.getProperty(Cat.Context.PARENT));
            headers.add(CatHttpConstants.CAT_HTTP_HEADER_CHILD_MESSAGE_ID, ctx.getProperty(Cat.Context.CHILD));

            // 保證請(qǐng)求繼續(xù)被執(zhí)行
            ClientHttpResponse response =  execution.execute(request, body);
            t.setStatus(Transaction.SUCCESS);
            return response;
        } catch (Exception e) {
            Cat.getProducer().logError(e);
            t.setStatus(e);
            throw e;
        } finally {
            t.complete();
        }

    }
}

CatServletFilter 對(duì) cat-ui 的入口進(jìn)行了埋點(diǎn),CatRestInterceptor 實(shí)現(xiàn) ClientHttpRequestInterceptor接口 可以對(duì) RestTemplate 發(fā)起的請(qǐng)求進(jìn)行攔截,利用這一點(diǎn)對(duì)調(diào)用點(diǎn)埋點(diǎn),同時(shí)在 Http Header 中存入 調(diào)用鏈的上下文,將調(diào)用鏈傳遞下去。

cat-business-consumer、cat-order-service、cat-storage-service 中的埋點(diǎn)與 cat-ui 埋點(diǎn)的方式相同。

測(cè)試

發(fā)起請(qǐng)求

curl http://127.0.0.1:8082/start

cat 監(jiān)控界面可以看到本節(jié)實(shí)例的服務(wù)。

調(diào)用鏈監(jiān)控 CAT 之 URL埋點(diǎn)實(shí)踐

點(diǎn)開(kāi) “l(fā)ogView” 可以看到完整的調(diào)用鏈信息。

調(diào)用鏈監(jiān)控 CAT 之 URL埋點(diǎn)實(shí)踐

點(diǎn)擊 “Graph” 查看圖表形式的調(diào)用鏈信息。

調(diào)用鏈監(jiān)控 CAT 之 URL埋點(diǎn)實(shí)踐

源碼

https://github.com/gf-huanchupk/SpringCloudLearning/tree/master/chapter15

參考

https://github.com/dianping/cat/wiki

歡迎關(guān)注我的公眾號(hào)《程序員果果》,關(guān)注有驚喜~~
調(diào)用鏈監(jiān)控 CAT 之 URL埋點(diǎn)實(shí)踐

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI