Spring Cloud health节点通过注册中心扫描状态的简单实现

package com.zjs.web;

import com.netflix.appinfo.InstanceInfo;
import com.zjs.FallbackApiApplication;
import lombok.Data;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.netflix.eureka.EurekaDiscoveryClient;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 李文
 * @create 2019-05-27 11:42
 **/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = FallbackApiApplication.class)
public class EurekaUrlTest
{
    Logger logger = LoggerFactory.getLogger(this.getClass());
    private static Map<String, ExceptionCount> maps = new ConcurrentHashMap<>();

    @Autowired
    private DiscoveryClient discoveryClient;
    private RestTemplate restTemplate;

    public EurekaUrlTest() {
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        requestFactory.setConnectTimeout(1000);
        requestFactory.setReadTimeout(1000);
        restTemplate = new RestTemplate(requestFactory);
    }


    @Test
    public void test_1() {
        List<String> services = discoveryClient.getServices();
        for (String service : services) {
            List<ServiceInstance> sis = discoveryClient.getInstances(service);
            for (ServiceInstance si : sis) {
                EurekaDiscoveryClient.EurekaServiceInstance s = (EurekaDiscoveryClient.EurekaServiceInstance) si;
                InstanceInfo instanceInfo = s.getInstanceInfo();
                String body = isTheServiceAbnormal(instanceInfo);
                exceptionServiceHandling(instanceInfo, body);
            }
        }
    }

    @Test
    public void test_2() {
        for (int i = 0; i < 3; i++) {
            test_1();
        }
    }

    private void exceptionServiceHandling(InstanceInfo instanceInfo, String body) {
        if (!StringUtils.isEmpty(body)) {
            ExceptionCount count = maps.get(instanceInfo.getInstanceId());
            if (count == null) {
                maps.put(instanceInfo.getInstanceId(), new ExceptionCount(instanceInfo, body));
            } else {
                if (count.continuousAnomalies()) {
                    count.setData(body);
                    //TODO 推送消息  清空计量 重新开始
                    System.out.println(instanceInfo.getInstanceId() + "  触发异常推送  ");
                    maps.remove(instanceInfo.getInstanceId());
                } else {
                    maps.put(instanceInfo.getInstanceId(), count);
                }
            }
        }
    }

    private String isTheServiceAbnormal(InstanceInfo health) {
        String body = null;
        try {
            //body = restTemplate.getForObject(health, String.class);
            // 直接获取health路径会出现 主机名+health 的情况,虽然是由于配置不规范照成的,
            // 但是还是劲量保证地址的正确性 通过IP 和 端口 来替换掉原先的
            String healthURL = health.getHealthCheckUrl();
            java.net.URL url = new java.net.URL(healthURL);
            String httpUlr = healthURL.replace(url.getHost(), health.getIPAddr())
                    .replace(String.valueOf(url.getPort()), String.valueOf(health.getPort()));
            String data = restTemplate.getForObject(httpUlr, String.class);
            logger.info(data);
        } catch (Exception e) {
            body = e.getMessage();
            logger.info(body);
        }
        return body;
        //if (body.contains("DOWN")) {
        //    return body;
        //} else {
        //    return null;
        //}
    }

    @Data
    public class ExceptionCount
    {
        ExceptionCount(InstanceInfo i, String body) {
            this.data = body;
            this.date = new Date();
            this.frequency = 1;
            this.instanceId = i.getInstanceId();
            this.appName = i.getInstanceId();
            this.appGroupName = i.getAppGroupName();
            this.ipAddr = i.getIPAddr();
            this.homePageUrl = i.getHomePageUrl();
            this.statusPageUrl = i.getStatusPageUrl();
            this.healthCheckUrl = i.getHealthCheckUrl();
            this.secureHealthCheckUrl = i.getSecureHealthCheckUrl();
            this.vipAddress = i.getVIPAddress();
        }

        private String data;
        private Date date;
        private Integer frequency;
        private String instanceId;
        private String appName;
        private String appGroupName;
        private String ipAddr;
        private String homePageUrl;
        private String statusPageUrl;
        private String healthCheckUrl;
        private String secureHealthCheckUrl;
        private String vipAddress;

        boolean continuousAnomalies() {
            Date newDate = new Date();
            long time = newDate.getTime() - date.getTime();
            //判断时间 是否小于等于 3分钟
            if (time <= (180 * 1000)) {
                date = new Date();
                ++frequency;
            } else {
                // 大于 3分钟 说明不是连续的错误
                frequency = 1;
            }
            return frequency >= 3;
        }
    }
}

 

posted @ 2019-05-28 09:36  atliwen  阅读(762)  评论(0编辑  收藏  举报