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

com.alibaba.nacos.naming.healthcheck.AbstractHealthCheckProcessor Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 1999-2018 Alibaba Group Holding Ltd.
 *
 * 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.alibaba.nacos.naming.healthcheck;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker;
import com.alibaba.nacos.naming.boot.RunningConfig;
import com.alibaba.nacos.naming.core.Cluster;
import com.alibaba.nacos.naming.core.DistroMapper;
import com.alibaba.nacos.naming.core.IpAddress;
import com.alibaba.nacos.naming.core.VirtualClusterDomain;
import com.alibaba.nacos.naming.misc.*;
import com.alibaba.nacos.naming.push.PushService;
import org.apache.commons.lang3.StringUtils;

import java.net.HttpURLConnection;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @author nacos
 */
public abstract class AbstractHealthCheckProcessor {

    private static final String HTTP_CHECK_MSG_PREFIX = "http:";

    static class HealthCheckResult {
        private String dom;
        private IpAddress ipAddress;

        public HealthCheckResult(String dom, IpAddress ipAddress) {
            this.dom = dom;
            this.ipAddress = ipAddress;
        }

        public String getDom() {
            return dom;
        }

        public void setDom(String dom) {
            this.dom = dom;
        }

        public IpAddress getIpAddress() {
            return ipAddress;
        }

        public void setIpAddress(IpAddress ipAddress) {
            this.ipAddress = ipAddress;
        }
    }

    public static final int CONNECT_TIMEOUT_MS = 500;
    private static LinkedBlockingDeque healthCheckResults = new LinkedBlockingDeque<>(1024 * 128);

    private void addResult(HealthCheckResult result) {

        if (!Switch.getIncrementalList().contains(result.getDom())) {
            return;
        }

        if (!healthCheckResults.offer(result)) {
            Loggers.EVT_LOG.warn("[HEALTH-CHECK-SYNC] failed to add check result to queue, queue size: {}", healthCheckResults.size());
        }
    }

    private static ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r);
            thread.setDaemon(true);
            thread.setName("com.taobao.health-check.notifier");
            return thread;
        }
    });


    static {
        executorService.schedule(new Runnable() {
            @Override
            public void run() {
                List list = Arrays.asList(healthCheckResults.toArray());
                healthCheckResults.clear();

                List sameSiteServers = NamingProxy.getSameSiteServers().get("sameSite");

                if (sameSiteServers == null || sameSiteServers.size() <= 0 || !NamingProxy.getServers().contains(NetUtils.localServer())) {
                    return;
                }

                for (String server : sameSiteServers) {
                    if (server.equals(NetUtils.localServer())) {
                        continue;
                    }
                    Map params = new HashMap<>(10);
                    params.put("result", JSON.toJSONString(list));
                    if (Loggers.DEBUG_LOG.isDebugEnabled()) {
                        Loggers.DEBUG_LOG.debug("[HEALTH-SYNC] server: {}, healthCheckResults: {}",
                            server, JSON.toJSONString(list));
                    }
                    if (!server.contains(":")) {
                        server = server + ":" + RunningConfig.getServerPort();
                    }
                    HttpClient.HttpResult httpResult = HttpClient.httpPost("http://" + server
                        + RunningConfig.getContextPath() + UtilsAndCommons.NACOS_NAMING_CONTEXT
                        + "/api/healthCheckResult", null, params);

                    if (httpResult.code != HttpURLConnection.HTTP_OK) {
                        Loggers.EVT_LOG.warn("[HEALTH-CHECK-SYNC] failed to send result to {}, result: {}",
                            server, JSON.toJSONString(list));
                    }

                }

            }
        }, 500, TimeUnit.MILLISECONDS);
    }

    /**
     * Run check task for domain
     *
     * @param task check task
     */
    public abstract void process(HealthCheckTask task);

    /**
     * Get check task type, refer to enum HealthCheckType
     *
     * @return check type
     */
    public abstract String getType();

    public static final HttpHealthCheckProcessor HTTP_PROCESSOR = new HttpHealthCheckProcessor();
    public static final TcpSuperSenseProcessor TCP_PROCESSOR = new TcpSuperSenseProcessor();
    public static final MysqlHealthCheckProcessor MYSQL_PROCESSOR = new MysqlHealthCheckProcessor();

    public static AbstractHealthCheckProcessor getProcessor(AbstractHealthChecker config) {
        if (config == null || StringUtils.isEmpty(config.getType())) {
            throw new IllegalArgumentException("empty check type");
        }

        if (config.getType().equals(HTTP_PROCESSOR.getType())) {
            return HTTP_PROCESSOR;
        }

        if (config.getType().equals(TCP_PROCESSOR.getType())) {
            return TCP_PROCESSOR;
        }

        if (config.getType().equals(MYSQL_PROCESSOR.getType())) {
            return MYSQL_PROCESSOR;
        }

        throw new IllegalArgumentException("Unknown check type: " + config.getType());
    }

    protected boolean isHealthCheckEnabled(VirtualClusterDomain virtualClusterDomain) {
        if (virtualClusterDomain.getEnableClientBeat()) {
            return false;
        }

        return virtualClusterDomain.getEnableHealthCheck();
    }

    protected void reEvaluateCheckRT(long checkRT, HealthCheckTask task, SwitchDomain.HealthParams params) {
        task.setCheckRTLast(checkRT);

        if (checkRT > task.getCheckRTWorst()) {
            task.setCheckRTWorst(checkRT);
        }

        if (checkRT < task.getCheckRTBest()) {
            task.setCheckRTBest(checkRT);
        }

        checkRT = (long) ((params.getFactor() * task.getCheckRTNormalized()) + (1 - params.getFactor()) * checkRT);

        if (checkRT > params.getMax()) {
            checkRT = params.getMax();
        }

        if (checkRT < params.getMin()) {
            checkRT = params.getMin();
        }

        task.setCheckRTNormalized(checkRT);
    }

    protected void checkOK(IpAddress ip, HealthCheckTask task, String msg) {
        Cluster cluster = task.getCluster();

        try {
            if (!ip.isValid() || !ip.isMockValid()) {
                if (ip.getOKCount().incrementAndGet() >= Switch.getCheckTimes()) {
                    if (cluster.responsible(ip)) {
                        ip.setValid(true);
                        ip.setMockValid(true);

                        VirtualClusterDomain vDom = (VirtualClusterDomain) cluster.getDom();
                        vDom.setLastModifiedMillis(System.currentTimeMillis());

                        PushService.domChanged(vDom.getNamespaceId(), vDom.getName());
                        addResult(new HealthCheckResult(vDom.getName(), ip));

                        Loggers.EVT_LOG.info("dom: {} {POS} {IP-ENABLED} valid: {}:{}@{}, region: {}, msg: {}",
                            cluster.getDom().getName(), ip.getIp(), ip.getPort(), cluster.getName(), DistroMapper.LOCALHOST_SITE, msg);
                    } else {
                        if (!ip.isMockValid()) {
                            ip.setMockValid(true);
                            Loggers.EVT_LOG.info("dom: {} {PROBE} {IP-ENABLED} valid: {}:{}@{}, region: {}, msg: {}",
                                cluster.getDom().getName(), ip.getIp(), ip.getPort(), cluster.getName(), DistroMapper.LOCALHOST_SITE, msg);
                        }
                    }
                } else {
                    Loggers.EVT_LOG.info("dom: {} {OTHER} {IP-ENABLED} pre-valid: {}:{}@{} in {}, msg: {}",
                        cluster.getDom().getName(), ip.getIp(), ip.getPort(), cluster.getName(), ip.getOKCount(), msg);
                }
            }
        } catch (Throwable t) {
            Loggers.SRV_LOG.error("[CHECK-OK] error when close check task.", t);
        }

        ip.getFailCount().set(0);
        ip.setBeingChecked(false);
    }

    protected void checkFail(IpAddress ip, HealthCheckTask task, String msg) {
        Cluster cluster = task.getCluster();

        try {
            if (ip.isValid() || ip.isMockValid()) {
                if (ip.getFailCount().incrementAndGet() >= Switch.getCheckTimes()) {
                    if (cluster.responsible(ip)) {
                        ip.setValid(false);
                        ip.setMockValid(false);

                        VirtualClusterDomain vDom = (VirtualClusterDomain) cluster.getDom();
                        vDom.setLastModifiedMillis(System.currentTimeMillis());
                        addResult(new HealthCheckResult(vDom.getName(), ip));

                        PushService.domChanged(vDom.getNamespaceId(), vDom.getName());

                        Loggers.EVT_LOG.info("dom: {} {POS} {IP-DISABLED} invalid: {}:{}@{}, region: {}, msg: {}",
                            cluster.getDom().getName(), ip.getIp(), ip.getPort(), cluster.getName(), DistroMapper.LOCALHOST_SITE, msg);
                    } else {
                        Loggers.EVT_LOG.info("dom: {} {PROBE} {IP-DISABLED} invalid: {}:{}@{}, region: {}, msg: {}",
                            cluster.getDom().getName(), ip.getIp(), ip.getPort(), cluster.getName(), DistroMapper.LOCALHOST_SITE, msg);
                    }

                } else {
                    Loggers.EVT_LOG.info("dom: {} {OTHER} {IP-DISABLED} pre-invalid: {}:{}@{} in {}, msg: {}",
                        cluster.getDom().getName(), ip.getIp(), ip.getPort(), cluster.getName(), ip.getFailCount(), msg);
                }
            }
        } catch (Throwable t) {
            Loggers.SRV_LOG.error("[CHECK-FAIL] error when close check task.", t);
        }

        ip.getOKCount().set(0);

        ip.setBeingChecked(false);
    }

    protected void checkFailNow(IpAddress ip, HealthCheckTask task, String msg) {
        Cluster cluster = task.getCluster();
        try {
            if (ip.isValid() || ip.isMockValid()) {
                if (cluster.responsible(ip)) {
                    ip.setValid(false);
                    ip.setMockValid(false);

                    VirtualClusterDomain vDom = (VirtualClusterDomain) cluster.getDom();
                    vDom.setLastModifiedMillis(System.currentTimeMillis());

                    PushService.domChanged(vDom.getNamespaceId(), vDom.getName());
                    addResult(new HealthCheckResult(vDom.getName(), ip));

                    Loggers.EVT_LOG.info("dom: {} {POS} {IP-DISABLED} invalid-now: {}:{}@{}, region: {}, msg: {}",
                        cluster.getDom().getName(), ip.getIp(), ip.getPort(), cluster.getName(), DistroMapper.LOCALHOST_SITE, msg);
                } else {
                    if (ip.isMockValid()) {
                        ip.setMockValid(false);
                        Loggers.EVT_LOG.info("dom: {} {PROBE} {IP-DISABLED} invalid-now: {}:{}@{}, region: {}, msg: {}",
                            cluster.getDom().getName(), ip.getIp(), ip.getPort(), cluster.getName(), DistroMapper.LOCALHOST_SITE, msg);
                    }

                }
            }
        } catch (Throwable t) {
            Loggers.SRV_LOG.error("[CHECK-FAIL-NOW] error when close check task.", t);
        }

        ip.getOKCount().set(0);
        ip.setBeingChecked(false);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy