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 标记为主要。
我正在尝试禁用 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 标记为主要。