首先,引入spring-cloud-starter-zuul之后会间接引入:
hystrix依赖已经引入,那么何种情况下使用hystrix呢?
在Zuul的自动配置类ZuulServerAutoConfiguration和ZuulProxyAutoConfiguration中总共会向Spring容器注入3个Zuul的RouteFilter,分别是
SimpleHostRoutingFilter
简单路由,通过HttpClient向预定的URL发送请求
生效条件:
RequestContext.getCurrentContext().getRouteHost() != null
&& RequestContext.getCurrentContext().sendZuulResponse()
1、RequestContext中的routeHost不为空,routeHost就是URL,即使用URL直连
2、RequestContext中的sendZuulResponse为true,即是否将response发送给客户端,默认为true
RibbonRoutingFilter
使用Ribbon、Hystrix和可插入的http客户端发送请求
生效条件:
(RequestContext.getRouteHost() == null && RequestContext.get(SERVICE_ID_KEY) != null
&& RequestContext.sendZuulResponse())
1、RequestContext中的routeHost为空,即URL为空
2、RequestContext中的serviceId不为空
3、RequestContext中的sendZuulResponse为true,即是否将response发送给客户端,默认为true
SendForwardFilter
forward到本地URL
生效条件:
RequestContext.containsKey(FORWARD_TO_KEY)
&& !RequestContext.getBoolean(SEND_FORWARD_FILTER_RAN, false)
1、RequestContext中包含FORWARD_TO_KEY,即URL使用 forward: 映射
2、RequestContext中SEND_FORWARD_FILTER_RAN为false,SEND_FORWARD_FILTER_RAN意为“send forward是否运行过了”,在SendForwardFilter#run()时会ctx.set(SEND_FORWARD_FILTER_RAN, true)
综上所述,在使用serviceId映射的方法路由转发的时候,会使用Ribbon+Hystrix
而哪种路由配置方式是“URL映射”,哪种配置方式又是“serviceId映射”呢?
Zuul有一个前置过滤器PreDecorationFilter用于通过RouteLocator路由定位器决定在何时以何种方式路由转发
RouteLocator是用于通过请求地址匹配到Route路由的,之后PreDecorationFilter再通过Route信息设置RequestContext上下文,决定后续使用哪个RouteFilter做路由转发
所以就引出以下问题:
什么是Route
RouteLocator路由定位器如何根据请求路径匹配路由
匹配到路由后,PreDecorationFilter如何设置RequestContext请求上下文
什么是Route
我总共见到两个和Route相关的类
ZuulProperties.ZuulRoute,用于和zuul配置文件关联,保存相关信息
org.springframework.cloud.netflix.zuul.filters.Route, RouteLocator找到的路由信息就是这个类,用于路由转发
public static class ZuulRoute { private String id; //ZuulRoute的id private String path; //路由的pattern,如 /foo/** private String serviceId; //要映射到此路由的服务id private String url; //要映射到路由的完整物理URL private boolean stripPrefix = true; //用于确定在转发之前是否应剥离此路由前缀的标志位 private Boolean retryable; //此路由是否可以重试,通常重试需要serviceId和ribbon private Set<String> sensitiveHeaders = new LinkedHashSet(); //不会传递给下游请求的敏感标头列表 private boolean customSensitiveHeaders = false; //是否自定义了敏感头列表 } public class Route { private String id; private String fullPath; private String path; private String location; //可能是 url 或 serviceId private String prefix; private Boolean retryable; private Set<String> sensitiveHeaders = new LinkedHashSet<>(); private boolean customSensitiveHeaders; }可以看到org.springframework.cloud.netflix.zuul.filters.Route和ZuulProperties.ZuulRoute基本一致,只是Route用于路由转发定位的属性location根据不同的情况,可能是一个具体的URL,可能是一个serviceId
RouteLocator路由定位器如何根据请求路径匹配路由
Zuul在自动配置加载时注入了2个RouteLocator
CompositeRouteLocator: 组合的RouteLocator,在getMatchingRoute()时会依次调用其它的RouteLocator,先找到先返回;CompositeRouteLocator的routeLocators集合中只有DiscoveryClientRouteLocator
DiscoveryClientRouteLocator: 可以将静态的、已配置的路由与来自DiscoveryClient服务发现的路由组合在一起,来自DiscoveryClient的路由优先;SimpleRouteLocator的子类(SimpleRouteLocator 基于加载到ZuulProperties中的配置定位Route路由信息)
其中CompositeRouteLocator是 @Primary 的,它是组合多个RouteLocator的Locator,其getMatchingRoute()方法会分别调用其它所有RouteLocator的getMatchingRoute()方法,通过请求路径匹配路由信息,只要匹配到了就马上返回