Make Eureka into a CF service broker

This commit is contained in:
Dave Syer
2014-10-14 17:03:46 +01:00
parent 94aba20a13
commit 55bd2dd821
2 changed files with 54 additions and 47 deletions

View File

@@ -21,21 +21,31 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cloudfoundry.community.servicebroker.model.Catalog;
import org.cloudfoundry.community.servicebroker.model.ServiceDefinition;
import org.cloudfoundry.community.servicebroker.service.BeanCatalogService;
import org.cloudfoundry.community.servicebroker.service.CatalogService;
import org.springframework.cloud.cloudfoundry.broker.FreeServiceDefinitionFactory;
import org.springframework.cloud.netflix.eureka.advice.LeaseManagerLite;
import org.springframework.cloud.netflix.eureka.event.EurekaInstanceCanceledEvent;
import org.springframework.cloud.netflix.eureka.event.EurekaInstanceRegisteredEvent;
import org.springframework.cloud.netflix.eureka.event.EurekaInstanceRenewedEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.SmartApplicationListener;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.appinfo.InstanceInfo.ActionType;
import com.netflix.eureka.lease.LeaseManager;
import com.netflix.eureka.lease.Lease;
/**
* @author Dave Syer
*
*/
public class CatalogLeaseManager implements LeaseManager<InstanceInfo>, CatalogService {
public class CatalogLeaseManager implements CatalogService, LeaseManagerLite<InstanceInfo>, SmartApplicationListener {
private static Log logger = LogFactory.getLog(CatalogLeaseManager.class);
private Map<String, ServiceDefinition> definitions = new HashMap<String, ServiceDefinition>();
@@ -55,9 +65,49 @@ public class CatalogLeaseManager implements LeaseManager<InstanceInfo>, CatalogS
return new BeanCatalogService(getCatalog()).getServiceDefinition(serviceId);
}
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return EurekaInstanceRegisteredEvent.class.isAssignableFrom(eventType)
|| EurekaInstanceCanceledEvent.class.isAssignableFrom(eventType)
|| EurekaInstanceRenewedEvent.class.isAssignableFrom(eventType);
}
@Override
public int getOrder() {
return 0;
}
@Override
public boolean supportsSourceType(Class<?> sourceType) {
return true;
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof EurekaInstanceRegisteredEvent) {
EurekaInstanceRegisteredEvent registered = (EurekaInstanceRegisteredEvent) event;
register(registered.getInstanceInfo(), registered.isReplication());
}
else if (event instanceof EurekaInstanceCanceledEvent) {
EurekaInstanceCanceledEvent canceled = (EurekaInstanceCanceledEvent) event;
cancel(canceled.getAppName(), canceled.getServerId(), canceled.isReplication());
}
else if (event instanceof EurekaInstanceRenewedEvent) {
EurekaInstanceRenewedEvent renewed = (EurekaInstanceRenewedEvent) event;
renew(renewed.getAppName(), renewed.getServerId(), renewed.isReplication());
}
}
@Override
public void register(InstanceInfo info, boolean isReplication) {
register(info, Lease.DEFAULT_DURATION_IN_SECS, isReplication);
}
@Override
public void register(InstanceInfo info, int leaseDuration, boolean isReplication) {
logger.info("Registration request for: " + info.getAppName());
if (!definitions.containsKey(info.getAppName())) {
logger.info("Registering: " + info.getAppName());
ServiceDefinition definition = getServiceDefinition(info);
definitions.put(info.getAppName(), definition);
values.add(definition);
@@ -68,6 +118,7 @@ public class CatalogLeaseManager implements LeaseManager<InstanceInfo>, CatalogS
public boolean cancel(String appName, String id, boolean isReplication) {
ServiceDefinition definition = definitions.remove(appName);
if (definition != null) {
logger.info("Cancelling: " + appName);
values.remove(definition);
}
return true;
@@ -76,6 +127,7 @@ public class CatalogLeaseManager implements LeaseManager<InstanceInfo>, CatalogS
@Override
public boolean renew(String appName, String id, boolean isReplication) {
if (definitions.containsKey(appName)) {
logger.info("Renewing: " + appName);
definitions.get(appName).getMetadata()
.put("timestamp", System.currentTimeMillis());
}

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.cloud.cloudfoundry.broker.configuration;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;
@@ -27,7 +25,6 @@ import org.cloudfoundry.community.servicebroker.service.BeanCatalogService;
import org.cloudfoundry.community.servicebroker.service.CatalogService;
import org.cloudfoundry.community.servicebroker.service.ServiceInstanceBindingService;
import org.cloudfoundry.community.servicebroker.service.ServiceInstanceService;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
@@ -44,21 +41,15 @@ import org.springframework.cloud.cloudfoundry.broker.simple.SimpleServiceInstanc
import org.springframework.cloud.cloudfoundry.broker.simple.SimpleServiceInstanceRepository;
import org.springframework.cloud.cloudfoundry.broker.simple.SimpleServiceInstanceService;
import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration;
import org.springframework.cloud.netflix.eureka.advice.PiggybackMethodInterceptor;
import org.springframework.cloud.netflix.eureka.event.EurekaRegistryAvailableEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider;
import com.netflix.eureka.PeerAwareInstanceRegistry;
import com.netflix.eureka.lease.LeaseManager;
/**
@@ -157,42 +148,6 @@ public class ServiceBrokerAutoConfiguration {
}
@Configuration
@ConditionalOnClass(PeerAwareInstanceRegistry.class)
@ConditionalOnBean(EurekaInstanceConfig.class)
protected static class Initializer implements
ApplicationListener<EurekaRegistryAvailableEvent> {
@Autowired
private ApplicationContext applicationContext;
@Autowired
private CatalogLeaseManager leaseManager;
@Override
public void onApplicationEvent(EurekaRegistryAvailableEvent event) {
ProxyFactory factory = new ProxyFactory(
PeerAwareInstanceRegistry.getInstance());
factory.addAdvice(new PiggybackMethodInterceptor(leaseManager,
LeaseManager.class));
factory.setProxyTargetClass(true);
Field field = ReflectionUtils.findField(PeerAwareInstanceRegistry.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, factory.getProxy());
}
catch (Exception e) {
throw new IllegalStateException("Cannot modify instance registry", e);
}
}
}
@Bean
@ConditionalOnMissingBean(ServiceInstanceService.class)
public SimpleServiceInstanceService serviceInstanceService(