Spring Cloud网关服务zuul过滤器作用

欢迎来我的博客参观,交流:https://endwas.cn

上文中得知,zuul核心用到就是过滤器模式,里面无论路由映射还是请求转发都需要使用到zuul过滤器。所以,过滤器可以说是Zuul实现API网关功能最为核心的部件,每一个进入Zuul的HTTP请求都会经过一系列的过滤器处理链得到请求响应并返回给客户端。

1.过滤器接口

在Spring Cloud Zuul中实现的过滤器接口ZuulFilter必须包含4个基本特征: 过滤类型、 执行顺序、执行条件、 具体操作。

// 过滤类型 pre/post等
String filterType();
// 过滤器优先级 
int filterOrder();
// 是否应该过滤 
boolean shouldFilter(); 
// 运行过滤器逻辑
Object run(); 
  • filterType: 该函数需要返回一个字符串来代表过滤器的类型, 而这个类型就是在HTTP请求过程中定义的各个阶段。在 Zuul 中默认定义了 4 种不同生命周期的过滤器类型, 具体如下所示。
  1. pre: 可以在请求被路由之前调用,可用于登录校验等。
  2. routing: 在路由请求时被调用。
  3. post: 在 routing 和 error 过滤器之后被调用。
  4. error: 处理请求时发生错误时被调用。
  • filterOrder: 通过 int 值来定义过滤器的执行顺序,数值越小优先级越高
  • shouldFilter: 返回一个 boolean 值来判断该过滤器是否要执行。 我们可以通过此方法来指定什么情况需要被执行。
  • run: 过滤器的具体逻辑。在该函数中,我们可以实现自定义的过滤逻辑, 来确定是否要拦截当前的请求,不对其进行后续的路由, 或是在请求路由返回结果之后,对处理结果做一些加工等。

2.核心过滤器

在zuul中已经包含很多默认的过滤器,他们作用在不同生命周期中,我们在z org.springframework.cloud.netflix.zuul.filters包下。可以看到这些过滤器。
在这里插入图片描述

下面是过滤器的执行时机,优先级和功能。

在这里插入图片描述

3.请求生命周期

在这里插入图片描述
我们可以看到在调用远程服务前会执行prefilters,在调用远程服务后会调用postfilters,如果在路由过滤器routingfilters时遇到错误,会调用errorfilters,当然无论在正常、异常执行路由过滤器后都会执行postfilters。

我们从源码看一下不同过滤器执行时候,各个阶段的过滤器如何进行调度的。

try { 
	// pre过滤器
	preRoute(); 
) catch (ZuulException e) { 
	error(e); 
	postRoute(); 
	return; 
}

try { 
	// 路由过滤器
	route(); 
} catch (ZuulException e) { 
	error(e);
	postRoute(); 
	return;
} 

try { 
	// post过滤器
	postRoute(} ; 
} catch (ZuulException e} { 
	error(e}; 
	// 不需要执行postRoute过滤器
	return;
}

我们可以看到在pre、route阶段的过滤器遇到异常会执行postRoute和error阶段过滤器,但postRoute阶段过滤器执行异常,就只会执行error过滤器了,我们前文可以得知,postRoute中sendErrorFilter是用来组织返回结果的,如果没有执行post过滤器,那么我们就无法得到返回结果,那么我们该如何处理?

4.思考

  1. postRoute抛出的异常怎么处理返回结果
    我们异常信息组织在sendErrorFilter中,他会将pre或route阶段保存在上下文中的错误信息、错误码进行组织,然后返回。
    那么我们是否可以增加一个error过滤器,对错误信息结果也组装返回,起到sendErrorFilter的作用呢?
    这样是可行,但我们在post和error阶段就存在两个一样作用的过滤器,就会在pre阶段抛出异常时,各执行一次。

更好的做法则是在error阶段,增加一个过滤器来实现sendErrorFilter来单独处理post阶段抛出异常。

  1. 怎么样判断是post类型过滤器
    我们要如何实现shouldFilter方法,控制他只处理post抛出的异常。
    我们首先是想到在上下文对象中找到是否在抛出异常时候会存储,但很遗憾并没有保存下来。所以我们就需要拓展处理器。在处理器执行各个阶段过滤器时若抛出异常,将filter进行存储。
public class ExtendFilterProcessor 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.filter", filter); 
			throw e; 
		}
	}
}

然后继承SendErrorFilter来处理post阶段抛出的异常。

@Component 
public class ErrorExtFilter extends SendErrorFilter { 
	@Override 
	public String filterType () { 
	return "error"; 
	@Override 
	public int filterOrder() { 
	return 30; //大于ErrorFilter的值
	@Override 
	public boolean shouldFilter() { 
		//判断:仅处理来自post过滤器引起的异常
		RequestContext ctx = RequestContext.getCurrentContext(); 
		ZuulFilter failedFilter = (ZuulFilter) ctx.get("failed.filter");
		if(failedFilter != null && failedFilter.filterType().equals ("post")) { 
			return true; 
		}
		return false;
	}
	// run
}

总结

Spring Cloud zuul的过滤器组件功能很强大,但他在实现时候并不是很友好,我们需要对其完善,否则有可能会出现拿不到想要结果情况。过滤器异常处理核心两个filter,第一个是Errorfilter它是属于error阶段的,在遇到异常时候,对异常信息进行封装到上下文对象的。第二个是sendErrorFilter它是属于post阶段的,它利用请求上下文中的错误信息来组成一个forward到API网关/error错误端点的请求来产生错误响应。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值