欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

CAT集成spring boot

程序员文章站 2022-07-15 16:49:56
...

1.背景

在上面介绍了CAT如何做跨进程追踪的。公司项目采用业务垂直切分的方式开发、前后端也是分离方式。那么实时监控埋点的地方有如下几处:

  • 前端和后端交互
  • 后端业务逻辑
  • 数据库存储
  • 远程PRC调用
  • 消息队列

 

2.集成spring boot

在git官网中有一个包是大家贡献的集成代码。里面就有各种的集成。里面就有和spring boot集成的代码。代码是直接使用了cat client包中catfilter这个类。这个类的逻辑比较复杂,分了不同的情况。然而公司系统结构中没有那么复杂。整体流程是:前端 -> 网关 -> 后端。后端spring boot 工程只有一种类型,就是作为server端。所以我并没有采用client 自带的代码。而是采用别的架构师分享的一种简单的方式。代码如下:

/**
 * 请求监控拦截
 * @author tengx
 */
public class CatServletFilter implements Filter {
   

    @Override
    public void init(FilterConfig filterConfig) {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        CatContext catContext = getCatContext(request);
        Cat.logRemoteCallServer(catContext);
        Transaction t = Cat.newTransaction(CatConstants.TYPE_URL, request.getRequestURL().toString());
        try {
            catLogEvent(request);
            filterChain.doFilter(servletRequest, servletResponse);
            t.setStatus(Transaction.SUCCESS);
        } catch (Exception ex) {
            t.setStatus(ex);
            Cat.logError(ex);
            throw ex;
        } finally {
            t.complete();
        }
    }

    /**
     * 获取CAT监控上下文环境
     * @param request 请求
     * @return CAT上下文环境
     */
    private CatContext getCatContext(HttpServletRequest request) {
        CatContext catContext = new CatContext();
        catContext.addProperty(Cat.Context.ROOT, request.getHeader(CatHttpConstants.CAT_HTTP_HEADER_ROOT_MESSAGE_ID));
        catContext.addProperty(Cat.Context.PARENT, request.getHeader(CatHttpConstants.CAT_HTTP_HEADER_PARENT_MESSAGE_ID));
        catContext.addProperty(Cat.Context.CHILD, request.getHeader(CatHttpConstants.CAT_HTTP_HEADER_CHILD_MESSAGE_ID));
        return catContext;
    }

    /**
     * 使用CAT event事件记录信息
     * @param request 请求
     */
    private void catLogEvent(HttpServletRequest request) {
        Cat.logEvent(CatHttpConstants.SERVER_METHOD, request.getMethod());
        Cat.logEvent(CatHttpConstants.SERVER_CLIENT, request.getRemoteHost());
        Cat.logEvent(CatHttpConstants.SERVER_REFERER, request.getHeader("referer"));
        Cat.logEvent(CatHttpConstants.SERVER_AGENT, request.getHeader("user-agent"));
        Cat.logEvent(CatHttpConstants.SERVER_TOKEN, request.getHeader("token"));
        Cat.logEvent(CatHttpConstants.SERVER_PARAMS, JsonUtils.toJSONString(request.getParameterMap()));
        Cat.logEvent(CatHttpConstants.SERVER_DATETIME, DateUtil.now());
    }

    @Override
    public void destroy() {

    }
}

 

类主要的核心思想就是实现拦截器,在拦截器中使用CAT模型进行记录请求信息。对于异常需要进行捕获,不然会影响正常业务。最后需要对Transaction 进行完成操作。逻辑十分简单。相信大家一看就能明白做什么。

 

3.集成系统

在工程实践中有这样的场景,有很多个独立的服务都需要使用这个Filter,如果每个工程都加这个类会存在以下缺点:

  1. 重复代码,每个工程都有这个类
  2. 不利于以后的扩展。如果以后要扩展这个类的内容,那么就需要替换每个工程中的类。增加的维护成本
  3. 暴露了监控逻辑。监控逻辑并非是业务逻辑。系统工程一般都是由项目组中的研发进行开发的。研发的能力参差不齐,不能保证研发对这个逻辑如何操作。

基于以上的缺点。我在公司采用的方式就是在业务系统之下还就有一个核心组件层。让各个业务系统依赖这个组件层。然后在这个组件层做一些工具类封装、第三方调用的封装等。这样做的好处有一下几点:

  1. 屏蔽对外依赖。借用业界的一句名言:“任何复杂的问题就能使用一个中间层来处理!”。有这样一个中间层可以将业务逻辑和三方技术使用进行隔离。在做技术调整的时候不会影响业务逻辑。
  2. 减少重复代码。将多个系统公用的技术下沉到中间层有利于代码的复用。并且维护成本降低。主要维护中间层一处就好。

 

确定了在中间层写Filter之后,那么就引申出来下一个问题,在中间层中定义的类,如何让业务系统中加载到呢?如何让业务系统中spring 加载到这个Bean呢?

这里就要知道spring boot 的自动加载机制了。通过在MEAT-INF 下配置spring.factories 文件。在文件中配置自动加载的类。这样当工程引用了这个jar包的时候spring boot 就会自动加载指定的类。代码如下:

/**
 * 对URL进行拦截的类
 * @author tengx
 */

@Configuration
public class CatFilterConfigure {

    @Bean("catFilter")
    public Filter createFilter(){
        return new CatServletFilter();
    }

    @Bean
    public FilterRegistrationBean catFilter(Filter catFilter) {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(catFilter);
        registration.addUrlPatterns("/*");
        registration.setName("cat-filter");
        registration.setOrder(1);
        return registration;
    }
}

 

4.总结:

  1. 使用filter的方式对spring boot 工程的API请求进行监控
  2. 任何问题都可以使用一个中间层的方式来处理
  3. 使用spring boot 动态加载机制来解决中间层类加载问题

相关标签: CAT