spring cloud 服务注册和发现
本文只讨论spring cloud commons中关于服务注册、服务发现的规范定义以及spring cloud alibaba中nacos相应实现。关于nacos client以及 nacos service 中服务注册、发现的实现细节在nacos相关文章中分析。
spring cloud 服务注册和发现
SC 服务注册概述
以下都是spring cloud commons定义的服务注册的规范接口。
ServiceInstance
表示的是服务发现中的一个实例这个接口定义了类似于
getHost
,getIp
获取注册实例host,ip等方法。Registration
一个标记接口,ServiceRegistry<R>
这里面的R泛型就是Registration
是springcloud定义的规范接口。
ServiceRegistry
服务注册,定义如何向注册中心进行注册,和取消注册这个接口定义了
register服务注册
,deregister服务取消注册
等方法,入参是Registration
。它是springcloud定义的规范接口。AutoServiceRegistration 标识应用自动进行服务注册的接口,是springcloud定义的规范接口。
/**
* 表示系统中服务的实例。
*
* @author Spencer Gibb
* @author Tim Ysewyn
*/
public interface ServiceInstance {
/**
* @return The unique instance ID as registered.
*/
default String getInstanceId() {
return null;
}
/**
* @return The service ID as registered.
*/
String getServiceId();
/**
* @return The hostname of the registered service instance.
*/
String getHost();
/**
* @return The port of the registered service instance.
*/
int getPort();
/**
* @return Whether the port of the registered service instance uses HTTPS.
*/
boolean isSecure();
/**
* @return The service URI address.
*/
URI getUri();
/**
* @return The key / value pair metadata associated with the service instance.
*/
Map<String, String> getMetadata();
/**
* @return The scheme of the service instance.
*/
default String getScheme() {
return null;
}
}
/**
* {@link ServiceRegistry} 使用的标记接口。
*
* @author Spencer Gibb
* @since 1.2.0
*/
public interface Registration extends ServiceInstance {
}
/**
* 向 Service Registry 注册和注销实例的接口。
*
* @param <R> registration meta data
* @author Spencer Gibb
* @since 1.2.0
*/
public interface ServiceRegistry<R extends Registration> {
/**
* Registers the registration. A registration typically has information about an
* instance, such as its hostname and port.
*
* @param registration registration meta data
*/
void register(R registration);
/**
* Deregisters the registration.
*
* @param registration registration meta data
*/
void deregister(R registration);
/**
* Closes the ServiceRegistry. This is a lifecycle method.
*/
void close();
/**
* Sets the status of the registration. The status values are determined by the
* individual implementations.
*
* @param registration The registration to update.
* @param status The status to set.
* @see org.springframework.cloud.client.serviceregistry.endpoint.ServiceRegistryEndpoint
*/
void setStatus(R registration, String status);
/**
* Gets the status of a particular registration.
*
* @param registration The registration to query.
* @param <T> The type of the status.
* @return The status of the registration.
* @see org.springframework.cloud.client.serviceregistry.endpoint.ServiceRegistryEndpoint
*/
<T> T getStatus(R registration);
}
public interface AutoServiceRegistration {
}
/**
* {@link AutoServiceRegistration} 抽象模版方法。监听事件,回调注册方法。
* <p>
* TODO: Document the lifecycle.
*
* @param <R> Registration type passed to the {@link ServiceRegistry}.
* @author Spencer Gibb
*/
public abstract class AbstractAutoServiceRegistration<R extends Registration>
implements AutoServiceRegistration, ApplicationContextAware, ApplicationListener<WebServerInitializedEvent> {
private static final Log logger = LogFactory.getLog(AbstractAutoServiceRegistration.class);
private final ServiceRegistry<R> serviceRegistry;
private boolean autoStartup = true;
private AtomicBoolean running = new AtomicBoolean(false);
private int order = 0;
private ApplicationContext context;
private Environment environment;
private AtomicInteger port = new AtomicInteger(0);
private AutoServiceRegistrationProperties properties;
@Deprecated
protected AbstractAutoServiceRegistration(ServiceRegistry<R> serviceRegistry) {
this.serviceRegistry = serviceRegistry;
}
protected AbstractAutoServiceRegistration(ServiceRegistry<R> serviceRegistry,
AutoServiceRegistrationProperties properties) {
this.serviceRegistry = serviceRegistry;
this.properties = properties;
}
protected ApplicationContext getContext() {
return this.context;
}
/**
* 自动服务注册的入口 监听{@link WebServerInitializedEvent}
*
* @param event the event to respond to
*/
@Override
@SuppressWarnings("deprecation")
public void onApplicationEvent(WebServerInitializedEvent event) {
bind(event);
}
@Deprecated
public void bind(WebServerInitializedEvent event) {
ApplicationContext context = event.getApplicationContext();
if (context instanceof ConfigurableWebServerApplicationContext) {
if ("management".equals(((ConfigurableWebServerApplicationContext) context).getServerNamespace())) {
return;
}
}
this.port.compareAndSet(0, event.getWebServer().getPort());
this.start();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
this.environment = this.context.getEnvironment();
}
@Deprecated
protected Environment getEnvironment() {
return this.environment;
}
@Deprecated
protected AtomicInteger getPort() {
return this.port;
}
public boolean isAutoStartup() {
return this.autoStartup;
}
public void start() {
if (!isEnabled()) {
if (logger.isDebugEnabled()) {
logger.debug("Discovery Lifecycle disabled. Not starting");
}
return;
}
// only initialize if nonSecurePort is greater than 0 and it isn't already running
// because of containerPortInitializer below
if (!this.running.get()) {
this.context.publishEvent(new InstancePreRegisteredEvent(this, getRegistration()));
// 注册服务
register();
if (shouldRegisterManagement()) {
registerManagement();
}
this.context.publishEvent(new InstanceRegisteredEvent<>(this, getConfiguration()));
this.running.compareAndSet(false, true);
}
}
/**
* @return Whether the management service should be registered with the
* {@link ServiceRegistry}.
*/
protected boolean shouldRegisterManagement() {
if (this.properties == null || this.properties.isRegisterManagement()) {
return getManagementPort() != null && ManagementServerPortUtils.isDifferent(this.context);
}
return false;
}
/**
* @return The object used to configure the registration.
*/
@Deprecated
protected abstract Object getConfiguration();
/**
* @return True, if this is enabled.
*/
protected abstract boolean isEnabled();
/**
* @return The serviceId of the Management Service.
*/
@Deprecated
protected String getManagementServiceId() {
// TODO: configurable management suffix
return this.context.getId() + ":management";
}
/**
* @return The service name of the Management Service.
*/
@Deprecated
protected String getManagementServiceName() {
// TODO: configurable management suffix
return getAppName() + ":management";
}
/**
* @return The management server port.
*/
@Deprecated
protected Integer getManagementPort() {
return ManagementServerPortUtils.getPort(this.context);
}
/**
* @return The app name (currently the spring.application.name property).
*/
@Deprecated
protected String getAppName() {
return this.environment.getProperty("spring.application.name", "application");
}
@PreDestroy
public void destroy() {
stop();
}
public boolean isRunning() {
return this.running.get();
}
protected AtomicBoolean getRunning() {
return this.running;
}
public int getOrder() {
return this.order;
}
public int getPhase() {
return 0;
}
protected ServiceRegistry<R> getServiceRegistry() {
return this.serviceRegistry;
}
protected abstract R getRegistration();
protected abstract R getManagementRegistration();
/**
* Register the local service with the {@link ServiceRegistry}.
*/
protected void register() {
this.serviceRegistry.register(getRegistration());
}
/**
* Register the local management service with the {@link ServiceRegistry}.
*/
protected void registerManagement() {
R registration = getManagementRegistration();
if (registration != null) {
this.serviceRegistry.register(registration);
}
}
/**
* De-register the local service with the {@link ServiceRegistry}.
*/
protected void deregister() {
this.serviceRegistry.deregister(getRegistration());
}
/**
* De-register the local management service with the {@link ServiceRegistry}.
*/
protected void deregisterManagement() {
R registration = getManagementRegistration();
if (registration != null) {
this.serviceRegistry.deregister(registration);
}
}
public void stop() {
if (this.getRunning().compareAndSet(true, false) && isEnabled()) {
deregister();
if (shouldRegisterManagement()) {
deregisterManagement();
}
this.serviceRegistry.close();
}
}
}
SCA 服务注册概述
以下都是spring cloud alibaba实现的服务注册的规范接口。
NacosServiceInstance
表示的是服务发现中的一个实例这个接口定义了类似于
getHost
,getIp
获取注册实例host,ip等方法。NacosRegistration
一个标记接口,标识服务注册实例。NacosServiceRegistry
服务注册,定义如何向注册中心进行注册,和取消注册。NacosAutoServiceRegistration
标识应用自动进行服务注册的接口。
自动配置类
NacosServiceRegistryAutoConfiguration向容器中注入了nacos关于服务注册的实现、nacos注册服务实例和nacos服务自动注册对象。
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnNacosDiscoveryEnabled
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled",
matchIfMissing = true)
@AutoConfigureAfter({ AutoServiceRegistrationConfiguration.class,
AutoServiceRegistrationAutoConfiguration.class,
NacosDiscoveryAutoConfiguration.class })
public class NacosServiceRegistryAutoConfiguration {
@Bean
public NacosServiceRegistry nacosServiceRegistry(
NacosServiceManager nacosServiceManager,
NacosDiscoveryProperties nacosDiscoveryProperties) {
return new NacosServiceRegistry(nacosServiceManager, nacosDiscoveryProperties);
}
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
public NacosRegistration nacosRegistration(
ObjectProvider<List<NacosRegistrationCustomizer>> registrationCustomizers,
NacosDiscoveryProperties nacosDiscoveryProperties,
ApplicationContext context) {
return new NacosRegistration(registrationCustomizers.getIfAvailable(),
nacosDiscoveryProperties, context);
}
// 这也是为什么会自动注册服务的原因
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
public NacosAutoServiceRegistration nacosAutoServiceRegistration(
NacosServiceRegistry registry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
NacosRegistration registration) {
return new NacosAutoServiceRegistration(registry,
autoServiceRegistrationProperties, registration);
}
}
服务注册
/**
* 自动注册nacos服务
* @author xiaojing
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
public class NacosAutoServiceRegistration
extends AbstractAutoServiceRegistration<Registration> {
private static final Logger log = LoggerFactory
.getLogger(NacosAutoServiceRegistration.class);
private NacosRegistration registration;
public NacosAutoServiceRegistration(ServiceRegistry<Registration> serviceRegistry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
NacosRegistration registration) {
super(serviceRegistry, autoServiceRegistrationProperties);
this.registration = registration;
}
@Deprecated
public void setPort(int port) {
getPort().set(port);
}
@Override
protected NacosRegistration getRegistration() {
if (this.registration.getPort() < 0 && this.getPort().get() > 0) {
this.registration.setPort(this.getPort().get());
}
Assert.isTrue(this.registration.getPort() > 0, "service.port has not been set");
return this.registration;
}
@Override
protected NacosRegistration getManagementRegistration() {
return null;
}
@Override
protected void register() {
// 检查是否开启服务自动注册
if (!this.registration.getNacosDiscoveryProperties().isRegisterEnabled()) {
log.debug("Registration disabled.");
return;
}
if (this.registration.getPort() < 0) {
this.registration.setPort(getPort().get());
}
// 注册服务
super.register();
}
@Override
protected void registerManagement() {
if (!this.registration.getNacosDiscoveryProperties().isRegisterEnabled()) {
return;
}
super.registerManagement();
}
@Override
protected Object getConfiguration() {
return this.registration.getNacosDiscoveryProperties();
}
@Override
protected boolean isEnabled() {
return this.registration.getNacosDiscoveryProperties().isRegisterEnabled();
}
@Override
@SuppressWarnings("deprecation")
protected String getAppName() {
String appName = registration.getNacosDiscoveryProperties().getService();
return StringUtils.isEmpty(appName) ? super.getAppName() : appName;
}
@EventListener
public void onNacosDiscoveryInfoChangedEvent(NacosDiscoveryInfoChangedEvent event) {
restart();
}
private void restart() {
this.stop();
this.start();
}
}
NacosServiceRegistry核心是使用了nacos client的NamingService进行服务注册。
/**
* @author xiaojing
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @author <a href="mailto:78552423@qq.com">eshun</a>
* @author JAY
*/
public class NacosServiceRegistry implements ServiceRegistry<Registration> {
private static final String STATUS_UP = "UP";
private static final String STATUS_DOWN = "DOWN";
private static final Logger log = LoggerFactory.getLogger(NacosServiceRegistry.class);
private final NacosDiscoveryProperties nacosDiscoveryProperties;
private final NacosServiceManager nacosServiceManager;
public NacosServiceRegistry(NacosServiceManager nacosServiceManager,
NacosDiscoveryProperties nacosDiscoveryProperties) {
this.nacosDiscoveryProperties = nacosDiscoveryProperties;
this.nacosServiceManager = nacosServiceManager;
}
@Override
public void register(Registration registration) {
if (StringUtils.isEmpty(registration.getServiceId())) {
log.warn("No service to register for nacos client...");
return;
}
NamingService namingService = namingService();
String serviceId = registration.getServiceId();
String group = nacosDiscoveryProperties.getGroup();
Instance instance = getNacosInstanceFromRegistration(registration);
try {
namingService.registerInstance(serviceId, group, instance);
log.info("nacos registry, {} {} {}:{} register finished", group, serviceId,
instance.getIp(), instance.getPort());
}
catch (Exception e) {
if (nacosDiscoveryProperties.isFailFast()) {
log.error("nacos registry, {} register failed...{},", serviceId,
registration.toString(), e);
rethrowRuntimeException(e);
}
else {
log.warn("Failfast is false. {} register failed...{},", serviceId,
registration.toString(), e);
}
}
}
@Override
public void deregister(Registration registration) {
log.info("De-registering from Nacos Server now...");
if (StringUtils.isEmpty(registration.getServiceId())) {
log.warn("No dom to de-register for nacos client...");
return;
}
NamingService namingService = namingService();
String serviceId = registration.getServiceId();
String group = nacosDiscoveryProperties.getGroup();
try {
namingService.deregisterInstance(serviceId, group, registration.getHost(),
registration.getPort(), nacosDiscoveryProperties.getClusterName());
}
catch (Exception e) {
log.error("ERR_NACOS_DEREGISTER, de-register failed...{},",
registration.toString(), e);
}
log.info("De-registration finished.");
}
@Override
public void close() {
try {
nacosServiceManager.nacosServiceShutDown();
}
catch (NacosException e) {
log.error("Nacos namingService shutDown failed", e);
}
}
@Override
public void setStatus(Registration registration, String status) {
if (!STATUS_UP.equalsIgnoreCase(status)
&& !STATUS_DOWN.equalsIgnoreCase(status)) {
log.warn("can't support status {},please choose UP or DOWN", status);
return;
}
String serviceId = registration.getServiceId();
Instance instance = getNacosInstanceFromRegistration(registration);
if (STATUS_DOWN.equalsIgnoreCase(status)) {
instance.setEnabled(false);
}
else {
instance.setEnabled(true);
}
try {
Properties nacosProperties = nacosDiscoveryProperties.getNacosProperties();
nacosServiceManager.getNamingMaintainService(nacosProperties).updateInstance(
serviceId, nacosDiscoveryProperties.getGroup(), instance);
}
catch (Exception e) {
throw new RuntimeException("update nacos instance status fail", e);
}
}
@Override
public Object getStatus(Registration registration) {
String serviceName = registration.getServiceId();
String group = nacosDiscoveryProperties.getGroup();
try {
List<Instance> instances = namingService().getAllInstances(serviceName,
group);
for (Instance instance : instances) {
if (instance.getIp().equalsIgnoreCase(nacosDiscoveryProperties.getIp())
&& instance.getPort() == nacosDiscoveryProperties.getPort()) {
return instance.isEnabled() ? STATUS_UP : STATUS_DOWN;
}
}
}
catch (Exception e) {
log.error("get all instance of {} error,", serviceName, e);
}
return null;
}
private Instance getNacosInstanceFromRegistration(Registration registration) {
Instance instance = new Instance();
instance.setIp(registration.getHost());
instance.setPort(registration.getPort());
instance.setWeight(nacosDiscoveryProperties.getWeight());
instance.setClusterName(nacosDiscoveryProperties.getClusterName());
instance.setEnabled(nacosDiscoveryProperties.isInstanceEnabled());
instance.setMetadata(registration.getMetadata());
instance.setEphemeral(nacosDiscoveryProperties.isEphemeral());
return instance;
}
private NamingService namingService() {
return nacosServiceManager.getNamingService();
}
}
总结
通过ServiceRegistry实现执行最终的服务注册。AbstractAutoServiceRegistration会在监听事件最终回调服务注册方法实现服务注册。
Spring cloud servicediscovery
SC服务发现概述
DiscoveryClient
是一个用于服务发现的接口,它允许应用程序查询服务注册中心以获取可用的服务实例信息。DiscoveryClient是Spring Cloud对服务发现功能的抽象,它可以与各种不同的服务注册中心集成,并提供统一的API来进行服务发现操作。
/**
* 表示通常可用于发现服务的读取操作,例如 Netflix Eureka or consul.io.
*
* @author Spencer Gibb
* @author Olga Maciaszek-Sharma
* @author Chris Bono
*/
public interface DiscoveryClient extends Ordered {
int DEFAULT_ORDER = 0;
String description();
/**
* 获取与特定 serviceId 关联的所有 ServiceInstances。
* @param serviceId The serviceId to query.
* @return A List of ServiceInstance.
*/
List<ServiceInstance> getInstances(String serviceId);
/**
* @return 所有已知的服务 ID。
*/
List<String> getServices();
default void probe() {
getServices();
}
@Override
default int getOrder() {
return DEFAULT_ORDER;
}
}
EnableDiscoveryClient
作用就是import了EnableDiscoveryClientImportSelector。其中EnableDiscoveryClientImportSelector的作用:- 读取并注册 META-INF/spring.factories 中 key 是
EnableDiscoveryClient.class.getName()
的类信息。 - 配置服务自动注册的信息。
- 读取并注册 META-INF/spring.factories 中 key 是
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableDiscoveryClientImportSelector.class)
public @interface EnableDiscoveryClient {
/**
* 如果为 true,ServiceRegistry 将自动注册本地服务器。
* @return - {@code true} 如果您想自动注册。
*/
boolean autoRegister() default true;
}
/**
* 作用一:读取并注册 META-INF/spring.factories 中 key 是 `EnableDiscoveryClient.class.getName()` 的类信息
* 作用二:配置服务自动注册的信息
* @author Spencer Gibb
*/
@Order(Ordered.LOWEST_PRECEDENCE - 100)
public class EnableDiscoveryClientImportSelector extends SpringFactoryImportSelector<EnableDiscoveryClient> {
@Override
public String[] selectImports(AnnotationMetadata metadata) {
/**
* 读取 META-INF/spring.factories 中 key 是 `EnableDiscoveryClient.class.getName()`
* 的类信息
*/
String[] imports = super.selectImports(metadata);
AnnotationAttributes attributes = AnnotationAttributes
.fromMap(metadata.getAnnotationAttributes(getAnnotationClass().getName(), true));
// 注解的值是 true
boolean autoRegister = attributes.getBoolean("autoRegister");
if (autoRegister) {
List<String> importsList = new ArrayList<>(Arrays.asList(imports));
/**
* 添加 AutoServiceRegistrationConfiguration 这个类,
* 这个类的目的很简单,就是注册 AutoServiceRegistrationProperties 到BeanFactory中
* @EnableConfigurationProperties(AutoServiceRegistrationProperties.class)
* */
importsList.add("org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration");
imports = importsList.toArray(new String[0]);
}
else {
Environment env = getEnvironment();
if (ConfigurableEnvironment.class.isInstance(env)) {
ConfigurableEnvironment configEnv = (ConfigurableEnvironment) env;
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
map.put("spring.cloud.service-registry.auto-registration.enabled", false);
MapPropertySource propertySource = new MapPropertySource("springCloudDiscoveryClient", map);
configEnv.getPropertySources().addLast(propertySource);
}
}
return imports;
}
@Override
protected boolean isEnabled() {
return getEnvironment().getProperty("spring.cloud.discovery.enabled", Boolean.class, Boolean.TRUE);
}
@Override
protected boolean hasDefaultFactory() {
return true;
}
}
SCA服务发现概述
spring cloud alibaba实现了spring cloud规范,本质上还是使用nacos client 中的NamingService
进行服务发现,这里只分析nacos的规范实现,nacos的细节在nacos相关文章中分析。
NacosDiscoveryClient
实现了DiscoveryClient,本质上是用自己实现的serviceDiscovery进行服务发现,然后使用ServiceCache进行服务的缓存,这样可以在服务发现出现异常得时候使用缓存进行容错。
/**
* @author xiaojing
* @author renhaojun
* @author echooymxq
* @author freeman
*/
public class NacosDiscoveryClient implements DiscoveryClient {
private static final Logger log = LoggerFactory.getLogger(NacosDiscoveryClient.class);
/**
* Nacos Discovery Client Description.
*/
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();
}
}
}
NacosServiceDiscovery
本质上用的NamingService进行服务发现,然后对服务实例进行属性映射处理。
/**
* @author <a href="mailto:echooy.mxq@gmail.com">echooymxq</a>
* @author changjin wei(魏昌进)
**/
public class NacosServiceDiscovery {
private NacosDiscoveryProperties discoveryProperties;
private NacosServiceManager nacosServiceManager;
public NacosServiceDiscovery(NacosDiscoveryProperties discoveryProperties,
NacosServiceManager nacosServiceManager) {
this.discoveryProperties = discoveryProperties;
this.nacosServiceManager = nacosServiceManager;
}
/**
* Return all instances for the given service.
* @param serviceId id of service
* @return list of instances
* @throws NacosException nacosException
*/
public List<ServiceInstance> getInstances(String serviceId) throws NacosException {
String group = discoveryProperties.getGroup();
List<Instance> instances = namingService().selectInstances(serviceId, group,
true);
return hostToServiceInstanceList(instances, serviceId);
}
/**
* Return the names of all services.
* @return list of service names
* @throws NacosException nacosException
*/
public List<String> getServices() throws NacosException {
String group = discoveryProperties.getGroup();
ListView<String> services = namingService().getServicesOfServer(1,
Integer.MAX_VALUE, group);
return services.getData();
}
public static List<ServiceInstance> hostToServiceInstanceList(
List<Instance> instances, String serviceId) {
List<ServiceInstance> result = new ArrayList<>(instances.size());
for (Instance instance : instances) {
ServiceInstance serviceInstance = hostToServiceInstance(instance, serviceId);
if (serviceInstance != null) {
result.add(serviceInstance);
}
}
return result;
}
public static ServiceInstance hostToServiceInstance(Instance instance,
String serviceId) {
if (instance == null || !instance.isEnabled() || !instance.isHealthy()) {
return null;
}
NacosServiceInstance nacosServiceInstance = new NacosServiceInstance();
nacosServiceInstance.setHost(instance.getIp());
nacosServiceInstance.setPort(instance.getPort());
nacosServiceInstance.setServiceId(serviceId);
nacosServiceInstance.setInstanceId(instance.getInstanceId());
Map<String, String> metadata = new HashMap<>();
metadata.put("nacos.instanceId", instance.getInstanceId());
metadata.put("nacos.weight", instance.getWeight() + "");
metadata.put("nacos.healthy", instance.isHealthy() + "");
metadata.put("nacos.cluster", instance.getClusterName() + "");
if (instance.getMetadata() != null) {
metadata.putAll(instance.getMetadata());
}
metadata.put("nacos.ephemeral", String.valueOf(instance.isEphemeral()));
nacosServiceInstance.setMetadata(metadata);
if (metadata.containsKey("secure")) {
boolean secure = Boolean.parseBoolean(metadata.get("secure"));
nacosServiceInstance.setSecure(secure);
}
return nacosServiceInstance;
}
private NamingService namingService() {
return nacosServiceManager.getNamingService();
}
}
总结
spring cloud alibaba使用nacos实现了sc的服务发现规范,本质上还是用NamingService进行服务发现。