当前位置: 首页 > news >正文

【接口耗时】⭐️自定义拦截器实现接口耗时统计

💥💥✈️✈️欢迎阅读本文章❤️❤️💥💥

🏆本篇文章阅读大约耗时三分钟

⛳️motto不积跬步、无以千里

📋📋📋本文目录如下:🎁🎁🎁

目录

前言

实现

测试

章末

前言

        小伙伴们大家好,上篇文章在本地模拟了如何控制接口的负载,通过引入 Resilience4j 依赖实现,整体操作简单,并且不需要额外启动服务,文章链接如下:

【接口负载】✈️整合 Resilience4j 指定接口负载,避免过载_resilience4j 如果多个接口指定一个 api , 会判断成同一个吗-CSDN博客

        在实际项目中有很多监控指标,比如接口请求整体耗时,针对请求耗时过长的接口,需要进行统计并优化,本文 简单模拟下如何便捷实现接口耗时监控

实现

        2.1 统计接口耗时这种需求,是针对全部接口的,所以不能对业务代码造成侵入,并且要统一监控,所以可以使用拦截器,自定义一个拦截器,具体的作用就是请求进来的前后统计下时间,然后统一格式输出,方便查看

        2.2 整体流程如下

        2.3 代码实现

         拦截器方法体如下,简单看下内容:

             1.包括初始化 ThreadLocal 对象,重写了 preHandle 方法和 afterCompletion 方法

             2.请求进来后,对应的线程会先初始化一个 threadLocal 对象,之后调用执行 preHandle 方法,在这一步会往该线程的 threadLocal 对象中存放一个开始时间,之后去执行业务方法,执行结束后,会流转到 afterCompletion 方法中,这时会计算当前时间与开始时间的差值,如果超过指定范围 打印一个 Warn 级别的日志

             注:这里最后会手动调用 threadLocal 的 remove 方法释放占用,避免内存溢出风险

import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 * @author HuangBenben 
 */
@Slf4j
@Component
public class RequestHeaderHandlerInterceptor implements HandlerInterceptor {
    // 为 ThreadLocal 提供初始值
    private final ThreadLocal<Map<String, Object>> contexts = ThreadLocal.withInitial(HashMap::new);

    private void set(String key, Object value) {
        contexts.get().put(key, value);
    }

    private Object get(String key) {
        return contexts.get().get(key);
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        long start = System.currentTimeMillis();
        set("Request_begin", start);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) {
        try {
            Long start = (Long) get("Request_begin");
            if (start != null) {
                long time = System.currentTimeMillis() - start;
                StringBuilder sb = new StringBuilder();
                sb.append("接口:").append(request.getRequestURI()).append(" 耗时:").append(time);
                if (time > 1000) {
                    log.warn(sb.toString());
                } else {
                    log.info(sb.toString());
                }
            }
        } finally {
        contexts.remove();
        }
    }
}

         拦截器创建好之后需要手动添加注册,保证生效

              将自定义的拦截器对象注入之后,重写 addInterceptors 方法将其添加注册,并且指定该拦截器针对的请求地址,这里配置的全部请求

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @author HuangBenben 
 */
@Configuration
public class AutoWebMvcConfigurer implements WebMvcConfigurer {

    @Autowired
    private RequestHeaderHandlerInterceptor requestHeaderHandlerInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 添加自定义的拦截器
        registry.addInterceptor(requestHeaderHandlerInterceptor).addPathPatterns("/**");
    }
}

 

测试

        简单测试下,如下

        拦截器中针对耗时大于1000ms的请求会打印 Warn 级别的日志,这里就让请求 sleep 一段时间,看下执行情况

 

        结果如下,接口的请求耗时有对应的日志,并且按照规则打印日志的级别 

章末

         文章到这里就结束了,如果有其他问题,欢迎评论区沟通。

往期推荐 > > > 

【接口负载】✈️整合 Resilience4j 指定接口负载,避免过载

 【SpringBoot】⭐️整合 Redis 实现百万级数据实时排序

 【SpringBoot】✈️本地集成支付宝支付功能

相关文章:

  • 基于消息方式的系统间通信
  • (分块)洛谷 P2801 教主的魔法 题解
  • TimeGAN:开启时间序列生成新纪元,结合GAN与自回归模型的优势
  • 智能运维管理系统的主要优势
  • 基于asp.net实现的连锁餐厅收银系统[包运行成功+永久免费答疑辅导]
  • 4、linux c 进程
  • RK3568 android11 基于PN7160的NXP NFC移植
  • C++基础——从C语言快速入门
  • 前端权限系统
  • ctfshow web刷题记录
  • 2.机器学习-回归模型-非线性模型
  • 面试求助:接口测试用例设计主要考虑哪些方面?
  • Matlab自学笔记四十八:各类型缺失值的创建、判断、替换、移位和处理方法
  • 计算机网络笔记再战——理解几个经典的协议HTTP章3
  • 【Gitee】删除仓库的详细步骤
  • centos8 安装指定版本 nodejs
  • 【数据结构】ArrayList顺序表
  • 数据库:一文掌握 PostgreSQL 的各种指令(PostgreSQL指令备忘)
  • Mac 使用 Crossover 加载 Windows Steam 游戏库,实现 Windows/Mac 共享移动硬盘
  • NO.40十六届蓝桥杯备战|指针和动态内存管理|取地址操作符|解引用操作符|指针+-整数|void*|new|delete(C++)
  • “世界茶树原产地”打通全产业链,茶文旅融合助力西双版纳高质量发展
  • 财政部:4月份中央收入增长1.6%,今年以来首月实现正增长
  • “敌人已经够多了”,菲总统马科斯:愿与杜特尔特家族和解
  • 让中小学生体验不同职业,上海中高职院校提供超5万个体验名额
  • 以色列媒体:以总理称将接管整个加沙
  • 释新闻|拜登确诊恶性前列腺癌,预后情况如何?