深入詳解美團點評CAT跨語言服務監控(一) CAT簡介與部署
原文連結: https://blog.csdn.net/caohao0591/article/details/80693289
前言: CAT是一個實時和接近全量的監控系統,它側重於對Java應用的監控,除了與點評RPC元件融合的很好之外,他將會能與Spring、MyBatis、Dubbo 等框架以及Log4j 等結合,支援PHP、C++、Go等多語言應用,基本接入了美團點評上海側所有核心應用。目前在中介軟體(MVC、RPC、資料庫、快取等)框架中得到廣泛應用,為美團點評各業務線提供系統的效能指標、健康狀況、監控告警等,在微服務監控領域也是非常有用的一套元件。支撐這美團每天450億的訊息,50TB的資料監控,應用於 7000+應用伺服器,2000+的業務,單臺機器能15W qps,15臺CAT物理叢集,有著極高的效能,同時CAT支援豐富的報表,架構擁有靈活的擴充套件性,使用者可以定製自己的監控、報表需求,本文將就CAT的部署、架構原始碼以及多語言支援等方面展開剖析。CAT在攜程、陸金所、獵聘網、找鋼網、平安銀行等多家網際網路公司生產環境應用。
目錄:
(一) CAT簡介與部署
介紹
背景介紹
Cat系統的特性
訊息樹
CAT服務端部署
CAT客戶端Demo
(二) CAT服務端初始化
Cat模組
Cat-servlet初始化
plexus - IOC容器
模組的載入 - 模型模式
cat-home的setup
TcpSocketReceiver--- netty reactor 模式的應用
訊息的解碼
(三) CAT客戶端原理
cat客戶端部分核心類
訊息的組織 - 訊息樹
客戶端的初始化
訊息生產 -- 入棧
Context 執行緒本地變數
Transaction事務的開啟
其他型別訊息組合
訊息的完成-出棧
訊息的傳送-佇列化
訊息的序列化
MessageId的設計
(四) 服務端訊息分發
分發架構
分析管理器的初始化
消費者與週期管理器的初始化
什麼是週期?
週期任務-任務佇列
訊息分發
週期策略
(五) 配置與資料庫操作
CAT配置
程式碼自動生成
資料庫操作
資料庫連線管理
(六) 訊息分析器與報表(一)
訊息分析器的構建
TopAnalyzer
EventAnalyzer - 事件發生次數分析
MetricAnalyzer - 業務分析
ProblemAnalyzer -異常分析
TransactionAnalyzer - 事務分析
(七)訊息分析器與報表(二)
CrossAnalyzer-呼叫鏈分析
StorageAnalyzer --資料庫/快取分析
StateAnalyzer -- CAT狀態分析
HeartbeatAnalyzer -- 心跳分析
DumpAnalyzer -- 原始訊息LogView儲存
自定義分析器與報表
(八) 報表持久化
週期結束
分析器的結束 -- 報表持久化
報表預處理
報表的檔案儲存 -- 重入鎖
報表的資料庫儲存
定時任務
(九) 管理平臺MVC框架
Servlet容器與請求生命週期
頁面路由初始化
請求處理流程
(十)與JAVA框架的整合
與Spring MVC整合
與Spring Boot 整合
與Spring Cloud 整合
與dubbo整合
與MyBatis整合
與Log4j整合
(十一) 其他語言支援
PHP語言
C++語言
LUA語言
Go語言
Python語言
Node.js語言
Android埋點
Object C -- IOS 埋點
(十二) 報警與監控提醒
簡訊通知
郵件通知
(十三) CAT與實時計算
hadoop模組
spark實時計算模組
介紹
大眾點評CAT系統原型和理念來源於eBay的CAL的系統,CAT系統第一代設計者吳其敏在eBay工作長達十幾年,對CAL系統有深刻的理解。CAT不僅增強了CAL系統核心模型,還添加了更豐富的報表。自2014年開源以來,CAT在攜程、陸金所、獵聘網、找鋼網等多家網際網路公司生產環境應用。
CAT是一個實時和接近全量的監控系統,它側重於對Java應用的監控,除了與點評RPC元件融合的很好之外,他將會能與Spring、MyBatis、Dubbo 等框架以及Log4j 等結合,不久將會支援PHP、C++、Go等多語言應用,基本接入了美團點評上海側所有核心應用。目前在中介軟體(MVC、RPC、資料庫、快取等)框架中得到廣泛應用,為美團點評各業務線提供系統的效能指標、健康狀況、監控告警等,在微服務監控領域也是非常有用的一套元件。
在詳細瞭解CAT的整體設計細節之後,我們可以在CAT基礎之上輕鬆擴充套件我們自己的監控和資料收集模組。
CAT專案的開源地址: https://github.com/dianping/cat
背景介紹
CAT整個產品研發是從2011年底開始的,當時正是大眾點評App Net遷移Java的核心起步階段。當初大眾點評App已經有核心的基礎中介軟體、RPC元件Pigeon、統一配置元件lion。整體Java遷移已經在服務化的路上。隨著服務化的深入,整體Java在線上部署規模逐漸變多,同時,暴露的問題也越來越多。典型的問題有:
大量報錯,特別是核心服務,需要花很久時間才能定位。
異常日誌都需要線上許可權登陸線上機器排查,排錯時間長。
有些簡單的錯誤定位都非常困難(一次將線上的庫配置到了Beta,花了整個通宵排錯)。
很多不了了之的問題都懷疑是網路問題(從現在看,內網真的很少出問題)。
雖然那時候也有一些簡單的監控工具(比如Zabbix,自己研發的Hawk系統等),可能單個工具在某方面的功能還不錯,但整體服務化水平參差不齊、擴充套件能力相對較弱,監控工具間不能互通互聯,使得查詢問題根源基本都需要在多個系統之間切換,有時候真的是靠“人品”才能找出根源。適逢吳其敏從eBay加入大眾點評成為首席架構師,eBay的CAL系統在內部非常成功,就在這樣天時地利與人和的情況下,我們開始研發了大眾點評App第一代監控系統——CAT。
Cat系統的特性
實時處理:資訊的價值會隨時間銳減,尤其是事故處理過程中。
全量資料:最開始的設計目標就是全量採集,全量的好處有很多。
高可用:所有應用都倒下了,需要監控還站著,並告訴工程師發生了什麼,做到故障還原和問題定位。
故障容忍:CAT本身故障不應該影響業務正常運轉,CAT掛了,應用不該受影響,只是監控能力暫時減弱。
高吞吐:要想還原真相,需要全方位地監控和度量,必須要有超強的處理吞吐能力。
可擴充套件:支援分散式、跨IDC部署,橫向擴充套件的監控系統。
不保證可靠:允許訊息丟失,這是一個很重要的trade-off,目前CAT服務端可以做到4個9的可靠性,可靠系統和不可靠性系統的設計差別非常大。
CAT支援的監控訊息型別包括:
Transaction 適合記錄跨越系統邊界的程式訪問行為,比如遠端呼叫,資料庫呼叫,也適合執行時間較長的業務邏輯監控,Transaction用來記錄一段程式碼的執行時間和次數。
Event 用來記錄一件事發生的次數,比如記錄系統異常,它和transaction相比缺少了時間的統計,開銷比transaction要小。
Heartbeat 表示程式內定期產生的統計資訊, 如CPU%, MEM%, 連線池狀態, 系統負載等。
Metric 用於記錄業務指標、指標可能包含對一個指標記錄次數、記錄平均值、記錄總和,業務指標最低統計粒度為1分鐘。
Trace 用於記錄基本的trace資訊,類似於log4j的info資訊,這些資訊僅用於檢視一些相關資訊
訊息樹
CAT監控系統將每次URL、Service的請求內部執行情況都封裝為一個完整的訊息樹、訊息樹可能包括Transaction、Event、Heartbeat、Metric和Trace資訊,各個訊息樹之間,通過 rootMessageId以及parentMessageId串聯起來,形成整個呼叫鏈條。
完整的訊息樹:
視覺化的訊息樹:
分散式訊息樹【一臺機器呼叫另外一臺機器】:
CAT服務端部署
CAT安裝環境:
Linux 2.6以及之上(2.6核心才可以支援epoll),線上服務端部署請使用Linux環境,Mac以及Windows環境可以作為開發環境,美團點評內部CentOS 6.5
Java 6,7,8,服務端推薦是用jdk7的版本,客戶端jdk6、7、8都支援
Maven 3.3.3
MySQL 5.6,5.7,更高版本MySQL都不建議使用,不清楚相容性
J2EE容器建議使用tomcat,建議版本7.0.70
Hadoop環境可選,一般建議規模較小的公司直接使用磁碟模式,可以申請CAT服務端,500GB磁碟或者更大磁碟,這個磁碟掛載在/data/目錄上
目前我司線上環境:
Distributor ID: CentOS
Description: CentOS release 6.5 (Final)
Release: 6.5
Codename: Final
Server version: Apache Tomcat/8.0.30
Server built: Dec 1 2015 22:30:46 UTC
Server number: 8.0.30.0
OS Name: Linux
OS Version: 2.6.32-431.el6.x86_64
Architecture: amd64
JVM Version: 1.8.0_111-b14
JVM Vendor: Oracle Corporation
Maven 3.3.3
Mysql 5.6
Tomcat 7.0.70 建議使用此版本
我的開發環境:
作業系統: Windows 7
IDE: Intelij IDEA
JDK版本:1.8
Mysql: 5.6
Maven: 3.3.3
Server version:Apache Tomcat/8.0.30
安裝CAT叢集大致步驟
初始化Mysql資料庫,一套CAT叢集部署一個數據庫,初始化指令碼在script下的Cat.sql
準備三臺CAT伺服器,IP比如為10.1.1.1,10.1.1.2,10.1.1.3,下面的例子會以這個IP為例子
初始化/data/目錄,配置幾個配置檔案/data/appdatas/cat/*.xml 幾個配置檔案,具體下面有詳細說明
打包cat.war 放入tomcat容器
修改一個路由配置,重啟tomcat
Tomcat啟動引數調整,修改 catalina.sh檔案【服務端】
需要每臺CAT叢集10.1.1.1,10.1.1.2,10.1.1.3都進行部署
建議使用cms gc策略
建議cat的使用堆大小至少10G以上,開發環境啟動2G堆啟動即可
CATALINA_OPTS="$CATALINA_OPTS -server -Djava.awt.headless=true -Xms25G -Xmx25G -XX:PermSize=256m -XX:MaxPermSize=256m -XX:NewSize=10144m -XX:MaxNewSize=10144m -XX:SurvivorRatio=10 -XX:+UseParNewGC -XX:ParallelGCThreads=4 -XX:MaxTenuringThreshold=13 -XX:+UseConcMarkSweepGC -XX:+DisableExplicitGC -XX:+UseCMSInitiatingOccupancyOnly -XX:+ScavengeBeforeFullGC -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=9 -XX:CMSInitiatingOccupancyFraction=60 -XX:+CMSClassUnloadingEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:-ReduceInitialCardMarks -XX:+CMSPermGenSweepingEnabled -XX:CMSInitiatingPermOccupancyFraction=70 -XX:+ExplicitGCInvokesConcurrent -Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.EPollSelectorProvider -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file="%CATALINA_HOME%\conf\logging.properties" -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationConcurrentTime -XX:+PrintHeapAtGC -Xloggc:/data/applogs/heap_trace.txt -XX:-HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/applogs/HeapDumpOnOutOfMemoryError -Djava.util.Arrays.useLegacyMergeSort=true"
修改中文亂碼 tomcat conf 目錄下 server.xml:
<Connector port="8080" protocol="HTTP/1.1" URIEncoding="utf-8" connectionTimeout="20000" redirectPort="8443" /> 增加 URIEncoding="utf-8"
程式對於/data/目錄具體讀寫許可權【包括客戶端&服務端】
注意無論是CAT客戶端和服務端都要求/data/目錄能進行讀寫操作,如果/data/目錄不能寫,建議使用linux的軟連結連結到一個固定可寫的目錄,軟連結的基本命令請自行搜尋google
此目錄會存一些CAT必要的配置檔案,執行時候的快取檔案,建議不要修改,如果想改,請自行研究好原始碼裡面的東西,在酌情修改,此目錄不支援進行配置化
mkdir /data
chmod 777 /data/ -R
如果是Windows開發環境則是對程式執行盤下的/data/appdatas/cat和/data/applogs/cat有讀寫許可權,如果cat服務執行在e盤的tomcat中,則需要對e:/data/appdatas/cat和e:/data/applogs/cat有讀寫許可權
如果windows實在不知道哪個盤,就所有盤都建好,最後看哪個盤多檔案,就知道哪個了,當然你也可以通過配置系統環境變數CAT_HOME來指定伺服器日誌儲存的路徑,不過好像資料庫連線xml資訊等好像不太好自己配置,最好還是採用系統預設的 /data 目錄。
配置/data/appdatas/cat/client.xml【包括客戶端&服務端】
此配置檔案的作用是所有的客戶端都需要一個地址指向CAT的服務端,比如CAT服務端有三個IP,10.1.1.1,10.1.1.2,10.1.1.3,2280是預設的CAT服務端接受資料的埠,不允許修改,http-port是Tomcat啟動的埠,預設是8080,建議使用預設埠。
此檔案可以通過運維統一進行部署和維護,比如使用puppert等運維工具。
不同環境這份檔案不一樣,比如區分prod環境以及test環境,在美團點評內部一共是2套環境的CAT,一份是生產環境,一份是測試環境
<?xml version="1.0" encoding="utf-8"?>
<config mode="client">
<servers>
<server ip="10.1.1.1" port="2280" http-port="8080"/>
<server ip="10.1.1.2" port="2280" http-port="8080"/>
<server ip="10.1.1.3" port="2280" http-port="8080"/>
</servers>
</config>
安裝CAT的資料庫
資料庫的指令碼檔案 script/Cat.sql
MySQL的一個系統引數:max_allowed_packet,其預設值為1048576(1M),修改為1000M,修改完需要重啟mysql
注意:一套獨立的CAT叢集只需要一個數據庫(之前碰到過個別同學在每臺cat的服務端節點都安裝了一個數據庫)
配置/data/appdatas/cat/datasources.xml【服務端配置】
需要每臺CAT叢集10.1.1.1,10.1.1.2,10.1.1.3都進行部署
注意:此xml僅僅為模板,請根據自己實際的情況替換jdbc.url,jdbc.user,jdbc.password的實際值。 app資料庫和cat資料配置為一樣,app庫不起作用,為了執行時候程式碼不報錯。
<?xml version="1.0" encoding="utf-8"?>
<data-sources>
<data-source id="cat">
<maximum-pool-size>3</maximum-pool-size>
<connection-timeout>1s</connection-timeout>
<idle-timeout>10m</idle-timeout>
<statement-cache-size>1000</statement-cache-size>
<properties>
<driver>com.mysql.jdbc.Driver</driver>
<url><![CDATA[${jdbc.url}]]></url>
<user>${jdbc.user}</user>
<password>${jdbc.password}</password>
<connectionProperties><![CDATA[useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&socketTimeout=120000]]></connectionProperties>
</properties>
</data-source>
<data-source id="app">
<maximum-pool-size>3</maximum-pool-size>
<connection-timeout>1s</connection-timeout>
<idle-timeout>10m</idle-timeout>
<statement-cache-size>1000</statement-cache-size>
<properties>
<driver>com.mysql.jdbc.Driver</driver>
<url><![CDATA[${jdbc.url}]]></url>
<user>${jdbc.user}</user>
<password>${jdbc.password}</password>
<connectionProperties><![CDATA[useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&socketTimeout=120000]]></connectionProperties>
</properties>
</data-source>
</data-sources>
配置/data/appdatas/cat/server.xml【服務端配置】
需要每臺CAT叢集10.1.1.1,10.1.1.2,10.1.1.3都進行部署
CAT節點一共有四個職責
控制檯 - 提供給業務人員進行資料檢視【預設所有的cat節點都可以作為控制檯,不可配置】
消費機 - 實時接收業務資料,實時處理,提供實時分析報表【預設所有的cat節點都可以作為消費機,不可配置】
告警端 - 啟動告警執行緒,進行規則匹配,傳送告警(目前僅支援單點部署)【可以配置】
任務機 - 做一些離線的任務,合併天、周、月等報表 【可以配置】
線上做多叢集部署,比如說10.1.1.1,10.1.1.2,10.1.1.3這三臺機器
建議選取一臺10.1.1.1 負責角色有控制檯、告警端、任務機,建議配置域名訪問CAT,就配置一臺機器10.1.1.1一臺機器掛在域名下面
10.1.1.2,10.1.1.3 負責消費機處理,這樣能做到有效隔離,任務機、告警等問題不影響實時資料處理
預設script下的server.xml為
<?xml version="1.0" encoding="utf-8"?>
<config local-mode="false" hdfs-machine="false" job-machine="true" alert-machine="false">
<storage local-base-dir="/data/appdatas/cat/bucket/" max-hdfs-storage-time="15" local-report-storage-time="7" local-logivew-storage-time="7">
<hdfs id="logview" max-size="128M" server-uri="hdfs://10.1.77.86/user/cat" base-dir="logview"/>
<hdfs id="dump" max-size="128M" server-uri="hdfs://10.1.77.86/user/cat" base-dir="dump"/>
<hdfs id="remote" max-size="128M" server-uri="hdfs://10.1.77.86/user/cat" base-dir="remote"/>
</storage>
<console default-domain="Cat" show-cat-domain="true">
<remote-servers>127.0.0.1:8080</remote-servers>
</console>
</config>
配置說明:
local-mode : 建議在開發環境以及生產環境時,都設定為false
hdfs-machine : 定義是否啟用HDFS儲存方式,預設為 false
job-machine : 定義當前服務是否為報告工作機(開啟生成彙總報告和統計報告的任務,只需要一臺服務機開啟此功能),預設為 false
alert-machine : 定義當前服務是否為報警機(開啟各類報警監聽,只需要一臺服務機開啟此功能),預設為 false;
storage : 定義資料儲存配置資訊
local-report-storage-time : 定義本地報告檔案存放時長,單位為(天)
local-logivew-storage-time : 定義本地日誌檔案存放時長,單位為(天)
local-base-dir : 定義本地資料儲存目錄,建議直接使用/data/appdatas/cat/bucket目錄
hdfs : 定義HDFS配置資訊
server-uri : 定義HDFS服務地址
console : 定義服務控制檯資訊
remote-servers : 定義HTTP服務列表,(遠端監聽端同步更新服務端資訊即取此值)
ldap : 定義LDAP配置資訊(這個可以忽略)
ldapUrl : 定義LDAP服務地址(這個可以忽略)
按照如上的說明,10.1.1.1 機器/data/appdatas/cat/serverm.xml配置,注意hdfs配置就隨便下了一個,請忽略
<?xml version="1.0" encoding="utf-8"?>
<config local-mode="false" hdfs-machine="false" job-machine="true" alert-machine="true">
<storage local-base-dir="/data/appdatas/cat/bucket/" max-hdfs-storage-time="15" local-report-storage-time="7" local-logivew-storage-time="7">
<hdfs id="logview" max-size="128M" server-uri="hdfs://10.1.77.86/user/cat" base-dir="logview"/>
<hdfs id="dump" max-size="128M" server-uri="hdfs://10.1.77.86/user/cat" base-dir="dump"/>
<hdfs id="remote" max-size="128M" server-uri="hdfs://10.1.77.86/user/cat" base-dir="remote"/>
</storage>
<console default-domain="Cat" show-cat-domain="true">
<remote-servers>10.1.1.1:8080,10.1.1.2:8080,10.1.1.3:8080</remote-servers>
</console>
</config>
10.1.1.2,10.1.1.3 機器/data/appdatas/cat/serverm.xml配置如下,僅僅job-machine&alert-machine修改為false
<?xml version="1.0" encoding="utf-8"?>
<config local-mode="false" hdfs-machine="false" job-machine="false" alert-machine="false">
<storage local-base-dir="/data/appdatas/cat/bucket/" max-hdfs-storage-time="15" local-report-storage-time="7" local-logivew-storage-time="7">
<hdfs id="logview" max-size="128M" server-uri="hdfs://10.1.77.86/user/cat" base-dir="logview"/>
<hdfs id="dump" max-size="128M" server-uri="hdfs://10.1.77.86/user/cat" base-dir="dump"/>
<hdfs id="remote" max-size="128M" server-uri="hdfs://10.1.77.86/user/cat" base-dir="remote"/>
</storage>
<console default-domain="Cat" show-cat-domain="true">
<remote-servers>10.1.1.1:8080,10.1.1.2:8080,10.1.1.3:8080</remote-servers>
</console>
</config>
war打包
1、在cat的原始碼目錄,執行mvn clean install -DskipTests
2、如果發現cat的war打包不通過,CAT所需要依賴jar都部署在 http://unidal.org/nexus/
3、可以配置這個公有云的倉庫地址到本地的settings路徑,理論上不需要配置即可,可以參考cat的pom.xml配置
4、如果自行打包仍然問題,請使用下面連結進行下載http://unidal.org/nexus/service/local/repositories/releases/content/com/dianping/cat/cat-home/2.0.0/cat-home-2.0.0.war
5、官方的cat的master版本,重新命名為cat.war進行部署,注意此war是用jdk8,服務端請使用jdk8版本
6、如下是個人本機電腦的測試,下載的jar來自於repo1.maven.org 以及 unidal.org
Downloading: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-utils/3.0.24/plexus-utils-3.0.24.jar
Downloaded: http://repo1.maven.org/maven2/org/apache/commons/commons-email/1.1/commons-email-1.1.jar (30 KB at 9.8 KB/sec)
Downloaded: http://repo1.maven.org/maven2/javax/servlet/jstl/1.2/jstl-1.2.jar (405 KB at 107.7 KB/sec)
Downloaded: http://repo1.maven.org/maven2/com/google/code/javaparser/javaparser/1.0.8/javaparser-1.0.8.jar (235 KB at 55.4 KB/sec)
Downloaded: http://repo1.maven.org/maven2/org/codehaus/plexus/plexus-utils/3.0.24/plexus-utils-3.0.24.jar (242 KB at 46.9 KB/sec)
Downloaded: http://repo1.maven.org/maven2/org/freemarker/freemarker/2.3.9/freemarker-2.3.9.jar (789 KB at 113.3 KB/sec)
Downloading: http://unidal.org/nexus/content/repositories/releases/org/unidal/webres/WebResServer/1.2.1/WebResServer-1.2.1.jar
Downloading: http://unidal.org/nexus/content/repositories/releases/org/unidal/webres/WebResTagLibrary/1.2.1/WebResTagLibrary-1.2.1.jar
Downloading: http://unidal.org/nexus/content/repositories/releases/org/unidal/webres/WebResTag/1.2.1/WebResTag-1.2.1.jar
Downloading: http://unidal.org/nexus/content/repositories/releases/org/unidal/webres/WebResRuntime/1.2.1/WebResRuntime-1.2.1.jar
Downloading: http://unidal.org/nexus/content/repositories/releases/org/unidal/webres/WebResApi/1.2.1/WebResApi-1.2.1.jar
Downloaded: http://unidal.org/nexus/content/repositories/releases/org/unidal/webres/WebResApi/1.2.1/WebResApi-1.2.1.jar (21 KB at 82.7 KB/sec)
Downloading: http://unidal.org/nexus/content/repositories/releases/org/unidal/webres/WebResBase/1.2.1/WebResBase-1.2.1.jar
```
[INFO] parent ............................................. SUCCESS [ 40.478 s]
[INFO] cat-client ......................................... SUCCESS [03:47 min]
[INFO] cat-core ........................................... SUCCESS [ 31.740 s]
[INFO] cat-hadoop ......................................... SUCCESS [02:50 min]
[INFO] cat-consumer ....................................... SUCCESS [ 3.197 s]
[INFO] cat-home ........................................... SUCCESS [ 58.964 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
```
war部署
1、將cat.war部署到10.1.1.1的tomcat的webapps下,啟動tomcat,注意webapps下只允許放一個war,僅僅為cat.war
2、如果發現重啟報錯,裡面有NPE等特殊情況,可以檢查當前java程序,ps aux | grep java,可能存在之前的tomcat的程序沒有關閉,又新啟動了一個,導致出問題,建議kill -9 幹掉所有的java程序
3、開啟控制檯的URL,http://10.1.1.1:8080/cat/s/config?op=routerConfigUpdate
4、注意10.1.1.1這個IP需要替換為自己實際的IP連結,修改路由配置只能修改一次即可
5、修改路由配置為如下,當為如下配置時,10.1.1.1 正常不起消費資料的作用,僅當10.1.1.2以及10.1.1.3都掛掉才會進行實時流量消費
<?xml version="1.0" encoding="utf-8"?>
<router-config backup-server="10.1.1.1" backup-server-port="2280">
<default-server id="10.1.1.2" weight="1.0" port="2280" enable="true"/>
<default-server id="10.1.1.3" weight="1.0" port="2280" enable="true"/>
</router-config>
6、重啟10.1.1.1的機器的tomcat
7、將cat.war部署到10.1.1.2,10.1.1.3這兩臺機器中,啟動tomcat
8、cat叢集部署完畢,如果有問題,歡迎在微信群諮詢,如果文件有誤差,歡迎指正以及提交pullrequest
重啟保證資料不丟
請在tomcat重啟之前呼叫當前tomcat的儲存資料的連結 http://${ip}:8080/cat/r/home?op=checkpoint,重啟之後資料會恢復。【注意重啟時間在每小時的整點10-55分鐘之間】
線上部署時候,建議把此連結呼叫存放於tomcat的stop指令碼中,這樣不需要每次手工呼叫
開發環境CAT的部署
1、請按照如上部署/data/環境目錄,資料庫配置client.xml ,datasources.xml,server.xml這三個配置檔案,注意server.xml裡面的節點角色,job-machine&alert-machine都可以配置為true
2、在cat目錄中執行 mvn eclipse:eclipse,此步驟會生成一些程式碼檔案,直接匯入到工程會發現找不到類
3、將原始碼以普通專案到入eclipse中,注意不要以maven專案匯入工程
4、執行com.dianping.cat.TestServer 這個類,即可啟動cat伺服器
5、這裡和叢集版本唯一區別就是服務端部署單節點,client.xml server.xml以及路由地址配置為單臺即可
CAT客戶端Demo
cat客戶端的配置:
cat客戶端也需要配置 /data 目錄,程式對於/data/目錄具體讀寫許可權可以參考上一節,
然後通過maven引入cat客戶端包,在pom.xml 加入:
<dependency>
<groupId>com.dianping.cat</groupId>
<artifactId>cat-core</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.dianping.cat</groupId>
<artifactId>cat-client</artifactId>
<version>2.0.0</version>
</dependency>
引入之後:
以上配置會通過maven從網上引入 cat-core和cat-client 包,如果無法配置引入,也可以手動引入 cat-client.jar 包。
CAT預設會將/data/appdatas/cat 作為CAT Home目錄,這個目錄至關重要,CAT客戶端配置檔案 client.xml 是在這個目錄內,當然,如果你是在 windows 下除錯, 你也可以在src/main/resources/ 目錄下新建 META-INF/cat 目錄, 並將 client.xml 配置檔案放入 src/main/resources/META-INF/cat 目錄裡,你可以為你的監控配置domain,即專案名,如下配置 <domain id="translate"/> 。
<?xml version="1.0" encoding="utf-8"?>
<config mode="client" xmlns:xsi="http://www.w3.org/2001/XMLSchema" xsi:noNamespaceSchemaLocation="config.xsd">
<domain id="translate"/>
<servers>
<!-- Local mode for development -->
<server ip="127.0.0.1" port="2280" http-port="8080" />
<!-- If under production environment, put actual server address as list. -->
<!--
<server ip="192.168.7.71" port="2280" />
<server ip="192.168.7.72" port="2280" />
-->
</servers>
</config>
第一個監控程式:
所有都配置好了,接下來我們來寫第一個監控程式,監控都是由使用者自己埋點,當然,在本書最後,我們將會講解CAT監控如何與各個流行框架之間更好的融合,以幫助使用者達到無侵入式的監控埋點,假設我們對使用者提供了一個翻譯服務,其中有個介面就是HelloWorld,在下面程式中,我們將以事務日誌形式記錄使用者呼叫行為:
public Object helloWorld(HttpServletRequest request, HttpServletResponse response) {
MessageProducer cat = Cat.getProducer();
Transaction t = cat.newTransaction("URL", "Translate/HelloWorld"); //type=URL的事務記錄: 你的介面/方法名稱
try{
//do your business
t.setStatus(Message.SUCCESS);
} catch (Exception e) {
Cat.getProducer().logError(e);
t.setStatus(e);
} finally {
t.complete();
}
return null;
}
好了,我們再去管理平臺去看看報表資訊把,Transaction事務報表中,type=URL的事務有3條,我們通常用URL型別的事務訊息標誌著介面服務的開始,展開之後,我們看到這個裡面該專案提供的3個服務被呼叫了,其中就有我們的 Translate/HelloWorld:
再點開某個介面的[::show::]進入詳細統計,包括耗時分佈、每分鐘的資料、以及該服務叢集下各個機器的統計情況,我們可以通過這個看出是不是某臺機器出了問題:
點選LogView進入最近一條事務的原始日誌(problem報表才會記錄全部的原始日誌):
接下來,我們來看一個更復雜的案例,涉及服務的呼叫以及資料庫、快取的呼叫,如下:
@Controller
public class Translate {
public Map<String, String> maps = new HashMap<String, String>();
public Cat.Context context;
@RequestMapping(value = "/translate/getWordMean", produces = "application/json")
@ResponseBody
//獲取翻譯釋義
public Object getWordMean(HttpServletRequest request, HttpServletResponse response) {
context = new Cat.Context() {
@Override
public void addProperty(String key, String value) {
maps.put(key, value);
}
@Override
public String getProperty(String key) {
return maps.get(key);
}
}; //服務呼叫訊息上下文
MessageProducer cat = Cat.getProducer();
Transaction t = cat.newTransaction("URL", "translate/getWordMean"); //你的介面/方法名稱
cat.logEvent("ClientInfo", "RemoteIp=127.0.0.1&Referer=..."); //記錄遠端呼叫端資訊
cat.logEvent("Payload", "HTTP/GET /translate/getWordMean?client=3&clientVersion=0&v=9.5&uid=3214567...."); //呼叫端引數
//使用者校驗
authCheck();
//先從快取Redis獲取結果
Transaction cacheT = cat.newTransaction("Cache.memcached.redis", "translate_result:get");
cat.logEvent("Cache.memcached.redis.server", "127.0.0.1:6379");
//do your cache operation
cacheT.setStatus(Message.SUCCESS);
cacheT.complete();
//do your translate operation
//記錄遠端語音服務呼叫
Transaction callT = cat.newTransaction("Call", "voice:getVoice");
Cat.logEvent("Call.server","localhost"); //遠端服務地址
Cat.logEvent("Call.app","voice"); //語音服務
Cat.logEvent("Call.port","8080"); //語音服務埠
Cat.logRemoteCallClient(context); //生成訊息呼叫上下文,主要是幾個messageId的建立。
voiceService(context);
callT.setStatus(Message.SUCCESS);
callT.complete();
OutputData result = new OutputData();
result.setErrno(0);
result.setErrmsg("success");
result.setTranslateResult("translate result ...");
t.setStatus(Message.SUCCESS);
t.complete();
return result;
}
public boolean authCheck() {
MessageProducer cat = Cat.getProducer();
Transaction checkUser = cat.newTransaction("Method", "checkAuth");
//從資料庫查詢使用者資訊
Transaction sqlT = cat.newTransaction("SQL", "Select");
cat.logEvent("SQL.Database", "jdbc:mysql://127.0.0.1:3306/user");
cat.logEvent("SQL.Method", "select");
cat.logEvent("SQL.Statement", "SELECT", Message.SUCCESS, "select * from user_info");
//to do your SQL query
sqlT.setStatus(Message.SUCCESS);
sqlT.complete();
//to do your auth check
checkUser.setStatus(Message.SUCCESS);
checkUser.complete();
return true;
}
//執行緒模擬語音服務
protected void voiceService(final Cat.Context context) {
Thread thread = new Thread() {
@Override
public void run() {
//伺服器埋點,Domain為 voice 提供語音服務
Cat.getManager().getThreadLocalMessageTree().setDomain("voice");
MessageProducer cat = Cat.getProducer();
Transaction voiceService = Cat.newTransaction("URL", "voice/getVoice"); //你的介面/方法名稱
cat.logEvent("ClientInfo", "RemoteIp=127.0.0.1&Referer=..."); //記錄遠端呼叫端資訊
cat.logEvent("Payload", "HTTP/GET /voice/getVoice?client=3&clientVersion=0&v=9.5&uid=3214567...."); //呼叫端引數
//記錄服務資訊
Transaction child = Cat.newTransaction("Service", "voice:getVoice");
Cat.logEvent("Service.client", "localhost"); //客戶端地址
Cat.logEvent("Service.app", "translate"); //客戶端domain
Cat.logRemoteCallServer(context); //記錄訊息上下文
//to do your business
child.setStatus(Message.SUCCESS);
child.complete();
voiceService.setStatus(Message.SUCCESS);
voiceService.complete();
}
};
thread.start();
// wait for it to complete
try {
thread.join();
} catch (InterruptedException e) {
// ignore it
}
}
}
這是我們一個對外提供的翻譯服務,getWordMean為服務控制器入口,我們將原始訊息展開如下,整個服務處理耗時571ms,一進來我們會記錄URL型別事務,以及呼叫引數,然後記錄使用者校驗函式,在函式內部,有查詢使用者資訊的資料庫操作,也會被記錄下,查詢耗時150ms,接下來我們會先從快取獲取結果, 快取查詢耗時 59ms,隨後我們翻譯內容,翻譯之後我們會呼叫語音服務提供的發音介面,voice/getVoice,發音介面呼叫一共耗時 361 ms。
下一篇: CAT跨語言服務鏈監控(二) CAT服務端初始化