Spring Zuul:动态禁用到服务的路由

Spring Zuul: Dynamically disable a route to a service

我正在尝试禁用 Zuul 路由到在运行时向 Eureka 注册的微服务(我正在使用 spring 启动)。

这是一个例子:

localhost/hello
localhost/world

这两个是注册的微服务。我想在运行时禁用到其中之一的路由而不关闭它。

有办法吗?

谢谢,

纳米

除了使用 Cloud Config,还可以使用自定义 ZuulFilter。类似的东西(部分实现以显示概念):

public class BlackListFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return "pre";
    }
    ...
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        String uri = ctx.getRequest().getRequestURI();
        String appId = uri.split("/")[1];
        if (blackList.contains(appId)) {
            ctx.setSendZuulResponse(false);
            LOG.info("Request '{}' from {}:{} is blocked",
                    uri, ctx.getRequest().getRemoteHost(), ctx.getRequest().getRemotePort());
        }
        return null;
    }

}

其中 blackList 包含应用程序 ID 列表(Spring 引导应用程序名称),例如通过某些 RESTful API.

进行管理

经过一番努力,我想出了这个解决方案。首先,我使用 Netflix Archaius 观看了一个 属性 文件。然后我进行了如下处理:

public class ApplicationRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator {

public ApplicationRouteLocator(String servletPath, ZuulProperties properties) {
    super(servletPath, properties );
}


@Override
public void refresh() {
   doRefresh();
}
}

通过扩展 SimpleRouteLocator 并在 RefreshableRouteLocator 接口的重写之一中调用其方法,制作了 doRefresh() 方法 public。

然后我用我的自定义实现重新定义了 bean RouteLocator:

@Configuration
@EnableConfigurationProperties( { ZuulProperties.class } )
public class ZuulConfig {

public static ApplicationRouteLocator simpleRouteLocator;

@Autowired
private ZuulProperties zuulProperties;

@Autowired
private ServerProperties server;

@Bean
@Primary
public RouteLocator routeLocator() {
    logger.info( "zuulProperties are: {}", zuulProperties );
    simpleRouteLocator = new ApplicationRouteLocator( this.server.getServletPrefix(),
            this.zuulProperties );


    ConfigurationManager.getConfigInstance().addConfigurationListener( configurationListener );

    return simpleRouteLocator;
}


private ConfigurationListener configurationListener =
        new ConfigurationListener() {

            @Override
            public void configurationChanged( ConfigurationEvent ce ) {

                            // zuulProperties.getRoutes() do something
                            // zuulProperties.getIgnoredPatterns() do something
                            simpleRouteLocator.refresh();
                        }



                }

}

每次修改文件中的 属性 都会触发一个事件,ConfigurationEvent 能够处理它(getPropertyName() 和 getPropertyValue() 从事件中提取数据)。因为我还自动连接了 ZuulProperties,所以我能够访问它。通过正确的规则,我可以找到 Zuul

的 属性
zuul.ignoredPatterns

已修改相应地更改其在 ZuulProperties 中的值。

这里刷新上下文应该可以工作(只要您不添加新的路由规则或删除当前存在的路由规则),如果您要添加或删除路由规则,则必须为 ZuulProperties 添加一个新 bean 并标记它与@RefreshScope, @Primary.

例如,您可以自动装配 refreshEndpoint bean 并在侦听器上应用 refreshEndpoint.refresh()。

将自定义 RouteLocator 标记为主要会导致问题,因为 zuul 已经将相同类型的 bean 标记为主要。