如何在Zuul 2中仅通过代码声明路由(无需配置文件及Spring组件)
纯代码实现Zuul 2路由(无配置文件、无Spring/Eureka依赖)
基于Zuul 2的原生机制,我们可以通过自定义路由注册表+Ribbon负载均衡器初始化的方式,完全用代码替代配置文件声明路由,实现类似Spring Cloud Gateway的路由定义风格。以下是具体实现方案:
1. 定义路由模型与注册表
首先创建路由配置类和全局注册表,集中管理所有路由规则:
RouteConfig.groovy(路由模型)
package info.novatec.zuul2.config class RouteConfig { // 路径匹配规则(支持**通配符) String pathPattern // 路由唯一标识(对应Ribbon的VIP) String vip // 后端服务器列表 List<String> servers RouteConfig(String pathPattern, String vip, List<String> servers) { this.pathPattern = pathPattern this.vip = vip this.servers = servers } }
RouteRegistry.groovy(路由注册表)
package info.novatec.zuul2.config import java.util.regex.Pattern class RouteRegistry { // 初始化所有路由规则,可按需扩展 private static final List<RouteConfig> ROUTES = [ new RouteConfig("/hello/**", "hello-service", ["localhost:8081"]), new RouteConfig("/test/**", "test-service", ["localhost:8080"]) ] // 根据请求路径匹配路由 static RouteConfig findMatchingRoute(String path) { return ROUTES.find { route -> Pattern.compile(route.pathPattern.replace("**", ".*")).matcher(path).matches() } } // 获取VIP与服务器列表的映射关系,供Ribbon初始化使用 static Map<String, List<String>> getVipToServersMap() { return ROUTES.collectEntries { [(it.vip): it.servers] } } }
2. 修改路由过滤器
替换原有的Routes.groovy,通过注册表匹配路由并设置Zuul上下文:
package info.novatec.zuul2.filters.inbound import com.netflix.zuul.context.SessionContext import com.netflix.zuul.filters.endpoint.ProxyEndpoint import com.netflix.zuul.filters.http.HttpInboundSyncFilter import com.netflix.zuul.message.http.HttpRequestMessage import info.novatec.zuul2.config.RouteRegistry class Routes extends HttpInboundSyncFilter { @Override HttpRequestMessage apply(HttpRequestMessage request) { SessionContext context = request.getContext() String path = request.getPath() RouteConfig matchedRoute = RouteRegistry.findMatchingRoute(path) if (matchedRoute) { // 设置代理端点 context.setEndpoint(ProxyEndpoint.class.getCanonicalName()) // 设置路由VIP,关联Ribbon负载均衡器 context.setRouteVIP(matchedRoute.vip) // 可选:移除路径前缀(比如把/hello/api转为/api) // String newPath = path.replaceFirst(matchedRoute.pathPattern.replace("**", ""), "") // request.setPath(newPath) } else { // 无匹配路由时返回404 context.setResponseStatusCode(404) context.setEndpoint(null) } return request } @Override int filterOrder() { return 0 } @Override boolean shouldFilter(HttpRequestMessage request) { return true } }
3. 初始化Ribbon负载均衡器
创建初始化类,在Zuul启动时为每个路由VIP绑定对应的服务器列表:
RibbonLoadBalancerInitializer.groovy
package info.novatec.zuul2.init import com.netflix.client.config.DefaultClientConfigImpl import com.netflix.loadbalancer.DynamicServerListLoadBalancer import com.netflix.loadbalancer.LoadBalancerManager import com.netflix.loadbalancer.Server import com.netflix.loadbalancer.StaticServerList import info.novatec.zuul2.config.RouteRegistry class RibbonLoadBalancerInitializer { static void init() { def vipToServers = RouteRegistry.vipToServersMap() vipToServers.each { vip, servers -> // 将服务器地址转为Ribbon Server对象 List<Server> serverList = servers.collect { new Server(it) } // 初始化Ribbon客户端配置 DefaultClientConfigImpl clientConfig = new DefaultClientConfigImpl() clientConfig.loadProperties(vip) // 创建动态服务器列表负载均衡器 DynamicServerListLoadBalancer<Server> loadBalancer = new DynamicServerListLoadBalancer<>( clientConfig, null, null, new StaticServerList<>(serverList), null ) // 可选:自定义负载均衡策略(比如随机策略) // loadBalancer.setRule(new com.netflix.loadbalancer.RandomRule()) // 将负载均衡器注册到Ribbon管理器 LoadBalancerManager.getInstance().setLoadBalancer(vip, loadBalancer) } } }
4. 修改Zuul启动类
在启动时先初始化Ribbon负载均衡器,再启动Zuul服务器:
package info.novatec.zuul2 import com.netflix.zuul.ZuulServer import info.novatec.zuul2.init.RibbonLoadBalancerInitializer class ZuulServerMain { static void main(String[] args) { // 初始化Ribbon负载均衡器 RibbonLoadBalancerInitializer.init() // 启动Zuul服务器 ZuulServer server = new ZuulServer() server.init() server.start() } }
5. 清理配置文件
移除application.properties中所有路由和Eureka相关配置,最终配置如下:
zuul.server.port.main=9001 # 过滤器配置 zuul.filters.root=src/main/groovy/info/novatec/zuul2/filters zuul.filters.locations=${zuul.filters.root}/inbound,${zuul.filters.root}/outbound,${zuul.filters.root}/endpoint zuul.filters.packages=com.netflix.zuul.filters.common @next=application-${@environment}.properties
方案说明
- 完全脱离配置文件:路由规则、后端服务器列表均通过代码声明,可动态修改或扩展
- 无Spring/Eureka依赖:基于Zuul 2和Ribbon原生API实现,无需引入Spring生态组件
- 支持自定义扩展:可添加路径重写、负载均衡策略、路由动态刷新等功能
内容的提问来源于stack exchange,提问作者kanai
相关产品推荐
相关产品推荐

