From ffb1c698558d1fce5e1bdabcbdb370d3c18b4c87 Mon Sep 17 00:00:00 2001 From: curry772 Date: Fri, 3 Apr 2026 17:40:10 +0900 Subject: [PATCH] =?UTF-8?q?feature:=20circuitBreaker=20=ED=83=80=EC=9E=85?= =?UTF-8?q?=20=EC=B2=98=EB=A6=AC=20=EB=B0=8F=20RESTProcess=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../type/TypedCircuitBreakerDAO.java | 20 ++++----- .../type/TypedCircuitBreakerManager.java | 15 ++++++- .../type/TypedCircuitBreakerMapper.java | 1 + .../type/TypedCircuitBreakerVO.java | 1 + .../com/eactive/eai/outbound/RESTProcess.java | 41 +++++++++++-------- 5 files changed, 47 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/eactive/eai/common/circuitBreaker/type/TypedCircuitBreakerDAO.java b/src/main/java/com/eactive/eai/common/circuitBreaker/type/TypedCircuitBreakerDAO.java index e465655..dafdfb2 100644 --- a/src/main/java/com/eactive/eai/common/circuitBreaker/type/TypedCircuitBreakerDAO.java +++ b/src/main/java/com/eactive/eai/common/circuitBreaker/type/TypedCircuitBreakerDAO.java @@ -18,7 +18,7 @@ import com.eactive.eai.data.entity.onl.circuitbreaker.CircuitBreakerConfig; @Service @Transactional public class TypedCircuitBreakerDAO extends BaseDAO { - private static Logger logger; + private static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT); @Autowired private CircuitBreakerConfigLoader loader; @Autowired @@ -41,26 +41,22 @@ public class TypedCircuitBreakerDAO extends BaseDAO { } public TypedCircuitBreakerVO get(String key) throws DAOException { - TypedCircuitBreakerVO var3; + TypedCircuitBreakerVO vo; try { logger.info("[ @@ Load UrlCircuitBreaker Configuration - starting >>>>>>>>>>>>>>>>> " + key + "]"); Optional optionalRow = this.loader.findById(key); if (!optionalRow.isPresent()) { - var3 = null; - return var3; + vo = null; + return vo; } - var3 = this.mapper.toVo((CircuitBreakerConfig) optionalRow.get()); - } catch (Exception var7) { - throw new DAOException(ExceptionUtil.getErrorCode(var7, "RECEAICMM101")); + vo = this.mapper.toVo((CircuitBreakerConfig) optionalRow.get()); + } catch (Exception e) { + throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICMM101")); } finally { logger.info("[>> Load UrlCircuitBreaker Configuration - ended " + key + "]"); } - return var3; - } - - static { - logger = Logger.getLogger(Logger.LOGGER_DEFAULT); + return vo; } } \ No newline at end of file diff --git a/src/main/java/com/eactive/eai/common/circuitBreaker/type/TypedCircuitBreakerManager.java b/src/main/java/com/eactive/eai/common/circuitBreaker/type/TypedCircuitBreakerManager.java index c6622ce..6028b9d 100644 --- a/src/main/java/com/eactive/eai/common/circuitBreaker/type/TypedCircuitBreakerManager.java +++ b/src/main/java/com/eactive/eai/common/circuitBreaker/type/TypedCircuitBreakerManager.java @@ -43,6 +43,7 @@ public class TypedCircuitBreakerManager implements Lifecycle { PrometheusMeterRegistry meterRegistry; CircuitBreakerRegistry circuitBreakerRegistry; TypedCircuitBreakerVO defaultConfigVo; + HashMap idCBConfigMap = new HashMap<>(); HashMap apiIdCBConfigMap = new HashMap<>(); HashMap urlCBConfigMap = new HashMap<>(); private boolean started; @@ -109,11 +110,13 @@ public class TypedCircuitBreakerManager implements Lifecycle { for (TypedCircuitBreakerVO vo : circuitBreakerList) { if (!StringUtils.equalsIgnoreCase(vo.useYn, "1")) { this.apiIdCBConfigMap.remove(vo.getName()); + this.idCBConfigMap.remove(vo.getId()); logger.info("init skip (useYn) - " + vo); } else { CircuitBreakerConfig circuitBreakerConfig = this.createCircuitBreakerConfig(vo); vo.setCircuitBreakerConfig(circuitBreakerConfig); this.apiIdCBConfigMap.put(vo.getName(), vo); + this.idCBConfigMap.remove(vo.getId(), vo); } } @@ -156,7 +159,17 @@ public class TypedCircuitBreakerManager implements Lifecycle { public void reload(String key) throws Exception { logger.info("reload start."); TypedCircuitBreakerVO vo = this.dao.get(key); - if (StringUtils.equalsIgnoreCase(vo.useYn, "0")) { + if(vo == null) { + vo = this.idCBConfigMap.get(key); + if(vo != null) { + this.idCBConfigMap.remove(key); + this.apiIdCBConfigMap.remove(vo.getName()); + this.circuitBreakerRegistry.remove(vo.getName()); + logger.info("removed. - " + vo); + } else { + logger.info("not exist in memory. - " + key); + } + } else if (StringUtils.equalsIgnoreCase(vo.useYn, "0")) { this.apiIdCBConfigMap.remove(vo.getName()); this.circuitBreakerRegistry.remove(vo.getName()); logger.info("removed. - " + vo); diff --git a/src/main/java/com/eactive/eai/common/circuitBreaker/type/TypedCircuitBreakerMapper.java b/src/main/java/com/eactive/eai/common/circuitBreaker/type/TypedCircuitBreakerMapper.java index ba10797..6a97a95 100644 --- a/src/main/java/com/eactive/eai/common/circuitBreaker/type/TypedCircuitBreakerMapper.java +++ b/src/main/java/com/eactive/eai/common/circuitBreaker/type/TypedCircuitBreakerMapper.java @@ -11,6 +11,7 @@ import org.mapstruct.ReportingPolicy; @Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE) public interface TypedCircuitBreakerMapper extends GenericMapper { @Mappings({ + @Mapping(source = "cbreakerId", target = "id"), @Mapping(source = "cbreakerName", target = "name"), @Mapping(source = "cbreakerDesc", target = "desc"), @Mapping(source = "cbreakerType", target = "type"), diff --git a/src/main/java/com/eactive/eai/common/circuitBreaker/type/TypedCircuitBreakerVO.java b/src/main/java/com/eactive/eai/common/circuitBreaker/type/TypedCircuitBreakerVO.java index c96a727..9e99165 100644 --- a/src/main/java/com/eactive/eai/common/circuitBreaker/type/TypedCircuitBreakerVO.java +++ b/src/main/java/com/eactive/eai/common/circuitBreaker/type/TypedCircuitBreakerVO.java @@ -7,6 +7,7 @@ import lombok.Data; @Data @Builder public class TypedCircuitBreakerVO { + String id; String type; String name; String desc; diff --git a/src/main/java/com/eactive/eai/outbound/RESTProcess.java b/src/main/java/com/eactive/eai/outbound/RESTProcess.java index e05c556..24f10ae 100644 --- a/src/main/java/com/eactive/eai/outbound/RESTProcess.java +++ b/src/main/java/com/eactive/eai/outbound/RESTProcess.java @@ -5,6 +5,7 @@ import java.util.Properties; import com.eactive.eai.common.TransactionContextKeys; import com.eactive.eai.common.circuitBreaker.CircuitBreakerManager; +import com.eactive.eai.common.circuitBreaker.type.TypedCircuitBreakerManager; import com.eactive.eai.message.StandardMessage; import com.eactive.eai.util.PropertiesUtil; import com.fasterxml.jackson.databind.JsonNode; @@ -98,28 +99,32 @@ public class RESTProcess extends HTTPProcess { int iTimeoutValue = getTimeoutCodeToValue(); this.timeout = iTimeoutValue * 1000; this.tempProp.put(INTERFACE_TIME_OUT, "" + this.timeout); - String circuitBreakerUseYn = PropManager.getInstance().getProperty("CircuitBreaker", "useYn"); - + try { - if ("Y".equals(circuitBreakerUseYn)) { + // API별 이용 String apiId = reqEaiMsg.getEAISvcCd(); - CircuitBreaker circuitBreaker = CircuitBreakerManager.getInstance().getCircuitBreaker(apiId); - - // ObjectMapper 인스턴스 생성 - ObjectMapper objectMapper = new ObjectMapper(); - - // 서킷 브레이커의 메트릭 정보와 상태 정보를 직접 Node로 변환 - ObjectNode combinedNode = objectMapper.createObjectNode(); - combinedNode.put("state", circuitBreaker.getState().toString()); - combinedNode.set("metrics", objectMapper.valueToTree(circuitBreaker.getMetrics())); - - logger.info("CircuitBreaker state " + combinedNode.toString()); - this.resObject = circuitBreaker.executeCallable(() -> HttpSender - .callService(this.adapterGroupName, this.outboundProp, this.reqObject, this.tempProp)); + CircuitBreaker circuitBreaker = TypedCircuitBreakerManager.getInstance().getCircuitBreaker(apiId); + // 디폴트 이용 + if(circuitBreaker == null) { + String circuitBreakerUseYn = PropManager.getInstance().getProperty("CircuitBreaker", "useYn"); + if ("Y".equals(circuitBreakerUseYn)) + circuitBreaker = CircuitBreakerManager.getInstance().getCircuitBreaker(apiId); + } - - }else{ + if (circuitBreaker != null) { + // ObjectMapper 인스턴스 생성 + ObjectMapper objectMapper = new ObjectMapper(); + + // 서킷 브레이커의 메트릭 정보와 상태 정보를 직접 Node로 변환 + ObjectNode combinedNode = objectMapper.createObjectNode(); + combinedNode.put("state", circuitBreaker.getState().toString()); + combinedNode.set("metrics", objectMapper.valueToTree(circuitBreaker.getMetrics())); + + logger.info("CircuitBreaker state " + combinedNode.toString()); + this.resObject = circuitBreaker.executeCallable(() -> HttpSender + .callService(this.adapterGroupName, this.outboundProp, this.reqObject, this.tempProp)); + } else { this.resObject = HttpSender.callService(this.adapterGroupName, this.outboundProp, this.reqObject, this.tempProp); }