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

com.baidu.formula.discovery.serviceregistry.FormulaAutoRegistration Maven / Gradle / Ivy

package com.baidu.formula.discovery.serviceregistry;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.springframework.cloud.client.discovery.ManagementServerPortUtils;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
import org.springframework.cloud.commons.util.IdUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import com.baidu.discovery.client.model.Instance;
import com.baidu.formula.discovery.autoconfigure.FormulaDiscoveryProperties;

/**
 * 实例注册主要逻辑
 *
 * @author Bowu Dong ([email protected])
 */
public class FormulaAutoRegistration extends FormulaRegistration {
    public static final char SEPARATOR = '-';

    private final AutoServiceRegistrationProperties autoServiceRegistrationProperties;

    private final ApplicationContext context;

    public FormulaAutoRegistration(Instance instance,
                                   AutoServiceRegistrationProperties autoServiceRegistrationProperties,
                                   FormulaDiscoveryProperties properties, ApplicationContext context) {
        super(instance, properties);
        this.autoServiceRegistrationProperties = autoServiceRegistrationProperties;
        this.context = context;
    }

    public static FormulaAutoRegistration registration(
            AutoServiceRegistrationProperties autoServiceRegistrationProperties,
            FormulaDiscoveryProperties properties, ApplicationContext context,
            List registrationCustomers) {
        Instance instance = new Instance();
        String appName = getAppName(properties, context.getEnvironment());
        instance.setAppName(normalizeForDns(appName));
        // set formula discovery unique id
        instance.setInstanceId(uniqInstanceId(properties, appName, context.getEnvironment()));
        if (properties.isPreferIpAddress()) {
            instance.setHost(properties.getIpAddress());
        } else {
            instance.setHost(properties.getHostname());
        }

        instance.setTags(createTags(properties));
        instance.setCustoms(getCustoms(properties, context));

        if (properties.getPort() != null) {
            instance.setPort(properties.getPort());
            // we known the port and can set the check
            setCheck(instance, autoServiceRegistrationProperties, properties, context);
        }

        instance.setScheme(properties.getScheme());
        instance.setType("restful");
        instance.setPort(properties.getPort());
        instance.setZone(properties.getZone());
        instance.setStatus(Instance.STATUS_UP);

        FormulaAutoRegistration registration = new FormulaAutoRegistration(
                instance, autoServiceRegistrationProperties, properties, context);
        customize(registrationCustomers, registration);
        return registration;
    }

    private static String uniqInstanceId(FormulaDiscoveryProperties properties,
                                         String appName, Environment environment) {
        return normalizeForDns(String.format("%s-%s-%s-%s", properties.getProductName(),
                properties.getResourceIsolation(), appName, IdUtils.getDefaultInstanceId(environment)));
    }

    private static Map getCustoms(FormulaDiscoveryProperties properties, ApplicationContext context) {
        Map customs = new LinkedHashMap<>(
                properties.getCustoms() == null ? Collections.emptyMap() : properties.getCustoms());

        if (properties.getZone() != null) {
            customs.put("zone", properties.getZone());
        }
        customs.put("appName", properties.getApp());
        customs.put("serviceName", getAppName(properties, context.getEnvironment()));
        customs.put("instanceId", getInstanceId(properties, context));
        customs.put("environment", properties.getEnvironment());
        if (properties.getRegion() != null) {
            customs.put("region", properties.getRegion());
        }
        return customs;
    }

    private static void customize(List registrationCustomers,
                                  FormulaAutoRegistration registration) {
        if (registrationCustomers != null) {
            registrationCustomers.forEach(c -> c.customize(registration));
        }
    }

    private static void setCheck(Instance instance,
                                 AutoServiceRegistrationProperties autoServiceRegistrationProperties,
                                 FormulaDiscoveryProperties properties, ApplicationContext context) {
        Integer checkPort;
        if (shouldRegisterManagement(autoServiceRegistrationProperties, properties, context)) {
            checkPort = getManagementPort(properties, context);
        } else {
            checkPort = instance.getPort();
        }

        Assert.notNull(checkPort, "checkPort may not be null");
        doSetCheck(instance, checkPort, properties);
    }

    private static void doSetCheck(Instance instance, Integer port, FormulaDiscoveryProperties properties) {
        // TODO 规范里在没有提到check的事情, 先不搞

    }

    private static Integer getManagementPort(FormulaDiscoveryProperties properties, ApplicationContext context) {
        // if an alternate external port is specified, use it instead
        if (properties.getManagementPort() != null) {
            return properties.getManagementPort();
        }

        return ManagementServerPortUtils.getPort(context);
    }

    private static boolean shouldRegisterManagement(
            AutoServiceRegistrationProperties autoServiceRegistrationProperties,
            FormulaDiscoveryProperties properties, ApplicationContext context) {
        return autoServiceRegistrationProperties.isRegisterManagement()
                && getManagementPort(properties, context) != null
                && ManagementServerPortUtils.isDifferent(context);
    }

    private static List createTags(FormulaDiscoveryProperties properties) {
        List tags = properties.getTags();
        if (!tags.contains(properties.getZone())) {
            tags.add(properties.getZone());
        }
        return tags;
    }

    private static String normalizeForDns(String s) {
        StringBuilder normalized = new StringBuilder();
        Character prev = null;
        for (char curr : s.toCharArray()) {
            Character toAppend = null;
            if (Character.isLetterOrDigit(curr)) {
                toAppend = curr;
            } else if (prev == null || prev != SEPARATOR) {
                toAppend = SEPARATOR;
            }

            if (toAppend != null) {
                normalized.append(toAppend);
                prev = toAppend;
            }
        }

        return normalized.toString();

    }

    private static String getInstanceId(FormulaDiscoveryProperties properties, ApplicationContext context) {
        if (!StringUtils.hasText(properties.getInstanceId())) {
            return normalizeForDns(IdUtils.getDefaultInstanceId(context.getEnvironment(), true));
        }

        return properties.getInstanceId();
    }

    public static String getAppName(FormulaDiscoveryProperties properties, Environment environment) {
        String appName = properties.getApp();
        if (!StringUtils.hasText(appName)) {
            appName = environment.getProperty("spring.application.name");
        }
        if (!StringUtils.hasText(appName)) {
            appName = environment.getProperty("spring.cloud.config.name", "application");
        }
        // check service name.
        for (char c : appName.toCharArray()) {
            if (c == '.') {
                throw new IllegalArgumentException("service name contains illegal . character!");
            }
        }

        return appName;
    }

    public void initializePort(int knownPort) {
        if (getInstance().getPort() == null) {
            // not set by properties
            getInstance().setPort(knownPort);
        }

        // we might not have a port until now, so that is the earliest we can create a check
        setCheck(getInstance(), autoServiceRegistrationProperties, getProperties(), context);
    }

    public FormulaAutoRegistration managementRegistration() {
        return managementRegistration(autoServiceRegistrationProperties, getProperties(), context);
    }

    private FormulaAutoRegistration managementRegistration(
            AutoServiceRegistrationProperties autoServiceRegistrationProperties,
            FormulaDiscoveryProperties properties, ApplicationContext context) {
        Instance management = new Instance();
        management.setInstanceId(getManagementServiceId(properties, context));
        management.setHost(properties.getHostname());
        management.setAppName(getManagementServiceName(properties, context.getEnvironment()));
        management.setPort(getManagementPort(properties, context));
        management.setTags(properties.getTags());
        management.setScheme(properties.getScheme());
        management.setStatus(Instance.STATUS_UP);
        management.setType("restful");
        management.setCustoms(getManagementCustoms(properties, context));
        String path = "";
        if (getInstance() != null) {
            path = getInstance().getPath();
        }
        management.setPath(path);
        // deal with check object
        return new FormulaAutoRegistration(management, autoServiceRegistrationProperties, properties, context);
    }

    private String getManagementServiceName(FormulaDiscoveryProperties properties, Environment environment) {
        return normalizeForDns(getAppName(properties, environment)) + SEPARATOR + "management";
    }

    private String getManagementServiceId(FormulaDiscoveryProperties properties, ApplicationContext context) {
        return normalizeForDns(IdUtils.getDefaultInstanceId(context.getEnvironment(), false))
                + SEPARATOR + "management";
    }

    private Map getManagementCustoms(FormulaDiscoveryProperties properties,
                                                     ApplicationContext context) {
        Map customs = new LinkedHashMap<>(
                properties.getCustoms() == null ? Collections.emptyMap() : properties.getCustoms());

        if (properties.getZone() != null) {
            customs.put("zone", properties.getZone());
        }
        customs.put("appName", getManagementServiceName(properties, context.getEnvironment()));
        customs.put("instanceId", getManagementServiceId(properties, context));
        customs.put("environment", properties.getEnvironment());
        if (properties.getRegion() != null) {
            customs.put("region", properties.getRegion());
        }
        return customs;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy