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

com.huawei.discovery.service.lb.DiscoveryManager Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. 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.huawei.discovery.service.lb;

import com.huawei.discovery.config.LbConfig;
import com.huawei.discovery.entity.ServiceInstance;
import com.huawei.discovery.service.lb.cache.InstanceCacheManager;
import com.huawei.discovery.service.lb.discovery.InstanceListenable;
import com.huawei.discovery.service.lb.discovery.ServiceDiscoveryClient;
import com.huawei.discovery.service.lb.filter.InstanceFilter;
import com.huawei.discovery.service.lb.rule.AbstractLoadbalancer;
import com.huawei.discovery.service.lb.rule.Loadbalancer;
import com.huawei.discovery.service.lb.rule.RoundRobinLoadbalancer;

import com.huaweicloud.sermant.core.common.LoggerFactory;
import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * 负载均衡管理器
 *
 * @author zhouss
 * @since 2022-09-26
 */
public enum DiscoveryManager {
    /**
     * 单例
     */
    INSTANCE;

    private static final Logger LOGGER = LoggerFactory.getLogger();

    /**
     * lb类型缓存
     * key: lb类型
     * value: class类型
     */
    private final Map> lbCache = new HashMap<>();

    /**
     * 各个服务自身的负载均衡缓存, 分开管理, 防止有状态负载均衡实例相互影响
     */
    private final Map serviceLbCache = new ConcurrentHashMap<>();

    private final List filters = new ArrayList<>();

    private final AtomicBoolean isStarted = new AtomicBoolean();

    private final LbConfig lbConfig;

    private ServiceDiscoveryClient serviceDiscoveryClient;

    private InstanceListenable instanceListenable;

    private InstanceCacheManager cacheManager;

    DiscoveryManager() {
        lbConfig = PluginConfigManager.getPluginConfig(LbConfig.class);
    }

    private void initServiceDiscoveryClient() {
        final String registryCenterType = lbConfig.getRegistryCenterType();
        for (ServiceDiscoveryClient discoveryClient : ServiceLoader.load(ServiceDiscoveryClient.class, this.getClass()
                .getClassLoader())) {
            if (discoveryClient.name().equalsIgnoreCase(lbConfig.getRegistryCenterType())) {
                this.serviceDiscoveryClient = discoveryClient;
                break;
            }
        }
        if (this.serviceDiscoveryClient == null) {
            throw new IllegalStateException("Can not support register center type: " + registryCenterType);
        }
        this.serviceDiscoveryClient.init();
    }

    private void loadLb() {
        for (AbstractLoadbalancer loadbalancer : ServiceLoader.load(AbstractLoadbalancer.class, this.getClass()
                .getClassLoader())) {
            lbCache.put(loadbalancer.lbType(), loadbalancer.getClass());
        }
    }

    private void loadListen() {
        for (InstanceListenable listenable : ServiceLoader.load(InstanceListenable.class, this.getClass()
                .getClassLoader())) {
            if (listenable.name().equalsIgnoreCase(lbConfig.getRegistryCenterType())) {
                this.instanceListenable = listenable;
                break;
            }
        }
        if (this.instanceListenable != null) {
            this.instanceListenable.init();
        }
    }

    /**
     * 启动方法
     */
    public void start() {
        initServiceDiscoveryClient();
        loadLb();
        loadFilter();
        loadListen();
        cacheManager = new InstanceCacheManager(serviceDiscoveryClient, instanceListenable);
    }

    /**
     * 注册
     *
     * @param serviceInstance 注册实例
     */
    public void registry(ServiceInstance serviceInstance) {
        checkStats();
        if (serviceDiscoveryClient.registry(serviceInstance)) {
            LOGGER.info("Registry instance to registry center success!");
        }
    }

    private void loadFilter() {
        for (InstanceFilter filter : ServiceLoader.load(InstanceFilter.class, this.getClass()
                .getClassLoader())) {
            this.filters.add(filter);
        }
    }

    /**
     * 停止相关服务
     *
     * @throws IOException 停止失败抛出
     */
    public void stop() throws IOException {
        lbCache.clear();
        serviceLbCache.clear();
        if (serviceDiscoveryClient.unRegistry()) {
            LOGGER.info("Cur instance has been un registry from registry center success!");
        }
        serviceDiscoveryClient.close();
        if (instanceListenable != null) {
            instanceListenable.close();
        }
        if (this.cacheManager != null) {
            this.cacheManager.stop();
        }
    }

    /**
     * 基于缓存以及负载均衡规则选择实例
     *
     * @param serviceName 服务名
     * @return ServiceInstance
     */
    public Optional choose(String serviceName) {
        return choose(serviceName, getLoadbalancer(serviceName));
    }

    /**
     * 选择实例, 支持自定义lb
     *
     * @param serviceName 服务名
     * @param customLb 负载均衡
     * @return ServiceInstance
     */
    public Optional choose(String serviceName, Loadbalancer customLb) {
        return choose(serviceName, customLb, null);
    }

    /**
     * 选择实例, 支持自定义过滤器
     *
     * @param serviceName 服务名
     * @param customLb 负载均衡
     * @param customFilter 自定义过滤器
     * @return ServiceInstance
     */
    public Optional choose(String serviceName, Loadbalancer customLb, InstanceFilter customFilter) {
        checkStats();
        List instances = cacheManager.getInstances(serviceName);
        for (InstanceFilter filter : filters) {
            instances = filter.filter(serviceName, instances);
        }
        if (customFilter != null) {
            instances = customFilter.filter(serviceName, instances);
        }
        return customLb.choose(serviceName, instances);
    }

    private void checkStats() {
        if (isStarted.compareAndSet(false, true)) {
            this.start();
        }
    }

    private Loadbalancer getLoadbalancer(String serviceName) {
        checkStats();
        return serviceLbCache.computeIfAbsent(serviceName, curService -> {
            LOGGER.info(String.format(Locale.ENGLISH,
                    "Use the loadbalancer [%s], if the lb does not support, it will replace by RoundRobin",
                    lbConfig.getLbType()));
            final Class lbClazz = lbCache
                    .getOrDefault(lbConfig.getLbType(), RoundRobinLoadbalancer.class);
            return createLb(lbClazz).orElse(null);
        });
    }

    private Optional createLb(Class clazz) {
        try {
            return Optional.of(clazz.newInstance());
        } catch (InstantiationException e) {
            LOGGER.log(Level.WARNING, String.format(Locale.ENGLISH,
                    "Can not create instance for clazz [%s] with no params constructor!", clazz.getName()),
                    e);
        } catch (IllegalAccessException e) {
            LOGGER.log(Level.WARNING, String.format(Locale.ENGLISH,
                    "Can not access no params constructor for clazz [%s]!", clazz.getName()), e);
        }
        return Optional.empty();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy