背景:防止恶意多次访问接口,实现限流。
使用jar包:spring-cloud-zuul-ratelimit 版本:1.5.0.RELEASE
此jar包引用后,可以直接在配置上实现基于redis存储,控制粒度达到具体接口级别,不用添加任何代码
问题:由于实现完全基于封装好的jar包,所以当异常发生时,接口返回的数据格式无法控制(直接在源码里写死了)
解决思路:1.发现spring-cloud-zuul-ratelimit源码里的filterOrder为-1 (过滤器执行顺序,数字越小优先级别越大)
2.写一个error-filter(filterOrder为-2,filterType为“error”)截拦住上一个filter已经设定好的response
3.此时debug发现,虽然error-filter已经重新设置了response,但是接口返回的数据并没有发生变化(设置失效)
4.再次debug zuul的源码发现,在error-filter执行之后,程序还会执行SendErrorFilter(zuul自带的filter,用于整合返回数据之类的,filterOrder为0)
5.在SendErrorFilter中会处理ZuulException(此异常在spring-cloud-zuul-ratelimit的源码中抛出),并重新设置response(例如StatusCode之类)
6.这导致了error-filter设置的response失效,所以在error-filter中需要去除ZuulException
Object e = ctx.getThrowable();
if (e != null && e instanceof ZuulException) {
ctx.remove("throwable");
}
7.在此之后,返回的数据可以按照在error-filter中设置的一样返回
结论或启示:需要注意zuul自带的SendErrorFilter可能会对最后返回的数据造成影响。
同时filter中处理数据遇到异常时,可以用try-catch处理,然后设置返回数据。避免直接抛出exception,而后被SendErrorFilter捕获,对其他filter造成影响。
spring cloud zuul中的SendErrorFilter
最新推荐文章于 2022-06-30 08:15:23 发布