zuul入门

zuul是spring cloud的网关组件,用户在微服务中提供一个统一的对外接口,官方对zuul的说明是

Zuul is an edge service that provides dynamic routing, monitoring, resiliency, security, and more.

ZuulFilter

zuul是的核心就是com.netflix.zuul.ZuulFilter,对于zuul网关的相关功能都是通过扩展这个ZuulFilter来实现的

ZuulFilter只需要实现几个方法就行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public abstract class ZuulFilter implements IZuulFilter, Comparable<ZuulFilter> {
/**
* 指明过滤器的类型 zuul定义类四种类型 pre, route, post, error
* 可以在 com.netflix.zuul.FilterProcessor 中看到
*/
abstract public String filterType();
/**
* filter的排序序号 在同类型中 filterOrder 越小约先执行
*/
abstract public int filterOrder();
/**
* 是否应该执行Filter
*/
abstract public boolean shouldFilter();

/**
* 如果 shouldFilter() 为 true, 才会调用这个方法.
* 这个方法是一个ZuulFilter的核心方法
* @return 随意返回,反正zuul会忽略这个返回值
*/
abstract public Object run();
}

编写ZuulFilter

例如实现一个判断请求是否带有accessToken的Filter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class AuthenticationFilter extends ZuulPreFilter {
public String filterType(){
return "pre";
}
public int filterOrder(){
return 0;
}
public boolean shouldFilter(){
return true;
}
public Object run(){
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String accessToken = request.getParameter("access_token");
if(accessToken == null || "".equals(accessToken)){
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(403);
return null;
}
return null;
}

}

注册ZuulFilter

实现的ZuulFilter都通过com.netflix.zuul.filters.FilterRegistry#put(String, ZuulFilter)进行注册

FilterRegistry是个单例

直接通过com.netflix.zuul.filters.FilterRegistry#instance就可以获取实例

Zuul里面单例用的比较多

配置Zuul

要使用Zuul 需要配置一个com.netflix.zuul.context.ContextLifecycleFilter和一个

com.netflix.zuul.filters.ZuulServletFilter

或者 com.netflix.zuul.http.ZuulServlet

ZuulServlertFilterZuulServlet二选一就行 这两个就是请求的入口

ContextLifecycleFilter主要是对com.netflix.zuul.context.RequestContext的生命周期做管理

com.netflix.zuul.context.RequestContext是一个上下问对象,在ZuulFilter中可以使用RequestContext#getInstacne()获取到当前的请求上下文,
RequestContext内部使用ThreadLocal来实现

配置了ZuulServlertFilter或者ZuulServlet之后

ZuulServlet

ZuulServlet来说,service方法就是核心

service方法中主要就是初始化RequestContext以及调用各个类型的ZuulFilter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
try {
init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);

// Marks this request as having passed through the "Zuul engine", as opposed to servlets
// explicitly bound in web.xml, for which requests will not have the same data attached
RequestContext context = RequestContext.getCurrentContext();
context.setZuulEngineRan();

try {
preRoute();
} catch (ZuulException e) {
error(e);
postRoute();
return;
}
try {
route();
} catch (ZuulException e) {
error(e);
postRoute();
return;
}
try {
postRoute();
} catch (ZuulException e) {
error(e);
return;
}
} catch (Throwable e) {
error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName()));
} finally {
RequestContext.getCurrentContext().unset();
}

ZuulServlet内部持有个com.netflix.zuul.ZuulRunner对象

各个xxRoute()方法都是委托给ZuulRunner的方法去调用

ZuulRunner在委托给FilterProcessor去调用, FilterProcessor是一个单例

FilterProcessor使用FilterLoad最后调用到FilterRegistry获取注册的Filter进行调用