調用鏈監控 CAT 之 URL埋點實踐

来源:https://www.cnblogs.com/huanchupkblog/archive/2019/04/16/10714768.html
-Advertisement-
Play Games

URL監控埋點作用 一個http請求來了之後,會自動打點,能夠記錄每個url的訪問情況,並將以此請求後續的調用鏈路串起來,可以在cat上查看logview 可以在cat Transaction及Event 頁面上都看到URL和URL.Forward(如果有Forward請求的話)兩類數據;Trans ...


URL監控埋點作用

  • 一個http請求來了之後,會自動打點,能夠記錄每個url的訪問情況,並將以此請求後續的調用鏈路串起來,可以在cat上查看logview
  • 可以在cat Transaction及Event 頁面上都看到URL和URL.Forward(如果有Forward請求的話)兩類數據;Transaction數據中URL點進去的數據就是被訪問的具體URL(去掉參數的首碼部分)
  • 請將catFilter存放filter的第一個,這樣可以保證最大可能性監控所有的請求

實踐

工程說明

工程名 作用
cat-ui 8082 調用入口服務
cat-business-consumer 8083 業務消費服務
cat-order-service 8084 訂單服務
cat-storage-service 8085 庫存服務

上圖是本節實例的埋點圖,首先 cat-ui 的入口 和 調用點 加入cat埋點,cat-business-consumer的入口和調用點加入埋點,cat-order-service 和 cat-storage-service 不再調用其他微服務,所以只在入口加入埋點。通過這樣的埋點,可以組成一條完整的調用鏈。

關鍵代碼

調用鏈上下文通用類

CatContextImpl.java
/**
 * Cat.context介面實現類,用於context調用鏈傳遞,相關方法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協議傳輸rootId、parentId、childId三個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協議傳輸,遠程調用鏈目標端接收context的filter,
 * 通過header接收rootId、parentId、childId並放入CatContextImpl中,調用Cat.logRemoteCallServer()進行調用鏈關聯
 * 註:若不涉及調用鏈,則直接使用cat-client.jar中提供的filter即可
 * 使用方法(視項目框架而定):
 *      1、web項目:在web.xml中引用此filter
 *      2、Springboot項目,通過註入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() {

    }
}

本節實例中每個工程都會用到調用鏈上下文通用類。

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調用鏈上下文
            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));

            // 保證請求繼續被執行
            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 對 cat-ui 的入口進行了埋點,CatRestInterceptor 實現 ClientHttpRequestInterceptor介面 可以對 RestTemplate 發起的請求進行攔截,利用這一點對調用點埋點,同時在 Http Header 中存入 調用鏈的上下文,將調用鏈傳遞下去。

cat-business-consumer、cat-order-service、cat-storage-service 中的埋點與 cat-ui 埋點的方式相同。

測試

發起請求

curl http://127.0.0.1:8082/start

cat 監控界面可以看到本節實例的服務。

點開 “logView” 可以看到完整的調用鏈信息。

點擊 “Graph” 查看圖表形式的調用鏈信息。

源碼

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

參考

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




歡迎掃碼或微信搜索公眾號《程式員果果》關註我,關註有驚喜~


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 最近看了 "Dan Abramov" 的一些 "博客" ,學到了一些React的一些有趣的知識。決定結合自己的理解總結下。這些內容可能對你實際開發並沒有什麼幫助,不過這可以讓你瞭解到更多React底層實現的內容以及為什麼要怎樣實現。可以讓你跟別人有更多的談資,當然,也可以在某些場合裝一下逼。那麼接下 ...
  • 一、請求後端的JSON數據 JSON是前後端通信的交互格式,JSON(JavaScript Object Notation, JS 對象標記) 是一種輕量級的數據交換格式。 JSON是互聯網各個後臺與前代溝通必備格式,取代了原來的XML。 XML數據格式特別“噁心”,現在市場上99%以上的數據格式都 ...
  • 一、資料庫基礎 1.1什麼是資料庫? 什麼是資料庫? 答:就是一個很大的一個文件,只不過這個文件可以通過一些‘命令’操作數據; 增、刪、改、查數據; 資料庫等於持久數據和數據操作的一個統稱。 資料庫是按照數據結構來組織、存儲及管理數據的倉庫。 資料庫有哪些? MySQL、SQL server、Ora ...
  • 文章首發: "行為型模式:訪問者模式" 十一大行為型模式之十一:訪問者模式。 簡介 姓名 :訪問者模式 英文名 :Visitor Pattern 價值觀 :來訪者便是客,招待就是 個人介紹 : Represent an operation to be performed on the element ...
  • 一、簡介 ntop是一家以技術為驅動的公司,用戶多為個人和小公司,主要經營四款產品:Packet Capture、Traffic Recording、Network Probe、Traffic Analysis。 二、packet Capture 網路抓包使用具有PF_RING的商用硬體進行線速數據 ...
  • 系列鏈接地址: 深入理解設計模式 系列目錄 一、產品汪的神助攻,代碼狗的安慰劑 定義:設計模式,指的是一個場景(context)下的一種解決方法(Solution),只要大家都認可某種模式,那麼就只需要很短的一個名字,就可以代替很多很多的語言和文字交流,如果你覺得設計模式降低生產效率,那隻能說你在這 ...
  • 類是不是越小越好?最近在讀John Ousterhout的《A Philosophy of Software Design》,感到作者文筆流暢,書中內容具有啟發性。這裡摘要一部分內容,以供參考、學習。 本文鏈接:https://www.cnblogs.com/hhelibeb/p/10708951. ...
  • 多態的概述多態是繼封裝、繼承之後,面向對象的第三大特性。現實事物經常會體現出多種形態,如學生,學生是人的一種,則一個具體的同學張三既是學生也是人,即出現兩種形態。 Java作為面向對象的語言,同樣可以描述一個事物的多種形態。如Student類繼承了Person類,一個Student的對象便既是Stu... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...