From 2bfc3d0bdeae9e4718f0872fdd3ed989bfe65fa3 Mon Sep 17 00:00:00 2001 From: curry772 Date: Thu, 30 Apr 2026 10:14:31 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20AbstractInflowControlManager=20?= =?UTF-8?q?=EC=83=81=EC=86=8D=20=EA=B5=AC=EC=A1=B0=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81=20=EB=B0=8F=20=EC=BB=A4=EB=A7=A8=EB=93=9C=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=ED=83=80=EC=9E=85=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit InflowControlManager에서 공통 로직을 AbstractInflowControlManager로 분리하고, 커맨드 클래스들이 AbstractInflowControlManager 타입을 사용하도록 변경. InflowControlUtil에 cachedInflowControlManager 정적 캐시 도입. Co-Authored-By: Claude Sonnet 4.6 --- .../ReloadInflowAdapterControlCommand.java | 5 +- .../ReloadInflowClientControlCommand.java | 5 +- .../ReloadInflowGroupControlCommand.java | 5 +- .../ReloadInflowInterfaceControlCommand.java | 5 +- .../RemoveInflowAdapterControlCommand.java | 5 +- .../RemoveInflowClientControlCommand.java | 5 +- .../RemoveInflowGroupControlCommand.java | 5 +- .../RemoveInflowInterfaceControlCommand.java | 5 +- .../inflow/AbstractInflowControlManager.java | 496 +++++++++++++++++ .../common/inflow/InflowControlManager.java | 527 +----------------- .../eai/common/inflow/InflowControlUtil.java | 100 +++- 11 files changed, 592 insertions(+), 571 deletions(-) create mode 100644 src/main/java/com/eactive/eai/common/inflow/AbstractInflowControlManager.java diff --git a/src/main/java/com/eactive/eai/agent/inflow/ReloadInflowAdapterControlCommand.java b/src/main/java/com/eactive/eai/agent/inflow/ReloadInflowAdapterControlCommand.java index 5506c0d..c9f2241 100644 --- a/src/main/java/com/eactive/eai/agent/inflow/ReloadInflowAdapterControlCommand.java +++ b/src/main/java/com/eactive/eai/agent/inflow/ReloadInflowAdapterControlCommand.java @@ -2,7 +2,8 @@ package com.eactive.eai.agent.inflow; import com.eactive.eai.agent.command.Command; import com.eactive.eai.agent.command.CommandException; -import com.eactive.eai.common.inflow.InflowControlManager; +import com.eactive.eai.common.inflow.AbstractInflowControlManager; +import com.eactive.eai.common.inflow.InflowControlUtil; import com.eactive.eai.common.util.Logger; public class ReloadInflowAdapterControlCommand extends Command { @@ -27,7 +28,7 @@ public class ReloadInflowAdapterControlCommand extends Command { String keyName = (String) args; try { - InflowControlManager manager = InflowControlManager.getInstance(); + AbstractInflowControlManager manager = InflowControlUtil.getInflowControlManager(); if (keyName != null) { if ("ALL".equals(keyName)) { diff --git a/src/main/java/com/eactive/eai/agent/inflow/ReloadInflowClientControlCommand.java b/src/main/java/com/eactive/eai/agent/inflow/ReloadInflowClientControlCommand.java index 55c00a4..8afe1e1 100644 --- a/src/main/java/com/eactive/eai/agent/inflow/ReloadInflowClientControlCommand.java +++ b/src/main/java/com/eactive/eai/agent/inflow/ReloadInflowClientControlCommand.java @@ -2,7 +2,8 @@ package com.eactive.eai.agent.inflow; import com.eactive.eai.agent.command.Command; import com.eactive.eai.agent.command.CommandException; -import com.eactive.eai.common.inflow.InflowControlManager; +import com.eactive.eai.common.inflow.AbstractInflowControlManager; +import com.eactive.eai.common.inflow.InflowControlUtil; import com.eactive.eai.common.inflow.dual.DualInflowControlManager; import com.eactive.eai.common.util.Logger; @@ -29,7 +30,7 @@ public class ReloadInflowClientControlCommand extends Command { String keyName = (String) args; try { - InflowControlManager base = InflowControlManager.getInstance(); + AbstractInflowControlManager base = InflowControlUtil.getInflowControlManager(); if (!(base instanceof DualInflowControlManager)) { throw new IllegalStateException("DualInflowControlManager 가 활성화되지 않았습니다."); } diff --git a/src/main/java/com/eactive/eai/agent/inflow/ReloadInflowGroupControlCommand.java b/src/main/java/com/eactive/eai/agent/inflow/ReloadInflowGroupControlCommand.java index 0582f01..a156cff 100644 --- a/src/main/java/com/eactive/eai/agent/inflow/ReloadInflowGroupControlCommand.java +++ b/src/main/java/com/eactive/eai/agent/inflow/ReloadInflowGroupControlCommand.java @@ -2,7 +2,8 @@ package com.eactive.eai.agent.inflow; import com.eactive.eai.agent.command.Command; import com.eactive.eai.agent.command.CommandException; -import com.eactive.eai.common.inflow.InflowControlManager; +import com.eactive.eai.common.inflow.AbstractInflowControlManager; +import com.eactive.eai.common.inflow.InflowControlUtil; import com.eactive.eai.common.util.Logger; public class ReloadInflowGroupControlCommand extends Command { @@ -28,7 +29,7 @@ public class ReloadInflowGroupControlCommand extends Command { String keyName = (String) args; try { - InflowControlManager manager = InflowControlManager.getInstance(); + AbstractInflowControlManager manager = InflowControlUtil.getInflowControlManager(); if (keyName != null) { if ("ALL".equals(keyName)) { diff --git a/src/main/java/com/eactive/eai/agent/inflow/ReloadInflowInterfaceControlCommand.java b/src/main/java/com/eactive/eai/agent/inflow/ReloadInflowInterfaceControlCommand.java index ab9dc47..45e5dc1 100644 --- a/src/main/java/com/eactive/eai/agent/inflow/ReloadInflowInterfaceControlCommand.java +++ b/src/main/java/com/eactive/eai/agent/inflow/ReloadInflowInterfaceControlCommand.java @@ -2,7 +2,8 @@ package com.eactive.eai.agent.inflow; import com.eactive.eai.agent.command.Command; import com.eactive.eai.agent.command.CommandException; -import com.eactive.eai.common.inflow.InflowControlManager; +import com.eactive.eai.common.inflow.AbstractInflowControlManager; +import com.eactive.eai.common.inflow.InflowControlUtil; import com.eactive.eai.common.util.Logger; public class ReloadInflowInterfaceControlCommand extends Command { @@ -28,7 +29,7 @@ public class ReloadInflowInterfaceControlCommand extends Command { String keyName = (String) args; try { - InflowControlManager manager = InflowControlManager.getInstance(); + AbstractInflowControlManager manager = InflowControlUtil.getInflowControlManager(); if (keyName != null) { if ("ALL".equals(keyName)) { diff --git a/src/main/java/com/eactive/eai/agent/inflow/RemoveInflowAdapterControlCommand.java b/src/main/java/com/eactive/eai/agent/inflow/RemoveInflowAdapterControlCommand.java index cce81bb..77bbaf3 100644 --- a/src/main/java/com/eactive/eai/agent/inflow/RemoveInflowAdapterControlCommand.java +++ b/src/main/java/com/eactive/eai/agent/inflow/RemoveInflowAdapterControlCommand.java @@ -2,7 +2,8 @@ package com.eactive.eai.agent.inflow; import com.eactive.eai.agent.command.Command; import com.eactive.eai.agent.command.CommandException; -import com.eactive.eai.common.inflow.InflowControlManager; +import com.eactive.eai.common.inflow.AbstractInflowControlManager; +import com.eactive.eai.common.inflow.InflowControlUtil; import com.eactive.eai.common.util.Logger; public class RemoveInflowAdapterControlCommand extends Command { @@ -26,7 +27,7 @@ public class RemoveInflowAdapterControlCommand extends Command { String key = (String) args; try { - InflowControlManager manager = InflowControlManager.getInstance(); + AbstractInflowControlManager manager = InflowControlUtil.getInflowControlManager(); manager.removeAdapter(key); } catch (Exception e) { String rspErrorCode = "RECEAIMCM002"; diff --git a/src/main/java/com/eactive/eai/agent/inflow/RemoveInflowClientControlCommand.java b/src/main/java/com/eactive/eai/agent/inflow/RemoveInflowClientControlCommand.java index d4fcbad..fe02028 100644 --- a/src/main/java/com/eactive/eai/agent/inflow/RemoveInflowClientControlCommand.java +++ b/src/main/java/com/eactive/eai/agent/inflow/RemoveInflowClientControlCommand.java @@ -2,7 +2,8 @@ package com.eactive.eai.agent.inflow; import com.eactive.eai.agent.command.Command; import com.eactive.eai.agent.command.CommandException; -import com.eactive.eai.common.inflow.InflowControlManager; +import com.eactive.eai.common.inflow.AbstractInflowControlManager; +import com.eactive.eai.common.inflow.InflowControlUtil; import com.eactive.eai.common.inflow.dual.DualInflowControlManager; import com.eactive.eai.common.util.Logger; @@ -29,7 +30,7 @@ public class RemoveInflowClientControlCommand extends Command { String key = (String) args; try { - InflowControlManager base = InflowControlManager.getInstance(); + AbstractInflowControlManager base = InflowControlUtil.getInflowControlManager(); if (!(base instanceof DualInflowControlManager)) { throw new IllegalStateException("DualInflowControlManager 가 활성화되지 않았습니다."); } diff --git a/src/main/java/com/eactive/eai/agent/inflow/RemoveInflowGroupControlCommand.java b/src/main/java/com/eactive/eai/agent/inflow/RemoveInflowGroupControlCommand.java index a4bdf03..a96fed0 100644 --- a/src/main/java/com/eactive/eai/agent/inflow/RemoveInflowGroupControlCommand.java +++ b/src/main/java/com/eactive/eai/agent/inflow/RemoveInflowGroupControlCommand.java @@ -2,7 +2,8 @@ package com.eactive.eai.agent.inflow; import com.eactive.eai.agent.command.Command; import com.eactive.eai.agent.command.CommandException; -import com.eactive.eai.common.inflow.InflowControlManager; +import com.eactive.eai.common.inflow.AbstractInflowControlManager; +import com.eactive.eai.common.inflow.InflowControlUtil; import com.eactive.eai.common.util.Logger; public class RemoveInflowGroupControlCommand extends Command { @@ -28,7 +29,7 @@ public class RemoveInflowGroupControlCommand extends Command { String key = (String) args; try { - InflowControlManager manager = InflowControlManager.getInstance(); + AbstractInflowControlManager manager = InflowControlUtil.getInflowControlManager(); manager.removeGroup(key); if (logger.isWarn()) logger.warn(this.name + "] group " + key + " removed."); diff --git a/src/main/java/com/eactive/eai/agent/inflow/RemoveInflowInterfaceControlCommand.java b/src/main/java/com/eactive/eai/agent/inflow/RemoveInflowInterfaceControlCommand.java index 597e6fa..04e8a17 100644 --- a/src/main/java/com/eactive/eai/agent/inflow/RemoveInflowInterfaceControlCommand.java +++ b/src/main/java/com/eactive/eai/agent/inflow/RemoveInflowInterfaceControlCommand.java @@ -2,7 +2,8 @@ package com.eactive.eai.agent.inflow; import com.eactive.eai.agent.command.Command; import com.eactive.eai.agent.command.CommandException; -import com.eactive.eai.common.inflow.InflowControlManager; +import com.eactive.eai.common.inflow.AbstractInflowControlManager; +import com.eactive.eai.common.inflow.InflowControlUtil; import com.eactive.eai.common.util.Logger; public class RemoveInflowInterfaceControlCommand extends Command { @@ -25,7 +26,7 @@ public class RemoveInflowInterfaceControlCommand extends Command { String key = (String) args; try { - InflowControlManager manager = InflowControlManager.getInstance(); + AbstractInflowControlManager manager = InflowControlUtil.getInflowControlManager(); manager.removeInterface(key); } catch (Exception e) { String rspErrorCode = "RECEAIMCM002"; diff --git a/src/main/java/com/eactive/eai/common/inflow/AbstractInflowControlManager.java b/src/main/java/com/eactive/eai/common/inflow/AbstractInflowControlManager.java new file mode 100644 index 0000000..12c23b1 --- /dev/null +++ b/src/main/java/com/eactive/eai/common/inflow/AbstractInflowControlManager.java @@ -0,0 +1,496 @@ +package com.eactive.eai.common.inflow; + +import java.time.Duration; +import java.util.Arrays; +import java.util.Calendar; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; + +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.util.Logger; + +import io.github.bucket4j.Bandwidth; +import io.github.bucket4j.Bucket4j; +import io.github.bucket4j.local.LocalBucket; +import io.github.bucket4j.local.LocalBucketBuilder; + +public abstract class AbstractInflowControlManager implements Lifecycle, Bucket { + static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT); + public static final String QUOTA_TIMEUNIT_SECOND = "SEC"; + public static final String QUOTA_TIMEUNIT_MINUTE = "MIN"; + public static final String QUOTA_TIMEUNIT_HOUR = "HOU"; + public static final String QUOTA_TIMEUNIT_DAY = "DAY"; + public static final String QUOTA_TIMEUNIT_MONTH = "MON"; + + private volatile Map adapterBucketList = new ConcurrentHashMap<>(); + private volatile Map interfaceBucketList = new ConcurrentHashMap<>(); + private volatile Map groupBucketList = new ConcurrentHashMap<>(); + private volatile Map interfaceToGroupMap = new ConcurrentHashMap<>(); + private volatile Map groupVoMap = new ConcurrentHashMap<>(); + private boolean started; + private LifecycleSupport lifecycle = new LifecycleSupport(this); + + @Autowired + protected InflowControlDAO inflowControlDAO; + + public void start() throws LifecycleException { + if (started) + throw new LifecycleException("RECEAICMM201"); + + lifecycle.fireLifecycleEvent(STARTING_EVENT, this); + try { + init(); + } catch (Exception e) { + throw new LifecycleException(ExceptionUtil.getErrorCode(e, "RECEAICMM202")); + } + started = true; + lifecycle.fireLifecycleEvent(STARTED_EVENT, this); + } + + private void init() throws Exception { + initAdapter(); + initInterface(); + initGroup(); + } + + private void initAdapter() throws Exception { + Map newMap = new HashMap<>(); + List inflowAdapterVoList = inflowControlDAO.getInflowAdapterList(); + + for (InflowTargetVO inflowVo : inflowAdapterVoList) { + if (AbstractInflowControlManager.isInflowTarget(inflowVo)) { + CustomBucket bucket = makeBucketUsingInflowVO(inflowVo); + if (bucket != null) { + newMap.put(inflowVo.getName(), bucket); + } + } + } + this.adapterBucketList = newMap; + } + + private void initInterface() throws Exception { + Map newMap = new HashMap<>(); + List inflowInterfaceVoList = inflowControlDAO.getInflowInterfaceList(); + + for (InflowTargetVO inflowVo : inflowInterfaceVoList) { + if (AbstractInflowControlManager.isInflowTarget(inflowVo)) { + CustomBucket bucket = makeBucketUsingInflowVO(inflowVo); + if (bucket != null) { + newMap.put(inflowVo.getName(), bucket); + } + } + } + this.interfaceBucketList = newMap; + } + + private void initGroup() throws Exception { + Map newGroupBucketList = new HashMap<>(); + Map newInterfaceToGroupMap = new HashMap<>(); + Map newGroupVoMap = new HashMap<>(); + + List inflowGroupVoList = inflowControlDAO.getInflowGroupList(); + + for (InflowGroupVO groupVo : inflowGroupVoList) { + if (isInflowGroupTarget(groupVo)) { + CustomGroupBucket bucket = makeGroupBucket(groupVo); + if (bucket != null) { + newGroupBucketList.put(groupVo.getGroupId(), bucket); + newGroupVoMap.put(groupVo.getGroupId(), groupVo); + for (String interfaceId : groupVo.getInterfaceList()) { + newInterfaceToGroupMap.put(interfaceId, groupVo.getGroupId()); + } + } + } + } + + if (logger.isInfo()) { + logger.info("InflowControlManager] initGroup completed. groups=" + newGroupBucketList.size() + + ", mappings=" + newInterfaceToGroupMap.size()); + } + + this.groupBucketList = newGroupBucketList; + this.interfaceToGroupMap = newInterfaceToGroupMap; + this.groupVoMap = newGroupVoMap; + } + + public synchronized void reloadAdapter() throws Exception { + if (logger.isWarn()) { + logger.warn("InflowControlManager] reload all Started ..."); + } + initAdapter(); + if (logger.isWarn()) { + logger.warn("InflowControlManager] reload all finished ..."); + } + } + + public synchronized void reloadInterface() throws Exception { + if (logger.isWarn()) { + logger.warn("InflowControlManager] reload all Started ..."); + } + initInterface(); + if (logger.isWarn()) { + logger.warn("InflowControlManager] reload all finished ..."); + } + } + + public synchronized void reloadAdapter(String adapter) throws Exception { + if (logger.isWarn()) { + logger.warn("InflowControlManager] reload Started ..."); + } + Map map = inflowControlDAO.getInflowTargetByAdater(adapter); + if (map != null) { + Iterator it = map.keySet().iterator(); + String key = ""; + while (it.hasNext()) { + key = it.next(); + + InflowTargetVO inflowTarget = map.get(key); + if (AbstractInflowControlManager.isInflowTarget(inflowTarget)) { + CustomBucket bucket = makeBucketUsingInflowVO(inflowTarget); + if (bucket != null) { + adapterBucketList.put(inflowTarget.getName(), bucket); + } else { + adapterBucketList.remove(inflowTarget.getName()); + } + } else { + adapterBucketList.remove(inflowTarget.getName()); + } + } + } + if (logger.isWarn()) { + logger.warn("InflowControlManager] reload finished ..."); + } + } + + public synchronized void reloadInterface(String inter) throws Exception { + if (logger.isWarn()) { + logger.warn("InflowControlManager] reload Started ..."); + } + Map map = inflowControlDAO.getInflowTargetByInterface(inter); + if (map != null) { + Iterator it = map.keySet().iterator(); + String key = ""; + while (it.hasNext()) { + key = it.next(); + + InflowTargetVO inflowTarget = map.get(key); + if (AbstractInflowControlManager.isInflowTarget(inflowTarget)) { + CustomBucket bucket = makeBucketUsingInflowVO(inflowTarget); + if (bucket != null) { + interfaceBucketList.put(inflowTarget.getName(), bucket); + } else { + interfaceBucketList.remove(inflowTarget.getName()); + } + } else { + interfaceBucketList.remove(inflowTarget.getName()); + } + } + } + + if (logger.isWarn()) { + logger.warn("InflowControlManager] reload finished ..."); + } + } + + public synchronized void reloadGroup() throws Exception { + if (logger.isWarn()) { + logger.warn("InflowControlManager] reloadGroup all Started ..."); + } + initGroup(); + if (logger.isWarn()) { + logger.warn("InflowControlManager] reloadGroup all finished ..."); + } + } + + public synchronized void reloadGroup(String groupId) throws Exception { + if (logger.isWarn()) { + logger.warn("InflowControlManager] reloadGroup Started ... groupId=" + groupId); + } + Map map = inflowControlDAO.getInflowTargetByGroup(groupId); + if (map != null) { + Iterator> mappingIt = interfaceToGroupMap.entrySet().iterator(); + while (mappingIt.hasNext()) { + Map.Entry entry = mappingIt.next(); + if (groupId.equals(entry.getValue())) { + mappingIt.remove(); + } + } + + Iterator it = map.keySet().iterator(); + while (it.hasNext()) { + String key = it.next(); + InflowGroupVO groupVo = map.get(key); + + if (isInflowGroupTarget(groupVo)) { + CustomGroupBucket bucket = makeGroupBucket(groupVo); + if (bucket != null) { + groupBucketList.put(groupVo.getGroupId(), bucket); + groupVoMap.put(groupVo.getGroupId(), groupVo); + for (String interfaceId : groupVo.getInterfaceList()) { + interfaceToGroupMap.put(interfaceId, groupVo.getGroupId()); + } + } else { + groupBucketList.remove(groupVo.getGroupId()); + groupVoMap.remove(groupVo.getGroupId()); + } + } else { + groupBucketList.remove(groupVo.getGroupId()); + groupVoMap.remove(groupVo.getGroupId()); + } + } + } + + if (logger.isWarn()) { + logger.warn("InflowControlManager] reloadGroup finished ..."); + } + } + + public void stop() throws LifecycleException { + if (!started) + throw new LifecycleException("RECEAICMM203"); + + lifecycle.fireLifecycleEvent(STOPING_EVENT, this); + + adapterBucketList = new ConcurrentHashMap<>(); + interfaceBucketList = new ConcurrentHashMap<>(); + groupBucketList = new ConcurrentHashMap<>(); + interfaceToGroupMap = new ConcurrentHashMap<>(); + groupVoMap = new ConcurrentHashMap<>(); + + started = false; + lifecycle.fireLifecycleEvent(STOPPED_EVENT, this); + } + + public void addLifecycleListener(LifecycleListener listener) { + lifecycle.addLifecycleListener(listener); + } + + public LifecycleListener[] findLifecycleListeners() { + return lifecycle.findLifecycleListeners(); + } + + public void removeLifecycleListener(LifecycleListener listener) { + lifecycle.removeLifecycleListener(listener); + } + + public boolean isStarted() { + return this.started; + } + + public String[] getAdapterAllKeys() { + Iterator it = this.adapterBucketList.keySet().iterator(); + String[] svcCd = new String[this.adapterBucketList.size()]; + for (int i = 0; it.hasNext(); i++) { + svcCd[i] = it.next(); + } + Arrays.sort(svcCd); + return svcCd; + } + + public String[] getInterfaceAllKeys() { + Iterator it = this.interfaceBucketList.keySet().iterator(); + String[] svcCd = new String[this.interfaceBucketList.size()]; + for (int i = 0; it.hasNext(); i++) { + svcCd[i] = it.next(); + } + Arrays.sort(svcCd); + return svcCd; + } + + public synchronized void removeAdapter(String adapter) { + adapterBucketList.remove(adapter); + } + + public synchronized void removeInterface(String inter) { + interfaceBucketList.remove(inter); + } + + public synchronized void removeGroup(String groupId) { + groupBucketList.remove(groupId); + groupVoMap.remove(groupId); + Iterator> it = interfaceToGroupMap.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry entry = it.next(); + if (groupId.equals(entry.getValue())) { + it.remove(); + } + } + } + + public String[] getGroupAllKeys() { + Iterator it = this.groupBucketList.keySet().iterator(); + String[] groupIds = new String[this.groupBucketList.size()]; + for (int i = 0; it.hasNext(); i++) { + groupIds[i] = it.next(); + } + Arrays.sort(groupIds); + return groupIds; + } + + public CustomGroupBucket getGroupBucket(String groupId) { + return groupBucketList.get(groupId); + } + + private CustomBucket makeBucketUsingInflowVO(InflowTargetVO inflowTarget) { + if (AbstractInflowControlManager.isInflowTarget(inflowTarget)) { + LocalBucketBuilder builder = Bucket4j.builder(); + if (inflowTarget.getThresholdPerSecond() > 0) { + builder.addLimit(Bandwidth.simple(inflowTarget.getThresholdPerSecond(), Duration.ofSeconds(1))); + } + + if (inflowTarget.getThreshold() > 0 && StringUtils.isNotBlank(inflowTarget.getThresholdTimeUnit())) { + builder.addLimit(Bandwidth.simple(inflowTarget.getThreshold(), + AbstractInflowControlManager.getPeriod(inflowTarget.getThresholdTimeUnit()))); + } + + return new CustomBucket(builder.build(), inflowTarget); + } + + return null; + } + + private CustomGroupBucket makeGroupBucket(InflowGroupVO groupVo) { + if (!isInflowGroupTarget(groupVo)) { + return null; + } + + LocalBucket perSecondBucket = null; + LocalBucket thresholdBucket = null; + + if (groupVo.getThresholdPerSecond() > 0) { + perSecondBucket = Bucket4j.builder() + .addLimit(Bandwidth.simple(groupVo.getThresholdPerSecond(), Duration.ofSeconds(1))) + .build(); + } + + if (groupVo.getThreshold() > 0 && StringUtils.isNotBlank(groupVo.getThresholdTimeUnit())) { + thresholdBucket = Bucket4j.builder() + .addLimit(Bandwidth.simple(groupVo.getThreshold(), + AbstractInflowControlManager.getPeriod(groupVo.getThresholdTimeUnit()))) + .build(); + } + + return new CustomGroupBucket(perSecondBucket, thresholdBucket, groupVo); + } + + @Override + public boolean isAdapterPass(String adapter) { + CustomBucket b = adapterBucketList.get(adapter); + + if (b == null) + return true; + + return b.getLocalBucket().tryConsume(1); + } + + @Override + public boolean isInterfacePass(String inter) { + CustomBucket b = interfaceBucketList.get(inter); + + if (b == null) + return true; + + return b.getLocalBucket().tryConsume(1); + } + + @Override + public InflowTargetVO getAdapterInflowThreashold(String adapter) { + CustomBucket b = adapterBucketList.get(adapter); + if (b == null) + return null; + return b.getInflowTargetVo(); + } + + @Override + public InflowTargetVO getInterfaceInflowThreashold(String inter) { + CustomBucket b = interfaceBucketList.get(inter); + if (b == null) + return null; + return b.getInflowTargetVo(); + } + + @Override + public InflowTargetVO getInflowThreashold(String inter) { + return null; + } + + public InflowTargetVO getAdapterInflow(String adapter) { + return getAdapterInflowThreashold(adapter); + } + + public InflowTargetVO getInterfaceInflow(String inter) { + return getInterfaceInflowThreashold(inter); + } + + @Override + public String isGroupPass(String groupId) { + CustomGroupBucket b = groupBucketList.get(groupId); + + if (b == null) + return null; + + return b.tryConsume(); + } + + @Override + public InflowGroupVO getGroupInflowThreshold(String groupId) { + return groupVoMap.get(groupId); + } + + @Override + public String getGroupIdByInterface(String interfaceId) { + return interfaceToGroupMap.get(interfaceId); + } + + public InflowGroupVO getGroupInflow(String groupId) { + return getGroupInflowThreshold(groupId); + } + + public static boolean isInflowTarget(InflowTargetVO inflowTarget) { + if (inflowTarget == null || !inflowTarget.isActivate()) { + return false; + } + + return inflowTarget.getThresholdPerSecond() > 0 || (inflowTarget.getThreshold() > 0 && StringUtils + .equalsAnyIgnoreCase(inflowTarget.getThresholdTimeUnit(), QUOTA_TIMEUNIT_DAY, QUOTA_TIMEUNIT_SECOND, + QUOTA_TIMEUNIT_MINUTE, QUOTA_TIMEUNIT_HOUR, QUOTA_TIMEUNIT_DAY, QUOTA_TIMEUNIT_MONTH)); + + } + + public static boolean isInflowGroupTarget(InflowGroupVO groupVo) { + if (groupVo == null || !groupVo.isActivate()) { + return false; + } + + return groupVo.getThresholdPerSecond() > 0 || (groupVo.getThreshold() > 0 && StringUtils + .equalsAnyIgnoreCase(groupVo.getThresholdTimeUnit(), QUOTA_TIMEUNIT_DAY, QUOTA_TIMEUNIT_SECOND, + QUOTA_TIMEUNIT_MINUTE, QUOTA_TIMEUNIT_HOUR, QUOTA_TIMEUNIT_DAY, QUOTA_TIMEUNIT_MONTH)); + } + + public static Duration getPeriod(String timeUnit) { + if (StringUtils.equalsIgnoreCase(timeUnit, QUOTA_TIMEUNIT_SECOND)) { + return Duration.ofSeconds(1); + } else if (StringUtils.equalsIgnoreCase(timeUnit, QUOTA_TIMEUNIT_MINUTE)) { + return Duration.ofMinutes(1); + } else if (StringUtils.equalsIgnoreCase(timeUnit, QUOTA_TIMEUNIT_HOUR)) { + return Duration.ofHours(1); + } else if (StringUtils.equalsIgnoreCase(timeUnit, QUOTA_TIMEUNIT_DAY)) { + return Duration.ofDays(1); + } else if (StringUtils.equalsIgnoreCase(timeUnit, QUOTA_TIMEUNIT_MONTH)) { + Calendar calendar = Calendar.getInstance(); + return Duration.ofDays(calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); + } else { + return null; + } + } +} 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 1992993..7418cc0 100644 --- a/src/main/java/com/eactive/eai/common/inflow/InflowControlManager.java +++ b/src/main/java/com/eactive/eai/common/inflow/InflowControlManager.java @@ -1,55 +1,11 @@ package com.eactive.eai.common.inflow; -import java.time.Duration; -import java.util.Arrays; -import java.util.Calendar; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.commons.lang3.StringUtils; -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.message.EAIMessage; -import com.eactive.eai.common.server.EAIServerManager; import com.eactive.eai.common.util.ApplicationContextProvider; -import com.eactive.eai.common.util.Logger; -import com.eactive.eai.common.util.MessageUtil; -import com.eactive.eai.message.service.InterfaceMapper; -import com.ext.eai.common.stdmessage.STDMessageKeys; - -import io.github.bucket4j.Bandwidth; -import io.github.bucket4j.Bucket4j; -import io.github.bucket4j.local.LocalBucket; -import io.github.bucket4j.local.LocalBucketBuilder; @Component -public class InflowControlManager implements Lifecycle, Bucket { - static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT); - public static final String QUOTA_TIMEUNIT_SECOND = "SEC"; - public static final String QUOTA_TIMEUNIT_MINUTE = "MIN"; - public static final String QUOTA_TIMEUNIT_HOUR = "HOU"; - public static final String QUOTA_TIMEUNIT_DAY = "DAY"; - public static final String QUOTA_TIMEUNIT_MONTH = "MON"; - - private volatile Map adapterBucketList = new ConcurrentHashMap<>(); - private volatile Map interfaceBucketList = new ConcurrentHashMap<>(); - private volatile Map groupBucketList = new ConcurrentHashMap<>(); - private volatile Map interfaceToGroupMap = new ConcurrentHashMap<>(); - private volatile Map groupVoMap = new ConcurrentHashMap<>(); - private boolean started; - private LifecycleSupport lifecycle = new LifecycleSupport(this); - - @Autowired - private InflowControlDAO inflowControlDAO; +public class InflowControlManager extends AbstractInflowControlManager { public static synchronized InflowControlManager getInstance() { return ApplicationContextProvider.getContext().getBean(InflowControlManager.class); @@ -58,485 +14,4 @@ public class InflowControlManager implements Lifecycle, Bucket { public static synchronized Bucket getBucket() { return ApplicationContextProvider.getContext().getBean(InflowControlManager.class); } - - /** - * 유량제어 대상인 거래인지 체크한다.(사이트에 맞게 구성) - * - * @param eaiServerManager - * @param eaiMessage - * @return - */ - public static Boolean isTargetOfInflowControl(EAIServerManager eaiServerManager, EAIMessage eaiMessage) { - InterfaceMapper mapper = eaiMessage.getMapper(); - String returnType = mapper.getSendRecvDivision(eaiMessage.getStandardMessage()); // S|R - - if (STDMessageKeys.SEND_RECV_CD_SEND.equals(returnType)) { - return Boolean.valueOf(true); - } - - return Boolean.valueOf(false); - } - - public void start() throws LifecycleException { - if (started) - throw new LifecycleException("RECEAICMM201"); - - lifecycle.fireLifecycleEvent(STARTING_EVENT, this); - try { - init(); - } catch (Exception e) { - throw new LifecycleException(ExceptionUtil.getErrorCode(e, "RECEAICMM202")); - } - started = true; - lifecycle.fireLifecycleEvent(STARTED_EVENT, this); - } - - private void init() throws Exception { - initAdapter(); - initInterface(); - initGroup(); - } - - private void initAdapter() throws Exception { - Map newMap = new HashMap<>(); - List inflowAdapterVoList = inflowControlDAO.getInflowAdapterList(); - - for (InflowTargetVO inflowVo : inflowAdapterVoList) { - if (InflowControlManager.isInflowTarget(inflowVo)) { - CustomBucket bucket = makeBucketUsingInflowVO(inflowVo); - if (bucket != null) { - newMap.put(inflowVo.getName(), bucket); - } - } - } - this.adapterBucketList = newMap; - } - - private void initInterface() throws Exception { - Map newMap = new HashMap<>(); - List inflowInterfaceVoList = inflowControlDAO.getInflowInterfaceList(); - - for (InflowTargetVO inflowVo : inflowInterfaceVoList) { - if (InflowControlManager.isInflowTarget(inflowVo)) { - CustomBucket bucket = makeBucketUsingInflowVO(inflowVo); - if (bucket != null) { - newMap.put(inflowVo.getName(), bucket); - } - } - } - this.interfaceBucketList = newMap; - } - - private void initGroup() throws Exception { - Map newGroupBucketList = new HashMap<>(); - Map newInterfaceToGroupMap = new HashMap<>(); - Map newGroupVoMap = new HashMap<>(); - - List inflowGroupVoList = inflowControlDAO.getInflowGroupList(); - - for (InflowGroupVO groupVo : inflowGroupVoList) { - if (isInflowGroupTarget(groupVo)) { - CustomGroupBucket bucket = makeGroupBucket(groupVo); - if (bucket != null) { - newGroupBucketList.put(groupVo.getGroupId(), bucket); - newGroupVoMap.put(groupVo.getGroupId(), groupVo); - // 인터페이스 → 그룹 매핑 등록 - for (String interfaceId : groupVo.getInterfaceList()) { - newInterfaceToGroupMap.put(interfaceId, groupVo.getGroupId()); - } - } - } - } - - if (logger.isInfo()) { - logger.info("InflowControlManager] initGroup completed. groups=" + newGroupBucketList.size() - + ", mappings=" + newInterfaceToGroupMap.size()); - } - - this.groupBucketList = newGroupBucketList; - this.interfaceToGroupMap = newInterfaceToGroupMap; - this.groupVoMap = newGroupVoMap; - } - - public synchronized void reloadAdapter() throws Exception { - if (logger.isWarn()) { - logger.warn("InflowControlManager] reload all Started ..."); - } - initAdapter(); - if (logger.isWarn()) { - logger.warn("InflowControlManager] reload all finished ..."); - } - } - - public synchronized void reloadInterface() throws Exception { - if (logger.isWarn()) { - logger.warn("InflowControlManager] reload all Started ..."); - } - initInterface(); - if (logger.isWarn()) { - logger.warn("InflowControlManager] reload all finished ..."); - } - } - - public synchronized void reloadAdapter(String adapter) throws Exception { - if (logger.isWarn()) { - logger.warn("InflowControlManager] reload Started ..."); - } - Map map = inflowControlDAO.getInflowTargetByAdater(adapter); - if (map != null) { - Iterator it = map.keySet().iterator(); - String key = ""; - while (it.hasNext()) { - key = it.next(); - - InflowTargetVO inflowTarget = map.get(key); - if (InflowControlManager.isInflowTarget(inflowTarget)) { - CustomBucket bucket = makeBucketUsingInflowVO(inflowTarget); - if (bucket != null) { - adapterBucketList.put(inflowTarget.getName(), bucket); - } else { - adapterBucketList.remove(inflowTarget.getName()); - } - } else { - adapterBucketList.remove(inflowTarget.getName()); - } - } - } - if (logger.isWarn()) { - logger.warn("InflowControlManager] reload finished ..."); - } - } - - public synchronized void reloadInterface(String inter) throws Exception { - if (logger.isWarn()) { - logger.warn("InflowControlManager] reload Started ..."); - } - Map map = inflowControlDAO.getInflowTargetByInterface(inter); - if (map != null) { - Iterator it = map.keySet().iterator(); - String key = ""; - while (it.hasNext()) { - key = it.next(); - - InflowTargetVO inflowTarget = map.get(key); - if (InflowControlManager.isInflowTarget(inflowTarget)) { - CustomBucket bucket = makeBucketUsingInflowVO(inflowTarget); - if (bucket != null) { - interfaceBucketList.put(inflowTarget.getName(), bucket); - } else { - interfaceBucketList.remove(inflowTarget.getName()); - } - } else { - interfaceBucketList.remove(inflowTarget.getName()); - } - } - } - - if (logger.isWarn()) { - logger.warn("InflowControlManager] reload finished ..."); - } - } - - public synchronized void reloadGroup() throws Exception { - if (logger.isWarn()) { - logger.warn("InflowControlManager] reloadGroup all Started ..."); - } - initGroup(); - if (logger.isWarn()) { - logger.warn("InflowControlManager] reloadGroup all finished ..."); - } - } - - public synchronized void reloadGroup(String groupId) throws Exception { - if (logger.isWarn()) { - logger.warn("InflowControlManager] reloadGroup Started ... groupId=" + groupId); - } - Map map = inflowControlDAO.getInflowTargetByGroup(groupId); - if (map != null) { - // 기존 그룹에 속한 인터페이스 매핑 제거 - Iterator> mappingIt = interfaceToGroupMap.entrySet().iterator(); - while (mappingIt.hasNext()) { - Map.Entry entry = mappingIt.next(); - if (groupId.equals(entry.getValue())) { - mappingIt.remove(); - } - } - - Iterator it = map.keySet().iterator(); - while (it.hasNext()) { - String key = it.next(); - InflowGroupVO groupVo = map.get(key); - - if (isInflowGroupTarget(groupVo)) { - CustomGroupBucket bucket = makeGroupBucket(groupVo); - if (bucket != null) { - groupBucketList.put(groupVo.getGroupId(), bucket); - groupVoMap.put(groupVo.getGroupId(), groupVo); - // 인터페이스 → 그룹 매핑 재등록 - for (String interfaceId : groupVo.getInterfaceList()) { - interfaceToGroupMap.put(interfaceId, groupVo.getGroupId()); - } - } else { - groupBucketList.remove(groupVo.getGroupId()); - groupVoMap.remove(groupVo.getGroupId()); - } - } else { - groupBucketList.remove(groupVo.getGroupId()); - groupVoMap.remove(groupVo.getGroupId()); - } - } - } - - if (logger.isWarn()) { - logger.warn("InflowControlManager] reloadGroup finished ..."); - } - } - - public void stop() throws LifecycleException { - // Validate and update our current component state - if (!started) - throw new LifecycleException("RECEAICMM203"); - - // Notify our interested LifecycleListeners - lifecycle.fireLifecycleEvent(STOPING_EVENT, this); - - adapterBucketList = new ConcurrentHashMap<>(); - interfaceBucketList = new ConcurrentHashMap<>(); - groupBucketList = new ConcurrentHashMap<>(); - interfaceToGroupMap = new ConcurrentHashMap<>(); - groupVoMap = new ConcurrentHashMap<>(); - - started = false; - // Notify our interested LifecycleListeners - lifecycle.fireLifecycleEvent(STOPPED_EVENT, this); - } - - public void addLifecycleListener(LifecycleListener listener) { - lifecycle.addLifecycleListener(listener); - } - - public LifecycleListener[] findLifecycleListeners() { - return lifecycle.findLifecycleListeners(); - } - - public void removeLifecycleListener(LifecycleListener listener) { - lifecycle.removeLifecycleListener(listener); - } - - public boolean isStarted() { - return this.started; - } - - public String[] getAdapterAllKeys() { - Iterator it = this.adapterBucketList.keySet().iterator(); - String[] svcCd = new String[this.adapterBucketList.size()]; - for (int i = 0; it.hasNext(); i++) { - svcCd[i] = it.next(); - } - Arrays.sort(svcCd); - return svcCd; - } - - public String[] getInterfaceAllKeys() { - Iterator it = this.interfaceBucketList.keySet().iterator(); - String[] svcCd = new String[this.interfaceBucketList.size()]; - for (int i = 0; it.hasNext(); i++) { - svcCd[i] = it.next(); - } - Arrays.sort(svcCd); - return svcCd; - } - - public synchronized void removeAdapter(String adapter) { - adapterBucketList.remove(adapter); - } - - public synchronized void removeInterface(String inter) { - interfaceBucketList.remove(inter); - } - - public synchronized void removeGroup(String groupId) { - groupBucketList.remove(groupId); - groupVoMap.remove(groupId); - // 해당 그룹에 속한 인터페이스 매핑도 제거 - Iterator> it = interfaceToGroupMap.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = it.next(); - if (groupId.equals(entry.getValue())) { - it.remove(); - } - } - } - - public String[] getGroupAllKeys() { - Iterator it = this.groupBucketList.keySet().iterator(); - String[] groupIds = new String[this.groupBucketList.size()]; - for (int i = 0; it.hasNext(); i++) { - groupIds[i] = it.next(); - } - Arrays.sort(groupIds); - return groupIds; - } - - public CustomGroupBucket getGroupBucket(String groupId) { - return groupBucketList.get(groupId); - } - - private CustomBucket makeBucketUsingInflowVO(InflowTargetVO inflowTarget) { - if (InflowControlManager.isInflowTarget(inflowTarget)) { - LocalBucketBuilder builder = Bucket4j.builder(); - if (inflowTarget.getThresholdPerSecond() > 0) { - builder.addLimit(Bandwidth.simple(inflowTarget.getThresholdPerSecond(), Duration.ofSeconds(1))); - } - - if (inflowTarget.getThreshold() > 0 && StringUtils.isNotBlank(inflowTarget.getThresholdTimeUnit())) { - builder.addLimit(Bandwidth.simple(inflowTarget.getThreshold(), - InflowControlManager.getPeriod(inflowTarget.getThresholdTimeUnit()))); - } - - return new CustomBucket(builder.build(), inflowTarget); - } - - return null; - } - - /** - * 그룹용 버킷 생성 - 초당/추가 임계치를 별도 버킷으로 분리 - */ - private CustomGroupBucket makeGroupBucket(InflowGroupVO groupVo) { - if (!isInflowGroupTarget(groupVo)) { - return null; - } - - LocalBucket perSecondBucket = null; - LocalBucket thresholdBucket = null; - - // 초당 임계치 버킷 (별도) - if (groupVo.getThresholdPerSecond() > 0) { - perSecondBucket = Bucket4j.builder() - .addLimit(Bandwidth.simple(groupVo.getThresholdPerSecond(), Duration.ofSeconds(1))) - .build(); - } - - // 추가 임계치 버킷 (별도) - if (groupVo.getThreshold() > 0 && StringUtils.isNotBlank(groupVo.getThresholdTimeUnit())) { - thresholdBucket = Bucket4j.builder() - .addLimit(Bandwidth.simple(groupVo.getThreshold(), - InflowControlManager.getPeriod(groupVo.getThresholdTimeUnit()))) - .build(); - } - - return new CustomGroupBucket(perSecondBucket, thresholdBucket, groupVo); - } - - @Override - public boolean isAdapterPass(String adapter) { - CustomBucket b = adapterBucketList.get(adapter); - - if (b == null) - return true; - - return b.getLocalBucket().tryConsume(1); - } - - @Override - public boolean isInterfacePass(String inter) { - CustomBucket b = interfaceBucketList.get(inter); - - if (b == null) - return true; - - return b.getLocalBucket().tryConsume(1); - } - - @Override - public InflowTargetVO getAdapterInflowThreashold(String adapter) { - CustomBucket b = adapterBucketList.get(adapter); - if (b == null) - return null; - return b.getInflowTargetVo(); - } - - @Override - public InflowTargetVO getInterfaceInflowThreashold(String inter) { - CustomBucket b = interfaceBucketList.get(inter); - if (b == null) - return null; - return b.getInflowTargetVo(); - } - - @Override - public InflowTargetVO getInflowThreashold(String inter) { - return null; - } - - public InflowTargetVO getAdapterInflow(String adapter) { - return getAdapterInflowThreashold(adapter); - } - - public InflowTargetVO getInterfaceInflow(String inter) { - return getInterfaceInflowThreashold(inter); - } - - @Override - public String isGroupPass(String groupId) { - CustomGroupBucket b = groupBucketList.get(groupId); - - if (b == null) - return null; - - return b.tryConsume(); - } - - @Override - public InflowGroupVO getGroupInflowThreshold(String groupId) { - return groupVoMap.get(groupId); - } - - @Override - public String getGroupIdByInterface(String interfaceId) { - return interfaceToGroupMap.get(interfaceId); - } - - public InflowGroupVO getGroupInflow(String groupId) { - return getGroupInflowThreshold(groupId); - } - - public static boolean isInflowTarget(InflowTargetVO inflowTarget) { - if (inflowTarget == null || !inflowTarget.isActivate()) { - return false; - } - - return inflowTarget.getThresholdPerSecond() > 0 || (inflowTarget.getThreshold() > 0 && StringUtils - .equalsAnyIgnoreCase(inflowTarget.getThresholdTimeUnit(), QUOTA_TIMEUNIT_DAY, QUOTA_TIMEUNIT_SECOND, - QUOTA_TIMEUNIT_MINUTE, QUOTA_TIMEUNIT_HOUR, QUOTA_TIMEUNIT_DAY, QUOTA_TIMEUNIT_MONTH)); - - } - - public static boolean isInflowGroupTarget(InflowGroupVO groupVo) { - if (groupVo == null || !groupVo.isActivate()) { - return false; - } - - return groupVo.getThresholdPerSecond() > 0 || (groupVo.getThreshold() > 0 && StringUtils - .equalsAnyIgnoreCase(groupVo.getThresholdTimeUnit(), QUOTA_TIMEUNIT_DAY, QUOTA_TIMEUNIT_SECOND, - QUOTA_TIMEUNIT_MINUTE, QUOTA_TIMEUNIT_HOUR, QUOTA_TIMEUNIT_DAY, QUOTA_TIMEUNIT_MONTH)); - } - - public static Duration getPeriod(String timeUnit) { - if (StringUtils.equalsIgnoreCase(timeUnit, QUOTA_TIMEUNIT_SECOND)) { - return Duration.ofSeconds(1); - } else if (StringUtils.equalsIgnoreCase(timeUnit, QUOTA_TIMEUNIT_MINUTE)) { - return Duration.ofMinutes(1); - } else if (StringUtils.equalsIgnoreCase(timeUnit, QUOTA_TIMEUNIT_HOUR)) { - return Duration.ofHours(1); - } else if (StringUtils.equalsIgnoreCase(timeUnit, QUOTA_TIMEUNIT_DAY)) { - return Duration.ofDays(1); - } else if (StringUtils.equalsIgnoreCase(timeUnit, QUOTA_TIMEUNIT_MONTH)) { - Calendar calendar = Calendar.getInstance(); - return Duration.ofDays(calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); - } else { - return null; - } - } } diff --git a/src/main/java/com/eactive/eai/common/inflow/InflowControlUtil.java b/src/main/java/com/eactive/eai/common/inflow/InflowControlUtil.java index 3fa037f..d4b7b48 100644 --- a/src/main/java/com/eactive/eai/common/inflow/InflowControlUtil.java +++ b/src/main/java/com/eactive/eai/common/inflow/InflowControlUtil.java @@ -8,7 +8,10 @@ import org.apache.commons.lang3.StringUtils; import com.eactive.eai.common.message.EAIMessage; import com.eactive.eai.common.property.PropManager; import com.eactive.eai.common.server.EAIServerManager; +import com.eactive.eai.common.util.ApplicationContextProvider; import com.eactive.eai.common.util.Logger; +import com.eactive.eai.message.service.InterfaceMapper; +import com.ext.eai.common.stdmessage.STDMessageKeys; public class InflowControlUtil { private InflowControlUtil() { @@ -16,28 +19,70 @@ public class InflowControlUtil { static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT); + private static volatile AbstractInflowControlManager cachedInflowControlManager; + private static volatile Bucket cachedBucket; + + /** + * INFLOW.properties의 inflow.control.bucket.className 설정에 따라 + * 활성화된 InflowControlManager 구현체를 반환한다. + * + * getBean(InflowControlManager.class) 대신 설정된 구체 타입으로 조회하므로 + * InflowControlManager와 DualInflowControlManager가 모두 Bean으로 등록된 + * 환경에서도 NoUniqueBeanDefinitionException 없이 올바른 인스턴스를 반환한다. + * + * 최초 1회만 조회하고 이후에는 캐시된 인스턴스를 반환한다. + */ @SuppressWarnings({ "rawtypes", "unchecked" }) - public static Bucket getBucket() { - Properties inFlowProp = PropManager.getInstance().getProperties("INFLOW"); - String className = inFlowProp.getProperty("inflow.control.bucket.className"); - if (StringUtils.isBlank(className) - || StringUtils.equals(className, "com.eactive.eai.common.inflow.InflowControlManager")) { - return InflowControlManager.getBucket(); - } else { - try { - Class clazz = Class.forName(className); - Method method = clazz.getMethod("getBucket", (Class[]) null); - return (Bucket) method.invoke(null, (Object[]) null); - } catch (Exception e) { - logger.error("Method call error class= {}, method= getBucket", className); - logger.error(e.getMessage()); + public static AbstractInflowControlManager getInflowControlManager() { + if (cachedInflowControlManager == null) { + synchronized (InflowControlUtil.class) { + if (cachedInflowControlManager == null) { + Properties inFlowProp = PropManager.getInstance().getProperties("INFLOW"); + String className = inFlowProp.getProperty("inflow.control.bucket.className"); + if (StringUtils.isBlank(className) + || StringUtils.equals(className, "com.eactive.eai.common.inflow.InflowControlManager")) { + cachedInflowControlManager = InflowControlManager.getInstance(); + } else { + try { + Class clazz = Class.forName(className); + cachedInflowControlManager = (AbstractInflowControlManager) ApplicationContextProvider.getContext().getBean(clazz); + } catch (Exception e) { + logger.error("getInflowControlManager error class= {}", className); + logger.error(e.getMessage()); + } + } + } } } - - return null; + return cachedInflowControlManager; } @SuppressWarnings({ "rawtypes", "unchecked" }) + public static Bucket getBucket() { + if (cachedBucket == null) { + synchronized (InflowControlUtil.class) { + if (cachedBucket == null) { + Properties inFlowProp = PropManager.getInstance().getProperties("INFLOW"); + String className = inFlowProp.getProperty("inflow.control.bucket.className"); + if (StringUtils.isBlank(className) + || StringUtils.equals(className, "com.eactive.eai.common.inflow.InflowControlManager")) { + cachedBucket = InflowControlManager.getBucket(); + } else { + try { + Class clazz = Class.forName(className); + Method method = clazz.getMethod("getBucket", (Class[]) null); + cachedBucket = (Bucket) method.invoke(null, (Object[]) null); + } catch (Exception e) { + logger.error("Method call error class= {}, method= getBucket", className); + logger.error(e.getMessage()); + } + } + } + } + } + return cachedBucket; + } + public static boolean isTargetOfInflowControl(EAIServerManager eaiServerManager, EAIMessage eaiMessage) { Properties inFlowProp = PropManager.getInstance().getProperties("INFLOW"); String controlInflow = inFlowProp.getProperty("inflow.control.yn", "N"); @@ -45,21 +90,18 @@ public class InflowControlUtil { if (!"Y".equalsIgnoreCase(controlInflow)) { return false; } + + try { + InterfaceMapper mapper = eaiMessage.getMapper(); + String returnType = mapper.getSendRecvDivision(eaiMessage.getStandardMessage()); // S|R - String className = inFlowProp.getProperty("inflow.control.bucket.className"); - if (StringUtils.isBlank(className) - || StringUtils.equals(className, "com.eactive.eai.common.inflow.InflowControlManager")) { - return InflowControlManager.isTargetOfInflowControl(eaiServerManager, eaiMessage).booleanValue(); - } else { - try { - Class clazz = Class.forName(className); - Method method = clazz.getMethod("isTargetOfInflowControl", EAIServerManager.class, EAIMessage.class); - Boolean returnBoolean = (Boolean) method.invoke(null, eaiServerManager, eaiMessage); - return returnBoolean.booleanValue(); - } catch (Exception e) { - logger.error("Method call error class= {}, method= isTargetOfInflowControl", className); - logger.error(e.getMessage()); + if (STDMessageKeys.SEND_RECV_CD_SEND.equals(returnType)) { + return Boolean.valueOf(true); } + + return Boolean.valueOf(false); + } catch (Exception e) { + logger.error("isTargetOfInflowControl call error", e.getMessage()); } return false;