Commit 1e716ff2 by Spencer Gibb

Upgrade eureka to v1.3.4

fixes gh-589
parent 55667497
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
<spring-cloud-stream.version>1.0.0.BUILD-SNAPSHOT</spring-cloud-stream.version> <spring-cloud-stream.version>1.0.0.BUILD-SNAPSHOT</spring-cloud-stream.version>
<main.basedir>${basedir}</main.basedir> <main.basedir>${basedir}</main.basedir>
<archaius.version>0.6.5</archaius.version> <archaius.version>0.6.5</archaius.version>
<eureka.version>1.2.5</eureka.version> <eureka.version>1.3.4</eureka.version>
<feign.version>8.11.0</feign.version> <feign.version>8.11.0</feign.version>
<hystrix.version>1.4.18</hystrix.version> <hystrix.version>1.4.18</hystrix.version>
<ribbon.version>2.1.0</ribbon.version> <ribbon.version>2.1.0</ribbon.version>
......
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.eureka;
import com.netflix.discovery.shared.transport.EurekaTransportConfig;
import lombok.Data;
/**
* @author Spencer Gibb
*/
@Data
public class CloudEurkeaTransportConfig implements EurekaTransportConfig {
private int sessionedClientReconnectIntervalSeconds = 20 * 60;
private double retryableClientQuarantineRefreshPercentage = 0.66;
private int bootstrapResolverRefreshIntervalSeconds = 5 * 60;
private int applicationsResolverDataStalenessThresholdSeconds = 5 * 60;
private int asyncResolverRefreshIntervalMs = 5 * 60 * 1000;
private int asyncResolverWarmUpTimeoutMs = 5000;
private int asyncExecutorThreadPoolSize = 5;
private String readClusterVip;
private boolean bootstrapResolverForQuery = true;
@Override
public boolean useBootstrapResolverForQuery() {
return this.bootstrapResolverForQuery;
}
}
...@@ -22,22 +22,30 @@ import java.util.HashMap; ...@@ -22,22 +22,30 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import lombok.Data; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.env.PropertyResolver;
import com.netflix.appinfo.EurekaAccept; import com.netflix.appinfo.EurekaAccept;
import com.netflix.discovery.EurekaClientConfig; import com.netflix.discovery.EurekaClientConfig;
import com.netflix.discovery.shared.transport.EurekaTransportConfig;
import lombok.Data;
/** /**
* @author Dave Syer * @author Dave Syer
*/ */
@Data @Data
@ConfigurationProperties("eureka.client") @ConfigurationProperties(EurekaClientConfigBean.PREFIX)
public class EurekaClientConfigBean implements EurekaClientConfig { public class EurekaClientConfigBean implements EurekaClientConfig, EurekaConstants {
public static final String PREFIX = "eureka.client";
@Autowired(required = false)
PropertyResolver propertyResolver;
public static final String DEFAULT_URL = "http://localhost:8761" public static final String DEFAULT_URL = "http://localhost:8761"
+ EurekaServerConfigBean.DEFAULT_PREFIX + "/"; + DEFAULT_PREFIX + "/";
public static final String DEFAULT_ZONE = "defaultZone"; public static final String DEFAULT_ZONE = "defaultZone";
...@@ -45,6 +53,8 @@ public class EurekaClientConfigBean implements EurekaClientConfig { ...@@ -45,6 +53,8 @@ public class EurekaClientConfigBean implements EurekaClientConfig {
private boolean enabled = true; private boolean enabled = true;
private EurekaTransportConfig transport = new CloudEurkeaTransportConfig();
private int registryFetchIntervalSeconds = 30; private int registryFetchIntervalSeconds = 30;
private int instanceInfoReplicationIntervalSeconds = 30; private int instanceInfoReplicationIntervalSeconds = 30;
...@@ -207,4 +217,17 @@ public class EurekaClientConfigBean implements EurekaClientConfig { ...@@ -207,4 +217,17 @@ public class EurekaClientConfigBean implements EurekaClientConfig {
return this.onDemandUpdateStatusChange; return this.onDemandUpdateStatusChange;
} }
@Override
public String getExperimental(String name) {
if (propertyResolver != null) {
return propertyResolver.getProperty(PREFIX + ".experimental." + name,
String.class, null);
}
return null;
}
@Override
public EurekaTransportConfig getTransportConfig() {
return getTransport();
}
} }
/* /*
* Copyright 2013-2014 the original author or authors. * Copyright 2013-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -14,16 +14,13 @@ ...@@ -14,16 +14,13 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.netflix.eureka.server.advice; package org.springframework.cloud.netflix.eureka;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.eureka.lease.LeaseManager;
/** /**
* @author Dave Syer * @author Spencer Gibb
*/ */
public interface LeaseManagerLite<T> extends LeaseManager<T> { public interface EurekaConstants {
void register(InstanceInfo info, boolean isReplication); String DEFAULT_PREFIX = "/eureka";
} }
...@@ -68,6 +68,10 @@ ...@@ -68,6 +68,10 @@
<groupId>com.netflix.archaius</groupId> <groupId>com.netflix.archaius</groupId>
<artifactId>archaius-core</artifactId> <artifactId>archaius-core</artifactId>
</dependency> </dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
</dependency>
<!-- Eureka deps that are now optional in eureka --> <!-- Eureka deps that are now optional in eureka -->
<dependency> <dependency>
<groupId>com.thoughtworks.xstream</groupId> <groupId>com.thoughtworks.xstream</groupId>
......
...@@ -27,6 +27,10 @@ import java.util.Map; ...@@ -27,6 +27,10 @@ import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import com.netflix.eureka.EurekaServerContext;
import com.netflix.eureka.EurekaServerContextHolder;
import com.netflix.eureka.registry.PeerAwareInstanceRegistry;
import com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
...@@ -39,7 +43,6 @@ import com.netflix.appinfo.InstanceInfo; ...@@ -39,7 +43,6 @@ import com.netflix.appinfo.InstanceInfo;
import com.netflix.config.ConfigurationManager; import com.netflix.config.ConfigurationManager;
import com.netflix.discovery.shared.Application; import com.netflix.discovery.shared.Application;
import com.netflix.discovery.shared.Pair; import com.netflix.discovery.shared.Pair;
import com.netflix.eureka.PeerAwareInstanceRegistryImpl;
import com.netflix.eureka.cluster.PeerEurekaNode; import com.netflix.eureka.cluster.PeerEurekaNode;
import com.netflix.eureka.resources.StatusResource; import com.netflix.eureka.resources.StatusResource;
import com.netflix.eureka.util.StatusInfo; import com.netflix.eureka.util.StatusInfo;
...@@ -78,19 +81,17 @@ public class EurekaController { ...@@ -78,19 +81,17 @@ public class EurekaController {
@RequestMapping(value = "/lastn", method = RequestMethod.GET) @RequestMapping(value = "/lastn", method = RequestMethod.GET)
public String lastn(HttpServletRequest request, Map<String, Object> model) { public String lastn(HttpServletRequest request, Map<String, Object> model) {
populateBase(request, model); populateBase(request, model);
PeerAwareInstanceRegistryImpl registery = PeerAwareInstanceRegistryImpl.getInstance(); PeerAwareInstanceRegistryImpl registry = (PeerAwareInstanceRegistryImpl) getRegistry();
ArrayList<Map<String, Object>> lastNCanceled = new ArrayList<>(); ArrayList<Map<String, Object>> lastNCanceled = new ArrayList<>();
List<Pair<Long, String>> list = registery.getLastNCanceledInstances(); List<Pair<Long, String>> list = registry.getLastNCanceledInstances();
for (Pair<Long, String> entry : list) { for (Pair<Long, String> entry : list) {
lastNCanceled.add(registeredInstance(entry.second(), entry.first() lastNCanceled.add(registeredInstance(entry.second(), entry.first()));
.longValue()));
} }
model.put("lastNCanceled", lastNCanceled); model.put("lastNCanceled", lastNCanceled);
list = registery.getLastNRegisteredInstances(); list = registry.getLastNRegisteredInstances();
ArrayList<Map<String, Object>> lastNRegistered = new ArrayList<>(); ArrayList<Map<String, Object>> lastNRegistered = new ArrayList<>();
for (Pair<Long, String> entry : list) { for (Pair<Long, String> entry : list) {
lastNRegistered.add(registeredInstance(entry.second(), entry.first() lastNRegistered.add(registeredInstance(entry.second(), entry.first()));
.longValue()));
} }
model.put("lastNRegistered", lastNRegistered); model.put("lastNRegistered", lastNRegistered);
return "eureka/lastn"; return "eureka/lastn";
...@@ -119,9 +120,9 @@ public class EurekaController { ...@@ -119,9 +120,9 @@ public class EurekaController {
.getDeploymentEnvironment()); .getDeploymentEnvironment());
model.put("datacenter", ConfigurationManager.getDeploymentContext() model.put("datacenter", ConfigurationManager.getDeploymentContext()
.getDeploymentDatacenter()); .getDeploymentDatacenter());
model.put("registry", PeerAwareInstanceRegistryImpl.getInstance()); PeerAwareInstanceRegistry registry = getRegistry();
model.put("isBelowRenewThresold", PeerAwareInstanceRegistryImpl.getInstance() model.put("registry", registry);
.isBelowRenewThresold() == 1); model.put("isBelowRenewThresold", registry.isBelowRenewThresold() == 1);
DataCenterInfo info = applicationInfoManager.getInfo().getDataCenterInfo(); DataCenterInfo info = applicationInfoManager.getInfo().getDataCenterInfo();
if (info.getName() == DataCenterInfo.Name.Amazon) { if (info.getName() == DataCenterInfo.Name.Amazon) {
AmazonInfo amazonInfo = (AmazonInfo) info; AmazonInfo amazonInfo = (AmazonInfo) info;
...@@ -133,10 +134,17 @@ public class EurekaController { ...@@ -133,10 +134,17 @@ public class EurekaController {
} }
} }
private PeerAwareInstanceRegistry getRegistry() {
return getServerContext().getRegistry();
}
private EurekaServerContext getServerContext() {
return EurekaServerContextHolder.getInstance().getServerContext();
}
private void populateNavbar(HttpServletRequest request, Map<String, Object> model) { private void populateNavbar(HttpServletRequest request, Map<String, Object> model) {
Map<String, String> replicas = new LinkedHashMap<>(); Map<String, String> replicas = new LinkedHashMap<>();
List<PeerEurekaNode> list = PeerAwareInstanceRegistryImpl.getInstance() List<PeerEurekaNode> list = getServerContext().getPeerEurekaNodes().getPeerNodesView();
.getReplicaNodes();
for (PeerEurekaNode node : list) { for (PeerEurekaNode node : list) {
try { try {
URI uri = new URI(node.getServiceUrl()); URI uri = new URI(node.getServiceUrl());
...@@ -151,8 +159,7 @@ public class EurekaController { ...@@ -151,8 +159,7 @@ public class EurekaController {
} }
private void populateApps(Map<String, Object> model) { private void populateApps(Map<String, Object> model) {
List<com.netflix.discovery.shared.Application> sortedApplications = PeerAwareInstanceRegistryImpl List<Application> sortedApplications = getRegistry().getSortedApplications();
.getInstance().getSortedApplications();
ArrayList<Map<String, Object>> apps = new ArrayList<>(); ArrayList<Map<String, Object>> apps = new ArrayList<>();
for (Application app : sortedApplications) { for (Application app : sortedApplications) {
LinkedHashMap<String, Object> appData = new LinkedHashMap<>(); LinkedHashMap<String, Object> appData = new LinkedHashMap<>();
...@@ -174,17 +181,17 @@ public class EurekaController { ...@@ -174,17 +181,17 @@ public class EurekaController {
} }
Integer count = amiCounts.get(ami); Integer count = amiCounts.get(ami);
if (count != null) { if (count != null) {
amiCounts.put(ami, Integer.valueOf(count.intValue() + 1)); amiCounts.put(ami, count + 1);
} }
else { else {
amiCounts.put(ami, Integer.valueOf(1)); amiCounts.put(ami, 1);
} }
count = zoneCounts.get(zone); count = zoneCounts.get(zone);
if (count != null) { if (count != null) {
zoneCounts.put(zone, Integer.valueOf(count.intValue() + 1)); zoneCounts.put(zone, count + 1);
} }
else { else {
zoneCounts.put(zone, Integer.valueOf(1)); zoneCounts.put(zone, 1);
} }
List<Pair<String, String>> list = instancesByStatus.get(status); List<Pair<String, String>> list = instancesByStatus.get(status);
if (list == null) { if (list == null) {
......
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.eureka.server;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.config.ConfigurationManager;
import com.netflix.discovery.EurekaClientConfig;
import com.netflix.discovery.converters.JsonXStream;
import com.netflix.discovery.converters.XmlXStream;
import com.netflix.eureka.EurekaBootStrap;
import com.netflix.eureka.EurekaServerConfig;
import com.netflix.eureka.EurekaServerContext;
import com.netflix.eureka.EurekaServerContextHolder;
import com.netflix.eureka.V1AwareInstanceInfoConverter;
import com.netflix.eureka.aws.AwsBinderDelegate;
import com.netflix.eureka.registry.PeerAwareInstanceRegistry;
import com.netflix.eureka.util.EurekaMonitors;
import com.thoughtworks.xstream.XStream;
import lombok.extern.apachecommons.CommonsLog;
/**
* @author Spencer Gibb
*/
@CommonsLog
public class EurekaServerBootstrap extends EurekaBootStrap {
private static final String TEST = "test";
private static final String ARCHAIUS_DEPLOYMENT_ENVIRONMENT = "archaius.deployment.environment";
private static final String EUREKA_ENVIRONMENT = "eureka.environment";
private static final String DEFAULT = "default";
private static final String ARCHAIUS_DEPLOYMENT_DATACENTER = "archaius.deployment.datacenter";
private static final String EUREKA_DATACENTER = "eureka.datacenter";
private EurekaServerConfig eurekaServerConfig;
private ApplicationInfoManager applicationInfoManager;
private EurekaClientConfig eurekaClientConfig;
private PeerAwareInstanceRegistry registry;
public EurekaServerBootstrap(ApplicationInfoManager applicationInfoManager, EurekaClientConfig eurekaClientConfig, EurekaServerConfig eurekaServerConfig, PeerAwareInstanceRegistry registry, EurekaServerContext serverContext) {
this.applicationInfoManager = applicationInfoManager;
this.eurekaClientConfig = eurekaClientConfig;
this.eurekaServerConfig = eurekaServerConfig;
this.registry = registry;
this.serverContext = serverContext;
}
@Override
public void contextInitialized(ServletContextEvent event) {
//NO-OP so it doesn't get initialzed by servlet container, we want spring to init
}
@Override
public void contextDestroyed(ServletContextEvent event) {
//NO-OP so it doesn't get destroyed by servlet container, we want spring to destroy
}
public void contextInitialized(ServletContext context) {
try {
initEurekaEnvironment();
initEurekaServerContext();
context.setAttribute(EurekaServerContext.class.getName(), serverContext);
} catch (Throwable e) {
log.error("Cannot bootstrap eureka server :", e);
throw new RuntimeException("Cannot bootstrap eureka server :", e);
}
}
public void contextDestroyed(ServletContext context) {
try {
log.info("Shutting down Eureka Server..");
context.removeAttribute(EurekaServerContext.class.getName());
destroyEurekaServerContext();
destroyEurekaEnvironment();
} catch (Throwable e) {
log.error("Error shutting down eureka", e);
}
log.info("Eureka Service is now shutdown...");
}
@Override
protected void initEurekaEnvironment() throws Exception {
log.info("Setting the eureka configuration..");
String dataCenter = ConfigurationManager.getConfigInstance().getString(EUREKA_DATACENTER);
if (dataCenter == null) {
log.info("Eureka data center value eureka.datacenter is not set, defaulting to default");
ConfigurationManager.getConfigInstance().setProperty(ARCHAIUS_DEPLOYMENT_DATACENTER, DEFAULT);
} else {
ConfigurationManager.getConfigInstance().setProperty(ARCHAIUS_DEPLOYMENT_DATACENTER, dataCenter);
}
String environment = ConfigurationManager.getConfigInstance().getString(EUREKA_ENVIRONMENT);
if (environment == null) {
ConfigurationManager.getConfigInstance().setProperty(ARCHAIUS_DEPLOYMENT_ENVIRONMENT, TEST);
log.info("Eureka environment value eureka.environment is not set, defaulting to test");
}
}
@Override
protected void initEurekaServerContext() throws Exception {
// For backward compatibility
JsonXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(), XStream.PRIORITY_VERY_HIGH);
XmlXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(), XStream.PRIORITY_VERY_HIGH);
if (isAws(applicationInfoManager.getInfo())) {
awsBinder = new AwsBinderDelegate(eurekaServerConfig, eurekaClientConfig, registry, applicationInfoManager);
awsBinder.start();
}
EurekaServerContextHolder.initialize(serverContext);
log.info("Initialized server context");
// Copy registry from neighboring eureka node
int registryCount = registry.syncUp();
registry.openForTraffic(applicationInfoManager, registryCount);
// Register all monitoring statistics.
EurekaMonitors.registerAllStats();
}
}
/* /*
* Copyright 2013-2014 the original author or authors. * Copyright 2013-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -14,30 +14,38 @@ ...@@ -14,30 +14,38 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.netflix.eureka; package org.springframework.cloud.netflix.eureka.server;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import com.netflix.eureka.aws.AwsBindingStrategy;
import lombok.Data; import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import com.netflix.eureka.EurekaServerConfig; import com.netflix.eureka.EurekaServerConfig;
import org.springframework.cloud.netflix.eureka.EurekaConstants;
import org.springframework.core.env.PropertyResolver;
/** /**
* @author Dave Syer * @author Dave Syer
*/ */
@Data @Data
@ConfigurationProperties("eureka.server") @ConfigurationProperties(EurekaServerConfigBean.PREFIX)
public class EurekaServerConfigBean implements EurekaServerConfig { public class EurekaServerConfigBean implements EurekaServerConfig, EurekaConstants {
public static final String DEFAULT_PREFIX = "/eureka"; public static final String PREFIX = "eureka.server";
private static final int MINUTES = 60 * 1000; private static final int MINUTES = 60 * 1000;
@Autowired(required = false)
PropertyResolver propertyResolver;
private String aWSAccessId; private String aWSAccessId;
private String aWSSecretKey; private String aWSSecretKey;
...@@ -46,6 +54,8 @@ public class EurekaServerConfigBean implements EurekaServerConfig { ...@@ -46,6 +54,8 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
private int eIPBindingRetryIntervalMs = 5 * MINUTES; private int eIPBindingRetryIntervalMs = 5 * MINUTES;
private int eIPBindingRetryIntervalMsWhenUnbound = 1 * MINUTES;
private boolean enableSelfPreservation = true; private boolean enableSelfPreservation = true;
private double renewalPercentThreshold = 0.85; private double renewalPercentThreshold = 0.85;
...@@ -100,7 +110,10 @@ public class EurekaServerConfigBean implements EurekaServerConfig { ...@@ -100,7 +110,10 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
private boolean syncWhenTimestampDiffers = true; private boolean syncWhenTimestampDiffers = true;
private int registrySyncRetries = 5; //TODO: what should these defaults be? for single first?
private int registrySyncRetries = 0;
private long registrySyncRetryWaitMs = 30 * 1000;
private int maxElementsInPeerReplicationPool = 10000; private int maxElementsInPeerReplicationPool = 10000;
...@@ -128,7 +141,7 @@ public class EurekaServerConfigBean implements EurekaServerConfig { ...@@ -128,7 +141,7 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
private boolean gZipContentFromRemoteRegion = true; private boolean gZipContentFromRemoteRegion = true;
private Map<String, String> remoteRegionUrlsWithName = new HashMap<String, String>(); private Map<String, String> remoteRegionUrlsWithName = new HashMap<>();
private String[] remoteRegionUrls; private String[] remoteRegionUrls;
...@@ -168,6 +181,14 @@ public class EurekaServerConfigBean implements EurekaServerConfig { ...@@ -168,6 +181,14 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
private String xmlCodecName; private String xmlCodecName;
private int route53BindRebindRetries = 3;
private int route53BindingRetryIntervalMs = 5 * MINUTES;
private long route53DomainTTL = 30;
private AwsBindingStrategy bindingStrategy = AwsBindingStrategy.EIP;
@Override @Override
public boolean shouldEnableSelfPreservation() { public boolean shouldEnableSelfPreservation() {
return this.enableSelfPreservation; return this.enableSelfPreservation;
...@@ -238,4 +259,13 @@ public class EurekaServerConfigBean implements EurekaServerConfig { ...@@ -238,4 +259,13 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
public boolean shouldEnableReplicatedRequestCompression() { public boolean shouldEnableReplicatedRequestCompression() {
return this.enableReplicatedRequestCompression; return this.enableReplicatedRequestCompression;
} }
@Override
public String getExperimental(String name) {
if (propertyResolver != null) {
return propertyResolver.getProperty(PREFIX + ".experimental." + name,
String.class, null);
}
return null;
}
} }
...@@ -28,13 +28,14 @@ import javax.ws.rs.ext.Provider; ...@@ -28,13 +28,14 @@ import javax.ws.rs.ext.Provider;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.HttpEncodingProperties;
import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.actuator.HasFeatures; import org.springframework.cloud.client.actuator.HasFeatures;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EurekaServerConfigBean;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -47,6 +48,15 @@ import org.springframework.util.ClassUtils; ...@@ -47,6 +48,15 @@ import org.springframework.util.ClassUtils;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.netflix.appinfo.ApplicationInfoManager; import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.EurekaClientConfig;
import com.netflix.eureka.DefaultEurekaServerContext;
import com.netflix.eureka.EurekaServerConfig;
import com.netflix.eureka.EurekaServerContext;
import com.netflix.eureka.cluster.PeerEurekaNodes;
import com.netflix.eureka.registry.PeerAwareInstanceRegistry;
import com.netflix.eureka.resources.DefaultServerCodecs;
import com.netflix.eureka.resources.ServerCodecs;
import com.sun.jersey.api.core.DefaultResourceConfig; import com.sun.jersey.api.core.DefaultResourceConfig;
import com.sun.jersey.spi.container.servlet.ServletContainer; import com.sun.jersey.spi.container.servlet.ServletContainer;
...@@ -68,17 +78,82 @@ public class EurekaServerConfiguration extends WebMvcConfigurerAdapter { ...@@ -68,17 +78,82 @@ public class EurekaServerConfiguration extends WebMvcConfigurerAdapter {
@Autowired @Autowired
private ApplicationInfoManager applicationInfoManager; private ApplicationInfoManager applicationInfoManager;
@Autowired
private EurekaServerConfig eurekaServerConfig;
@Autowired
private EurekaClientConfig eurekaClientConfig;
@Autowired
private EurekaClient eurekaClient;
/*
* Setting expectedNumberOfRenewsPerMin to non-zero to ensure that even an isolated
* server can adjust its eviction policy to the number of registrations (when it's
* zero, even a successful registration won't reset the rate threshold in
* InstanceRegistry.register()).
*/
@Value("${eureka.server.expectedNumberOfRenewsPerMin:1}")
private int expectedNumberOfRenewsPerMin;
@Value("${eureka.server.defaultOpenForTrafficCount:1}")
private int defaultOpenForTrafficCount;
@Bean @Bean
public HasFeatures eurekaServerFeature() { public HasFeatures eurekaServerFeature() {
return HasFeatures.namedFeature("Eureka Server", EurekaServerConfiguration.class); return HasFeatures.namedFeature("Eureka Server", EurekaServerConfiguration.class);
} }
//TODO: is there a better way?
@Bean(name = "spring.http.encoding.CONFIGURATION_PROPERTIES")
public HttpEncodingProperties httpEncodingProperties() {
HttpEncodingProperties properties = new HttpEncodingProperties();
properties.setForce(false);
return properties;
}
@Bean @Bean
@ConditionalOnProperty(prefix = "eureka.dashboard", name = "enabled", matchIfMissing = true) @ConditionalOnProperty(prefix = "eureka.dashboard", name = "enabled", matchIfMissing = true)
public EurekaController eurekaController() { public EurekaController eurekaController() {
return new EurekaController(applicationInfoManager); return new EurekaController(applicationInfoManager);
} }
@Bean
public ServerCodecs serverCodecs() {
return new DefaultServerCodecs(eurekaServerConfig);
}
@Bean
public PeerAwareInstanceRegistry peerAwareInstanceRegistry(ServerCodecs serverCodecs) {
eurekaClient.getApplications(); // force initialization
expectedNumberOfRenewsPerMin = 1;
defaultOpenForTrafficCount = 1;
return new InstanceRegistry(eurekaServerConfig, eurekaClientConfig, serverCodecs,
eurekaClient, expectedNumberOfRenewsPerMin, defaultOpenForTrafficCount);
}
@Bean
public PeerEurekaNodes peerEurekaNodes(PeerAwareInstanceRegistry registry,
ServerCodecs serverCodecs) {
return new PeerEurekaNodes(registry, eurekaServerConfig, eurekaClientConfig,
serverCodecs, applicationInfoManager);
}
@Bean
public EurekaServerContext eurekaServerContext(ServerCodecs serverCodecs,
PeerAwareInstanceRegistry registry,
PeerEurekaNodes peerEurekaNodes) {
return new DefaultEurekaServerContext(eurekaServerConfig, serverCodecs, registry,
peerEurekaNodes, applicationInfoManager);
}
@Bean
public EurekaServerBootstrap eurekaServerBootstrap(PeerAwareInstanceRegistry registry,
EurekaServerContext serverContext) {
return new EurekaServerBootstrap(applicationInfoManager, eurekaClientConfig,
eurekaServerConfig, registry, serverContext);
}
/** /**
* Register the Jersey filter * Register the Jersey filter
* *
......
...@@ -16,58 +16,33 @@ ...@@ -16,58 +16,33 @@
package org.springframework.cloud.netflix.eureka.server; package org.springframework.cloud.netflix.eureka.server;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextEvent;
import org.aopalliance.intercept.MethodInterceptor; import lombok.extern.apachecommons.CommonsLog;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.logging.log4j.Log4JLoggingSystem;
import org.springframework.cloud.netflix.eureka.EurekaServerConfigBean;
import org.springframework.cloud.netflix.eureka.server.advice.LeaseManagerLite;
import org.springframework.cloud.netflix.eureka.server.advice.PiggybackMethodInterceptor;
import org.springframework.cloud.netflix.eureka.server.event.EurekaRegistryAvailableEvent; import org.springframework.cloud.netflix.eureka.server.event.EurekaRegistryAvailableEvent;
import org.springframework.cloud.netflix.eureka.server.event.EurekaServerStartedEvent; import org.springframework.cloud.netflix.eureka.server.event.EurekaServerStartedEvent;
import org.springframework.cloud.netflix.eureka.server.event.LeaseManagerMessageBroker;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener; import org.springframework.context.ApplicationEvent;
import org.springframework.context.SmartLifecycle; import org.springframework.context.SmartLifecycle;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.context.ServletContextAware; import org.springframework.web.context.ServletContextAware;
import com.netflix.discovery.EurekaClient;
import com.netflix.eureka.AbstractInstanceRegistry;
import com.netflix.eureka.EurekaBootStrap;
import com.netflix.eureka.EurekaServerConfig; import com.netflix.eureka.EurekaServerConfig;
import com.netflix.eureka.EurekaServerConfigurationManager;
import com.netflix.eureka.PeerAwareInstanceRegistry;
import com.netflix.eureka.PeerAwareInstanceRegistryImpl;
/** /**
* @author Dave Syer * @author Dave Syer
*/ */
@Configuration @Configuration
@EnableConfigurationProperties(EurekaServerConfigBean.class) @EnableConfigurationProperties(EurekaServerConfigBean.class)
@CommonsLog
public class EurekaServerInitializerConfiguration public class EurekaServerInitializerConfiguration
implements ServletContextAware, SmartLifecycle, Ordered { implements ServletContextAware, SmartLifecycle, Ordered {
private static Log logger = LogFactory
.getLog(EurekaServerInitializerConfiguration.class);
@Autowired @Autowired
private EurekaServerConfig eurekaServerConfig; private EurekaServerConfig eurekaServerConfig;
...@@ -76,6 +51,9 @@ public class EurekaServerInitializerConfiguration ...@@ -76,6 +51,9 @@ public class EurekaServerInitializerConfiguration
@Autowired @Autowired
private ApplicationContext applicationContext; private ApplicationContext applicationContext;
@Autowired
private EurekaServerBootstrap eurekaServerBootstrap;
private boolean running; private boolean running;
private int order = 1; private int order = 1;
...@@ -91,46 +69,34 @@ public class EurekaServerInitializerConfiguration ...@@ -91,46 +69,34 @@ public class EurekaServerInitializerConfiguration
@Override @Override
public void run() { public void run() {
try { try {
new EurekaBootStrap() { //TODO: is this class even needed now?
@Override eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
protected void initEurekaEnvironment() { log.info("Started Eureka Server");
try {
if (System.getProperty("log4j.configuration") == null) { publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()));
System.setProperty("log4j.configuration",
new ClassPathResource("log4j.properties",
Log4JLoggingSystem.class).getURL()
.toString());
}
}
catch (IOException ex) {
// ignore
}
EurekaServerConfigurationManager.getInstance()
.setConfiguration(
EurekaServerInitializerConfiguration.this.eurekaServerConfig);
EurekaServerInitializerConfiguration.this.applicationContext
.publishEvent(new EurekaRegistryAvailableEvent(
EurekaServerInitializerConfiguration.this.eurekaServerConfig));
}
}.contextInitialized(new ServletContextEvent(
EurekaServerInitializerConfiguration.this.servletContext));
logger.info("Started Eureka Server");
EurekaServerInitializerConfiguration.this.running = true; EurekaServerInitializerConfiguration.this.running = true;
EurekaServerInitializerConfiguration.this.applicationContext publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
.publishEvent(new EurekaServerStartedEvent(
EurekaServerInitializerConfiguration.this.eurekaServerConfig));
} }
catch (Exception ex) { catch (Exception ex) {
// Help! // Help!
logger.error("Could not initialize Eureka servlet context", ex); log.error("Could not initialize Eureka servlet context", ex);
} }
} }
}).start(); }).start();
} }
private EurekaServerConfig getEurekaServerConfig() {
return this.eurekaServerConfig;
}
private void publish(ApplicationEvent event) {
this.applicationContext.publishEvent(event);
}
@Override @Override
public void stop() { public void stop() {
this.running = false; this.running = false;
eurekaServerBootstrap.contextDestroyed(this.servletContext);
} }
@Override @Override
...@@ -158,116 +124,4 @@ public class EurekaServerInitializerConfiguration ...@@ -158,116 +124,4 @@ public class EurekaServerInitializerConfiguration
return this.order; return this.order;
} }
@Configuration
@ConditionalOnClass(PeerAwareInstanceRegistry.class)
protected static class RegistryInstanceProxyInitializer
implements ApplicationListener<EurekaRegistryAvailableEvent> {
@Autowired(required = false)
private EurekaClient client;
private PeerAwareInstanceRegistryImpl instance;
@Bean
public LeaseManagerMessageBroker leaseManagerMessageBroker() {
return new LeaseManagerMessageBroker();
}
@Override
public void onApplicationEvent(EurekaRegistryAvailableEvent event) {
if (this.client != null) {
this.client.getApplications(); // force initialization
}
if (this.instance == null) {
this.instance = PeerAwareInstanceRegistryImpl.getInstance();
safeInit();
replaceInstance(getProxyForInstance());
expectRegistrations(1);
}
}
private void safeInit() {
Method method = ReflectionUtils.findMethod(AbstractInstanceRegistry.class,
"postInit");
ReflectionUtils.makeAccessible(method);
ReflectionUtils.invokeMethod(method, this.instance);
}
private void replaceInstance(Object proxy) {
Field field = ReflectionUtils.findField(PeerAwareInstanceRegistryImpl.class,
"instance");
try {
// Awful ugly hack to work around lack of DI in eureka
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
ReflectionUtils.setField(field, null, proxy);
}
catch (Exception ex) {
throw new IllegalStateException("Cannot modify instance registry", ex);
}
}
private Object getProxyForInstance() {
// Wrap the instance registry...
ProxyFactory factory = new ProxyFactory(this.instance);
// ...with the LeaseManagerMessageBroker
factory.addAdvice(new PiggybackMethodInterceptor(leaseManagerMessageBroker(),
LeaseManagerLite.class));
factory.addAdvice(new TrafficOpener());
factory.setProxyTargetClass(true);
return factory.getProxy();
}
private void expectRegistrations(int count) {
/*
* Setting expectedNumberOfRenewsPerMin to non-zero to ensure that even an
* isolated server can adjust its eviction policy to the number of
* registrations (when it's zero, even a successful registration won't reset
* the rate threshold in InstanceRegistry.register()).
*/
Field field = ReflectionUtils.findField(AbstractInstanceRegistry.class,
"expectedNumberOfRenewsPerMin");
try {
// Awful ugly hack to work around lack of DI in eureka
field.setAccessible(true);
int value = (int) ReflectionUtils.getField(field, this.instance);
if (value == 0 && count > 0) {
ReflectionUtils.setField(field, this.instance, count);
}
}
catch (Exception ex) {
throw new IllegalStateException(
"Cannot modify instance registry expected renews", ex);
}
}
/**
* Additional aspect for intercepting method invocations on
* PeerAwareInstanceRegistry. If
* {@link PeerAwareInstanceRegistryImpl#openForTraffic(int)} is called with a zero
* argument, it means that leases are not automatically cancelled if the instance
* hasn't sent any renewals recently. This happens for a standalone server. It
* seems like a bad default, so we set it to the smallest non-zero value we can,
* so that any instances that subsequently register can bump up the threshold.
*/
private class TrafficOpener implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
if ("openForTraffic".equals(invocation.getMethod().getName())) {
int count = (int) invocation.getArguments()[0];
ReflectionUtils.invokeMethod(invocation.getMethod(),
invocation.getThis(), count == 0 ? 1 : count);
return null;
}
return invocation.proceed();
}
}
}
} }
...@@ -14,29 +14,65 @@ ...@@ -14,29 +14,65 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cloud.netflix.eureka.server.event; package org.springframework.cloud.netflix.eureka.server;
import java.util.List; import java.util.List;
import lombok.extern.apachecommons.CommonsLog; import lombok.extern.apachecommons.CommonsLog;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.BeansException;
import org.springframework.cloud.netflix.eureka.server.advice.LeaseManagerLite; import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceCanceledEvent;
import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRegisteredEvent;
import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRenewedEvent;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.appinfo.InstanceInfo; import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.EurekaClientConfig;
import com.netflix.discovery.shared.Application; import com.netflix.discovery.shared.Application;
import com.netflix.eureka.PeerAwareInstanceRegistryImpl; import com.netflix.eureka.EurekaServerConfig;
import com.netflix.eureka.lease.Lease; import com.netflix.eureka.lease.Lease;
import com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl;
import com.netflix.eureka.resources.ServerCodecs;
/** /**
* @author Spencer Gibb * @author Spencer Gibb
*/ */
@CommonsLog @CommonsLog
public class LeaseManagerMessageBroker implements LeaseManagerLite<InstanceInfo> { public class InstanceRegistry extends PeerAwareInstanceRegistryImpl implements ApplicationContextAware {
@Autowired
private ApplicationContext ctxt; private ApplicationContext ctxt;
private int defaultOpenForTrafficCount;
public InstanceRegistry(EurekaServerConfig serverConfig,
EurekaClientConfig clientConfig, ServerCodecs serverCodecs,
EurekaClient eurekaClient, int expectedNumberOfRenewsPerMin, int defaultOpenForTrafficCount) {
super(serverConfig, clientConfig, serverCodecs, eurekaClient);
this.expectedNumberOfRenewsPerMin = expectedNumberOfRenewsPerMin;
this.defaultOpenForTrafficCount = defaultOpenForTrafficCount;
}
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
this.ctxt = context;
}
/**
* If {@link PeerAwareInstanceRegistryImpl#openForTraffic(ApplicationInfoManager, int)}
* is called with a zero * argument, it means that leases are not
* automatically * cancelled if the instance * hasn't sent any renewals
* recently. This happens for a standalone server. It seems like a bad
* default, so we set it to the smallest non-zero value we can, so that any
* instances that subsequently register can bump up the threshold.
*/
@Override
public void openForTraffic(ApplicationInfoManager applicationInfoManager, int count) {
super.openForTraffic(applicationInfoManager, count == 0 ? defaultOpenForTrafficCount : count);
}
@Override @Override
public void register(InstanceInfo info, boolean isReplication) { public void register(InstanceInfo info, boolean isReplication) {
...@@ -45,35 +81,31 @@ public class LeaseManagerMessageBroker implements LeaseManagerLite<InstanceInfo> ...@@ -45,35 +81,31 @@ public class LeaseManagerMessageBroker implements LeaseManagerLite<InstanceInfo>
@Override @Override
public void register(InstanceInfo info, int leaseDuration, boolean isReplication) { public void register(InstanceInfo info, int leaseDuration, boolean isReplication) {
if (log.isDebugEnabled()) {
log.debug("register " + info.getAppName() + ", vip " + info.getVIPAddress() log.debug("register " + info.getAppName() + ", vip " + info.getVIPAddress()
+ ", leaseDuration " + leaseDuration + ", isReplication " + isReplication); + ", leaseDuration " + leaseDuration + ", isReplication " + isReplication);
}
// TODO: what to publish from info (whole object?) // TODO: what to publish from info (whole object?)
this.ctxt.publishEvent(new EurekaInstanceRegisteredEvent(this, info, this.ctxt.publishEvent(new EurekaInstanceRegisteredEvent(this, info,
leaseDuration, isReplication)); leaseDuration, isReplication));
super.register(info, leaseDuration, isReplication);
} }
@Override @Override
public boolean cancel(String appName, String serverId, boolean isReplication) { public boolean cancel(String appName, String serverId, boolean isReplication) {
if (log.isDebugEnabled()) {
log.debug("cancel " + appName + " serverId " + serverId + ", isReplication {}" log.debug("cancel " + appName + " serverId " + serverId + ", isReplication {}"
+ isReplication); + isReplication);
}
this.ctxt.publishEvent(new EurekaInstanceCanceledEvent(this, appName, serverId, this.ctxt.publishEvent(new EurekaInstanceCanceledEvent(this, appName, serverId,
isReplication)); isReplication));
return false;
return super.cancel(appName, serverId, isReplication);
} }
@Override @Override
public boolean renew(final String appName, final String serverId, public boolean renew(final String appName, final String serverId,
boolean isReplication) { boolean isReplication) {
if (log.isDebugEnabled()) {
log.debug("renew " + appName + " serverId " + serverId + ", isReplication {}" log.debug("renew " + appName + " serverId " + serverId + ", isReplication {}"
+ isReplication); + isReplication);
} List<Application> applications = getSortedApplications();
List<Application> applications = PeerAwareInstanceRegistryImpl.getInstance()
.getSortedApplications();
for (Application input : applications) { for (Application input : applications) {
if (input.getName().equals(appName)) { if (input.getName().equals(appName)) {
InstanceInfo instance = null; InstanceInfo instance = null;
...@@ -88,11 +120,6 @@ public class LeaseManagerMessageBroker implements LeaseManagerLite<InstanceInfo> ...@@ -88,11 +120,6 @@ public class LeaseManagerMessageBroker implements LeaseManagerLite<InstanceInfo>
break; break;
} }
} }
return false; return super.renew(appName, serverId, isReplication);
} }
@Override
public void evict() {
}
} }
/*
* Copyright 2013-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.eureka.server.advice;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.util.ReflectionUtils;
/**
* @author Dave Syer
*/
public class PiggybackMethodInterceptor implements MethodInterceptor {
private Object delegate;
private Class<?>[] types;
public PiggybackMethodInterceptor(Object delegate, Class<?>... types) {
this.delegate = delegate;
this.types = types;
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Object result = invocation.proceed();
invokeAfter(invocation.getMethod(), invocation.getArguments());
return result;
}
private void invokeAfter(Method method, Object[] arguments) throws Exception {
for (Class<?> type : this.types) {
Method target = getTarget(type, method);
if (target != null) {
target.invoke(this.delegate, arguments);
return;
}
}
}
private Method getTarget(Class<?> type, Method method) {
Method target = ReflectionUtils.findMethod(type, method.getName(),
method.getParameterTypes());
return target;
}
}
/*
* Copyright 2012-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.eureka.server;
import java.io.IOException;
import org.apache.log4j.Logger;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggingInitializationContext;
import org.springframework.boot.logging.log4j.Log4JLoggingSystem;
import org.springframework.boot.test.OutputCapture;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.StringUtils;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
/**
* Tests for {@link Log4JLoggingSystem}.
*
* @author Phillip Webb
*/
public class Log4JLoggingSystemTests {
@Rule
public OutputCapture output = new OutputCapture();
private final Log4JLoggingSystem loggingSystem = new Log4JLoggingSystem(getClass()
.getClassLoader());
private Logger logger;
@Before
public void setup() throws IOException {
System.setProperty("log4j.configuration", new ClassPathResource(
"log4j.properties", Log4JLoggingSystem.class).getURL().toString());
this.logger = Logger.getLogger(getClass());
}
@Test
@Ignore("gh-48")
public void setLevel() throws Exception {
this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize(new LoggingInitializationContext(
new StandardEnvironment()), null, null);
this.logger.debug("Hello");
this.loggingSystem.setLogLevel("org.springframework.cloud", LogLevel.DEBUG);
this.logger.debug("Hello");
assertThat(StringUtils.countOccurrencesOf(this.output.toString(), "Hello"),
equalTo(1));
}
}
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