Typed 서킷브레이커 추가
This commit is contained in:
+61
@@ -0,0 +1,61 @@
|
||||
package com.eactive.eai.agent.circuitBreaker.type;
|
||||
|
||||
import com.eactive.eai.agent.command.Command;
|
||||
import com.eactive.eai.agent.command.CommandException;
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
import com.eactive.eai.common.circuitBreaker.type.TypedCircuitBreakerManager;
|
||||
|
||||
public class ReloadTypedCircuitBreakerCommand extends Command {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ReloadTypedCircuitBreakerCommand() {
|
||||
super("ReloadInflowInterfaceControlCommand");
|
||||
}
|
||||
|
||||
public Object execute() throws CommandException {
|
||||
Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
|
||||
if (logger.isInfo()) {
|
||||
logger.info(this.name + " is executed");
|
||||
}
|
||||
|
||||
String keyName;
|
||||
if (!(this.args instanceof String)) {
|
||||
keyName = "RECEAIMCM001";
|
||||
String msg = this.makeException(keyName, (Throwable) null);
|
||||
if (logger.isError()) {
|
||||
logger.error(msg);
|
||||
}
|
||||
|
||||
throw new CommandException(msg);
|
||||
} else {
|
||||
keyName = (String) this.args;
|
||||
|
||||
try {
|
||||
TypedCircuitBreakerManager manager = TypedCircuitBreakerManager.getInstance();
|
||||
if (keyName != null) {
|
||||
if ("ALL".equals(keyName)) {
|
||||
manager.reload();
|
||||
if (logger.isWarn()) {
|
||||
logger.warn(this.name + "] all rule Reload.");
|
||||
}
|
||||
} else {
|
||||
manager.reload(keyName);
|
||||
if (logger.isWarn()) {
|
||||
logger.warn(this.name + "] " + keyName + " Reload.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "success";
|
||||
} catch (Exception var6) {
|
||||
String rspErrorCode = "RECEAIMCM002";
|
||||
String msg = this.makeException(rspErrorCode, var6);
|
||||
if (logger.isError()) {
|
||||
logger.error(msg, var6);
|
||||
}
|
||||
|
||||
throw new CommandException(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.eactive.eai.common.circuitBreaker.type;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.eactive.eai.common.circuitbreak.loader.CircuitBreakerConfigLoader;
|
||||
import com.eactive.eai.common.dao.BaseDAO;
|
||||
import com.eactive.eai.common.dao.DAOException;
|
||||
import com.eactive.eai.common.exception.ExceptionUtil;
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
import com.eactive.eai.data.entity.onl.circuitbreaker.CircuitBreakerConfig;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
public class TypedCircuitBreakerDAO extends BaseDAO {
|
||||
private static Logger logger;
|
||||
@Autowired
|
||||
private CircuitBreakerConfigLoader loader;
|
||||
@Autowired
|
||||
private TypedCircuitBreakerMapper mapper;
|
||||
|
||||
public List<TypedCircuitBreakerVO> getList() throws DAOException {
|
||||
try {
|
||||
Iterable<CircuitBreakerConfig> rows = this.loader.findAll();
|
||||
List<TypedCircuitBreakerVO> result = new ArrayList<>();
|
||||
logger.info("[ @@ Load UrlCircuitBreaker Configuration - starting >>>>>>>>>>>>>>>>> ]");
|
||||
for ( CircuitBreakerConfig row : rows ) {
|
||||
result.add(this.mapper.toVo(row));
|
||||
}
|
||||
|
||||
logger.info("[>> Load UrlCircuitBreaker Configuration - ended ]");
|
||||
return result;
|
||||
} catch (Exception var5) {
|
||||
throw new DAOException(ExceptionUtil.getErrorCode(var5, "RECEAICMM101"));
|
||||
}
|
||||
}
|
||||
|
||||
public TypedCircuitBreakerVO get(String key) throws DAOException {
|
||||
TypedCircuitBreakerVO var3;
|
||||
try {
|
||||
logger.info("[ @@ Load UrlCircuitBreaker Configuration - starting >>>>>>>>>>>>>>>>> " + key + "]");
|
||||
Optional<CircuitBreakerConfig> optionalRow = this.loader.findById(key);
|
||||
if (!optionalRow.isPresent()) {
|
||||
var3 = null;
|
||||
return var3;
|
||||
}
|
||||
|
||||
var3 = this.mapper.toVo((CircuitBreakerConfig) optionalRow.get());
|
||||
} catch (Exception var7) {
|
||||
throw new DAOException(ExceptionUtil.getErrorCode(var7, "RECEAICMM101"));
|
||||
} finally {
|
||||
logger.info("[>> Load UrlCircuitBreaker Configuration - ended " + key + "]");
|
||||
}
|
||||
|
||||
return var3;
|
||||
}
|
||||
|
||||
static {
|
||||
logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
|
||||
}
|
||||
}
|
||||
+562
@@ -0,0 +1,562 @@
|
||||
package com.eactive.eai.common.circuitBreaker.type;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.eactive.eai.common.exception.ExceptionUtil;
|
||||
import com.eactive.eai.common.lifecycle.Lifecycle;
|
||||
import com.eactive.eai.common.lifecycle.LifecycleException;
|
||||
import com.eactive.eai.common.lifecycle.LifecycleListener;
|
||||
import com.eactive.eai.common.lifecycle.LifecycleSupport;
|
||||
import com.eactive.eai.common.property.PropManager;
|
||||
import com.eactive.eai.common.util.ApplicationContextProvider;
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
import com.eactive.eai.custom.alarm.AlarmStateManager;
|
||||
import com.eactive.eai.custom.alarm.condition.AlarmCondition;
|
||||
import com.eactive.eai.custom.alarm.event.AlarmEvent;
|
||||
import com.eactive.eai.custom.alarm.key.CoreAlarmKey;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
|
||||
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
|
||||
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig.SlidingWindowType;
|
||||
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
|
||||
import io.github.resilience4j.circuitbreaker.event.CircuitBreakerEvent;
|
||||
import io.github.resilience4j.circuitbreaker.event.CircuitBreakerOnStateTransitionEvent;
|
||||
import io.github.resilience4j.core.EventConsumer;
|
||||
import io.github.resilience4j.micrometer.tagged.TaggedCircuitBreakerMetrics;
|
||||
import io.micrometer.prometheus.PrometheusConfig;
|
||||
import io.micrometer.prometheus.PrometheusMeterRegistry;
|
||||
import io.vavr.collection.Seq;
|
||||
|
||||
@Component
|
||||
public class TypedCircuitBreakerManager implements Lifecycle {
|
||||
static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
|
||||
private static final String DEFAULT_CIRCUITBREAKER_NAME = "default";
|
||||
PrometheusMeterRegistry meterRegistry;
|
||||
CircuitBreakerRegistry circuitBreakerRegistry;
|
||||
TypedCircuitBreakerVO defaultConfigVo;
|
||||
HashMap<String, TypedCircuitBreakerVO> apiIdCBConfigMap = new HashMap<>();
|
||||
HashMap<String, TypedCircuitBreakerVO> urlCBConfigMap = new HashMap<>();
|
||||
private boolean started;
|
||||
|
||||
@Autowired
|
||||
private TypedCircuitBreakerDAO dao;
|
||||
private LifecycleSupport lifecycle = new LifecycleSupport(this);
|
||||
|
||||
public static synchronized TypedCircuitBreakerManager getInstance() {
|
||||
return (TypedCircuitBreakerManager) ApplicationContextProvider.getContext()
|
||||
.getBean(TypedCircuitBreakerManager.class);
|
||||
}
|
||||
|
||||
public void addLifecycleListener(LifecycleListener listener) {
|
||||
this.lifecycle.addLifecycleListener(listener);
|
||||
}
|
||||
|
||||
public LifecycleListener[] findLifecycleListeners() {
|
||||
return this.lifecycle.findLifecycleListeners();
|
||||
}
|
||||
|
||||
public void removeLifecycleListener(LifecycleListener listener) {
|
||||
this.lifecycle.removeLifecycleListener(listener);
|
||||
}
|
||||
|
||||
private void init() throws Exception {
|
||||
this.meterRegistry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
|
||||
int failureRateThreshold = NumberUtils
|
||||
.toInt(PropManager.getInstance().getProperty("CircuitBreaker", "failureRateThreshold"), 50);
|
||||
int slidingWindowSize = NumberUtils
|
||||
.toInt(PropManager.getInstance().getProperty("CircuitBreaker", "slidingWindowSize"), 100);
|
||||
int minimumNumberOfCalls = NumberUtils
|
||||
.toInt(PropManager.getInstance().getProperty("CircuitBreaker", "minimumNumberOfCalls"), 100);
|
||||
int waitDurationInOpenState = NumberUtils
|
||||
.toInt(PropManager.getInstance().getProperty("CircuitBreaker", "waitDurationInOpenState"), 60);
|
||||
int permittedNumberOfCallsInHalfOpenState = NumberUtils.toInt(
|
||||
PropManager.getInstance().getProperty("CircuitBreaker", "permittedNumberOfCallsInHalfOpenState"), 10);
|
||||
int slowCallRateThreshold = NumberUtils
|
||||
.toInt(PropManager.getInstance().getProperty("CircuitBreaker", "slowCallRateThreshold"), 100);
|
||||
int slowCallDurationThreshold = NumberUtils
|
||||
.toInt(PropManager.getInstance().getProperty("CircuitBreaker", "slowCallDurationThreshold"), 5);
|
||||
String useYn = PropManager.getInstance().getProperty("CircuitBreaker", "useYn", "N");
|
||||
useYn = normalizeUseYn(useYn);
|
||||
|
||||
CircuitBreakerConfig defaultConfig = CircuitBreakerConfig.custom()
|
||||
.failureRateThreshold((float) failureRateThreshold).slidingWindowSize(slidingWindowSize)
|
||||
.minimumNumberOfCalls(minimumNumberOfCalls)
|
||||
.waitDurationInOpenState(Duration.ofSeconds((long) waitDurationInOpenState))
|
||||
.permittedNumberOfCallsInHalfOpenState(permittedNumberOfCallsInHalfOpenState)
|
||||
.slidingWindowType(SlidingWindowType.COUNT_BASED).slowCallRateThreshold((float) slowCallRateThreshold)
|
||||
.slowCallDurationThreshold(Duration.ofSeconds((long) slowCallDurationThreshold)).build();
|
||||
this.defaultConfigVo = TypedCircuitBreakerVO.builder().name(DEFAULT_CIRCUITBREAKER_NAME).failureRateThreshold(failureRateThreshold)
|
||||
.slidingWindowSize(slidingWindowSize).minimumNumberOfCalls(minimumNumberOfCalls)
|
||||
.waitDurationInOpenState(waitDurationInOpenState)
|
||||
.permittedNumberOfCallsInHalfOpenState(permittedNumberOfCallsInHalfOpenState)
|
||||
.slowCallRateThreshold(slowCallRateThreshold).slowCallDurationThreshold(slowCallDurationThreshold)
|
||||
.useYn(useYn).circuitBreakerConfig(defaultConfig).build();
|
||||
this.circuitBreakerRegistry = CircuitBreakerRegistry.of(defaultConfig);
|
||||
CircuitBreakerConfig defaultCircuitBreakerConfig = this.createCircuitBreakerConfig(this.defaultConfigVo);
|
||||
this.defaultConfigVo.setCircuitBreakerConfig(defaultCircuitBreakerConfig);
|
||||
this.apiIdCBConfigMap.put(DEFAULT_CIRCUITBREAKER_NAME, this.defaultConfigVo);
|
||||
List<TypedCircuitBreakerVO> circuitBreakerList = this.dao.getList();
|
||||
|
||||
for (TypedCircuitBreakerVO vo : circuitBreakerList) {
|
||||
if (!StringUtils.equalsIgnoreCase(vo.useYn, "1")) {
|
||||
this.apiIdCBConfigMap.remove(vo.getName());
|
||||
logger.info("init skip (useYn) - " + vo);
|
||||
} else {
|
||||
CircuitBreakerConfig circuitBreakerConfig = this.createCircuitBreakerConfig(vo);
|
||||
vo.setCircuitBreakerConfig(circuitBreakerConfig);
|
||||
this.apiIdCBConfigMap.put(vo.getName(), vo);
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("init map - " + this.apiIdCBConfigMap);
|
||||
TaggedCircuitBreakerMetrics.ofCircuitBreakerRegistry(this.circuitBreakerRegistry).bindTo(this.meterRegistry);
|
||||
logger.info("init default - " + this.defaultConfigVo);
|
||||
for (TypedCircuitBreakerVO vo : circuitBreakerList) {
|
||||
CircuitBreaker cbreaker = this.getCircuitBreaker(vo.getName());
|
||||
this.printCircuitBreakerInfo(vo.getName(), cbreaker);
|
||||
}
|
||||
|
||||
CircuitBreaker cbreaker = this.getCircuitBreaker(DEFAULT_CIRCUITBREAKER_NAME);
|
||||
this.printCircuitBreakerInfo(DEFAULT_CIRCUITBREAKER_NAME, cbreaker);
|
||||
this.addListenerAll();
|
||||
}
|
||||
|
||||
private String normalizeUseYn(String useYn) {
|
||||
if(StringUtils.equalsAnyIgnoreCase(useYn, "Y", "1"))
|
||||
useYn = "1";//사용
|
||||
else
|
||||
useYn = "0";
|
||||
return useYn;
|
||||
}
|
||||
|
||||
private CircuitBreakerConfig createCircuitBreakerConfig(TypedCircuitBreakerVO vo) {
|
||||
return CircuitBreakerConfig.custom().failureRateThreshold((float) vo.failureRateThreshold)
|
||||
.slidingWindowSize(vo.slidingWindowSize).minimumNumberOfCalls(vo.minimumNumberOfCalls)
|
||||
.waitDurationInOpenState(Duration.ofSeconds((long) vo.waitDurationInOpenState))
|
||||
.permittedNumberOfCallsInHalfOpenState(vo.permittedNumberOfCallsInHalfOpenState)
|
||||
.slidingWindowType(SlidingWindowType.COUNT_BASED)
|
||||
.slowCallRateThreshold((float) vo.slowCallRateThreshold)
|
||||
.slowCallDurationThreshold(Duration.ofSeconds((long) vo.slowCallDurationThreshold)).build();
|
||||
}
|
||||
|
||||
public void reload() throws Exception {
|
||||
this.init();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void reload(String key) throws Exception {
|
||||
logger.info("reload start.");
|
||||
TypedCircuitBreakerVO vo = this.dao.get(key);
|
||||
if (StringUtils.equalsIgnoreCase(vo.useYn, "0")) {
|
||||
this.apiIdCBConfigMap.remove(vo.getName());
|
||||
this.circuitBreakerRegistry.remove(vo.getName());
|
||||
logger.info("removed. - " + vo);
|
||||
} else {
|
||||
CircuitBreakerConfig circuitBreakerConfig = this.createCircuitBreakerConfig(vo);
|
||||
vo.setCircuitBreakerConfig(circuitBreakerConfig);
|
||||
this.apiIdCBConfigMap.put(vo.getName(), vo);
|
||||
CircuitBreaker oldBreaker = this.circuitBreakerRegistry.circuitBreaker(vo.getName());
|
||||
if(oldBreaker != null)
|
||||
logger.info("oldBreaker={}, waitDurationInOpenState={}", new Object[]{oldBreaker.getCircuitBreakerConfig(),
|
||||
oldBreaker.getCircuitBreakerConfig().getWaitDurationInOpenState()});
|
||||
this.circuitBreakerRegistry.remove(vo.getName());
|
||||
this.circuitBreakerRegistry.circuitBreaker(vo.getName(), vo.getCircuitBreakerConfig());
|
||||
this.addListener(vo.getName());
|
||||
CircuitBreaker newBreaker = this.circuitBreakerRegistry.circuitBreaker(vo.getName());
|
||||
logger.info("newBreaker={}, waitDurationInOpenState={}", new Object[]{newBreaker.getCircuitBreakerConfig(),
|
||||
newBreaker.getCircuitBreakerConfig().getWaitDurationInOpenState()});
|
||||
logger.info("reload end." + vo);
|
||||
}
|
||||
}
|
||||
|
||||
public PrometheusMeterRegistry getMeterRegistry() {
|
||||
return this.meterRegistry;
|
||||
}
|
||||
|
||||
public void start() throws LifecycleException {
|
||||
this.lifecycle.fireLifecycleEvent("starting", this);
|
||||
|
||||
try {
|
||||
this.init();
|
||||
} catch (Exception var2) {
|
||||
throw new LifecycleException(ExceptionUtil.getErrorCode(var2, "RECEAICMM202"));
|
||||
}
|
||||
|
||||
this.started = true;
|
||||
this.lifecycle.fireLifecycleEvent("started", this);
|
||||
}
|
||||
|
||||
public void stop() throws LifecycleException {
|
||||
if (!this.started) {
|
||||
throw new LifecycleException("RECEAICRT203");
|
||||
} else {
|
||||
this.lifecycle.fireLifecycleEvent("stoping", this);
|
||||
this.started = false;
|
||||
this.circuitBreakerRegistry = null;
|
||||
this.lifecycle.fireLifecycleEvent("stopped", this);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isStarted() {
|
||||
return this.started;
|
||||
}
|
||||
|
||||
public CircuitBreaker getCircuitBreaker(String apiId) {
|
||||
CircuitBreaker circuitBreaker = this.getCircuitBreakerInternal(apiId);
|
||||
if (circuitBreaker != null) {
|
||||
return circuitBreaker;
|
||||
} else {
|
||||
return this.getCircuitBreakerInternal(DEFAULT_CIRCUITBREAKER_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
private CircuitBreaker getCircuitBreakerInternal(String url) {
|
||||
TypedCircuitBreakerVO vo = (TypedCircuitBreakerVO) this.apiIdCBConfigMap.get(url);
|
||||
if (vo == null) {
|
||||
return null;
|
||||
} else {
|
||||
return StringUtils.equals(vo.getUseYn(), "0")
|
||||
? null
|
||||
: this.circuitBreakerRegistry.circuitBreaker(url, vo.getCircuitBreakerConfig());
|
||||
}
|
||||
}
|
||||
|
||||
// public CircuitBreaker getUrlCircuitBreaker(String url) {
|
||||
// CircuitBreaker circuitBreaker = this.getUrlCircuitBreakerInternal(url);
|
||||
// if (circuitBreaker != null) {
|
||||
// return circuitBreaker;
|
||||
// } else {
|
||||
// URI uri = null;
|
||||
//
|
||||
// try {
|
||||
// uri = URLUtils.createURI(url);
|
||||
// } catch (Exception var6) {
|
||||
// logger.error("malformed url : " + url);
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// String tmpUrl = URLUtils.getURLWithoutQuery(uri);
|
||||
// circuitBreaker = this.getUrlCircuitBreakerInternal(tmpUrl);
|
||||
// if (circuitBreaker != null) {
|
||||
// return circuitBreaker;
|
||||
// } else {
|
||||
// String host = URLUtils.getHost(uri);
|
||||
// circuitBreaker = this.getUrlCircuitBreakerInternal(host);
|
||||
// return circuitBreaker != null ? circuitBreaker : this.getUrlCircuitBreakerInternal(DEFAULT_CIRCUITBREAKER_NAME);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private CircuitBreaker getUrlCircuitBreakerInternal(String url) {
|
||||
// TypedCircuitBreakerVO vo = (TypedCircuitBreakerVO) this.urlCBConfigMap.get(url);
|
||||
// if (vo == null) {
|
||||
// return null;
|
||||
// } else {
|
||||
// return StringUtils.equals(vo.getUseYn(), "0")
|
||||
// ? null
|
||||
// : this.circuitBreakerRegistry.circuitBreaker(url, vo.getCircuitBreakerConfig());
|
||||
// }
|
||||
// }
|
||||
|
||||
public String printCircuitBreakerInfo(String prefix, CircuitBreaker circuitBreaker) {
|
||||
if (circuitBreaker == null) {
|
||||
logger.info("CircuitBreaker state : " + prefix + " - null");
|
||||
return "null";
|
||||
} else {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
ObjectNode combinedNode = objectMapper.createObjectNode();
|
||||
combinedNode.put("state", circuitBreaker.getState().toString());
|
||||
combinedNode.put("config", circuitBreaker.getCircuitBreakerConfig().toString());
|
||||
combinedNode.set("metrics", objectMapper.valueToTree(circuitBreaker.getMetrics()));
|
||||
logger.info("CircuitBreaker state : " + prefix + " - " + combinedNode.toString());
|
||||
return combinedNode.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public void addListenerAll() {
|
||||
if (this.circuitBreakerRegistry != null) {
|
||||
Seq<CircuitBreaker> circuitBreakers = this.circuitBreakerRegistry.getAllCircuitBreakers();
|
||||
for (CircuitBreaker cBreaker : circuitBreakers) {
|
||||
TypedCircuitBreakerVO vo = (TypedCircuitBreakerVO) this.apiIdCBConfigMap.get(cBreaker.getName());
|
||||
cBreaker.getEventPublisher().onEvent(new CustomCircuitBreakerEventConsumer(vo));
|
||||
logger.info("Added Listener.[{}]", new Object[]{cBreaker.getName()});
|
||||
}
|
||||
|
||||
logger.info("Added all Listener.");
|
||||
} else {
|
||||
logger.error("CircuitBreakerRegistry not initialized.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void addListener(String cBreakerName) {
|
||||
if (this.circuitBreakerRegistry != null) {
|
||||
CircuitBreaker cBreaker = this.circuitBreakerRegistry.circuitBreaker(cBreakerName);
|
||||
if (cBreaker != null) {
|
||||
TypedCircuitBreakerVO vo = (TypedCircuitBreakerVO) this.apiIdCBConfigMap.get(cBreakerName);
|
||||
cBreaker.getEventPublisher().onEvent(new CustomCircuitBreakerEventConsumer(vo));
|
||||
logger.info("Added Listener.");
|
||||
} else {
|
||||
logger.error("CircuitBreaker[{}] not exist.", new Object[]{cBreakerName});
|
||||
}
|
||||
} else {
|
||||
logger.error("CircuitBreakerRegistry not initialized.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class CustomCircuitBreakerEventConsumer implements EventConsumer<CircuitBreakerEvent> {
|
||||
TypedCircuitBreakerVO vo;
|
||||
// private static final int MAX_THREADS = 5;
|
||||
// private static final ExecutorService ALERT_EXECUTOR;
|
||||
|
||||
public CustomCircuitBreakerEventConsumer(TypedCircuitBreakerVO vo) {
|
||||
this.vo = vo;
|
||||
}
|
||||
|
||||
public void consumeEvent(CircuitBreakerEvent event) {
|
||||
switch (event.getEventType()) {
|
||||
case ERROR :
|
||||
TypedCircuitBreakerManager.logger
|
||||
.error("CirbuitBreaker ERROR event occurred. CircuitBreakerEvent={}" + event);
|
||||
break;
|
||||
case STATE_TRANSITION :
|
||||
if (event instanceof CircuitBreakerOnStateTransitionEvent) {
|
||||
CircuitBreakerOnStateTransitionEvent stateTransitionEvent = (CircuitBreakerOnStateTransitionEvent) event;
|
||||
CircuitBreaker.StateTransition stateTransition = stateTransitionEvent.getStateTransition();
|
||||
CircuitBreaker.State toState = stateTransition.getToState();
|
||||
CircuitBreaker.State fromState = stateTransition.getFromState();
|
||||
TypedCircuitBreakerManager.logger.error(
|
||||
"CirbuitBreaker STATE_TRANSITION event occurred. {} : {} -> {}. CircuitBreakerEvent={}, UrlCircuitBreakerVO={}",
|
||||
new Object[]{event.getCircuitBreakerName(), fromState, toState, event, this.vo});
|
||||
// if (!toState.equals(State.OPEN) && !toState.equals(State.HALF_OPEN)
|
||||
// && !toState.equals(State.CLOSED)) {
|
||||
// TypedCircuitBreakerManager.logger.debug(
|
||||
// "CirbuitBreaker STATE_TRANSITION event alert 대상 아님. CircuitBreakerEvent={}, UrlCircuitBreakerVO={}",
|
||||
// new Object[]{event, this.vo});
|
||||
// } else {
|
||||
// this.sendAlert(stateTransitionEvent);
|
||||
// }
|
||||
AlarmEvent alarmEvent = AlarmEvent.builder().key(CoreAlarmKey.CircuitBreaker)
|
||||
.condition(AlarmCondition.builder().build())
|
||||
.message(String.format("CircuitBreaker state changed. apiId=%s, %s -> %s", event.getCircuitBreakerName(), fromState, toState))
|
||||
.build();
|
||||
|
||||
AlarmStateManager.getAlarmStateManager().onEvnet(alarmEvent);
|
||||
|
||||
logger.warn("CircuitBreaker state changed. apiId={}, {} -> {}", event.getCircuitBreakerName(), fromState, toState);
|
||||
|
||||
} else {
|
||||
TypedCircuitBreakerManager.logger.error(
|
||||
"CirbuitBreaker STATE_TRANSITION event occurred. CircuitBreakerEvent={}, UrlCircuitBreakerVO={}",
|
||||
new Object[]{event, this.vo});
|
||||
}
|
||||
break;
|
||||
|
||||
case NOT_PERMITTED :
|
||||
TypedCircuitBreakerManager.logger
|
||||
.warn("CirbuitBreaker NOT_PERMITTED event occurred. CircuitBreakerEvent={}" + event);
|
||||
break;
|
||||
default :
|
||||
TypedCircuitBreakerManager.logger
|
||||
.info("CirbuitBreaker event occurred. CircuitBreakerEvent={}" + event);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// private void sendAlert(final CircuitBreakerOnStateTransitionEvent event) {
|
||||
// this.runAsync(new Runnable() {
|
||||
// public void run() {
|
||||
// try {
|
||||
// String alertUrl = PropManager.getInstance().getProperty("CircuitBreaker", "alert.url");
|
||||
// if (StringUtils.isEmpty(alertUrl)) {
|
||||
// TypedCircuitBreakerManager.logger.warn("alert skip - alertUrl not set. - {}",
|
||||
// new Object[]{event});
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// String sendEventType = PropManager.getInstance().getProperty("CircuitBreaker",
|
||||
// "alert.message.send.event.type", "OPEN,HALF_OPEN,CLOSED");
|
||||
// String[] sendEventTypeArr = sendEventType.split(",");
|
||||
// CircuitBreaker.StateTransition stateTransition = event.getStateTransition();
|
||||
// CircuitBreaker.State toState = stateTransition.getToState();
|
||||
// boolean bSend = false;
|
||||
// String[] var7 = sendEventTypeArr;
|
||||
// int var8 = sendEventTypeArr.length;
|
||||
//
|
||||
// for (int var9 = 0; var9 < var8; ++var9) {
|
||||
// String eventType = var7[var9];
|
||||
// if (State.valueOf(eventType).equals(toState)) {
|
||||
// bSend = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (bSend) {
|
||||
// String json = CustomCircuitBreakerEventConsumer.this.createAlertMessage(event);
|
||||
// TypedCircuitBreakerManager.logger.info("alert request - {}", new Object[]{json});
|
||||
// String result = CustomCircuitBreakerEventConsumer.this.httpPost(alertUrl, json);
|
||||
// TypedCircuitBreakerManager.logger.info("alert result - {}", new Object[]{result});
|
||||
// } else {
|
||||
// TypedCircuitBreakerManager.logger.info("alert 전송대상 아님 - {}", new Object[]{event});
|
||||
// }
|
||||
// } catch (Exception var11) {
|
||||
// TypedCircuitBreakerManager.logger.error("alert 전송 처리 실패 - {}", event, var11);
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// private void runAsync(Runnable task) {
|
||||
// try {
|
||||
// ALERT_EXECUTOR.execute(task);
|
||||
// } catch (RejectedExecutionException var3) {
|
||||
// TypedCircuitBreakerManager.logger.error("alert 작업 제출 중 예외", var3);
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// private String createAlertMessage(CircuitBreakerOnStateTransitionEvent event) {
|
||||
// String alertMessageTemplate = PropManager.getInstance().getProperty("CircuitBreaker",
|
||||
// "alert.message.template", "CircuitBreaker({url},{desc}){from}->{to}");
|
||||
// String alertMsg = alertMessageTemplate.replace("{url}", this.vo.getName());
|
||||
// alertMsg = alertMsg.replace("{desc}", this.vo.getDesc() + "");
|
||||
// CircuitBreaker.StateTransition stateTransition = event.getStateTransition();
|
||||
// alertMsg = alertMsg.replace("{from}", stateTransition.getFromState() + "");
|
||||
// alertMsg = alertMsg.replace("{to}", stateTransition.getToState() + "");
|
||||
// JSONObject reqJson = new JSONObject();
|
||||
// reqJson.put("alertType", "C");
|
||||
// reqJson.put("alertMsg", alertMsg);
|
||||
// return reqJson.toJSONString();
|
||||
// }
|
||||
//
|
||||
// private String httpPost(String url, String json) {
|
||||
// String resultMsg = "";
|
||||
// StringBuilder result = new StringBuilder();
|
||||
//
|
||||
// try {
|
||||
// URL urlObject = new URL(url);
|
||||
// HttpURLConnection conn = (HttpURLConnection) urlObject.openConnection();
|
||||
// conn.setDoOutput(true);
|
||||
// conn.setDoInput(true);
|
||||
// conn.setRequestProperty("Content-Type", "application/json");
|
||||
// conn.setRequestMethod("POST");
|
||||
// OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
|
||||
// Throwable var8 = null;
|
||||
//
|
||||
// try {
|
||||
// if (StringUtils.isNotEmpty(json)) {
|
||||
// wr.write(json.toString());
|
||||
// wr.flush();
|
||||
// }
|
||||
// } catch (Throwable var55) {
|
||||
// var8 = var55;
|
||||
// throw var55;
|
||||
// } finally {
|
||||
// if (wr != null) {
|
||||
// if (var8 != null) {
|
||||
// try {
|
||||
// wr.close();
|
||||
// } catch (Throwable var54) {
|
||||
// var8.addSuppressed(var54);
|
||||
// }
|
||||
// } else {
|
||||
// wr.close();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// int resStatusCode = conn.getResponseCode();
|
||||
// Throwable var9;
|
||||
// String line;
|
||||
// BufferedReader normalBr;
|
||||
// if (resStatusCode != 201 && resStatusCode != 200) {
|
||||
// TypedCircuitBreakerManager.logger.debug("httpPost call response http code : {}" + resStatusCode);
|
||||
// TypedCircuitBreakerManager.logger
|
||||
// .debug("httpPost call response errror message : {}" + conn.getResponseMessage());
|
||||
// normalBr = new BufferedReader(new InputStreamReader(conn.getErrorStream(), "utf-8"));
|
||||
// var9 = null;
|
||||
//
|
||||
// try {
|
||||
// line = "";
|
||||
//
|
||||
// while ((line = normalBr.readLine()) != null) {
|
||||
// result.append(line);
|
||||
// }
|
||||
// } catch (Throwable var58) {
|
||||
// var9 = var58;
|
||||
// throw var58;
|
||||
// } finally {
|
||||
// if (normalBr != null) {
|
||||
// if (var9 != null) {
|
||||
// try {
|
||||
// normalBr.close();
|
||||
// } catch (Throwable var53) {
|
||||
// var9.addSuppressed(var53);
|
||||
// }
|
||||
// } else {
|
||||
// normalBr.close();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// normalBr = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
|
||||
// var9 = null;
|
||||
//
|
||||
// try {
|
||||
// line = "";
|
||||
//
|
||||
// while ((line = normalBr.readLine()) != null) {
|
||||
// result.append(line);
|
||||
// }
|
||||
// } catch (Throwable var56) {
|
||||
// var9 = var56;
|
||||
// throw var56;
|
||||
// } finally {
|
||||
// if (normalBr != null) {
|
||||
// if (var9 != null) {
|
||||
// try {
|
||||
// normalBr.close();
|
||||
// } catch (Throwable var52) {
|
||||
// var9.addSuppressed(var52);
|
||||
// }
|
||||
// } else {
|
||||
// normalBr.close();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// resultMsg = result.toString();
|
||||
// } catch (Exception var61) {
|
||||
// TypedCircuitBreakerManager.logger.error("url : para data => {} : {}" + url + " : " + json);
|
||||
// TypedCircuitBreakerManager.logger.error("http client error : {}" + var61.getMessage(), var61);
|
||||
// resultMsg = result.toString();
|
||||
// }
|
||||
//
|
||||
// return resultMsg;
|
||||
// }
|
||||
//
|
||||
// static {
|
||||
// ALERT_EXECUTOR = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MICROSECONDS, new SynchronousQueue(),
|
||||
// Executors.defaultThreadFactory(), new RejectedExecutionHandler() {
|
||||
// public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
|
||||
// TypedCircuitBreakerManager.logger.error("alert 작업 거부됨. 쓰레드 모두 사용중입니다.");
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.eactive.eai.common.circuitBreaker.type;
|
||||
|
||||
import com.eactive.eai.data.entity.onl.circuitbreaker.CircuitBreakerConfig;
|
||||
import com.eactive.eai.data.mapper.GenericMapper;
|
||||
import org.mapstruct.InheritInverseConfiguration;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.ReportingPolicy;
|
||||
|
||||
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
|
||||
public interface TypedCircuitBreakerMapper extends GenericMapper<TypedCircuitBreakerVO, CircuitBreakerConfig> {
|
||||
@Mappings({
|
||||
@Mapping(source = "cbreakerName", target = "name"),
|
||||
@Mapping(source = "cbreakerDesc", target = "desc"),
|
||||
@Mapping(source = "cbreakerType", target = "type"),
|
||||
})
|
||||
TypedCircuitBreakerVO toVo(CircuitBreakerConfig var1);
|
||||
|
||||
@InheritInverseConfiguration
|
||||
CircuitBreakerConfig toEntity(TypedCircuitBreakerVO var1);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.eactive.eai.common.circuitBreaker.type;
|
||||
|
||||
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class TypedCircuitBreakerVO {
|
||||
String type;
|
||||
String name;
|
||||
String desc;
|
||||
int failureRateThreshold;
|
||||
int slidingWindowSize;
|
||||
int minimumNumberOfCalls;
|
||||
int waitDurationInOpenState;
|
||||
int permittedNumberOfCallsInHalfOpenState;
|
||||
int slowCallRateThreshold;
|
||||
int slowCallDurationThreshold;
|
||||
String useYn;
|
||||
CircuitBreakerConfig circuitBreakerConfig;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.eactive.eai.common.circuitBreaker.type;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
public class URLUtils {
|
||||
public static URI createURI(String uri) {
|
||||
return URI.create(uri);
|
||||
}
|
||||
|
||||
public static String getURLWithoutQuery(URI uri) {
|
||||
String result = uri.getScheme() + "://" + uri.getHost();
|
||||
if (uri.getPort() != -1) {
|
||||
result = result + ":" + uri.getPort();
|
||||
}
|
||||
|
||||
result = result + uri.getPath();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String getHost(URI uri) {
|
||||
return uri.getHost();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
URI uri = URI.create("http://localhost:8001/path?query=a");
|
||||
System.out.println(uri.getHost());
|
||||
System.out.println(uri.getPath());
|
||||
System.out.println(uri.toString());
|
||||
System.out.println(uri.getRawPath());
|
||||
System.out.println(uri.toURL());
|
||||
System.out.println(getURLWithoutQuery(uri));
|
||||
System.out.println(getHost(uri));
|
||||
uri = URI.create("http://localhost/path?query=a");
|
||||
System.out.println(getURLWithoutQuery(uri));
|
||||
System.out.println(getHost(uri));
|
||||
uri = URI.create("http://localhost/path?query=a");
|
||||
System.out.println(getURLWithoutQuery(uri));
|
||||
System.out.println(getHost(uri));
|
||||
uri = URI.create("http://127.0.0.1/path?query=a");
|
||||
System.out.println(getURLWithoutQuery(uri));
|
||||
System.out.println(getHost(uri));
|
||||
uri = URI.create("http://www.example.com:8080/test/path?query=a");
|
||||
System.out.println(getURLWithoutQuery(uri));
|
||||
System.out.println(getHost(uri));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user