龙空技术网

深入详解美团点评CAT跨语言服务监控(一) CAT简介与部署

黑驴他爷 597

前言:

现在看官们对“nginxtomcatmem”都比较关怀,看官们都需要分析一些“nginxtomcatmem”的相关资讯。那么小编在网络上汇集了一些对于“nginxtomcatmem””的相关文章,希望看官们能喜欢,我们一起来了解一下吧!

前言:

CAT是一个实时和接近全量的监控系统,它侧重于对Java应用的监控,除了与点评RPC组件融合的很好之外,他将会能与Spring、MyBatis、Dubbo 等框架以及Log4j 等结合,支持PHP、C++、Go等多语言应用,基本接入了美团点评上海侧所有核心应用。目前在中间件(MVC、RPC、数据库、缓存等)框架中得到广泛应用,为美团点评各业务线提供系统的性能指标、健康状况、监控告警等,在微服务监控领域也是非常有用的一套组件。支撑这美团每天450亿的消息,50TB的数据监控,应用于 7000+应用服务器,2000+的业务,单台机器能15W qps,15台CAT物理集群,有着极高的性能,同时CAT支持丰富的报表,架构拥有灵活的扩展性,用户可以定制自己的监控、报表需求,本文将就CAT的部署、架构源码以及多语言支持等方面展开剖析。CAT在携程、陆金所、猎聘网、找钢网、平安银行等多家互联网公司生产环境应用。

目录:(一) CAT简介与部署    1.1 介绍    1.2 背景介绍    1.3 Cat系统的特性    1.4 消息树    1.5 CAT服务端部署    1.6 CAT客户端Demo(二) CAT服务端初始化    2.1 Cat模块    2.2 Cat-servlet初始化    2.3 plexus - IOC容器    2.4 模块的加载 - 模型模式    2.5 cat-home的setup    2.6 TcpSocketReceiver--- netty reactor 模式的应用    2.7 消息的解码    (三) CAT客户端原理    3.1 cat客户端部分核心类    3.2 消息的组织 - 消息树    3.3 客户端的初始化    3.4 消息生产 -- 入栈    3.5 Context 线程本地变量    3.6 Transaction事务的开启    3.7 其他类型消息组合    3.8 消息的完成-出栈    3.9 消息的发送-队列化    3.10 消息的序列化    3.11 MessageId的设计    (四) 服务端消息分发    4.1 分发架构    4.2 分析管理器的初始化    4.3 消费者与周期管理器的初始化    4.4 什么是周期?    4.5 周期任务-任务队列    4.6 消息分发    4.7 周期策略    (五) 配置与数据库操作    5.1 CAT配置    5.2 代码自动生成    5.3 数据库操作    5.4 数据库连接管理    (六) 消息分析器与报表(一)    6.1 消息分析器的构建    6.2 TopAnalyzer    6.3 EventAnalyzer - 事件发生次数分析    6.4 MetricAnalyzer - 业务分析    6.5 ProblemAnalyzer -异常分析    6.6 TransactionAnalyzer - 事务分析    (七)消息分析器与报表(二)    7.1 CrossAnalyzer-调用链分析    7.2 StorageAnalyzer  --数据库/缓存分析    7.3 StateAnalyzer -- CAT状态分析    7.4 HeartbeatAnalyzer  -- 心跳分析    7.5 DumpAnalyzer -- 原始消息LogView存储    7.6 自定义分析器与报表    (八) 报表持久化    8.1 周期结束    8.2 分析器的结束 -- 报表持久化    8.3 报表预处理    8.4 报表的文件存储 -- 重入锁    8.5 报表的数据库存储    8.6 定时任务    (九) 管理平台MVC框架    9.1 Servlet容器与请求生命周期    9.2 页面路由初始化    9.3 请求处理流程    (十)与JAVA框架的集成    10.1 与Spring MVC集成    10.2 与Spring Boot 集成    10.3 与Spring Cloud 集成    10.4 与dubbo集成    10.5 与MyBatis集成    10.6 与Log4j集成    (十一) 其他语言支持    11.1 PHP语言    11.2 C++语言    11.3 LUA语言    11.4 Go语言    11.5 Python语言    11.6 Node.js语言    11.7 Android埋点    11.8 Object  C -- IOS 埋点(十二) 报警与监控提醒    12.1 短信通知    12.2 邮件通知(十三) CAT与实时计算    13.1 hadoop模块    13.2 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项目的开源地址: GitHub - dianping/cat: CAT 作为服务端项目基础组件,提供了 Java, C/C++, Node.js, Python, Go 等多语言客户端,已经在美团点评的基础架构中间件框架(MVC框架,RPC框架,数据库框架,缓存框架等,消息队列,配置系统等)深度集成,为美团点评各业务线提供系统丰富的性能指标、健康状况、实时告警等。

背景介绍

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.5Java 6,7,8,服务端推荐是用jdk7的版本,客户端jdk6、7、8都支持Maven 3.3.3MySQL 5.6,5.7,更高版本MySQL都不建议使用,不清楚兼容性J2EE容器建议使用tomcat,建议版本7.0.70Hadoop环境可选,一般建议规模较小的公司直接使用磁盘模式,可以申请CAT服务端,500GB磁盘或者更大磁盘,这个磁盘挂载在/data/目录上

目前我司线上环境:

Distributor ID: CentOSDescription: CentOS release 6.5 (Final)Release: 6.5Codename: FinalServer version: Apache Tomcat/8.0.30Server built: Dec 1 2015 22:30:46 UTCServer number: 8.0.30.0OS Name: LinuxOS Version: 2.6.32-431.el6.x86_64Architecture: amd64JVM Version: 1.8.0_111-b14JVM Vendor: Oracle CorporationMaven 3.3.3Mysql 5.6Tomcat 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 /datachmod 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.sqlMySQL的一个系统参数: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 -DskipTests2、如果发现cat的war打包不通过,CAT所需要依赖jar都部署在 、可以配置这个公有云的仓库地址到本地的settings路径,理论上不需要配置即可,可以参考cat的pom.xml配置4、如果自行打包仍然问题,请使用下面链接进行下载、官方的cat的master版本,重命名为cat.war进行部署,注意此war是用jdk8,服务端请使用jdk8版本6、如下是个人本机电脑的测试,下载的jar来自于repo1.maven.org 以及 unidal.org
Downloading: :  (30 KB at 9.8 KB/sec)Downloaded:  (405 KB at 107.7 KB/sec)Downloaded:  (235 KB at 55.4 KB/sec)Downloaded:  (242 KB at 46.9 KB/sec)Downloaded:  (789 KB at 113.3 KB/sec)Downloading: : : : : :  (21 KB at 82.7 KB/sec)Downloading: 
```[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,    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的存储数据的链接 {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客户端Democat客户端的配置:

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="; 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报表才会记录全部的原始日志):

接下来,我们来看一个更复杂的案例,涉及服务的调用以及数据库、缓存的调用,如下:

@Controllerpublic 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。

标签: #nginxtomcatmem #centosjavaawt #cat 软件