diff --git a/settings.gradle.kts b/settings.gradle.kts index 35a0e30f..a82b8d5c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -14,8 +14,9 @@ include(":cosky-discovery") include(":cosky-bom") include(":cosky-dependencies") include(":cosky-spring-cloud-core") -include(":spring-cloud-starter-cosky-discovery") include(":spring-cloud-starter-cosky-config") +include(":spring-cloud-starter-cosky-discovery") +include(":spring-cloud-starter-cosky-discovery-ribbon") include(":cosky-rest-api") include(":cosky-mirror") @@ -27,3 +28,4 @@ buildscript { classpath("io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.30.0") } } + diff --git a/spring-cloud-starter-cosky-discovery-ribbon/src/main/java/me/ahoo/cosky/discovery/spring/cloud/discovery/ribbon/ConditionalOnCoskyRibbon.java b/spring-cloud-starter-cosky-discovery-ribbon/src/main/java/me/ahoo/cosky/discovery/spring/cloud/discovery/ribbon/ConditionalOnCoskyRibbon.java new file mode 100644 index 00000000..b79a3b6f --- /dev/null +++ b/spring-cloud-starter-cosky-discovery-ribbon/src/main/java/me/ahoo/cosky/discovery/spring/cloud/discovery/ribbon/ConditionalOnCoskyRibbon.java @@ -0,0 +1,17 @@ +package me.ahoo.cosky.discovery.spring.cloud.discovery.ribbon; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author ahoo wang + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD}) +@ConditionalOnProperty(value = "ribbon.cosky.enabled", matchIfMissing = true) +public @interface ConditionalOnCoskyRibbon { +} diff --git a/spring-cloud-starter-cosky-discovery-ribbon/src/main/java/me/ahoo/cosky/discovery/spring/cloud/discovery/ribbon/CoskyRibbonAutoConfiguration.java b/spring-cloud-starter-cosky-discovery-ribbon/src/main/java/me/ahoo/cosky/discovery/spring/cloud/discovery/ribbon/CoskyRibbonAutoConfiguration.java new file mode 100644 index 00000000..22abe37d --- /dev/null +++ b/spring-cloud-starter-cosky-discovery-ribbon/src/main/java/me/ahoo/cosky/discovery/spring/cloud/discovery/ribbon/CoskyRibbonAutoConfiguration.java @@ -0,0 +1,22 @@ +package me.ahoo.cosky.discovery.spring.cloud.discovery.ribbon; + +import me.ahoo.cosky.discovery.spring.cloud.discovery.ConditionalOnCoskyDiscoveryEnabled; +import me.ahoo.cosky.discovery.spring.cloud.discovery.CoskyDiscoveryAutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration; +import org.springframework.cloud.netflix.ribbon.RibbonClients; +import org.springframework.cloud.netflix.ribbon.SpringClientFactory; +import org.springframework.context.annotation.Configuration; + +/** + * @author ahoo wang + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnBean(SpringClientFactory.class) +@ConditionalOnCoskyRibbon +@ConditionalOnCoskyDiscoveryEnabled +@AutoConfigureAfter({RibbonAutoConfiguration.class, CoskyDiscoveryAutoConfiguration.class}) +@RibbonClients(defaultConfiguration = CoskyRibbonClientConfiguration.class) +public class CoskyRibbonAutoConfiguration { +} diff --git a/spring-cloud-starter-cosky-discovery-ribbon/src/main/java/me/ahoo/cosky/discovery/spring/cloud/discovery/ribbon/CoskyRibbonClientConfiguration.java b/spring-cloud-starter-cosky-discovery-ribbon/src/main/java/me/ahoo/cosky/discovery/spring/cloud/discovery/ribbon/CoskyRibbonClientConfiguration.java new file mode 100644 index 00000000..01ca8321 --- /dev/null +++ b/spring-cloud-starter-cosky-discovery-ribbon/src/main/java/me/ahoo/cosky/discovery/spring/cloud/discovery/ribbon/CoskyRibbonClientConfiguration.java @@ -0,0 +1,38 @@ +package me.ahoo.cosky.discovery.spring.cloud.discovery.ribbon; + +import com.netflix.client.config.IClientConfig; +import com.netflix.loadbalancer.ServerList; +import lombok.var; +import me.ahoo.cosky.discovery.ServiceDiscovery; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.cloud.netflix.ribbon.PropertiesFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author ahoo wang + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnCoskyRibbon +public class CoskyRibbonClientConfiguration { + + @Bean + @ConditionalOnMissingBean + public ServerList ribbonServerList(PropertiesFactory propertiesFactory, IClientConfig config, ServiceDiscovery serviceDiscovery) { + + if (propertiesFactory.isSet(ServerList.class, config.getClientName())) { + ServerList serverList = propertiesFactory.get(ServerList.class, config, + config.getClientName()); + return serverList; + } + var serverList = new CoskyServerList(serviceDiscovery); + serverList.initWithNiwsConfig(config); + return serverList; + } + + @Bean + @ConditionalOnMissingBean + public CoskyServerIntrospector coskyServerIntrospector() { + return new CoskyServerIntrospector(); + } +} diff --git a/spring-cloud-starter-cosky-discovery-ribbon/src/main/java/me/ahoo/cosky/discovery/spring/cloud/discovery/ribbon/CoskyServer.java b/spring-cloud-starter-cosky-discovery-ribbon/src/main/java/me/ahoo/cosky/discovery/spring/cloud/discovery/ribbon/CoskyServer.java new file mode 100644 index 00000000..debb793b --- /dev/null +++ b/spring-cloud-starter-cosky-discovery-ribbon/src/main/java/me/ahoo/cosky/discovery/spring/cloud/discovery/ribbon/CoskyServer.java @@ -0,0 +1,48 @@ +package me.ahoo.cosky.discovery.spring.cloud.discovery.ribbon; + +import com.netflix.loadbalancer.Server; +import me.ahoo.cosky.discovery.Instance; +import me.ahoo.cosky.discovery.ServiceInstance; + +/** + * @author ahoo wang + */ +public class CoskyServer extends Server { + private final ServiceInstance instance; + private final MetaInfo metaInfo; + + public CoskyServer(final ServiceInstance instance) { + super(instance.getSchema(), instance.getHost(), instance.getPort()); + this.instance = instance; + this.metaInfo = new MetaInfo() { + @Override + public String getAppName() { + return instance.getServiceId(); + } + + @Override + public String getServerGroup() { + return null; + } + + @Override + public String getServiceIdForDiscovery() { + return null; + } + + @Override + public String getInstanceId() { + return instance.getInstanceId(); + } + }; + } + + @Override + public MetaInfo getMetaInfo() { + return metaInfo; + } + + public ServiceInstance getInstance() { + return instance; + } +} diff --git a/spring-cloud-starter-cosky-discovery-ribbon/src/main/java/me/ahoo/cosky/discovery/spring/cloud/discovery/ribbon/CoskyServerIntrospector.java b/spring-cloud-starter-cosky-discovery-ribbon/src/main/java/me/ahoo/cosky/discovery/spring/cloud/discovery/ribbon/CoskyServerIntrospector.java new file mode 100644 index 00000000..a2ad36f1 --- /dev/null +++ b/spring-cloud-starter-cosky-discovery-ribbon/src/main/java/me/ahoo/cosky/discovery/spring/cloud/discovery/ribbon/CoskyServerIntrospector.java @@ -0,0 +1,28 @@ +package me.ahoo.cosky.discovery.spring.cloud.discovery.ribbon; + +import com.netflix.loadbalancer.Server; +import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector; + +import java.util.Map; + +/** + * @author ahoo wang + */ +public class CoskyServerIntrospector extends DefaultServerIntrospector { + + @Override + public boolean isSecure(Server server) { + if (server instanceof CoskyServer) { + return ((CoskyServer) server).getInstance().isSecure(); + } + return super.isSecure(server); + } + + @Override + public Map getMetadata(Server server) { + if (server instanceof CoskyServer) { + return ((CoskyServer) server).getInstance().getMetadata(); + } + return super.getMetadata(server); + } +} diff --git a/spring-cloud-starter-cosky-discovery-ribbon/src/main/java/me/ahoo/cosky/discovery/spring/cloud/discovery/ribbon/CoskyServerList.java b/spring-cloud-starter-cosky-discovery-ribbon/src/main/java/me/ahoo/cosky/discovery/spring/cloud/discovery/ribbon/CoskyServerList.java new file mode 100644 index 00000000..33832d02 --- /dev/null +++ b/spring-cloud-starter-cosky-discovery-ribbon/src/main/java/me/ahoo/cosky/discovery/spring/cloud/discovery/ribbon/CoskyServerList.java @@ -0,0 +1,52 @@ +package me.ahoo.cosky.discovery.spring.cloud.discovery.ribbon; + +import com.netflix.client.config.IClientConfig; +import com.netflix.loadbalancer.AbstractServerList; +import lombok.var; +import me.ahoo.cosky.core.util.Futures; +import me.ahoo.cosky.discovery.ServiceDiscovery; + +import java.time.Duration; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author ahoo wang + */ +public class CoskyServerList extends AbstractServerList { + private String serviceId; + private final ServiceDiscovery serviceDiscovery; + + public CoskyServerList(ServiceDiscovery serviceDiscovery) { + this.serviceDiscovery = serviceDiscovery; + } + + @Override + public void initWithNiwsConfig(IClientConfig iClientConfig) { + this.serviceId = iClientConfig.getClientName(); + } + + @Override + public List getInitialListOfServers() { + return getCoskyServers(); + } + + private List getCoskyServers() { + var getInstancesFuture = serviceDiscovery.getInstances(this.serviceId); + var instances = Futures.getUnChecked(getInstancesFuture, Duration.ofSeconds(2)); + if (instances.isEmpty()) { + Collections.emptyList(); + } + return instances.stream().map(instance -> new CoskyServer(instance)).collect(Collectors.toList()); + } + + /** + * Return updated list of servers. This is called say every 30 secs + * (configurable) by the Loadbalancer's Ping cycle + */ + @Override + public List getUpdatedListOfServers() { + return getCoskyServers(); + } +} diff --git a/spring-cloud-starter-cosky-discovery-ribbon/src/main/resources/META-INF/spring.factories b/spring-cloud-starter-cosky-discovery-ribbon/src/main/resources/META-INF/spring.factories new file mode 100644 index 00000000..ee22cc89 --- /dev/null +++ b/spring-cloud-starter-cosky-discovery-ribbon/src/main/resources/META-INF/spring.factories @@ -0,0 +1,4 @@ +# Auto Configuration +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +me.ahoo.cosky.discovery.spring.cloud.discovery.ribbon.CoskyRibbonAutoConfiguration +