述
本文来看一下Zuul的异常处理流程,以及如何自定义异常信息
Zuul生命周期
看一下官方给出的Zuul请求的生命周期图:
从图上可以看出,正常情况下,请求都是按照pre→route→post的顺序来执行,最后由post返回response.
在看一下pre下面的custom filter,就是说在pre阶段,如果有用户自定义的过滤器则执行自定义的过滤器.
pre routing post的任意一个阶段如果抛异常了,则执行error过滤器,然后再执行post给出响应.
源码分析
来看下源码com.netflix.zuul.http.ZuulServlet
这个类中的service方法,是整个调用过程的核心:
可以看到,内层的3个catch只捕获ZuulException这个异常,其他的异常是交给外层的catch去捕获.
pre和route执行出错之后都会先执行error再执行post,而post执行出错之后就只执行error而不会再执行post.
ZuulFilter最终会在com.netflix.zuul.FilterProcessor
的processZuulFilter方法中被调用,在该方法中会判断runFilter是否执行成功,如果执行失败,则将异常信息提取出来,然后抛出异常,抛出的异常如果是ZuulException的实例,则抛出一个ZuulException类型的异常,如果不是ZuulException的实例,则抛出一个状态码为500的ZuulException类型的异常,所以无论如何,我们最终看到的都是ZuulException类型的异常,下面我贴出processZuulFilter方法的代码,如下:
再看下runfilter这个方法:
在Zuul中,所有的错误问题的最终都是被SendErrorFilter类来处理,该类在早期的版本是一个post类型的filter,post类型的filter有一个缺陷就是不能处理post中抛出的异常,需要我们手动去完善,而我目前使用的这个版本(Dalston.SR3)已经修复了这个问题,SendErrorFilter现在是一个error类型的filter,而且只要RequestContext中有异常就会进入到SendErrorFilter中,错误信息也都从exception对象中提取出来,核心代码如下:
自定义异常信息
创建一个类,继承DefaultErrorAttributes类,然后重写getErrorAttributes 方法,具体代码如下:1
2
3
4
5
6
7
8
9
10
11public class MyErrorAttribute extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {
Map<String, Object> map = super.getErrorAttributes(requestAttributes, includeStackTrace);
map.put("status", 222);
map.put("error", "error");
map.put("exception", "exception");
map.put("message", "message");
return map;
}
}