Commit 0b8f8552 by Dave Syer

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
parent dafb5ecf
......@@ -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();
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment