zoukankan      html  css  js  c++  java
  • 点评cat系列-应用集成

    ========================
    消息的基本属性
    ========================
    消息的几个属性:
    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 文件
    LinuxMac 到 /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

  • 相关阅读:
    Solidworks草图或者特征无法删除怎么办
    Solidworks如何为装配体绘制剖面视图
    Solidworks如何在装配图中保存单独的一个零件
    [Algorithm] Check if a binary tree is binary search tree or not
    [PureScript] Break up Expressions into Cases in PureScript using Simple Pattern Matching
    [Docker] Hooking a Volume to Node.js Source Code
    [PureScript] Basic Data Constructors in PureScript
    [Algorithm] Check for balanced parentheses using stack
    [PureScript] Introduce to PureScript Specify Function Arguments
    [Node.js] process.nextTick for converting sync to async
  • 原文地址:https://www.cnblogs.com/harrychinese/p/dianping-cat-integration.html
Copyright © 2011-2022 走看看