DiscoveryClient
DiscoveryClient
接口定义了常见的服务发现操作,如获取服务实例、获取所有服务ID、验证客户端可用性等,通常用于 Eureka 或 Consul 等服务发现框架。
public interface DiscoveryClient extends Ordered {
/**
* Default order of the discovery client.
*/
int DEFAULT_ORDER = 0;
/**
* A human-readable description of the implementation, used in HealthIndicator.
* @return The description.
*/
String description();
/**
* Gets all ServiceInstances associated with a particular serviceId.
* @param serviceId The serviceId to query.
* @return A List of ServiceInstance.
*/
List<ServiceInstance> getInstances(String serviceId);
/**
* @return All known service IDs.
*/
List<String> getServices();
/**
* Can be used to verify the client is valid and able to make calls.
* <p>
* A successful invocation with no exception thrown implies the client is able to make
* calls.
* <p>
* The default implementation simply calls {@link #getServices()} - client
* implementations can override with a lighter weight operation if they choose to.
*/
default void probe() {
getServices();
}
/**
* Default implementation for getting order of discovery clients.
* @return order
*/
@Override
default int getOrder() {
return DEFAULT_ORDER;
}
}
Simple
1. SimpleDiscoveryClientAutoConfiguration
SimpleDiscoveryClientAutoConfiguration
是 Spring Boot 自动配置类,基于配置文件属性创建一个简单的服务发现客户端。
/**
* Spring Boot auto-configuration for simple properties-based discovery client.
*
* @author Biju Kunjummen
* @author Charu Covindane
*/
@Configuration(proxyBeanMethods = false)
@AutoConfigureBefore({ CommonsClientAutoConfiguration.class })
public class SimpleDiscoveryClientAutoConfiguration implements ApplicationListener<WebServerInitializedEvent> {
private ServerProperties server;
private InetUtils inet;
private int port = 0;
private SimpleDiscoveryProperties simple = new SimpleDiscoveryProperties();
@Autowired(required = false)
public void setServer(ServerProperties server) {
this.server = server;
}
@Autowired
public void setInet(InetUtils inet) {
this.inet = inet;
}
@Bean
@ConditionalOnMissingBean
public SimpleDiscoveryProperties simpleDiscoveryProperties(
@Value("${spring.application.name:application}") String serviceId) {
simple.getLocal().setServiceId(serviceId);
simple.getLocal().setHost(inet.findFirstNonLoopbackHostInfo().getHostname());
simple.getLocal().setPort(findPort());
return simple;
}
@Bean
@Order
public DiscoveryClient simpleDiscoveryClient(SimpleDiscoveryProperties properties) {
return new SimpleDiscoveryClient(properties);
}
private int findPort() {
if (port > 0) {
return port;
}
if (server != null && server.getPort() != null && server.getPort() > 0) {
return server.getPort();
}
return 8080;
}
@Override
public void onApplicationEvent(WebServerInitializedEvent webServerInitializedEvent) {
port = webServerInitializedEvent.getWebServer().getPort();
if (port > 0) {
simple.getLocal().setHost(inet.findFirstNonLoopbackHostInfo().getHostname());
simple.getLocal().setPort(port);
}
}
}
2. SimpleDiscoveryClient
SimpleDiscoveryClient
是一个简单的 DiscoveryClient
实现,使用属性文件作为服务实例的来源,提供获取服务实例和服务列表的功能。
/**
* A {@link org.springframework.cloud.client.discovery.DiscoveryClient} that will use the
* properties file as a source of service instances.
*
* @author Biju Kunjummen
* @author Olga Maciaszek-Sharma
* @author Charu Covindane
*/
public class SimpleDiscoveryClient implements DiscoveryClient {
private SimpleDiscoveryProperties simpleDiscoveryProperties;
public SimpleDiscoveryClient(SimpleDiscoveryProperties simpleDiscoveryProperties) {
this.simpleDiscoveryProperties = simpleDiscoveryProperties;
}
@Override
public String description() {
return "Simple Discovery Client";
}
@Override
public List<ServiceInstance> getInstances(String serviceId) {
List<ServiceInstance> serviceInstances = new ArrayList<>();
List<DefaultServiceInstance> serviceInstanceForService = this.simpleDiscoveryProperties.getInstances()
.get(serviceId);
if (serviceInstanceForService != null) {
serviceInstances.addAll(serviceInstanceForService);
}
return serviceInstances;
}
@Override
public List<String> getServices() {
return new ArrayList<>(this.simpleDiscoveryProperties.getInstances().keySet());
}
@Override
public int getOrder() {
return this.simpleDiscoveryProperties.getOrder();
}
}
Composite
1. CompositeDiscoveryClientAutoConfiguration
CompositeDiscoveryClientAutoConfiguration
是一个自动配置类,负责创建并注入 CompositeDiscoveryClient
,将多个 DiscoveryClient
合并成一个客户端。
/**
* Auto-configuration for composite discovery client.
*
* @author Biju Kunjummen
*/
@Configuration(proxyBeanMethods = false)
@AutoConfigureBefore(SimpleDiscoveryClientAutoConfiguration.class)
public class CompositeDiscoveryClientAutoConfiguration {
@Bean
@Primary
public CompositeDiscoveryClient compositeDiscoveryClient(List<DiscoveryClient> discoveryClients) {
return new CompositeDiscoveryClient(discoveryClients);
}
}
2. CompositeDiscoveryClient
CompositeDiscoveryClient
是一个将多个 DiscoveryClient
组合在一起的客户端,它依次查询各个客户端获取服务实例,确保高可用性和灵活性。
public class CompositeDiscoveryClient implements DiscoveryClient {
private final List<DiscoveryClient> discoveryClients;
public CompositeDiscoveryClient(List<DiscoveryClient> discoveryClients) {
AnnotationAwareOrderComparator.sort(discoveryClients);
this.discoveryClients = discoveryClients;
}
@Override
public String description() {
return "Composite Discovery Client";
}
@Override
public List<ServiceInstance> getInstances(String serviceId) {
if (this.discoveryClients != null) {
for (DiscoveryClient discoveryClient : this.discoveryClients) {
List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);
if (instances != null && !instances.isEmpty()) {
return instances;
}
}
}
return Collections.emptyList();
}
@Override
public List<String> getServices() {
LinkedHashSet<String> services = new LinkedHashSet<>();
if (this.discoveryClients != null) {
for (DiscoveryClient discoveryClient : this.discoveryClients) {
List<String> serviceForClient = discoveryClient.getServices();
if (serviceForClient != null) {
services.addAll(serviceForClient);
}
}
}
return new ArrayList<>(services);
}
@Override
public void probe() {
if (this.discoveryClients != null) {
for (DiscoveryClient discoveryClient : this.discoveryClients) {
discoveryClient.probe();
}
}
}
public List<DiscoveryClient> getDiscoveryClients() {
return this.discoveryClients;
}
}
Nacos
Nacos是一个开源的动态服务发现、配置管理和服务管理平台,广泛用于微服务架构中的服务治理与配置管理。
1. NacosDiscoveryAutoConfiguration
NacosDiscoveryAutoConfiguration
类是一个 Spring 配置类,用于自动配置 Nacos 服务发现功能。它在 Nacos 服务发现启用时创建所需的 NacosDiscoveryProperties
和 NacosServiceDiscovery
Bean,并确保在没有其他相关 Bean 的情况下提供默认配置。
@Configuration(proxyBeanMethods = false)
@ConditionalOnDiscoveryEnabled
@ConditionalOnNacosDiscoveryEnabled
public class NacosDiscoveryAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public NacosDiscoveryProperties nacosProperties() {
return new NacosDiscoveryProperties();
}
@Bean
@ConditionalOnMissingBean
public NacosServiceDiscovery nacosServiceDiscovery(NacosDiscoveryProperties discoveryProperties, NacosServiceManager nacosServiceManager) {
return new NacosServiceDiscovery(discoveryProperties, nacosServiceManager);
}
}
2. NacosDiscoveryClientConfiguration
NacosDiscoveryClientConfiguration
类用于配置和初始化 Nacos 服务发现客户端及其相关功能,如 DiscoveryClient
和 NacosWatch
。
@Configuration(proxyBeanMethods = false)
@ConditionalOnDiscoveryEnabled
@ConditionalOnBlockingDiscoveryEnabled
@ConditionalOnNacosDiscoveryEnabled
@AutoConfigureBefore({ SimpleDiscoveryClientAutoConfiguration.class, CommonsClientAutoConfiguration.class })
@AutoConfigureAfter(NacosDiscoveryAutoConfiguration.class)
public class NacosDiscoveryClientConfiguration {
@Bean
public DiscoveryClient nacosDiscoveryClient(NacosServiceDiscovery nacosServiceDiscovery) {
return new NacosDiscoveryClient(nacosServiceDiscovery);
}
/**
* NacosWatch is no longer enabled by default .
* see https://github.com/alibaba/spring-cloud-alibaba/issues/2868
*/
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(value = "spring.cloud.nacos.discovery.watch.enabled", matchIfMissing = false)
public NacosWatch nacosWatch(NacosServiceManager nacosServiceManager,
NacosDiscoveryProperties nacosDiscoveryProperties) {
return new NacosWatch(nacosServiceManager, nacosDiscoveryProperties);
}
}
3. NacosDiscoveryClient
NacosDiscoveryClient
实现了 DiscoveryClient
接口,通过与 Nacos 服务发现交互,提供获取服务实例和服务列表的功能,同时支持故障容错。
public class NacosDiscoveryClient implements DiscoveryClient {
private static final Logger log = LoggerFactory.getLogger(NacosDiscoveryClient.class);
public static final String DESCRIPTION = "Spring Cloud Nacos Discovery Client";
private NacosServiceDiscovery serviceDiscovery;
@Value("${spring.cloud.nacos.discovery.failure-tolerance-enabled:false}")
private boolean failureToleranceEnabled;
public NacosDiscoveryClient(NacosServiceDiscovery nacosServiceDiscovery) {
this.serviceDiscovery = nacosServiceDiscovery;
}
@Override
public String description() {
return DESCRIPTION;
}
@Override
public List<ServiceInstance> getInstances(String serviceId) {
try {
return Optional.of(serviceDiscovery.getInstances(serviceId))
.map(instances -> {
ServiceCache.setInstances(serviceId, instances);
return instances;
}).get();
}
catch (Exception e) {
if (failureToleranceEnabled) {
return ServiceCache.getInstances(serviceId);
}
throw new RuntimeException(
"Can not get hosts from nacos server. serviceId: " + serviceId, e);
}
}
@Override
public List<String> getServices() {
try {
return Optional.of(serviceDiscovery.getServices()).map(services -> {
ServiceCache.setServiceIds(services);
return services;
}).get();
}
catch (Exception e) {
log.error("get service name from nacos server failed.", e);
return failureToleranceEnabled ? ServiceCache.getServiceIds()
: Collections.emptyList();
}
}
}