Spring Cloud Ribbon
支持自定义的服务发现。服务发现时,可以实现自己的服务发现逻辑,可以配置一个或者多个服务的发现等等。
继承com.netflix.loadbalancer.AbstractServerList
实现自定义的服务发现获取方式,可以参考ribbon
默认的实现com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList
。
以一个需求为例,阐述如何实现和配置自定义的服务发现。
需求: 服务发现某个微服务,如果微服务不存在时,服务发现另一个微服务,伪装成未发现的微服务实例。
简单理解就是:服务发现微服务A
,如果找不到微服务A
的实例,服务发现微服务B
,把微服务B
发现的结果作为微服务A
的实例地址。
一个简单的实现方式: 复制com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList
代码并重命名。
...
public class ZeusDiscoveryEnabledNIWSServerList extends AbstractServerList<DiscoveryEnabledServer> {
...
private List<DiscoveryEnabledServer> obtainServersViaDiscovery() {
...
if (vipAddresses != null) {
...
}
// 实现自定义的服务发现逻辑
if (!serverList.isEmpty()) {
return serverList;
}
logger.warn("can not found service '{}' instance; Discover zeus instance as proxy service", vipAddresses);
// 服务发现自定义的微服务,假装为当前的微服务实例
client.getInstancesByVipAddress('custom-service-name', isSecure);
.stream()
.filter(i -> i.getStatus().equals(InstanceStatus.UP))
.map(i -> createServer(i, isSecure, shouldUseIpAddr))
.forEach(serverList::add);
if (!serverList.isEmpty()) {
logger.info("discover zeus instance count: {}", serverList.size());
}
return serverList;
}
...
}
增加配置类
...
import com.netflix.client.config.IClientConfig;
import com.netflix.discovery.EurekaClient;
import com.netflix.loadbalancer.ServerList;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.netflix.ribbon.RibbonClientName;
import org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.inject.Provider;
/**
* @author luobo.hwz on 2021/05/18 10:26 PM
*/
@Configuration
public class ZeusRibbonConfiguration {
//不需要修改
@Value("${ribbon.eureka.approximateZoneFromHostname:false}")
private boolean approximateZoneFromHostname = false;
// 不需要修改
@RibbonClientName
private String serviceId = "client";
// 创建上面自定义服务发现类的 Bean
@Bean
public ServerList<?> ribbonServerList(IClientConfig config, Provider<EurekaClient> eurekaClientProvider, ZeusDiscovery zeusDiscovery) {
ZeusDiscoveryEnabledNIWSServerList discoveryServerList = new ZeusDiscoveryEnabledNIWSServerList(config,
eurekaClientProvider, zeusDiscovery);
return new DomainExtractingServerList(discoveryServerList, config, this.approximateZoneFromHostname);
}
}
通过上述2
步,自定义的服务发现就实现了。上面的配置类是关键,SpringCloud Ribbon
会针对每个不同的微服务名,生成一个spring context
,每个context
都会生成上面配置类中的bean
,通过这种方式,将自定义的服务发现规则,配置到了ribbon
内。
ribbon
会定时调用该方法,从注册中心获取微服务地址。
上述代码实现的功能
微服务A
正常时的服务发现逻辑。
微服务A
找不到时,服务发现微服务B
,把结果作为微服务A
的实例地址。