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();
}

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

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

    Swagger 是一款RESTFUL接口的.基于YAML.JSON语言的文档在线自动生成.代码自动生成的工具. 通过在controller中添加注解,即可轻易实现代码文档化. Swagger提供ui界 ...

  2. Spring Cloud Zuul网关 Filter、熔断、重试、高可用的使用方式。

    时间过的很快,写springcloud(十):服务网关zuul初级篇还在半年前,现在已经是2018年了,我们继续探讨Zuul更高级的使用方式. 上篇文章主要介绍了Zuul网关使用模式,以及自动转发机制 ...

  3. Spring Cloud Zuul 网关使用与 OAuth2.0 认证授权服务

    API 网关的出现的原因是微服务架构的出现,不同的微服务一般会有不同的服务地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题: 客户端会 ...

  4. Spring Cloud Zuul 网关服务的fallback

    当我们的zuul进行路由分发时,如果后端服务没有启动,或者调用超时,这时候我们希望Zuul提供一种降级功能,而不是将异常暴露出来. Spring cloud zuul提供这种降级功能,操作步骤如下: ...

  5. Spring Cloud Zuul 网关的分布式系统中整合Swagger(转)和 zuul跨域访问问题

    首先恭喜自己终于找对了努力的方向,很荣幸能在公司接触到微服务架构,也很高兴公司一个大佬哥们愿意带我,他技术确实很牛逼,我也很佩服他,前后端通吃,干了六年能有这样的水平.最近跟着在搞微服务架构,给我分配 ...

  6. Spring Cloud(十一):Spring Cloud Zuul网关 Filter、熔断、重试、高可用的使用方式

    上篇文章主要介绍了Zuul网关使用模式,以及自动转发机制,但其实Zuul还有更多的应用场景,比如:鉴权.流量转发.请求统计等等,这些功能都可以使用Zuul来实现. Zuul的核心 Filter是Zuu ...

  7. Spring Cloud zuul网关服务 一

    上一篇进行Netflix Zuul 1.0 与 gateway的对比.今天来介绍一下 zuul的搭建及应用 Zuul 工程创建 工程创建 cloud-gateway-zuul.还是基于之前的工程 po ...

  8. Spring Cloud Zuul网关(快速搭建)

    zuul 是netflix开源的一个API Gateway 服务器, 本质上是一个web servlet应用. 在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架.相当于是设备和 Netflix ...

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

    Zuul的核心 Filter是Zuul的核心,用来实现对外服务的控制.Filter的生命周期有4个,分别是“PRE”.“ROUTING”.“POST”.“ERROR”,整个生命周期可以用下图来表示. ...

随机推荐

  1. redis cluster 的ERR max number of clients reached 问题排查

    早上发现微服务连不上redis cluster了,看来下日志如下 [root@win-jrh378d7scu 7005]# bin/redis-cli -c -h 15.31.213.183 -p 7 ...

  2. 把序列中的N个元素赋值给多个变量

    说明: python中序列和散列 序列:可通过偏移量来进行切片的对象.列表.元组.字符串都属于序列. 散列:无法通过偏移量来进行切片的对象.比如 集合.字典 一. 变量的数量跟序列元素的个数一样 1. ...

  3. React 组件模式

    简评:组件(component)是 React 的核心,了解它们有助于构建好的设计结构. 什么是组件(component) 组件运行你将 UI 拆分为独立的可重用的部分.和 JavaScript 函数 ...

  4. Java网络编程以及简单的聊天程序

    网络编程技术是互联网技术中的主流编程技术之一,懂的一些基本的操作是非常必要的.这章主要讲解网络编程,UDP和Socket编程,以及使用Socket做一个简单的聊天软件. 全部代码下载:链接 1.网络编 ...

  5. 对drf视图的理解

    视图说明 1. 两个基类 1)APIView rest_framework.views.APIView APIView是REST framework提供的所有视图的基类,继承自Django的View父 ...

  6. node-redis模块需要注意的事项

    node之中连接redis使用的redis模块,虽然好用,但是有些地方还是需要注意. npm install redis redis client 行为:1.客户端执行过程中断网的情况 由于原本连接正 ...

  7. FlowPortal-BPM——离线审批(邮箱审批)配置

    一.将系统文件复制到安装目录下 二.以管理员身份运行bat安装程序 三.开启邮件离线审批服务 四.创建数据库表(JAVA数据库 或 .Net数据库) 五.配置config文件(发件箱.收件箱.错误问题 ...

  8. 如何在本地连接服务器上的MySQL

    服务器以阿里云为例 1.首先确保防火墙开放了3306端口 2.确保服务器的linux系统防火墙开放了3306端口 firewall-cmd --list-ports # 查看端口 我这里已经启动了,如 ...

  9. [C语言]链表实现贪吃蛇及部分模块优化

    在继上篇[C语言]贪吃蛇_结构数组实现大半年后,链表实现的版本也终于出炉了.两篇隔了这么久除了是懒癌晚期的原因外,对整个游戏流程的改进,模块的精简也花了一些时间(都是借口). 优化模块的前沿链接: · ...

  10. 多线程编程(二)-Exchanger的使用

    Exchanger的介绍 类Exchanger的功能可以使两个线程之间传输数据. 方法exchange()的使用 package com.wjg.unit; import java.util.conc ...