diff --git a/src/main/java/com/eactive/eai/common/inflow/Bucket.java b/src/main/java/com/eactive/eai/common/inflow/Bucket.java index 3896171..b0888b0 100644 --- a/src/main/java/com/eactive/eai/common/inflow/Bucket.java +++ b/src/main/java/com/eactive/eai/common/inflow/Bucket.java @@ -8,7 +8,8 @@ public interface Bucket { public InflowTargetVO getInflowThreashold(String inter); // 그룹 관련 메서드 - public boolean isGroupPass(String groupId); + /** @return null이면 통과, "PER_SECOND" 또는 "THRESHOLD"면 해당 버킷에서 차단 */ + public String isGroupPass(String groupId); public InflowGroupVO getGroupInflowThreshold(String groupId); public String getGroupIdByInterface(String interfaceId); } diff --git a/src/main/java/com/eactive/eai/common/inflow/CustomGroupBucket.java b/src/main/java/com/eactive/eai/common/inflow/CustomGroupBucket.java index 296fb15..49d0aba 100644 --- a/src/main/java/com/eactive/eai/common/inflow/CustomGroupBucket.java +++ b/src/main/java/com/eactive/eai/common/inflow/CustomGroupBucket.java @@ -17,24 +17,31 @@ public class CustomGroupBucket { this.groupVo = groupVo; } + /** 소비 결과: 성공 */ + public static final String RESULT_PASS = null; + /** 소비 결과: 초당 임계치 초과 */ + public static final String RESULT_BLOCKED_PER_SECOND = "PER_SECOND"; + /** 소비 결과: 추가 임계치 초과 */ + public static final String RESULT_BLOCKED_THRESHOLD = "THRESHOLD"; + /** * 두 버킷 모두에서 토큰 소비 시도 - * @return 모든 버킷에서 소비 성공 시 true + * @return null이면 성공, "PER_SECOND" 또는 "THRESHOLD"면 해당 버킷에서 차단 */ - public boolean tryConsume() { + public String tryConsume() { boolean perSecondPass = (perSecondBucket == null) || perSecondBucket.tryConsume(1); if (!perSecondPass) { - return false; + return RESULT_BLOCKED_PER_SECOND; } boolean thresholdPass = (thresholdBucket == null) || thresholdBucket.tryConsume(1); if (!thresholdPass) { // 초당 버킷에서 이미 소비했으므로 롤백은 불가 (Token Bucket 특성상) // 하지만 초당 버킷은 빠르게 리필되므로 실질적 영향 미미 - return false; + return RESULT_BLOCKED_THRESHOLD; } - return true; + return RESULT_PASS; } /** diff --git a/src/main/java/com/eactive/eai/common/inflow/InflowControlManager.java b/src/main/java/com/eactive/eai/common/inflow/InflowControlManager.java index 29933bf..9c527fd 100644 --- a/src/main/java/com/eactive/eai/common/inflow/InflowControlManager.java +++ b/src/main/java/com/eactive/eai/common/inflow/InflowControlManager.java @@ -470,11 +470,11 @@ public class InflowControlManager implements Lifecycle, Bucket { } @Override - public boolean isGroupPass(String groupId) { + public String isGroupPass(String groupId) { CustomGroupBucket b = groupBucketList.get(groupId); if (b == null) - return true; + return null; return b.tryConsume(); } diff --git a/src/main/java/com/eactive/eai/common/session/SessionManagerForEhcache.java b/src/main/java/com/eactive/eai/common/session/SessionManagerForEhcache.java index 571afa3..8c876c3 100644 --- a/src/main/java/com/eactive/eai/common/session/SessionManagerForEhcache.java +++ b/src/main/java/com/eactive/eai/common/session/SessionManagerForEhcache.java @@ -155,7 +155,7 @@ public class SessionManagerForEhcache extends SessionManager { } System.setProperty("net.sf.ehcache.skipUpdateCheck", "true"); - String bootstrapAsynchronously = "false"; + String bootstrapAsynchronously = "true"; Configuration cf = new Configuration(); FactoryConfiguration ppFactory = new FactoryConfiguration(); diff --git a/src/main/java/com/eactive/eai/inbound/processor/RequestProcessor.java b/src/main/java/com/eactive/eai/inbound/processor/RequestProcessor.java index 43d84fb..7175d74 100644 --- a/src/main/java/com/eactive/eai/inbound/processor/RequestProcessor.java +++ b/src/main/java/com/eactive/eai/inbound/processor/RequestProcessor.java @@ -1022,9 +1022,11 @@ public class RequestProcessor extends RequestProcessorSupport { } // 그룹 우선, 없으면 인터페이스 유량제어 체크 String groupId = bucket.getGroupIdByInterface(vo.getEaiSvcCd()); + String groupBlockedType = null; if (groupId != null) { // 그룹에 속한 인터페이스 → 그룹 유량제어 체크 - if (!bucket.isGroupPass(groupId)) { + groupBlockedType = bucket.isGroupPass(groupId); + if (groupBlockedType != null) { blockedType += "G"; } } else { @@ -1044,11 +1046,26 @@ public class RequestProcessor extends RequestProcessorSupport { } else { inflowTargetVO = bucket.getInterfaceInflowThreashold(vo.getEaiSvcCd()); } + String inflowErrorMsg; // 에러처리 vo.setRspErrorCode(EAIMessageKeys.EAI_INFLOW_BLOCKED_CODE); - String inflowInfo = (inflowGroupVO != null) ? inflowGroupVO.toString() : - (inflowTargetVO != null ? inflowTargetVO.toString() : "N/A"); - vo.setRspErrorMsg(ExceptionUtil.make(vo.getRspErrorCode(), vo.getEaiSvcCd() ) + ", " + inflowInfo); + if (inflowGroupVO != null) { + if ("PER_SECOND".equals(groupBlockedType)) { + inflowErrorMsg = String.format("API 호출 한도 초과 [%s: %dreq/sec]", + inflowGroupVO.getGroupName(), + inflowGroupVO.getThresholdPerSecond()); + } else { + inflowErrorMsg = String.format("API 호출 한도 초과 [%s: %dreq/%s]", + inflowGroupVO.getGroupName(), + inflowGroupVO.getThreshold(), + inflowGroupVO.getThresholdTimeUnit()); + } + } else if (inflowTargetVO != null) { + inflowErrorMsg = String.format("API 호출 한도 초과 [%s]", inflowTargetVO.getName()); + } else { + inflowErrorMsg = "API 호출 한도 초과"; + } + vo.setRspErrorMsg(inflowErrorMsg); // eaiMsg.setRspErrCd(vo.getRspErrorCode()); // eaiMsg.setRspErrMsg(vo.getRspErrorMsg()); @@ -1082,7 +1099,7 @@ public class RequestProcessor extends RequestProcessorSupport { sb.append("EAISevrInstncName [" + eaiServerManager.getLocalServerName() + "]\n"); sb.append("EAISvcName [" + eaiMsg.getEAISvcCd() + "]\n"); sb.append("ADPTRBZWKGROUPNAME[" + vo.getAdapterGroupName() + "]\n"); - sb.append("InflowInfo [" + inflowInfo + "]\n"); + sb.append("InflowInfo [" + inflowErrorMsg + "]\n"); if (groupId != null) { sb.append("InflowGroupId [" + groupId + "]\n"); }