Spring cloud Zuul网关异常处理

一 异常测试:

1> 创建一个pre类型的过滤器,并在该过滤器的run方法实现中抛出一个异常。比如下面的实现,在run方法中调用的doSomething方法将抛出RuntimeException异常

package com.xbchen.springcloud.filter.post;

import com.netflix.zuul.ZuulFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class ThrowExceptionPostFilter extends ZuulFilter  {

    private static Logger log = LoggerFactory.getLogger(ThrowExceptionPostFilter.class);

    @Override
    public String filterType() {
        return "post";
    }

    @Override
    public int filterOrder() {
        return 10;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        log.info("This is a post filter, it will throw a RuntimeException");
        doSomething();
        return null;
    }

    private void doSomething() {
        throw new RuntimeException("Exist some errors...");
    }

}

2> 在启动类中为过滤器创建Bean

@Bean
public ThrowExceptionFilter throwExceptionFilter() {
  return new ThrowExceptionFilter();
}

3> 运行启动类

4> 发现后台并没抛出异常信息

二 问题分析:

查看postRoute阶段的异常处理过滤器SendErrorFilter中的方法shouldFilter

注意: 新版本中已经修复了该问题,取消了error.status_code的判断。

即: 只有上线文中包含error.status_code,才能被SendErrorFilter处理。

以此需要自行处理。

处理方式1: 在抛异常时,自行捕获设置error.status_code

@Override
public Object run() {
    log.info("This is a post filter, it will throw a RuntimeException");
    //doSomething();
    RequestContext context=RequestContext.getCurrentContext();
    try{
        doSomething();
    }catch (Exception e){
        context.set("error.status_code", HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        context.set("error.exception",3);
    }
    return null;
}

处理方式2:新增一个error处理的过滤器

@Component
public class ErrorFilter extends ZuulFilter {
    Logger log = LoggerFactory.getLogger(ErrorFilter.class);
    @Override
    public String filterType() {
        return "error";
    }
    @Override
    public int filterOrder() {
        return 20;
    }
    @Override
    public boolean shouldFilter() {
        return true;
    }
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        Throwable throwable = RequestContext.getCurrentContext().getThrowable();
        log.error("this is a ErrorFilter : {}", throwable.getCause().getMessage());
        ctx.set("error.status_code", HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        ctx.set("error.exception", throwable.getCause());
        return null;
    }

}

三:遗留问题:路由包括3阶段, 正常处理过程:preRoute-->route-->postRoute

其中preRoute 和route异常时,会被捕获直接进入postRoute;

会经过postRoute的过滤器(SendErrorFilter extends ZuulFilter)

但是postRoute阶段的异常,是没有处理的过滤器的。以此需要针对postRoute阶段的异常进行单独处理。

处理方式:

新增处理类,扩展过滤器处理类FilterProcessor的processZuulFilter方法

public class DidiFilterProcessor extends FilterProcessor {

    @Override
    public Object processZuulFilter(ZuulFilter filter) throws ZuulException {
        try {
            return super.processZuulFilter(filter);
        } catch (ZuulException e) {
            RequestContext ctx = RequestContext.getCurrentContext();
            ctx.set("failed.exception", e);
            ctx.set("failed.filter", filter);
            throw e;
        }
    }
}

在启动类中设置处理类

@SpringBootApplication
@EnableZuulProxy
public class GatewayApplication {

  public static void main(String[] args) {
    FilterProcessor.setProcessor(new DidiFilterProcessor());
    SpringApplication.run(GatewayApplication.class, args);
  }}

新增post阶段的异常处理过滤器

/**
 * 从POST抛出的异常,使用该过滤器返回错误信息
 */
@Component
public class ErrorExtFilter extends SendErrorFilter {
    Logger log = LoggerFactory.getLogger(ErrorExtFilter.class);
    @Override
    public String filterType() {
        return "error";
    }
    @Override
    public int filterOrder() {
        return 30;
    }
    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        ZuulFilter failedFilter = (ZuulFilter) ctx.get("failed.filter");
        if(failedFilter != null && failedFilter.filterType().equals("post")) {
            return true;
        }
        return false;
    }
}

四:异常自定义

以上异常已经正常抛出,但是格式并不一定符合项目要求,或者有时并不需要将异常返回给客户端。

由于异常信息格式是在DefaultErrorAttributes定义的,以此可对该类进行扩展。

比如:异常异常信息,避免返回到客户端。

public class DidiErrorAttributes extends DefaultErrorAttributes {

    @Override
    public Map<String, Object> getErrorAttributes (
            RequestAttributes requestAttributes, boolean includeStackTrace){
        Map<String, Object> result = super.getErrorAttributes(requestAttributes, includeStackTrace);
        result.remove("exception");
        return result;
    }
}

在启动类中新增异常属性扩展类的Bean创建。

@Bean
  public DefaultErrorAttributes errorAttributes() {
    return new DidiErrorAttributes();
  }

原文地址:https://www.cnblogs.com/brant/p/9415726.html

时间: 2024-10-04 00:12:13

Spring cloud Zuul网关异常处理的相关文章

创建swagger的springboot-stater,并在spring cloud zuul网关中引入

Swagger 是一款RESTFUL接口的.基于YAML.JSON语言的文档在线自动生成.代码自动生成的工具. 通过在controller中添加注解,即可轻易实现代码文档化. Swagger提供ui界面,方便查看接口说明和测试接口功能. swagger-github 本文主要讲解如何创建一个swagger 的springboot starter项目,只要在其他服务中引入该starter.并添加相关注解,即可完成接口文档化. 并讲解了如何在spring cloud zuul网关中引入swagger

spring cloud深入学习(十二)-----Spring Cloud Zuul网关 Filter、熔断、重试、高可用的使用方式

Zuul的核心 Filter是Zuul的核心,用来实现对外服务的控制.Filter的生命周期有4个,分别是“PRE”.“ROUTING”.“POST”.“ERROR”,整个生命周期可以用下图来表示. Zuul大部分功能都是通过过滤器来实现的,这些过滤器类型对应于请求的典型生命周期. PRE: 这种过滤器在请求被路由之前调用.我们可利用这种过滤器实现身份验证.在集群中选择请求的微服务.记录调试信息等. ROUTING:这种过滤器将请求路由到微服务.这种过滤器用于构建发送给微服务的请求,并使用Apa

Spring Cloud gateway 网关服务二 断言、过滤器

微服务当前这么火爆的程度,如果不能学会一种微服务框架技术.怎么能升职加薪,增加简历的筹码?spring cloud 和 Dubbo 需要单独学习.说没有时间?没有精力?要学俩个框架?而Spring Cloud alibaba只需要你学会一个就会拥有俩种微服务治理框架技术.何乐而不为呢?加油吧!骚猿年 上一篇我们讲述了gateway 的路由功能其实也类似与zuul服务的路由转发. 今天主要讲一下断言机制. 内置的断言工厂 介绍 Spring Cloud Gateway将路由作为Spring Web

SpringCloud---API网关服务---Spring Cloud Zuul

1.概述 1.1 微服务架构出现的问题   及  解决: 1.1.1 前言 每个微服务应用都提供对外的Restful API服务,它通过F5.Nginx等网络设备或工具软件实现对各个微服务的路由与负载均衡,并公开给外部客户端使用: 1.1.2 出现的问题 运维人员角度: 开发人员角度: 为了保证对外服务的安全性,在服务端实现都会加入一定的权限校验,同时为了安全,还会有签名校验等: 这样导致每个微服务应用都需要有冗余的代码,后期维护量非常大: 1.1.3 解决 为了解决这些常见的架构问题,API网

笔记:Spring Cloud Zuul 快速入门

Spring Cloud Zuul 实现了路由规则与实例的维护问题,通过 Spring Cloud Eureka 进行整合,将自身注册为 Eureka 服务治理下的应用,同时从 Eureka 中获取了所有其他微服务的实例信息,这样的设计非常巧妙的将服务治理体系中维护的实例信息利用起来,使得维护服务实例的工作交给了服务治理框架自动完成,而对路由规则的维护,默认会将通过以服务名作为 ContextPath 的方式来创建路由映射,也可以做一些特别的配置,对于签名校验.登录校验等在微服务架构中的冗余问题

spring cloud zuul

spring cloud zuul官网:http://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/1.3.1.RELEASE/,具体配置不记 spring cloud zuul是配置路由的,我们配置的时候,喜欢这么配置例如: zuul: routes: api-a: path: /api-a/** serviceId: service-A 但是其实我们不配置也是可以路由的,如果我们的api-gateway网关的开的端口是555

Spring Cloud Zuul 实现路由,获取参数

Spring Cloud Zuul作为网关,可实现请求验证过滤,路由到具体服务的作用. 举例: 比如请求订单接口,报文包括验证信息及具体请求参数. 通过配置路由到具体接口,通过参数调用接口,返回具体报文. 参数传递: 1.post请求,String类型json 2.接口获取@ResponseBody,将获取到String转json,再获取详细参数信息 验证:继承ZuulFilter类,重写run方法,调用具体验证服务,验证通过返回true.

Spring Cloud Zuul性能调整

Spring Cloud 版本: Dalston.SR5 这两天通过JMeter测了一下Spring Cloud Zuul的性能,用的是两台虚机8核8G和4核8G,宿主机是10核逻辑20核,代理的服务简单的返回字符串hello,vm堆内存1G够用 先说一下测试情况,值得一提的是测试并不严谨,因为用的是虚机,并且虚机上还跑了一些其它的东西,所以不能作为最终指导,仅供参考. 8核心的情况下: zuul的性能约是nginx(8个worker)的75%, nginx 8个worker 的cup总占用率为

Spring Cloud Zuul 快速入门

服务网关和Zuul 为什么要有服务网关: 我们都知道在微服务架构中,系统会被拆分为很多个微服务.那么作为客户端要如何去调用这么多的微服务呢?难道要一个个的去调用吗?很显然这是不太实际的,我们需要有一个统一的接口与这些微服务打交道,这就是我们需要服务网关的原因. 我们已经知道,在微服务架构中,不同的微服务可以有不同的网络地址,各个微服务之间通过互相调用完成用户请求,客户端可能通过调用N个微服务的接口完成一个用户请求.比如:用户查看一个商品的信息,它可能包含商品基本信息.价格信息.评论信息.折扣信息