Cat技术入门总结010.docx
《Cat技术入门总结010.docx》由会员分享,可在线阅读,更多相关《Cat技术入门总结010.docx(30页珍藏版)》请在冰豆网上搜索。
Cat技术入门总结010
CAT监控中心技术总结
一、概述2
1.CAT是什么2
2.CAT能给我们带来什么3
二、简单应用4
1.服务端配置与运行4
1.1需要环境4
1.2下载与安装5
1.3文件配置5
1.4启动运行和路由配置8
2.客户端配置与打点8
3.可能遇到的问题和解决方法10
3.1Jar包下载异常或缓慢10
3.2CAT服务端显示有乱码,部分功能中数据不能够正常添加保存11
3.3Nettywritebufferisfull11
3.4Errorwhentryconnectingto/10.10.10.2:
228011
3.5Cannotconverts1-small-dnsLookupoftypeclassjava.lang.Stringtoclassjava.lang.Long12
三、主流框架集成13
1.dubbo集成13
1.1CAT消息树原理13
1.2如何传递消息15
1.3集成实例16
2.SpringMvc集成20
3.mybatis集成22
四、其他功能介绍及相关配置说明26
1.产品线怎么添加26
2.监控的配置26
3.告警配置28
3.1告警策略配置29
3.2默认告警人30
3.3告警服务端30
五、写在最后32
一、概述
1.CAT是什么
CAT是一个实时监控系统,它更侧重于Java应用的监控,目前也有其他语言版本(.net),能够跟各种流行的中间件框架集成(MVC框架、RPC框架、数据库框架、缓存框架等),实现对应用各层级的系统运行状况监控。
2.CAT能给我们带来什么
细致的性能监控
CAT能够对一段代码的执行时间进行统计,在实际应用的场景中,根据埋点的情况,能够查看一个url的响应时间,以及嵌套在该过程中的子过程执行时间,如一个action的执行时间,一次远程调用时间,一个Dao方法的调用时间等。
精确的异常记录
当系统出现异常时,如代码报错,响应时间超长等,都能够方便的在系统中查看,并且可以根据日志准确定位到出现错误的行,或者是响应时间超长的代码区域。
实时的系统状态
在系统运行中,由于实际情况比较复杂,系统中出现的很多故障并非是由于代码的原因导致,还需要综合考虑系统运行环境的相关信息才能够确定故障原因,CAT在运行中能够记录系统环境的相关信息,如:
JVM、GC、Http线程、空闲内存、CAT使用信息等。
自定义业务指标
对于运维人员来说,需要监控的数据根据业务的不同,监控内容也会有差异,通过业务指标埋点可以更好的监控系统运行。
业务指标监控通常需要将埋点放置在业务代码中,如注册功能中可以放置用户注册指标,从而能够实时准确的了解到用户注册的情况。
及时的异常告警
在CAT中我们能够对系统内的各项数据:
异常、transaction、指标等进行告警设置,具体可以为异常数量,响应时间,指标数量或增长/降低比率等,当达到告警标准时,系统能够根据配置,及时的向项目维护人员、项目负责人发送短信、邮件、微信等形式的通知。
二、简单应用
1.服务端配置与运行
1.1需要环境
以上是必须环境,容器是可选的,我这里用的是tomcat8
1.2下载与安装
从github上将CAT下载至本地(链接:
下载至本地以后,在项目目录下运行maven命令
然后将生成的cat-home.war改名为cat.war放置在tomcat目录下。
1.3文件配置
CAT的配置文件需要放置在默认目录下(/data/appdatas/cat/),windows系统放置在与项目同盘符的该目录下。
将script目录下的client.xml以及server.xml、datasource.xml拷贝至默认目录
client.xml配置
Mode默认为client不需要修改
需要修改servers标签内的server服务端属性,这里我的cat服务器地址是192.168.2.181,port端口固定为2280,还有一个http-port属性,默认是tomcat端口,没有需要可以不指定。
编辑datasource.xml数据源配置文件和创建数据库
这里的配置比较简单,主要就是url和账号密码的配置,根据实际情况配置即可,我这里是本地测试库,cat和app的数据库配置为同一个。
配置完数据源后,我们需要将CAT的数据库结构在mysql中创建,在script目录下有个名为cat.sql的文件,创建一个名为cat的数据库然后执行cat.sql即可完成数据表的创建。
Server.xml的配置
Local-mode为本地模式,设置为false,否则将不会使用数据库和hdfs存储
Hdfs-machine是否启用hdfs存储,设为false
Job-machine当前服务为报告工作机,当有多台服务器时,开启一台即可
Alert-machine定义为报警机,同样开启一台即可,如没有一台开启,告警功能将不能够正常使用。
Storage定义数据存储相关信息,这里定义了本地目录/data/appdatas/cat/buket/为存储目录,本地报告及本地日志保存时间均为7天。
Console控制台信息,定义默认的domain为Cat(每个cat应用要求都需要有一个domain,Cat本身的domain为Cat),并显示cat的domain
Remote-servers定义http服务列表,我这里就一台机器
1.4启动运行和路由配置
完成以上配置后即可启动tomcat服务器,并在浏览器中输入地址http:
//Ip:
port/cat/看到如下界面表示运行成功
这时点击左上角的红色配置按钮,如出现登录窗口输入默认账号密码,catadmin/catadmin
进入配置界面后选择全局告警配置-客户端路由
Backup-server为当前服务器地址,端口固定2280
Default-server定义可跳转的路由地址,这里设置的是本机地址,enable设置true表示启用。
设置完成后点击提交保存。
2.客户端配置与打点
2.1配置监控项目名
在需要被监听的项目src/main/resources/META-INF目录下添加配置文件app.properties
文件内容为:
app.name=XXX(自己定义)
2.2pom.xml中引入cat-client.jar包。
2.3配置客户端路由
在所有的监控机器上需要加入/data/appdatas/cat/client.xml这个文件需要指向cat的服务端地址,一个client.xml的例子如下,这个文件可以统一装机的时候统一设置。
2.4埋点工作
用transaction记录一段代码的执行时间,这里的时间是指从创建至complete之间的耗时。
Event记录一个事件,如:
一次远程调用的地址。
Metric记录一个业务指标。
注意:
每一个transaction对象必须complete,并设置status,transaction对象是可以嵌套的,其他对象不可以嵌套。
Event放置在transaction内部用于记录一些参数,而metric指标是用来监控业务情况的,能够记录一个指标的count次数、sum总数等。
2.5项目接入验证
埋点完成后,接下来启动客户端,运行一遍埋点的代码,然后打开服务端地址,如下图
在上方的搜索栏左边可以展开/隐藏监控项目,点击下方的项目可以切换到该项目的视图,运行成功后即可在上方看到被监控项目的domain
3.可能遇到的问题和解决方法
3.1Jar包下载异常或缓慢
Cat依赖的部分jar,下载非常缓慢,甚至会出现因为下载异常导致的种种问题,对于这类问题我们可以去CAT的仓库分支下载相关资源
在mvn-repo下,下载后打包安装至本地即可。
3.2CAT服务端显示有乱码,部分功能中数据不能够正常添加保存
如产品线的添加,每次添加完后页面跳转到一片空白,刷新后发现没能添加成功,并且很多列表的中文字符都是乱码。
对于这种问题需要修改tomcat的server.xml文件,通过添加编码方式解决。
在两个connector标签均添加属性URIEncoding="UTF-8"
3.3Nettywritebufferisfull
从研究CAT以来,这是一个比较常见的警告,原因一般是由于客户端没能跟服务端正常连接导致,具体原因需要根据实际情况解决。
这个仅仅是个warning而已,后续cat会和服务端重新连接。
3.4Errorwhentryconnectingto/10.10.10.2:
2280
这是一个比较低级的错误,原因是没有配置客户端路由导致,怎么配置请看前面的介绍。
3.5Cannotconverts1-small-dnsLookupoftypeclassjava.lang.Stringtoclassjava.lang.Long
或者是报其他类似的包含一个如s1-small-dnsLookup这样奇怪名词的错,一般是由于系统里默认的一些配置导致,可以检查相关的监控配置,看有没有和该名词相同的配置,删掉即可。
不过这个s1-small-dnsLookup的错误,可能是进入[用户监控配置]-[web告警]功能时报的错,此时该功能也无法正常进入,所以不能从系统中删除。
解决方法是进入mysql数据库[cat]-[config]表
找到name为webRule的行,将rule标签的id(这个id的值应是报错中的名词)改成随意一个整数。
然后web告警功能就能够正常进入了,此时已经不会报错。
三、主流框架集成
主流框架集成也可以参考资源文件的框架集成,包括了很多主流框架的集成。
前面已经介绍了怎么运行一个简单的demo,在应用的时候应当尽可能的减少跟业务代码的耦合,所以我们需要跟常用的一些框架进行集成,以降低耦合性。
1.dubbo集成
1.1CAT消息树原理
远程调用时如何将消息串联起来,在CAT中提供了消息树结构来组合消息,下面看一下CAT上下文接口中的定义:
追踪跨服务的消息时,通过根消息id和父级消息id及子消息id三个属性进行消息串联,组成消息树。
在CAT中首先要创建一个包含节点数据的上下文对象,这里使用的是Cat.logRemoteCallClient方法,下面看一下源码:
这个方法需要一个上下文对象,通过消息树对象来创建获取各节点消息的id,然后填充给上下文对象。
然后远程服务端接收这个上下文对象,并读取节点消息的id组建消息树,这是使用的是Cat.logRemoteCallServer方法:
1.2如何传递消息
远程调用时会传递一些数据(调用信息和参数及状态信息),如果要使用消息树,应该将上下文对象一并传递过去。
首先因为CAT没有提供context的实现类,所以这里我们需要自己手动编写一个实现类:
实现类写完了,那么如何传递这个实现类呢,dubbo在进行远程调用时,允许携带一些附件过去,通过如下代码将节点消息存放至附件中:
当然在执行这段代码前,需要通过上面提到的方法先给context对象填充消息数据,否则传递过去的都是空值。
然后只需要调用Invocation对象的invoke方法,即可将消息传递至服务端。
当然这些对象需要在dubbo的filter中获取,下面看一下具体实现。
1.3集成实例
消息树的原理以及消息的传递已经讲完了,那么实际运用中应该怎么跟dubbo集成呢。
首先我们需要了解dubbo的SPI拓展机制,下面引入几张官方说明图:
简单总结一下上图的内容,以及我们该怎么做
①首先我们需要编写一个filter类继承com.alibaba.dubbo.rpc.Filter接口
②在src/main/resources/META-INF/dubbo目录下创建一个名为com.alibaba.dubbo.rpc.Filter的文件,文件的内容是纯文本,格式为xxx=com.xxx.xxxFilter,这里的xxx是随便取的名字,后面的是你filter路径
③在消费者端和服务提供者端都配置一下文件如下
消费者:
服务者:
通过以上配置即可给消费方和服务方设置默认的拦截。
接下来直接给出filter的简单代码示例
消费者:
publicclassCatFilterimplementsFilter{
@Override
publicResultinvoke(Invoker
>invoker,Invocationinvocation)
throwsRpcException{
Resultresult=null;
StringloggerName=invoker.getInterface().getSimpleName()+"."+invocation.getMethodName();
Transactiont=Cat.newTransaction(“services”,loggerName);
CatContextcatContext=newCatContext();
Cat.logRemoteCallClient(catContext);
setAttachment(catContext);
try{
result=invoker.invoke(invocation);
t.setStatus(Transaction.SUCCESS);
}catch(Exceptione){
t.setStatus("ERROR");
Cat.logError(e);
}finally{
plete();
}
returnresult;
}
privatevoidsetAttachment(Cat.Contextcontext){
RpcContext.getContext().setAttachment(Cat.Context.PARENT,context.getProperty(Cat.Context.PARENT));
RpcContext.getContext().setAttachment(Cat.Context.CHILD,context.getProperty(Cat.Context.CHILD));
RpcContext.getContext().setAttachment(Cat.Context.ROOT,context.getProperty(Cat.Context.ROOT));
}
}
服务者:
publicclassCatFilterimplementsFilter{
@Override
publicResultinvoke(Invoker
>invoker,Invocationinvocation)
throwsRpcException{
Resultresult=null;
StringloggerName=invoker.getInterface().getSimpleName()+"."+invocation.getMethodName();
Transactiont=Cat.newTransaction("service",loggerName);
CatContextcatContext=newCatContext();
catContext.addProperty(Context.ROOT,invocation.getAttachment(Context.ROOT));
catContext.addProperty(Context.PARENT,invocation.getAttachment(Context.PARENT));
catContext.addProperty(Context.CHILD,invocation.getAttachment(Context.CHILD));
Cat.logRemoteCallServer(catContext);
try{
result=invoker.invoke(invocation);
t.setStatus(Transaction.SUCCESS);
}catch(Exceptione){
t.setStatus("ERROR");
Cat.logError(e);
}finally{
plete();
}
returnresult;
}
}
说明:
这里的过滤器是分开写的,实际可以合并为一个,根据url中的“side”参数判断是消费者还是服务提供者。
Github上有一个跟dubbo整合的实例,叫dubboplus,可以去下载研究一下,这里我就不做过多描述。
2.SpringMvc集成
与springmvc是通过拦截器的形式进行集成,比较简单下面直接给出demo
publicclassCatInterceptorimplementsHandlerInterceptor{
privateThreadLocaltranLocal=newThreadLocal();
privateThreadLocalpageLocal=newThreadLocal();
@Override
publicbooleanpreHandle(HttpServletRequestrequest,
HttpServletResponseresponse,Objecthandler)throwsException{
Stringuri=request.getRequestURI();
Transactiont=Cat.newTransaction("URL",uri);
Cat.logEvent("URL.Method",request.getMethod(),Message.SUCCESS,request.getRequestURL().toString());
Cat.logEvent("URL.Host",request.getMethod(),Message.SUCCESS,request.getRemoteHost());
tranLocal.set(t);
returntrue;
}
@Override
publicvoidpostHandle(HttpServletRequestrequest,
HttpServletResponseresponse,Objecthandler,
ModelAndViewmodelAndView)throwsException{
StringviewName=modelAndView!
=null?
modelAndView.getViewName():
"无";
Transactiont=Cat.newTransaction("View",viewName);
pageLocal.set(t);
}
@Override
publicvoidafterCompletion(HttpServletRequestrequest,
HttpServletResponseresponse,Objecthandler,Exceptionex)
throwsException{
//请求-页面渲染前
Transactionpt=pageLocal.get();
pageLocal.remove();//needremove
pt.setStatus(Transaction.SUCCESS);
plete();
//总计
Transactiont=tranLocal.get();
tranLocal.remove();//needremove
t.setStatus(Transaction.SUCCESS);
plete();
}
}
因为spring的bean都是单例,所以要放在thredlocal中保存。
这里做了两个Transaction:
tranLocal是统计请求被处理至页面模板渲染完成的时间
pageLocal是记录controller处理完成返回页面至页面渲染完成的时间。
文件配置如下
Spring-mvc.xml
--配置拦截器-->
interceptors>
interceptor>
mappingpath="/**"/>
interceptor>
interceptors>
3.mybatis集成
与mybatis通过插件的方式集成,记录每一个Dao的方法调用情况及相关事件。
@Intercepts({@Signature(args={MappedStatement.class,Object.class},method="update",type=Executor.class),
@Signature(args={MappedStatement.class,Object.class,RowBounds.class,ResultHandler.class},method="query",type=Executor.class)})
publicclassCatMybatisPluginsimplementsInterceptor{
@Override
publicObjectintercept(Invocationinvocation)throwsThrowable{
MappedStatementmappedStatement=(MappedStatement)invocation.getArgs()[0];
//得到类名-方法
String[]strArr=mappedStatement.getId().split("\\.");
Stringclass_method=strArr[strArr.length-2]+"."+strArr[strArr.length-1];
//得到sql语句
Objectparameter=null;
if(invocation.getArgs().length>1){
parameter=invocation.getArgs()[1];
}
BoundS