========================
消息的基本屬性
========================
消息的幾個屬性:
type: 定義消息的 category, 比如 SQL 或 RPC 或 HTTP
name: 代表一個動作 action, 詳細的內容應該記錄到 data 屬性中, 而不是 name 屬性, 比如:
對於 SQL type 來講, name 應該是一個 SQL 模板, 如 select <?> from user where id = <?>
對於 RPC type 來講, name 應該是一個遠程函數的簽名, 如 QueryOrderByUserId(string, int)
對於 HTTP type 來講, name 應該是一個 base url, 比如 /api/v8/{int}/orders
status:
status <>0, 該消息會被認為是一個 problem, 而且該消息不會被聚合, 它會顯示在 Web UI 的 problemed logview 中的.
data:
記錄消息的詳細內容, 比如:
If the type is SQL, the data could be id=75442432
If the type is RPC, the data could be userType=dianping&userId=9987
If the type is HTTP, the data could be orderId=75442432
timestamp:
代表消息的創建時刻.
duration:
duration 只出現在 tranaction 類的消息中, 單位是毫秒
durationStart:
durationStart 只出現在 tranaction 類的消息中, 它代表 tranaction 開始時刻.
========================
環境准備
========================
參考: https://github.com/dianping/cat/blob/master/integration/springMVC-AOP/CAT%E9%83%A8%E7%BD%B2.txt
1. 配置客戶端文件, 拷貝 client.xml 文件
Linux\Mac 到 /data/appdatas/cat 下.
Windows 到項目程序運行盤的根目錄 /data/appdatas/cat 下.
/data/appdatas/cat/client.xml 客戶端配置文件的主要內容:
* servers : 定義多個服務端信息;
* server : 定義某個服務端信息;
* ip : 配置服務端(cat-home)對外 IP 地址;
* port : 配置服務端(cat-home)對外 TCP 協議開啟端口, 固定值為 2280;
* http-port : 配置服務端(cat-home)對外 HTTP 協議開啟端口, 如: tomcat 端口, 若未指定, 默認為 8080 端口;
<?xml version="1.0" encoding="utf-8"?> <config mode="client" xmlns:xsi="http://www.w3.org/2001/XMLSchema" xsi:noNamespaceSchemaLocation="config.xsd"> <servers> <server ip="10.1.5.87" port="2280" http-port="8080" /> <server ip="10.1.5.88" port="2280" http-port="8080" /> </servers> </config>
2. cat 管理頁面上增加一個新的項目名.
3. 在 Spring 程序中配置 app.properties 文件
在 src/main/resources/META-INF/app.properties 文件中設定項目名.
應用的名稱(可以根據此名稱在 CAT 的管理控制台查找對應的信息), 應用的名稱不要太長, 每個消息的前綴都是應用名.
內容如: app.name=${appName}
========================
pom.xml
========================
3.0 服務器應該需要和 3.0 客戶端搭配使用, 2.0 服務器應該是用 2.0 客戶端. 這里使用了 3.0 版.
文檔和源碼見: https://github.com/dianping/cat/tree/master/lib/java
cat-client 3.0.0 jar 包並沒有加到 maven 主 repository 中, 需要另加一個 repository 庫.
<dependency> <groupId>com.dianping.cat</groupId> <artifactId>cat-client</artifactId> <version>3.0.0</version> </dependency> <repository> <id>unidal.nexus</id> <url>http://unidal.org/nexus/content/repositories/releases/</url> </repository>
========================
程序集成方式
========================
在我們的業務代碼中, 不應該加入很多和 cat 監控相關的代碼, 監控代碼應該在基礎架構中實現, 除非是一些和業務指標相關的監控. 集成 cat 監控的方式有:
方式 1. 直接調用 cat api 實現基本監控.
方式 2. Url 請求監控, 通過注冊 CatFilter 實現.
方式 3. 日志類監控, 通過 cat 的 logback 插件實現.
方式 4. SQL 監控, 通過 cat 的 Mybatis Plugin 實現.
方式 5. 直接調用 cat api 實現調用鏈監控.
方式 6. 使用調用鏈的 CatCrossHttpClient 和 HttpCatCrossFilter
========================
方式 1. 直接調用 cat api 實現基本監控
========================
//------------------------ // transaction 類型的監控 //------------------------ Transaction t = Cat.newTransaction("some_type", "some_name"); //傳入 type 和 name try { // do something here double a=1/0; t.addData("some detail"); t.setStatus(Transaction.SUCCESS); } catch (Exception e) { Cat.logError(e); t.setStatus(e); } finally { t.complete(); }
//------------------------ // event 類型的監控 //------------------------ //Log an event, 並自動加上 success status and empty data. Cat.logEvent("URL.Server", "serverIp"); //Log an event with given status and given data //第三個參數為 status, "0"為正常, 其他為失敗, 可以傳入 error code 字符串 //第四個參數為 nameValuePairs, 可以按照 url 的 query string 形式傳入 kv 清單. Cat.logEvent("URL.Server", "serverIp", "failed", "ip=${serverIp}"); //Log exception Cat.logError(e); Cat.logError("error(X) := exception(X)", e); Cat.logErrorWithCategory("custom-category", e);
//------------------------ // Metric 的上報 //------------------------ Cat.logMetricForCount("Order", 100); //還有 logMetricForDuration()
//------------------------
// 組合消息樹
//------------------------
如果是直接使用 Cat 靜態方法調用多次 LogEvent() 方法, 這些 Event 並沒有組合到一個消息樹, 每個 Event 都是單獨一個消息樹. 要想將這些 Event 組成一個消息樹, 應該使用 MessageProducer 實例的方法, 而不是 Cat 靜態方法. 一個消息樹以 transaciton 創建為開始, 以 transaction 的 complete() 方法結束.
甚至, 可以在一個消息樹中嵌套另一個消息樹, 調用鏈監控就是基於父子消息樹嵌套實現的.
//單個消息樹 @RequestMapping("/mix") public String mix() { MessageProducer cat=Cat.getProducer(); // 獲取一個 MessageProducer 實例 Transaction t = cat.newTransaction("URL", "helloEtl"); //傳入 type 和 name cat.logEvent("EventType", "EventName"); cat.logMetric("aaaa", "bbb", "200"); try { // do something here double a=1/0; t.addData("some detail"); t.setStatus(Transaction.SUCCESS); } catch (Exception e) { t.setStatus(e); } finally { t.complete(); } return "mix"; }
//父子消息樹 @RequestMapping("/mix2") public String mix2() { MessageProducer cat=Cat.getProducer(); Transaction t = cat.newTransaction("URL", "helloEtl"); //傳入 type 和 name cat.logEvent("EventType", "EventName"); cat.logMetric("aaaa", "bbb", "200"); //cat2 為內嵌消息樹, 在一個transaction內部, 每新建一個新的transaction, 就采用push stack機制內嵌一個transaction. MessageProducer cat2=Cat.getProducer(); Transaction t2 = cat2.newTransaction("URL", "helloEtl222"); //傳入 type 和 name cat2.logEvent("EventType", "EventName"); t2.complete(); try { // do something here double a=1/0; t.addData("some detail"); t.setStatus(Transaction.SUCCESS); } catch (Exception e) { t.setStatus(e); } finally { t.complete(); } return "mix2"; }
========================
方式 2. Url 請求監控, 通過注冊 CatFilter 實現.
========================
監控 Url 訪問非常簡單, 直接注冊一個 CatFilter 即可.
對於 SpringBoot 程序, 參考: https://github.com/dianping/cat/blob/master/integration/spring-boot/CatFilterConfigure.java
對於 Spring MVC 程序, 參考 https://github.com/dianping/cat/blob/master/integration/springMVC-AOP
@Configuration public class CatFilterConfigure { @Bean public FilterRegistrationBean catFilter() { FilterRegistrationBean registration = new FilterRegistrationBean(); CatFilter filter = new CatFilter(); registration.setFilter(filter); registration.addUrlPatterns("/*"); registration.setName("cat-filter"); registration.setOrder(1); return registration; } }
========================
方式 3. 日志類監控, 通過 cat 的 logback 插件實現.
========================
參考: https://github.com/dianping/cat/tree/master/integration/logback
如果需要使用 Cat 自定義的 Appender, 需要在 logback.xml 中添加如下配置:
<appender name="CatAppender" class="com.dianping.cat.logback.CatLogbackAppender"></appender> <root level="info"> <appender-ref ref="CatAppender" /> </root>
========================
方式 4. SQL 監控, 通過 cat 的 Mybatis Plugin 實現.
========================
也很簡單, 配置 mybatis 配置插件即可.
參考 https://github.com/dianping/cat/tree/master/integration/mybatis
========================
方式 5. 直接調用 cat api 實現調用鏈監控.
========================
參考 https://www.cnblogs.com/xing901022/p/6237874.html
在微服務環境中, 如果要檢查調用鏈上每個服務的性能, 不是一件很容的事情, 幸好 cat 支持. 在 cat 中仍然可使用 transaction 來將調用次序構成一個鏈路, 和普通 transaction 不同的是, 它需要提供一個調用的 context, 該 context 主要包含三個 id:
1. RootId, 用於標識唯一一個調用鏈
2. ParentId, 父 Id 是誰, 誰在調用我.
3. ChildId, 我在調用誰?
另外, 需要服務端和調用端應用程序同屬於一個 domain.
Cat 的 Context 是一個接口, 需要我們實現, 由於這個 context 需要跨網絡傳輸, 如果使用 RMI 方式, 實現類要能夠序列化; 如果 rest 風格的 http 請求方式, 需要我們將在服務請求時把 context 放到 Http-Header 傳到服務提供方.
//Cat Context 接口 public interface Context { String ROOT = "_catRootMessageId"; String PARENT = "_catParentMessageId"; String CHILD = "_catChildMessageId"; void addProperty(String var1, String var2); String getProperty(String var1); } //Context 的實現類: public class MyContext implements Cat.Context,Serializable{ private static final long serialVersionUID = 7426007315111778513L; private Map<String,String> properties = new HashMap<String,String>(); @Override public void addProperty(String s, String s1) { properties.put(s,s1); } @Override public String getProperty(String s) { return properties.get(s); } }
如何初始化和使用一個 context 呢? Cat 已經提供了兩個方法, 分別是:
1. logRemoteCallClient(), 該方法用在微服務的調用端, 用來初始化 context.
2. logRemoteCallServer(), 該方法用在微服務的服務端, 將 context 傳遞給服務端的 threadLocal 變量, 形成消息樹的結構.
========================
方式 6. 使用調用鏈的 CatCrossHttpClient 和 HttpCatCrossFilter
========================
通過上面的 API 方式實現調用鏈監控, 比較復雜, 最好做一些封裝.
rest 風格的 http 請求方式, 調用時在服務請求方把消息 id 信息放到 Http-Header 中; 在服務提供方, 用 filter 攔截, 並獲得 http-header 中的消息 id, 這樣通過埋點, 串聯起消息樹.
下面的博客, 提供一個服務器端實現了一個 HttpCatCrossFilter,主調端采用 CatCrossHttpClient, 可以大大簡化代碼.
https://www.cnblogs.com/yeahwell/p/cat.html
下面博客也是一個思路:
https://my.oschina.net/u/129971/blog/688371
https://github.com/summerpotato/cat-monitor/blob/master/src/main/java/net/tomjerry/catmonitor/filter/HttpCatCrossFliter.java
======================
參考
======================
深入詳解美團點評 CAT 跨語言服務監控(三)CAT 客戶端原理
https://blog.csdn.net/caohao0591/article/details/80207806
美團 CAT 集群的搭建與集成
https://kefeng.wang/2018/07/06/tracing-cat/
大眾點評 CAT 開源監控系統剖析
https://www.cnblogs.com/yeahwell/p/cat.html
CAT 使用小結 -- 調用鏈
https://my.oschina.net/u/129971/blog/688371
基於 Cat 的分布式調用追蹤
http://www.cnblogs.com/xing901022/p/6237874.html
和 Spring-boot/logback 等集成
https://github.com/dianping/cat/tree/master/integration/
Cat 統一監控平台簡單使用
https://my.oschina.net/fuxingCoder/blog/750639
http://fanlychie.github.io/post/springmvc-dubbo-mybatis-with-cat.html
官網客戶端
https://github.com/dianping/cat/tree/master/lib
攜程開源的 .Net 客戶端
https://github.com/ctripcorp/cat.net