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();
// 直接获取health路径会出现 主机名+health 的情况,虽然是由于配置不规范照成的,但是还是劲量保证地址的正确性
String body = isTheServiceAbnormal(instanceInfo.getHomePageUrl() + "health");
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(String health) {
String body = null;
try {
//body = restTemplate.getForObject(health, String.class);
String data = restTemplate.getForObject(health, 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;
}
}
}
上一篇:SpringCloud(一)_健康自检


下一篇:自己从0开始学习Unity的笔记 VIII (C#中类继承练习 II)