首页 > 其他分享 >Spring Cloud Gateway关键点全局Token过滤器,局部过滤器接口耗时,全链路跟踪TraceId日志

Spring Cloud Gateway关键点全局Token过滤器,局部过滤器接口耗时,全链路跟踪TraceId日志

时间:2024-10-16 21:46:21浏览次数:3  
标签:TraceId exchange Spring token traceId MDC 过滤器 public

一.全局Token过滤器

在Spring Cloud Gateway中,实现全局过滤器的目的是对所有进入系统的请求或响应进行统一处理,比如添加日志、鉴权等。下面是如何创建一个全局过滤器的基本步骤:

步骤1: 创建过滤器类

首先,你需要创建一个实现了GlobalFilter接口,创建一个全局token过滤器。

@Slf4j
@Component
//@Order(2)
public class TokenFilter implements GlobalFilter, Ordered {
    @Value("${cn.smart.tokenx.key}")
    private String tokenKey;

    private static List<String> whiteList = CollUtil.newArrayList("/api/login", "/api/register");
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        ServerHttpRequest request = exchange.getRequest();

        URI uri = request.getURI();
        String path = uri.getPath().toLowerCase().trim();
        //排除白名单的验证
        if(whiteList.contains(path)){
            return chain.filter(exchange);
        }
        ServerHttpResponse response = exchange.getResponse();
        List<String> tokens = request.getHeaders().get("token");
        //验证的是有没有传token
        if(ObjectUtil.isEmpty(tokens)){
          log.error("请传token");
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
          return response.setComplete();
        }
        String token = tokens.get(0);
        //验证的是传的token值是否为空
        if(ObjectUtil.isEmpty(token)){
            log.error("token 不能为空");
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }

        boolean b = false;
        // 验证算法,JWTValidator包含过期的验证,验证比较全面
        try {
            JWTValidator.of(token).validateAlgorithm(JWTSignerUtil.hs256(tokenKey.getBytes())).validateDate();
            b = true;
        }catch (Exception ex){
            ex.printStackTrace();
            log.error("token不正确");
        }
        if(!b){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }

        //接着执行下面的过滤器,token还会带到下游,我们的服务还是要用我们之前的token-starter,token-starter功能只保留解析token写入Threadlocal,验证的功能不再需要
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 2;
    }
}

步骤2: 注册全局过滤器

为了让Spring Cloud Gateway应用识别并使用这个过滤器,你通常需要在配置类中注册它。但是,由于我们使用了@Component注解,Spring会自动扫描并注册该Bean。

使用@Component或下面代码,二选一。

@Configuration
public class FilterConfig {

    @Bean
    public TokenFilter tokenFilter() {
        return new TokenFilter();
    }
}

二.局部过滤器接口耗时

1.找规律

局部过滤器命名规则 XXXGatewayFilterFactory, 必须以GatewayFilterFactory结尾。

/*  注意名称约定
*   AddRequestHeaderGatewayFilterFactory    配置的时候写的是 AddRequestHeader
*   AddRequestParameterGatewayFilterFactory 配置的时候写的是 AddRequestParameter
*   LogTimeGatewayFilterFactory   配置的时候写什么? 
* */

spring.cloud.gateway.routes[0].filters[0] = LogTime=gte,500

2.接口耗时过滤器


@Slf4j
@Component
public class LogTimeGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {

    private static long timeSpan = 0;
    @Override
    public GatewayFilter apply(NameValueConfig config) {
        String timeSpanStr = config.getValue();
        timeSpan = Long.valueOf(timeSpanStr);
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange,  GatewayFilterChain chain) {

                long startTime = System.currentTimeMillis();
                return chain.filter(exchange).then(Mono.fromRunnable(()->{
                    long endTime = System.currentTimeMillis();
                    long time =  endTime-startTime;
                    if(time >= timeSpan){
                        log.debug("{} 耗时:{}",exchange.getRequest().getURI(), time);
                    }
                }));

            }
        };
    }
}




3.如何使用





3.全链路跟踪TraceId日志

1.创建全局过滤器,在请求头上带入traceId参数,穿透到下游服务.

@Slf4j
@Component
public class TraceIdFilter implements GlobalFilter {


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        ServerHttpRequest request = exchange.getRequest();
        List<String> traceIds = request.getHeaders().get("traceId");
        if(ObjectUtil.isNotEmpty(traceIds)){
            return chain.filter(exchange);
        }
        String traceId = IdUtil.simpleUUID();
        ServerHttpRequest request2 = request.mutate().header("traceId", traceId).build();
        ServerWebExchange  exchange2 = exchange.mutate().request(request2).build();
        return chain.filter(exchange2);
    }

   
}

2.MDC原理

当请求来时生成一个traceId放在ThreadLocal里,然后打印时去取就行了。但在不改动原有输出语句的前提下自然需要日志框架的支持了。

MDC 介绍​ MDC(Mapped Diagnostic Context,映射调试上下文)是 log4j 和 logback 提供的一种方便在多线程条件下记录日志的功能。MDC 可以看成是一个与当前线程绑定的Map,可以往其中添加键值对。MDC 中包含的内容可以被同一线程中执行的代码所访问。当前线程的子线程会继承其父线程中的 MDC 的内容。当需要记录日志时,只需要从 MDC 中获取所需的信息即可。MDC 的内容则由程序在适当的时候保存进去。对于一个 Web 应用来说,通常是在请求被处理的最开始保存这些数据。

简而言之,MDC就是日志框架提供的一个InheritableThreadLocal,项目代码中可以将键值对放入其中,然后使用指定方式取出打印即可。

3.下游服务如何使用全链路跟踪Id

3.1配置TraceId 过滤器

@Order(1)

@WebFilter(urlPatterns = "/*",filterName = "traceIdFilter")
public class TraceIdFilter implements Filter {

    public final static String MDC_TRACE_ID = "traceId";

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String traceId = httpRequest.getHeader(MDC_TRACE_ID);
        if (StringUtils.isBlank(traceId)) {
            traceId = IdUtil.fastSimpleUUID();;
        }
        MDC.put(MDC_TRACE_ID, traceId);

        chain.doFilter(request, response);
    }
}

3.2 启动类开启ServletComponentScan扫描。

@SpringBootApplication

@ServletComponentScan
public class OpenApp {
    public static void main(String[] args) {
        SpringApplication.run(OpenApp.class, args);
    }

}

3.3 配置文件配置日志输出格式

##日志输出格式
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} %clr(%-5level) %clr([%X{traceId}]) %clr(${PID:-}) --- %clr(%logger{50}) - %m%n

4.Openfeign扩展

@Component
public class OpenFeignRequestInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        String traceId = MDC.get(TraceIdFilter.MDC_TRACE_ID);
        requestTemplate.header(TraceIdFilter.MDC_TRACE_ID, traceId);
    }
}

5.附(Kibana日志图标)

标签:TraceId,exchange,Spring,token,traceId,MDC,过滤器,public
From: https://blog.csdn.net/zhzjn/article/details/142992276

相关文章

  • 基于SpringBoot的养生平台系统的设计与实现
    基于SpringBoot的养生平台系统的设计与实现1、项目的设计初衷:​随着生活水平的提高,大家对于生活品质,身体状况的最求也在变的越来越高,长寿,养生这样的词出现在大家生活中的频率越来越高。本系统设计是为了让大家能够咨询养生知识,分享养生知识。​项目基于SpringBoot+Vu......
  • SpringBoot Aop面向切面编程-快速入门-实战案例
    AOP部分笔记来自黑马程序员。一、AOP概述什么是AOP?AOP英文全称:AspectOrientedProgramming(面向切面编程、面向方面编程),其实说白了,面向切面编程就是面向特定方法编程。那什么又是面向方法编程呢,为什么又需要面向方法编程呢?来我们举个例子做一个说明:比如,我们这里有一个......
  • SpringBoot集成 规则引擎Drools 快速入门
    规则引擎Drools一、drools1、引入问题某电商平台的促销活动,活动规则是根据⽤户购买订单的⾦额给⽤户送相应的积分,购买的越多送的积分越多用户购买的金额和对应送多少积分的规则如下:规则编号订单金额奖励积分1100元以下不加分2100元-500元加10分3500元-1000元加50......
  • 基于Java+Springboot+Vue开发的健身房管理系统
    项目简介该项目是基于Java+Springboot+Vue开发的健身房管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的健身房管理系统项目,大学生可以在实践中学习和提升......
  • Java毕设项目案例实战II基于Spring Boot的科研项目验收管理系统(开发文档+数据库+源码)
    目录一、前言二、技术介绍三、系统实现四、论文参考五、核心代码六、源码获取全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末一、前言随着科研活动的日益增多,科研项目验收作为......
  • Java毕设项目案例实战II基于Spring Boot的校园资产管理系统(开发文档+数据库+源码)
    目录一、前言二、技术介绍三、系统实现四、论文参考五、核心代码六、源码获取全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末一、前言在信息化技术日益普及的今天,高效、智能的......
  • Java毕设项目案例实战II基于Spring Boot的在线互动学习网站(开发文档+数据库+源码)
    目录一、前言二、技术介绍三、系统实现四、论文参考五、核心代码六、源码获取全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末一、前言随着互联网技术的飞速发展,教育领域也迎来......
  • springboot+vue基于SpringBoot的音乐演出购票系统【开题+程序+论文】
    系统程序文件列表开题报告内容研究背景在当今数字化时代,音乐演出已经成为人们休闲娱乐的重要组成部分,它不仅丰富了人们的精神生活,还促进了音乐文化的交流与传播。然而,传统的购票方式,如现场购票或通过电话订票,已难以满足日益增长的观众需求。观众在购票过程中常常面临信息不......
  • 基于微信小程序的校园帮管理系统互帮互助系统springboot框架
    本课题围绕基于Java+SpringBoot的校园帮管理系统展开。在校园生活中,学生们常常面临各种学习和生活上的需求,校园帮管理系统应运而生。该系统利用Java的可靠性和SpringBoot的高效开发特性,为校园内的互助服务提供全面的管理平台。它涵盖了任务发布、任务承接、进度跟......
  • 【开题报告+论文+源码】基于SpringBoot+Vue的学生成绩管理系统
    项目背景与意义在当今社会,科技的迅猛发展和互联网的广泛应用为各种领域的创新与发展提供了广阔的空间。特别是IT软件信息技术的崛起,已经成为连接买卖双方、推动商业活动高效进行的重要力量。电子商务不仅通过技术手段实现了交易的便捷化,还打破了地域和时间的限制,为全球范围内......