Unplanned refresh routes when use Spring Eureka Client in Spring Cloud Gateway

huangapple go评论62阅读模式
英文:

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({&quot;ui&quot;, &quot;internal&quot;, &quot;rec&quot;})
@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&lt;ApplicationEvent&gt; {

	private final ApplicationEventPublisher publisher;

	private HeartbeatMonitor monitor = new HeartbeatMonitor();

	public RouteRefreshListener(ApplicationEventPublisher publisher) {
		Assert.notNull(publisher, &quot;publisher may not be null&quot;);
		this.publisher = publisher;
	}

	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		if (event instanceof ContextRefreshedEvent) {
			ContextRefreshedEvent refreshedEvent = (ContextRefreshedEvent) event;
			if (!WebServerApplicationContext.hasServerNamespace(
					refreshedEvent.getApplicationContext(), &quot;management&quot;)) {
				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 = &quot;org.springframework.cloud.client.discovery.event.HeartbeatMonitor&quot;)
	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(&quot;routeRefreshListener&quot;)) {
            return new RouteRefreshListenerCustom(publisher);
        } else {
            return bean;
        }
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}

huangapple
  • 本文由 发表于 2023年5月17日 18:04:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76270885.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定