Refresh health indicator for config server if present
Listen for heartbeats from discovery so that state changes can trigger a new status (and the client doesn't rely on the old address of the server if it has now changed). Fixes gh-232
This commit is contained in:
@@ -22,15 +22,16 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.event.HeartbeatEvent;
|
||||
import org.springframework.cloud.client.discovery.event.HeartbeatMonitor;
|
||||
import org.springframework.cloud.config.client.ConfigClientProperties;
|
||||
import org.springframework.cloud.config.client.ConfigServicePropertySourceLocator;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.context.event.SmartApplicationListener;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.discovery.DiscoveryClient;
|
||||
@@ -48,7 +49,9 @@ import com.netflix.discovery.DiscoveryClient;
|
||||
@Import(EurekaClientAutoConfiguration.class)
|
||||
@CommonsLog
|
||||
public class DiscoveryClientConfigServiceBootstrapConfiguration implements
|
||||
ApplicationListener<ContextRefreshedEvent> {
|
||||
SmartApplicationListener {
|
||||
|
||||
private HeartbeatMonitor monitor = new HeartbeatMonitor();
|
||||
|
||||
@Autowired
|
||||
private DiscoveryClient client;
|
||||
@@ -57,14 +60,36 @@ public class DiscoveryClientConfigServiceBootstrapConfiguration implements
|
||||
private ConfigClientProperties config;
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
public void onApplicationEvent(ApplicationEvent event) {
|
||||
if (event instanceof ContextRefreshedEvent) {
|
||||
refresh();
|
||||
}
|
||||
else if (event instanceof HeartbeatEvent) {
|
||||
if (this.monitor.update(((HeartbeatEvent) event).getValue())) {
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
|
||||
return ContextRefreshedEvent.class.isAssignableFrom(eventType)
|
||||
|| HeartbeatEvent.class.isAssignableFrom(eventType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsSourceType(Class<?> sourceType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void refresh() {
|
||||
try {
|
||||
log.info("Locating configserver via discovery");
|
||||
Environment environment = event.getApplicationContext().getEnvironment();
|
||||
if (!(environment instanceof ConfigurableEnvironment)) {
|
||||
log.info("Environment is not ConfigurableEnvironment so cannot look up configserver");
|
||||
return;
|
||||
}
|
||||
InstanceInfo server = this.client.getNextServerFromEureka(this.config
|
||||
.getDiscovery().getServiceId(), false);
|
||||
String url = server.getHomePageUrl();
|
||||
|
||||
@@ -24,7 +24,17 @@ import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.netflix.client.config.DefaultClientConfigImpl;
|
||||
import com.netflix.client.config.IClientConfig;
|
||||
import com.netflix.loadbalancer.*;
|
||||
import com.netflix.loadbalancer.ConfigurationBasedServerList;
|
||||
import com.netflix.loadbalancer.ILoadBalancer;
|
||||
import com.netflix.loadbalancer.IPing;
|
||||
import com.netflix.loadbalancer.IRule;
|
||||
import com.netflix.loadbalancer.LoadBalancerBuilder;
|
||||
import com.netflix.loadbalancer.NoOpPing;
|
||||
import com.netflix.loadbalancer.Server;
|
||||
import com.netflix.loadbalancer.ServerList;
|
||||
import com.netflix.loadbalancer.ServerListFilter;
|
||||
import com.netflix.loadbalancer.ZoneAvoidanceRule;
|
||||
import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
|
||||
import com.netflix.niws.client.http.RestClient;
|
||||
import com.netflix.servo.monitor.Monitors;
|
||||
|
||||
@@ -85,15 +95,11 @@ public class RibbonClientConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ILoadBalancer ribbonLoadBalancer(IClientConfig config,
|
||||
ServerList<Server> serverList,
|
||||
ServerListFilter<Server> serverListFilter,
|
||||
ServerList<Server> serverList, ServerListFilter<Server> serverListFilter,
|
||||
IRule rule, IPing ping) {
|
||||
ZoneAwareLoadBalancer<Server> balancer = LoadBalancerBuilder.newBuilder()
|
||||
.withClientConfig(config)
|
||||
.withRule(rule)
|
||||
.withPing(ping)
|
||||
.withServerListFilter(serverListFilter)
|
||||
.withDynamicServerList(serverList)
|
||||
.withClientConfig(config).withRule(rule).withPing(ping)
|
||||
.withServerListFilter(serverListFilter).withDynamicServerList(serverList)
|
||||
.buildDynamicServerListLoadBalancer();
|
||||
return balancer;
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.cloud.netflix.zuul;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.trace.TraceRepository;
|
||||
@@ -25,6 +23,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.event.HeartbeatEvent;
|
||||
import org.springframework.cloud.client.discovery.event.HeartbeatMonitor;
|
||||
import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent;
|
||||
import org.springframework.cloud.client.discovery.event.ParentHeartbeatEvent;
|
||||
import org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent;
|
||||
@@ -121,7 +120,7 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
|
||||
private static class ZuulRefreshListener implements
|
||||
ApplicationListener<ApplicationEvent> {
|
||||
|
||||
private AtomicReference<Object> latestHeartbeat = new AtomicReference<>();
|
||||
private HeartbeatMonitor monitor = new HeartbeatMonitor();
|
||||
|
||||
@Autowired
|
||||
private ProxyRouteLocator routeLocator;
|
||||
@@ -148,9 +147,7 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
|
||||
}
|
||||
|
||||
private void resetIfNeeded(Object value) {
|
||||
if (this.latestHeartbeat.get() == null
|
||||
|| !this.latestHeartbeat.get().equals(value)) {
|
||||
this.latestHeartbeat.set(value);
|
||||
if (this.monitor.update(value)) {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user