#spring-boot #java-8 #netflix-zuul #netflix-eureka
#spring-boot #java-8 #netflix-zuul #netflix-eureka
Вопрос:
Я пытаюсь отключить маршрут Zuul к микросервису, зарегистрированному в Eureka во время выполнения (я использую spring boot).
Это пример:
localhost/hello
localhost/world
Эти два являются зарегистрированными микросервисами. Я хотел бы отключить маршрут к одному из них во время выполнения, не отключая его.
Есть ли способ сделать это?
Спасибо,
Nano
Комментарии:
1. Под динамически вы подразумеваете с помощью кода … если вы используете cloud config, то вы можете удалить маршрутизацию из свойств zuul и обновить ее через actuator, тогда маршрутизация не произойдет… для меня это звучит динамично…
Ответ №1:
В качестве альтернативы использованию облачной конфигурации можно использовать пользовательскую 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
содержится список идентификаторов приложений (имя приложения Spring Boot), управляемых, например, через некоторый RESTful API.
Комментарии:
1. Я тоже думал о фильтре, но хотел попробовать использовать собственные свойства Zuul 🙂
Ответ №2:
После долгих усилий я пришел к этому решению. Сначала я использовал Netflix Archaius для просмотра файла свойств. Затем я поступил следующим образом:
public class ApplicationRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator {
public ApplicationRouteLocator(String servletPath, ZuulProperties properties) {
super(servletPath, properties );
}
@Override
public void refresh() {
doRefresh();
}
}
Сделал метод doRefresh() общедоступным, расширив SimpleRouteLocator и вызвав его метод в переопределенном интерфейсе RefreshableRouteLocator.
Затем я переопределил 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.
Комментарии:
1. Не удается разрешить метод ‘getServletPrefix’ в ‘ServerProperties’
Ответ №3:
Здесь должен сработать контекст обновления (пока вы не добавляете новое правило маршрутизации или не удаляете существующее в данный момент), если вы добавляете или удаляете правила маршрутизации, вам нужно добавить новый компонент для ZuulProperties и пометить его @RefreshScope, @Primary.
Например, вы можете автоматически подключить компонент refreshEndpoint и применить refreshEndpoint.refresh() к прослушивателю.
Пометка пользовательского RouteLocator как основного вызовет проблемы, поскольку в zuul уже есть компонент того же типа, помеченный как основной.