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; } } }