diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClientConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClientConfiguration.java index 6bc2747f..eb6d1c34 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClientConfiguration.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClientConfiguration.java @@ -19,6 +19,7 @@ import javax.annotation.PreDestroy; import com.netflix.appinfo.EurekaInstanceConfig; import com.netflix.appinfo.HealthCheckHandler; +import com.netflix.discovery.shared.EurekaJerseyClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -45,7 +46,9 @@ import com.netflix.appinfo.ApplicationInfoManager; import com.netflix.appinfo.InstanceInfo.InstanceStatus; import com.netflix.discovery.DiscoveryManager; import com.netflix.discovery.EurekaClientConfig; +import org.springframework.util.ReflectionUtils; +import java.lang.reflect.Field; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @@ -79,10 +82,29 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order @PreDestroy public void close() { + closeDiscoveryClientJersey(); logger.info("Removing application {} from eureka", instanceConfig.getAppname()); DiscoveryManager.getInstance().shutdownComponent(); } + private void closeDiscoveryClientJersey() { + logger.info("Closing DiscoveryClient.jerseyClient"); + Field jerseyClientField = ReflectionUtils.findField( + com.netflix.discovery.DiscoveryClient.class, + "discoveryJerseyClient", + EurekaJerseyClient.JerseyClient.class); + if (jerseyClientField != null) { + try { + jerseyClientField.setAccessible(true); + Object obj = jerseyClientField.get(DiscoveryManager.getInstance().getDiscoveryClient()); + EurekaJerseyClient.JerseyClient jerseyClient = (EurekaJerseyClient.JerseyClient) obj; + jerseyClient.destroyResources(); + } catch (Exception e) { + logger.error("Error closing DiscoveryClient.jerseyClient", e); + } + } + } + @Override public void start() { //only set the port if the nonSecurePort is 0 and this.port != 0 diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/servo/ServoMetricCollector.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/servo/ServoMetricCollector.java index d2d67326..8de0b7f0 100644 --- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/servo/ServoMetricCollector.java +++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/servo/ServoMetricCollector.java @@ -21,6 +21,8 @@ import java.util.Date; import java.util.List; import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.DisposableBean; import org.springframework.boot.actuate.metrics.Metric; import org.springframework.boot.actuate.metrics.reader.MetricReader; import org.springframework.boot.actuate.metrics.writer.MetricWriter; @@ -40,7 +42,8 @@ import com.netflix.servo.publish.PollScheduler; * @author Dave Syer * @author Christian Dupuis */ -public class ServoMetricCollector { +@Slf4j +public class ServoMetricCollector implements DisposableBean { public ServoMetricCollector(MetricWriter metrics) { List observers = new ArrayList(); @@ -55,6 +58,14 @@ public class ServoMetricCollector { PollScheduler.getInstance().addPoller(task, 5, TimeUnit.SECONDS); } + @Override + public void destroy() throws Exception { + log.info("Stopping Servo PollScheduler"); + if (PollScheduler.getInstance().isStarted()) { + PollScheduler.getInstance().stop(); + } + } + /** * {@link MetricObserver} to convert Servo metrics into Spring Boot {@link Metric} * instances.