前言: 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简介与部署的更多相关文章

  1. 深入详解美团点评CAT跨语言服务监控(七)消息分析器与报表(二)

    CrossAnalyzer-调用链分析 在分布式环境中,应用是运行在独立的进程中的,有可能是不同的机器,或者不同的服务器进程.那么他们如果想要彼此联系在一起,形成一个调用链,在Cat中,CrossAn ...

  2. 深入详解美团点评CAT跨语言服务监控(六)消息分析器与报表(一)

    大众点评CAT微服务监控架构对于消息的具体处理,是由消息分析器完成的,消息分析器会轮训读取PeriodTask中队列的消息来处理,一共有12类消息分析器,处理后的结果就是生成各类报表. 消息分析器的构 ...

  3. 深入详解美团点评CAT跨语言服务监控(三)CAT客户端原理

    cat客户端部分核心类 message目录下面有消息相关的部分接口 internal目录包含主要的CAT客户端内部实现类: io目录包含建立服务端连接.重连.消息队列监听.上报等io实现类: spi目 ...

  4. 深入详解美团点评CAT跨语言服务监控(五)配置与数据库操作

    CAT配置 在CAT中,有非常多的配置去指导监控的行为,每个配置都有相应的配置管理类来管理,都有一个配置名, 配置在数据库或者配置文件中都是以xml格式存储,在运行时会被解析到具体实体类存储.我们选取 ...

  5. 深入详解美团点评CAT跨语言服务监控(四)服务端消息分发

    这边首先介绍下大众点评CAT消息分发大概的架构如下: 图4 消息分发架构图 分析管理器的初始化 我们在第一章讲到服务器将接收到的消息交给解码器(MessageDecoder)去做解码最后交给具体的消费 ...

  6. 深入详解美团点评CAT跨语言服务监控(二) CAT服务端初始化

    Cat模块 Cat-client : cat客户端,编译后生成 cat-client-2.0.0.jar ,用户可以通过它来向cat-home上报统一格式的日志信息,可以集成到 mybatis.spr ...

  7. 深入详解美团点评CAT跨语言服务监控(九)CAT管理平台MVC框架

    在第2章我们讲到,服务器在初始化CatServlet 之后, 会初始化 MVC,MVC也是继承自AbstractContainerServlet , 同样也是一个 Servlet 容器,这是一个非常古 ...

  8. 深入详解美团点评CAT跨语言服务监控(八)报表持久化

    周期结束 我们从消息分发章节知道,RealtimeConsumer在初始化的时候,会启动一个线程,每隔1秒钟就去从判断是否需要开启或结束一个周期(Period),如下源码,如果 value < ...

  9. 一阶RC高通滤波器详解(仿真+matlab+C语言实现)

    文章目录 预备知识 关于电容 HPF的推导 simulink 仿真 simulink 运行结果 matlab 实现 matlab 运行结果 C语言实现 如果本文帮到了你,帮忙点个赞: 如果本文帮到了你 ...

随机推荐

  1. ssh框架中,工具类调用service层方法(参考https://www.cnblogs.com/l412382979/p/8526945.html)

    代码如下: package common.dataService; import javax.annotation.PostConstruct; import org.springframework. ...

  2. Linux文件系统命令 touch/rm

    命令:touch 功能:创建文件,后接相对路径或者绝对路径 eg: touch ./ren/jin/gui.txt 命令:rm 功能:删除文件,当删除的是目录的时候要加-R参数进行递归删除. eg: ...

  3. 实力封装:Unity打包AssetBundle(二)

    →前情提要:Unity最基本的AssetBundle打包方式. 第二种打包方式 Unity提供的BuildAssetBundles API还有一个重载形式,看下面↓↓ public static As ...

  4. mysql encode decode加密和解密

    加密:模板:insert into user(userpass) values(encode('useerpass','str')) insert into user(userid,username, ...

  5. 理解mpvue的生命周期

    mpvue是美团基于vue开发的一个开发小程序的框架,从而以vue的语法来开发小程序.在生命周期上,mpvue同时支持了vue的生命周期和小程序的生命周期,这可能让新上手的同学费解.这篇文章就来讲讲m ...

  6. error_log

    对于我们做php开发的人员,上了生产环境,一定要把相关debug,display_errors错误提示等关掉.谁还难免不犯个错呢?这样能防止非致命性报错下,导致项目路径.数据库等信息泄漏. 问:那么问 ...

  7. lintcode 刷题 by python 部分链表题总结(2)

    本篇博客对最近做的链表的算法题做个简单的小结,主要描述题目和提供解题思路,具体代码见我的 github:https://github.com/MUSK1881/lintcode-by-python 3 ...

  8. 图片上传并回显Ajax异步篇

    图片上传并回显Ajax异步篇 图片如何无刷新的上传到服务器呢?继前两篇文章后,我们来实战一下如何无刷新的异步上传图片,我们还是先看一下效果 在实战前呢,我们需要做些准备工作.比如说,了解一下FormD ...

  9. wireshark显示过滤器的几种用法(转自他人博客)

    本文章转自:http://blog.51cto.com/houm01/1872652 几种条件操作符 ==   eq    等于    ip.addr == 192.168.0.1   ip.addr ...

  10. 《DSP using MATLAB》Problem 5.20

    窗外的知了叽叽喳喳叫个不停,屋里温度应该有30°,伏天的日子难过啊! 频率域的方法来计算圆周移位 代码: 子函数的 function y = cirshftf(x, m, N) %% -------- ...