zuul网关问题记录及总结
问题一、
在实际使用zuul发现一个问题,在路由地址无法抵达时,zuul抛出 Filter threw Exception ,屏蔽了实际错误。
通过阅读源码可得,zuul会抛出ZuulException异常,将RunTimeException封装在内部。
需要使用throwable拦截器捕获。
重写findZuulException方法
问题二、
上面代码源自com.netflix.zuul.http.ZuulServlet
的service
方法实现,它定义了Zuul处理外部请求过程时,各个类型过滤器的执行逻辑。从代码中我们可以看到三个try-catch
块,它们依次分别代表了pre
、route
、post
三个阶段的过滤器调用,在catch
的异常处理中我们可以看到它们都会被error
类型的过滤器进行处理(之前使用error
过滤器来定义统一的异常处理也正是利用了这个特性);error
类型的过滤器处理完毕之后,除了来自post
阶段的异常之外,都会再被post
过滤器进行处理。而对于从post
过滤器中抛出异常的情况,在经过了error
过滤器处理之后,就没有其他类型的过滤器来接手了,这就是使用之前所述方案存在不足之处的根源。
回想一下之前实现的两种异常处理方法,其中非常核心的一点,这两种处理方法都在异常处理时候往请求上下文中添加了一系列的error.*
参数,而这些参数真正起作用的地方是在post
阶段的SendErrorFilter
,在该过滤器中会使用这些参数来组织内容返回给客户端。而对于post
阶段抛出异常的情况下,由error
过滤器处理之后并不会在调用post
阶段的请求,自然这些error.*
参数也就不会被SendErrorFilter
消费输出。所以,如果我们在自定义post
过滤器的时候,没有正确的处理异常,就依然有可能出现日志中没有异常并且请求响应内容为空的问题。我们可以通过修改之前ThrowExceptionFilter
的filterType
修改为post
来验证这个问题的存在,注意去掉try-catch
块的处理,让它能够抛出异常。
解决上述问题的方法有很多种,比如最直接的我们可以在实现error
过滤器的时候,直接来组织结果返回就能实现效果,但是这样的缺点也很明显,对于错误信息组织和返回的代码实现就会存在多份,这样非常不易于我们日后的代码维护工作。所以为了保持对异常返回处理逻辑的一致,我们还是希望将post
过滤器抛出的异常能够交给SendErrorFilter
来处理。
在前文中,我们已经实现了一个ErrorFilter
来捕获pre
、route
、post
过滤器抛出的异常,并组织error.*
参数保存到请求的上下文中。由于我们的目标是沿用SendErrorFilter
,这些error.*
参数依然对我们有用,所以我们可以继续沿用该过滤器,让它在post
过滤器抛出异常的时候,继续组织error.*
参数,只是这里我们已经无法将这些error.*
参数再传递给SendErrorFitler
过滤器来处理了。所以,我们需要在ErrorFilter
过滤器之后再定义一个error
类型的过滤器,让它来实现SendErrorFilter
的功能,但是这个error
过滤器并不需要处理所有出现异常的情况,它仅对post
过滤器抛出的异常才有效。根据上面的思路,我们完全可以创建一个继承自SendErrorFilter
的过滤器,就能复用它的run
方法,然后重写它的类型、顺序以及执行条件,实现对原有逻辑的复用,具体实现如下:
新增一个ErrorFilterExtFilter,专门过滤FilterType = POST的错误
https://www.cnblogs.com/duanxz/p/7543040.html