1.网关存在的意义
个人理解:1.zuul网关与servlet的过滤器或者AOP,可以在访问真正的服务模块前/后对请求做过滤,或者增加,修改一下东 西。如(是否带有已登陆的token等)
2.跨服务传递某些值(token,user等)
2.核心类 ZuulFilter
ZuulFilter是网关的核心类,同过extends ZuulFilter来定义自定义的Filter
@Component
public class MyFilter extends ZuulFilter {
/**
* 定义MyFilter的调用时机
* @return
*/
@Override
public String filterType() {
return PRE_TYPE;
}
/**
* 定义order调用顺序
* @return
*/
@Override
public int filterOrder() {
return 0;
}
/**
* 定义是否调用(可过滤某些逻辑下不调用MyFilter)
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 调用逻辑
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
//ctx中添加某些需要传递的东西,
ctx.addZuulRequestHeader("token","xxxxxxxx");
//在其他代码中可以通过以下方式获取出来
String tokenInContext=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader("token");
return null;
}
}
调用时机说明:
- PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
- ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
- POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
- ERROR:在其他阶段发生错误时执行该过滤器。 除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。
Zuul中默认实现的Filter
类型 | 顺序 | 过滤器 | 功能 |
---|---|---|---|
pre | -3 | ServletDetectionFilter | 标记处理Servlet的类型 |
pre | -2 | Servlet30WrapperFilter | 包装HttpServletRequest请求 |
pre | -1 | FormBodyWrapperFilter | 包装请求体 |
route | 1 | DebugFilter | 标记调试标志 |
route | 5 | PreDecorationFilter | 处理请求上下文供后续使用 |
route | 10 | RibbonRoutingFilter | serviceId请求转发 |
route | 100 | SimpleHostRoutingFilter | url请求转发 |
route | 500 | SendForwardFilter | forward请求转发 |
post | 0 | SendErrorFilter | 处理有错误的请求响应 |
post | 1000 | SendResponseFilter | 处理正常的请求响应 |
3.Application启动类
增加@EnableZuulProxy注解即可
*经过zuul网关服务过滤流程说明
实质上,zuul的最后filter是发起的http请求到对应的control,在发送之前,默认的filter会对http的header和body等进行处理存入到RequestContext中,在发起http请求的类中会从RequestContext中取出进行http请求组装,请求完成后会将response放入到RequestContext中,在"post filter"中会从RequestContext中取出response进行组装,返回。
但是我还没发现前端来的HttpServletRequset什么时候set进RequestContext中的,只看到getRequest,不知道在哪里调用的setRequest,后面再补充吧
请求经过pre的filter时
pre | -3 | ServletDetectionFilter | 标记处理Servlet的类型 |
pre | -2 | Servlet30WrapperFilter | 包装HttpServletRequest请求 |
pre | -1 | FormBodyWrapperFilter | 包装请求体 |
在经过pre的filter之后进入到route filter
route | 10 | RibbonRoutingFilter | serviceId请求转发 |
route | 100 | SimpleHostRoutingFilter | url请求转发 |
route | 500 | SendForwardFilter | forward请求转发 |
这三个filter是根据不同的调用服务的方式对所需请求的服务control进行调用,在这里会把之前的filter中设置的
RequestContext.getCurrentContext().addZuulRequestHeader(xx,xx)
中的header进行获取,并组装成http请求的header,并发起相应的url的http请求,之后将response用 RequestContext中对应的方法将response的header和body放如RequestContext中(例如:SimpleHostRoutingFilter中的run()调用了this.forward()方法就是发送一个http请求)
最后
post | 0 | SendErrorFilter | 处理有错误的请求响应 |
post | 1000 | SendResponseFilter | 处理正常的请求响应 |
这两个filter会对 RequestContext中的response进行处理,并返回给http的response(SendResponseFilter中的run()方法调用的writeResponse()方法)。