在Zuul网关中,一个请求从进入zuul到转发到后端服务的完整过程如下:
请求处理完整流程
1. 请求入口
- 请求首先到达Zuul Servlet(
ZuulServlet
) - 触发Zuul的过滤器链执行
2. 路由定位过程
// 通过 pre 路由阶段的过滤器(如 PreDecorationFilter)触发路由匹配
public Route getMatchingRoute(String path) {
// 提取路径信息和服务版本
String contextPath = getPathContext(path);
String systemVersion = modulePathMap.get(contextPath);
String version = getVersionFromPath(path);
// 路径重写处理
path = rewritePath(path, version);
// 版本兼容性检查和转换
if (!version.equals(systemVersion)
&& VersionUtils.isVersionCompatible(version, systemVersion)) {
path = path.replace(version, systemVersion);
}
// 最终路由匹配
return getSimpleMatchingRoute(path);
}
3. 负载均衡节点选择
// 在 getZuulRoute 中选择具体的服务实例
protected ZuulRoute getZuulRoute(String adjustedPath) {
// 匹配路由规则
for (Map.Entry<String, ZuulRoute> entry : super.getRoutesMap().entrySet()){
String pattern = (String)entry.getKey();
if (this.pathMatcher.match(pattern, adjustedPath)) {
ZuulRoute zuulRoute = (ZuulRoute)entry.getValue();
// 负载均衡选择具体节点
return chooseZuulRouteForBalance(pattern, zuulRoute);
}
}
}
// 随机负载均衡算法选择服务节点
private ZuulRoute chooseZuulRouteForBalance(String path, ZuulRoute defaultZuulRoute) {
List<ZuulRoute> serviceZuulRoutes = currentZuulRoute.get(path);
// 从多个服务实例中随机选择一个
Random random = new Random();
ZuulRoute zuulRoute = serviceZuulRoutes.get(
random.nextInt(serviceZuulRoutes.size())
);
return zuulRoute;
}
4. 路由信息设置
- 通过
PreDecorationFilter
设置路由相关信息到请求上下文 [RequestContext](file://com\netflix\zuul\context\RequestContext.java#L13-L93) - 主要设置的属性包括:
serviceId
: 目标服务IDrouteHost
: 目标服务URLrequestURI
: 请求URI
5. 请求转发执行
- 在 route 阶段,
RibbonRoutingFilter
或SimpleHostRoutingFilter
执行实际的请求转发 - 如果是服务ID方式,使用
RibbonRoutingFilter
结合Ribbon进行负载均衡调用 - 如果是URL方式,使用
SimpleHostRoutingFilter
直接HTTP转发
6. 响应返回
- 后端服务处理完成后,响应通过Zuul的 post 过滤器链返回给客户端
关键代码流程
- 路由匹配:
getSimpleMatchingRoute()
- 节点选择:
getZuulRoute()
→chooseZuulRouteForBalance()
[CustomRouteLocator.java]
- 上下文设置:
PreDecorationFilter
过滤器 - 请求转发:
RibbonRoutingFilter
或SimpleHostRoutingFilter
- 响应处理: post 过滤器链
这个过程确保了请求能够根据路由规则正确地转发到后端服务,并支持负载均衡、路径重写、版本兼容等高级功能。