英文:
Unplanned refresh routes when use Spring Eureka Client in Spring Cloud Gateway
问题
Your Gateway与Eureka服务发现相连。每当一个Gateway客户端在Eureka中刷新其状态时,Gateway中的所有路由都会被重建。这对我来说非常关键,因为我重新定义了路由定位器,并从另一个服务中下载我的路由。我如何禁用此行为或更改它?
@Profile({"ui", "internal", "rec"})
@Configuration
public class RouteConfiguration {
@Bean
@RefreshScope
public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder, RouteLoader routeLoader) {
return new RouteLocatorImpl(routeLocatorBuilder, routeLoader);
}
}
server.port=30037
spring.application.name=isf-gateway-rec
spring.cloud.loadbalancer.ribbon.enabled=false
eureka.client.service-url.defaultZone= http://127.0.0.1:30035/eureka/
configuration.server.url=http://127.0.0.1:30035
logging.level.root=DEBUG
spring.cloud.gateway.discovery.locator.enabled=false
gateway.load-route.path.all=/routes
EXECUTION_ENV=LOCAL
#Kafka
spring.kafka.bootstrap-servers=127.0.0.1:9092
gateway.kafka.topic=gateway-route-refresh
PARTITION_NUMBER=1
REPLICATION_FACTOR=1
FETCH_MAX_BYTES_CONFIG=5000000
MAX_PARTITION_FETCH_BYTES_CONFIG=5000000
#15 minutes
MAX_POLL_INTERVAL_MS=300000
CONSUMER_SESSION_TIMEOUT_MS=600000
HEARTBEAT_INTERVAL_MS=60000
整个问题涉及到org.springframework.cloud.gateway.route.RouteRefreshListener
。当Eureka客户端创建一个HeartbeatEvent
时,它会触发路由的重建,是否有一种方法可以覆盖此Bean?它没有实现接口((
public class RouteRefreshListener implements ApplicationListener<ApplicationEvent> {
private final ApplicationEventPublisher publisher;
private HeartbeatMonitor monitor = new HeartbeatMonitor();
public RouteRefreshListener(ApplicationEventPublisher publisher) {
Assert.notNull(publisher, "publisher may not be null");
this.publisher = publisher;
}
// ... (其他代码)
private void reset() {
this.publisher.publishEvent(new RefreshRoutesEvent(this));
}
}
@Bean
@ConditionalOnClass(
name = "org.springframework.cloud.client.discovery.event.HeartbeatMonitor")
public RouteRefreshListener routeRefreshListener(
ApplicationEventPublisher publisher) {
return new RouteRefreshListener(publisher);
}
我尝试使用属性,但没有帮助:
spring.cloud.gateway.discovery.locator.enabled=false
英文:
My Gateway is connected to Eureka Service Discovery. Every time a gateway client refresh its state in Eureka, all the routes in gateway are rebuilt. This is critical for me since I have redefined Route Locator and am downloading my routes from another service. How can I disable this behavior or change it?
@Profile({"ui", "internal", "rec"})
@Configuration
public class RouteConfiguration {
@Bean
@RefreshScope
public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder, RouteLoader routeLoader) {
return new RouteLocatorImpl(routeLocatorBuilder, routeLoader);
}
}
server.port=30037
spring.application.name=isf-gateway-rec
spring.cloud.loadbalancer.ribbon.enabled=false
eureka.client.service-url.defaultZone= http://127.0.0.1:30035/eureka/
configuration.server.url=http://127.0.0.1:30035
logging.level.root=DEBUG
spring.cloud.gateway.discovery.locator.enabled=false
gateway.load-route.path.all=/routes
EXECUTION_ENV=LOCAL
#Kafka
spring.kafka.bootstrap-servers=127.0.0.1:9092
gateway.kafka.topic=gateway-route-refresh
PARTITION_NUMBER=1
REPLICATION_FACTOR=1
FETCH_MAX_BYTES_CONFIG=5000000
MAX_PARTITION_FETCH_BYTES_CONFIG=5000000
#15 minutes
MAX_POLL_INTERVAL_MS=300000
CONSUMER_SESSION_TIMEOUT_MS=600000
HEARTBEAT_INTERVAL_MS=60000
The whole problem is org.springframework.cloud.gateway.route.RouteRefreshListener. When eureka client creates a HeartbeatEvent, it triggers the rebuilding of routes, is there any way to override this Bean? It does not implement the interface((
public class RouteRefreshListener implements ApplicationListener<ApplicationEvent> {
private final ApplicationEventPublisher publisher;
private HeartbeatMonitor monitor = new HeartbeatMonitor();
public RouteRefreshListener(ApplicationEventPublisher publisher) {
Assert.notNull(publisher, "publisher may not be null");
this.publisher = publisher;
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ContextRefreshedEvent) {
ContextRefreshedEvent refreshedEvent = (ContextRefreshedEvent) event;
if (!WebServerApplicationContext.hasServerNamespace(
refreshedEvent.getApplicationContext(), "management")) {
reset();
}
}
else if (event instanceof RefreshScopeRefreshedEvent
|| event instanceof InstanceRegisteredEvent) {
reset();
}
else if (event instanceof ParentHeartbeatEvent) {
ParentHeartbeatEvent e = (ParentHeartbeatEvent) event;
resetIfNeeded(e.getValue());
}
else if (event instanceof HeartbeatEvent) {
HeartbeatEvent e = (HeartbeatEvent) event;
resetIfNeeded(e.getValue());
}
}
private void resetIfNeeded(Object value) {
if (this.monitor.update(value)) {
reset();
}
}
private void reset() {
this.publisher.publishEvent(new RefreshRoutesEvent(this));
}
@Bean
@ConditionalOnClass(
name = "org.springframework.cloud.client.discovery.event.HeartbeatMonitor")
public RouteRefreshListener routeRefreshListener(
ApplicationEventPublisher publisher) {
return new RouteRefreshListener(publisher);
}
I tried using the property, but it didn't help
spring.cloud.gateway.discovery.locator.enabled=false
答案1
得分: 0
我用了BeanPostProcessor完成了这个。
@Component
public class GatewayPostProcessor implements BeanPostProcessor, Ordered {
private final ApplicationEventPublisher publisher;
public GatewayPostProcessor(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("routeRefreshListener")) {
return new RouteRefreshListenerCustom(publisher);
} else {
return bean;
}
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
}
英文:
I did it using the BeanPostProcessor
@Component
public class GatewayPostProcessor implements BeanPostProcessor, Ordered {
private final ApplicationEventPublisher publisher;
public GatewayPostProcessor(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("routeRefreshListener")) {
return new RouteRefreshListenerCustom(publisher);
} else {
return bean;
}
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论