All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.spi.discovery.impl.DefaultDiscoveryService Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2008-2024, Hazelcast, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hazelcast.spi.discovery.impl;

import com.hazelcast.cluster.Address;
import com.hazelcast.config.DiscoveryConfig;
import com.hazelcast.config.DiscoveryStrategyConfig;
import com.hazelcast.config.InvalidConfigurationException;
import com.hazelcast.config.properties.ValidationException;
import com.hazelcast.internal.util.ServiceLoader;
import com.hazelcast.logging.ILogger;
import com.hazelcast.spi.discovery.DiscoveryNode;
import com.hazelcast.spi.discovery.DiscoveryStrategy;
import com.hazelcast.spi.discovery.DiscoveryStrategyFactory;
import com.hazelcast.spi.discovery.NodeFilter;
import com.hazelcast.spi.discovery.integration.DiscoveryService;
import com.hazelcast.spi.discovery.integration.DiscoveryServiceSettings;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.hazelcast.internal.util.CollectionUtil.nullToEmpty;

public class DefaultDiscoveryService implements DiscoveryService {

    private static final String SERVICE_LOADER_TAG = DiscoveryStrategyFactory.class.getCanonicalName();

    private final ILogger logger;
    private final DiscoveryNode discoveryNode;
    private final NodeFilter nodeFilter;
    private final Iterable discoveryStrategies;

    public DefaultDiscoveryService(DiscoveryServiceSettings settings) {
        this.logger = settings.getLogger();
        this.discoveryNode = settings.getDiscoveryNode();
        this.nodeFilter = getNodeFilter(settings);
        this.discoveryStrategies = loadDiscoveryStrategies(settings);
    }

    @Override
    public void start() {
        for (DiscoveryStrategy discoveryStrategy : discoveryStrategies) {
            discoveryStrategy.start();
        }
    }

    @Override
    public Iterable discoverNodes() {
        Set discoveryNodes = new HashSet<>();
        for (DiscoveryStrategy discoveryStrategy : discoveryStrategies) {
            Iterable candidates = discoveryStrategy.discoverNodes();

            if (candidates != null) {
                for (DiscoveryNode candidate : candidates) {
                    if (validateCandidate(candidate)) {
                        discoveryNodes.add(candidate);
                    }
                }
            }
        }
        return discoveryNodes;
    }

    @Override
    public Map discoverLocalMetadata() {
        Map metadata = new HashMap<>();
        for (DiscoveryStrategy discoveryStrategy : discoveryStrategies) {
            metadata.putAll(discoveryStrategy.discoverLocalMetadata());
        }
        return metadata;
    }

    @Override
    public void destroy() {
        for (DiscoveryStrategy discoveryStrategy : discoveryStrategies) {
            discoveryStrategy.destroy();
        }
    }

    @Override
    public void markEndpointAsUnhealthy(Address address) {
        for (DiscoveryStrategy discoveryStrategy : discoveryStrategies) {
            discoveryStrategy.markEndpointAsUnhealthy(address);
        }
    }

    @Override
    public Set
getUnhealthyEndpoints() { Set
combinedAddresses = null; for (DiscoveryStrategy strategy : discoveryStrategies) { Set
strategyAddresses = strategy.getUnhealthyEndpoints(); if (!strategyAddresses.isEmpty()) { if (combinedAddresses == null) { combinedAddresses = new HashSet<>(strategyAddresses.size()); } combinedAddresses.addAll(strategyAddresses); } } return combinedAddresses == null ? Collections.emptySet() : combinedAddresses; } public Iterable getDiscoveryStrategies() { return discoveryStrategies; } private NodeFilter getNodeFilter(DiscoveryServiceSettings settings) { DiscoveryConfig discoveryConfig = settings.getDiscoveryConfig(); ClassLoader configClassLoader = settings.getConfigClassLoader(); if (discoveryConfig.getNodeFilter() != null) { return discoveryConfig.getNodeFilter(); } if (discoveryConfig.getNodeFilterClass() != null) { try { ClassLoader cl = configClassLoader; if (cl == null) { cl = DefaultDiscoveryService.class.getClassLoader(); } String className = discoveryConfig.getNodeFilterClass(); return (NodeFilter) cl.loadClass(className).getDeclaredConstructor().newInstance(); } catch (Exception e) { throw new RuntimeException("Failed to configure discovery node filter", e); } } return null; } private boolean validateCandidate(DiscoveryNode candidate) { return nodeFilter == null || nodeFilter.test(candidate); } private Iterable loadDiscoveryStrategies(DiscoveryServiceSettings settings) { ClassLoader configClassLoader = settings.getConfigClassLoader(); try { Collection discoveryStrategyConfigs = new ArrayList<>( settings.getAllDiscoveryConfigs()); List factories = collectFactories(discoveryStrategyConfigs, configClassLoader); List discoveryStrategies = new ArrayList<>(); for (DiscoveryStrategyConfig config : discoveryStrategyConfigs) { DiscoveryStrategy discoveryStrategy = buildDiscoveryStrategy(config, factories); discoveryStrategies.add(discoveryStrategy); } if (discoveryStrategies.isEmpty() && settings.isAutoDetectionEnabled()) { logger.fine("Discovery auto-detection enabled, looking for available discovery strategies"); DiscoveryStrategyFactory autoDetectedFactory = detectDiscoveryStrategyFactory(factories); if (autoDetectedFactory != null) { logger.info(String.format("Auto-detection selected discovery strategy: %s", autoDetectedFactory.getClass())); discoveryStrategies .add(autoDetectedFactory.newDiscoveryStrategy(discoveryNode, logger, Collections.emptyMap())); } else { logger.fine("No discovery strategy is applicable for auto-detection"); } } return discoveryStrategies; } catch (Exception e) { if (e instanceof ValidationException) { throw new InvalidConfigurationException("Invalid configuration", e); } else { throw new RuntimeException("Failed to configure discovery strategies", e); } } } private List collectFactories(Collection strategyConfigs, ClassLoader classloader) throws Exception { Iterator iterator = ServiceLoader .iterator(DiscoveryStrategyFactory.class, SERVICE_LOADER_TAG, classloader); // Collect possible factories List factories = new ArrayList<>(); while (iterator.hasNext()) { factories.add(iterator.next()); } for (DiscoveryStrategyConfig config : strategyConfigs) { DiscoveryStrategyFactory factory = config.getDiscoveryStrategyFactory(); if (factory != null) { factories.add(factory); } } return factories; } private DiscoveryStrategy buildDiscoveryStrategy(DiscoveryStrategyConfig config, List candidateFactories) { for (DiscoveryStrategyFactory factory : candidateFactories) { Class discoveryStrategyType = factory.getDiscoveryStrategyType(); String className = discoveryStrategyType.getName(); String factoryClassName = getFactoryClassName(config); if (className.equals(factoryClassName)) { Map properties = DiscoveryServicePropertiesUtil .prepareProperties(config.getProperties(), nullToEmpty(factory.getConfigurationProperties())); return factory.newDiscoveryStrategy(discoveryNode, logger, properties); } } throw new ValidationException( "There is no discovery strategy factory to create '" + config + "' Is it a typo in a strategy classname? " + "Perhaps you forgot to include implementation on a classpath?"); } private DiscoveryStrategyFactory detectDiscoveryStrategyFactory(List factories) { DiscoveryStrategyFactory highestPriorityFactory = null; for (DiscoveryStrategyFactory factory : factories) { try { if (factory.isAutoDetectionApplicable()) { logger.fine( String.format("Discovery strategy factory '%s' is auto-applicable to the current runtime environment", factory.getClass())); if (highestPriorityFactory == null || factory.discoveryStrategyLevel().getPriority() > highestPriorityFactory.discoveryStrategyLevel().getPriority()) { highestPriorityFactory = factory; } } else { logger.fine(String.format("Discovery Factory '%s' is not auto-applicable to the current runtime environment", factory.getClass())); } } catch (Exception e) { // exception in auto-detection should not prevent Hazelcast from starting logger.finest(e); } } return highestPriorityFactory; } private String getFactoryClassName(DiscoveryStrategyConfig config) { if (config.getDiscoveryStrategyFactory() != null) { DiscoveryStrategyFactory factory = config.getDiscoveryStrategyFactory(); return factory.getDiscoveryStrategyType().getName(); } return config.getClassName(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy