调用注册中心获取应用列表

This commit is contained in:
ChaosCoffee 2018-07-06 18:04:44 +08:00
parent 5c93aac62f
commit 1b8856bf11
6 changed files with 352 additions and 0 deletions

View File

@ -0,0 +1,28 @@
package com.raincat.admin.service.apps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author chaoshen
* @date 2018/7/6
* @description
*/
@Component
public class AcceptApplicationNameExecutor {
@Autowired
AcceptApplicationNameFactory acceptApplicationNameFactory;
/**
* 执行任务
*
* @param apps
*/
public void execute(List<String> apps) {
List<AcceptApplicationNameService> services = acceptApplicationNameFactory.getBeans();
services.forEach(service -> service.acceptAppNameList(apps));
}
}

View File

@ -0,0 +1,128 @@
package com.raincat.admin.service.apps;
import com.google.common.collect.Lists;
import com.raincat.admin.service.apps.enums.AcceptApplicationNameEnum;
import org.springframework.beans.BeansException;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 客户端从注册中心获取应用名称-工厂类
*
* @author chaoshen
* @date 2018/7/6
* @description
*/
@Component
public class AcceptApplicationNameFactory implements ApplicationContextAware {
//@Value("${accept.apps.server.type}")
private String acceptType;
private static AppsType types;
private static Map<AcceptApplicationNameEnum, AcceptApplicationNameService> beanMap;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map<String, AcceptApplicationNameService> map = applicationContext.getBeansOfType(AcceptApplicationNameService.class);
beanMap = new HashMap<>();
map.forEach((k, v) -> beanMap.put(v.code(), v));
}
/**
* 根据不同的类型获取bean
*
* @param code
* @param <T>
* @return
*/
public <T extends AcceptApplicationNameService> T getBean(AcceptApplicationNameEnum code) {
return (T) beanMap.get(code);
}
/**
* 根据配置文件来获取bean
*
* @param <T>
* @return
*/
public <T extends AcceptApplicationNameService> T getBean(String code) {
return getBean(AcceptApplicationNameEnum.getAcceptApplicationNameEnum(code));
}
/**
* 根据单一配置文件来获取bean
*
* @param <T>
* @return
*/
public <T extends AcceptApplicationNameService> T getBean() {
return getBean(acceptType);
}
/**
* 根据配置文件来获取beans
* accept.apps.server.type=eureka,dubbo...
* @param
* @return
*/
public List getBeans0() {
return Arrays.asList(acceptType.split(","))
.stream()
.distinct()
.map(v -> getBean(v))
.collect(Collectors.toList());
}
/**
* 根据配置文件来获取beans
* accept.apps.server.type[0]=eureka
* ...
* @param
* @return
*/
public List getBeans() {
return types.getType()
.stream()
.distinct()
.map(v -> getBean(v))
.collect(Collectors.toList());
}
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "accept.apps.server")
public static class AppsType {
private List<AcceptApplicationNameEnum> type;
@PostConstruct
public void init() {
types = this;
}
public AppsType() {
this.type = Lists.newArrayList();
}
public List<AcceptApplicationNameEnum> getType() {
return type;
}
public void setType(List<AcceptApplicationNameEnum> type) {
this.type = type;
}
}
}

View File

@ -0,0 +1,30 @@
package com.raincat.admin.service.apps;
import com.raincat.admin.service.apps.enums.AcceptApplicationNameEnum;
import java.util.List;
/**
* @author chaoshen
* @date 2018/7/5
* @description 从注册中心获取参与分布式事务应用名称列表
*/
public interface AcceptApplicationNameService {
String APP_URL = "/apps";
/***
* 获取注册中心所有应用列表
* @param apps 已有的应用列表
* @return 去重后的注册中心应用列表
*/
<T> List<T> acceptAppNameList(List<T> apps);
/**
* 注册中心方式
*
* @return 注册中心枚举类
*/
AcceptApplicationNameEnum code();
}

View File

@ -0,0 +1,31 @@
package com.raincat.admin.service.apps.enums;
import lombok.Getter;
/**
* @author chaoshen
* @date 2018/7/5
* @description
*/
public enum AcceptApplicationNameEnum {
EUREKA("eureka"),
ZOOKEEPER("zookeeper"),
DUBBO("dubbo"),
UNACCEPT("no");
@Getter
private String name;
AcceptApplicationNameEnum(String name) {
this.name = name;
}
public static AcceptApplicationNameEnum getAcceptApplicationNameEnum(String name) {
for (AcceptApplicationNameEnum acceptApplicationNameEnum : AcceptApplicationNameEnum.values()) {
if (acceptApplicationNameEnum.name.equals(name)) {
return acceptApplicationNameEnum;
}
}
return UNACCEPT;
}
}

View File

@ -0,0 +1,26 @@
package com.raincat.admin.service.apps.impl;
import com.raincat.admin.service.apps.AcceptApplicationNameService;
import com.raincat.admin.service.apps.enums.AcceptApplicationNameEnum;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author chaoshen
* @date 2018/7/6
* @description
*/
@Service
public class AcceptDefaultApplicationNameService implements AcceptApplicationNameService {
@Override
public <T> List<T> acceptAppNameList(List<T> apps) {
return apps;
}
@Override
public AcceptApplicationNameEnum code() {
return AcceptApplicationNameEnum.UNACCEPT;
}
}

View File

@ -0,0 +1,109 @@
package com.raincat.admin.service.apps.impl;
import com.google.common.collect.Sets;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.raincat.admin.service.apps.AcceptApplicationNameService;
import com.raincat.admin.service.apps.enums.AcceptApplicationNameEnum;
import com.raincat.common.holder.httpclient.OkHttpTools;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Request;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author chaoshen
* @date 2018/7/5
* @description
*/
@Service
@Slf4j
public class AcceptEurekaApplicationNameService implements AcceptApplicationNameService {
@Value("${accept.apps.eureka.url}")
private String eurekaServerUrl;
@Value("${accept.apps.eureka.intervalTime}")
private String appIntervalTime;
private static volatile ConcurrentHashMap<String, Object> CACHE_MAP = new ConcurrentHashMap<>();
private static String UPDATE_TIME_KEY = "ADMIN_UPDATE_TIME";
@Override
public <T> List<T> acceptAppNameList(List<T> apps) {
Object updateTime = CACHE_MAP.get(UPDATE_TIME_KEY);
if (updateTime == null) {
//CACHE_MAP.clear();
log.info("首次加入 [参与分布式事务项目的应用名称] 缓存数据!");
getEurekaAppList().stream().forEach(appName -> CACHE_MAP.put(appName, appName));
} else {
long dValue = System.currentTimeMillis() - (Long) updateTime;
if (dValue > Long.valueOf(appIntervalTime) * 1000) {
//若在eureka里能获取到应用信息说明已经用到分布式事务所以不用删除旧的缓存数据?
//CACHE_MAP.clear();
log.info("刷新 [参与分布式事务项目的应用名称] 缓存数据!");
getEurekaAppList().stream().forEach(appName -> CACHE_MAP.put(appName, appName));
}
}
CACHE_MAP.forEach((s, o) -> {
if (!UPDATE_TIME_KEY.equals(s) && !apps.contains(s)) {
apps.add((T) s);
}
});
return apps;
}
@Override
public AcceptApplicationNameEnum code() {
return AcceptApplicationNameEnum.EUREKA;
}
private Set<String> getEurekaAppList() {
Set<String> set = Sets.newHashSet();
try {
JsonObject response = OkHttpTools.getInstance().execute(buildRequest(eurekaServerUrl + APP_URL), JsonObject.class);
log.debug("Eureka server response: [{}]", response);
if (response == null) {
return set;
}
JsonArray jsonArray = response.getAsJsonObject("applications").getAsJsonArray("application");
if (jsonArray != null) {
jsonArray.forEach(jsonObject -> {
JsonObject application = jsonObject.getAsJsonObject();
//每个实例信息
application.getAsJsonArray("instance").forEach(jsonObj -> {
JsonObject instance = jsonObj.getAsJsonObject();
//是否使用tx
JsonElement jsonElement = instance.getAsJsonObject("metadata").get("tx-metadata");
Optional<String> optional = Optional
.ofNullable(jsonElement)
.map(r -> jsonElement.getAsBoolean() ? "true" : null);
optional.ifPresent(r -> set.add(instance.get("app").getAsString().toLowerCase()));
});
});
}
CACHE_MAP.put(UPDATE_TIME_KEY, System.currentTimeMillis());
} catch (IOException e) {
log.error("Eureka server response analysis error!", e);
}
return set;
}
private static Request buildRequest(String url) {
return new Request.Builder()
.url(url)
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
//.addHeader("Authorization", Credentials.basic("user", "password"))
.build();
}
}