Browse Source

channel map, session count algorithm modify, dup connect check add

shjung 1 week ago
parent
commit
5dae46aac0

+ 1 - 0
conf/tsi-comm-server.pid

@@ -0,0 +1 @@
+47029

+ 42 - 39
tsi-comm-server/src/main/java/com/tsi/comm/server/controller/TsiCommServerRestController.java

@@ -1,23 +1,21 @@
 package com.tsi.comm.server.controller;
 
 import com.tsi.comm.server.config.ApplicationConfig;
-import com.tsi.comm.server.config.DatabaseConfig;
 import com.tsi.comm.server.config.TsiCvimServerConfig;
-import com.tsi.comm.server.repository.ApplicationRepository;
+import com.tsi.comm.server.repository.TsiAlarmManager;
 import com.tsi.comm.server.repository.TsiNodeManager;
 import com.tsi.comm.server.repository.TsiSessionManager;
 import com.tsi.comm.server.vo.TsiNodeVo;
 import com.tsi.comm.server.xnet.NettyUtils;
 import com.tsi.common.utils.TimeUtils;
-import io.netty.channel.Channel;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 import java.text.SimpleDateFormat;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.Date;
+import java.util.Map;
 
 @RestController
 @RequiredArgsConstructor
@@ -29,11 +27,12 @@ public class TsiCommServerRestController {
     private final TsiCvimServerConfig serverConfig;
     private final TsiNodeManager nodeManager;
     private final TsiSessionManager sessionManager;
+    private final TsiAlarmManager alarmManager;
 
     @GetMapping(value = "/info", produces = {"application/json; charset=utf8"})
     public String info() {
         String sep = System.lineSeparator();
-        String heading = "----------------------------------------------------------------------------------------------------------------------------------";
+        String heading = "------------------------------------------------------------------------------------------------------------------------------------------------------";
 
         StringBuilder sb = new StringBuilder();
         sb.append(heading).append(sep);
@@ -54,12 +53,12 @@ public class TsiCommServerRestController {
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
         sdf.setTimeZone(java.util.TimeZone.getTimeZone("GMT+9"));
 
-        sb.append(String.format("   SEQ[U] %10s %4s %7s %19s %19s %9s %6s %19s  Remote-Address", "Node ID", "INTC", "Connect", "Connect Time", "Disconnect Time", "Connected", "Closed", "Last-Recv-Time")).append(sep);
+        sb.append(String.format("   SEQ[U] %10s %4s %7s %19s %19s %9s %6s %19s  IP Address        Remote-Address", "Node ID", "INTC", "Connect", "Connect Time", "Disconnect Time", "Connected", "Closed", "Last-Recv-Time")).append(sep);
         sb.append(heading).append(sep);
 
         int ii = 1;
         for (Map.Entry<Long, TsiNodeVo> obj : this.nodeManager.getTsiNodeVoMap().entrySet()) {
-            TsiNodeVo node = obj.getValue();
+            final TsiNodeVo node = obj.getValue();
             String check = (node.isInstalled() ? "Y" : "N");
             check = check + (node.isSendNode() ? "Y" : "N");
             check = check + (node.isSendTest() ? "Y" : "N");
@@ -89,43 +88,47 @@ public class TsiCommServerRestController {
             String disconnectTm = sdf.format(new Date(node.getDisconnectTm()));
             String lastCommTm = sdf.format(new Date(node.getLastCommTm()));
 
-            sb.append(String.format(" %5d%3s %10s %4s %7s %19s %19s %9d %6d %19s  %s",
-                    ii++, unknownNode, node.getKey(), check, connect, connectTm, disconnectTm, node.getConnectCount().get(), node.getDisconnectCount().get(), lastCommTm, info)).append(sep);
+            sb.append(String.format(" %5d%3s %10s %4s %7s %19s %19s %9d %6d %19s  %-17s %s",
+                    ii++, unknownNode, node.getKey(), check, connect, connectTm, disconnectTm, node.getConnectCount().get(),
+                    node.getDisconnectCount().get(), lastCommTm, node.getIpAddr(), info)).append(sep);
         }
-
         sb.append(heading).append(sep);
         sb.append(String.format(" Total Nodes: %d EA, Registered: %d EA, Unknown: %d EA, Connected: %d EA", nodeCount, registered, unknown, connected)).append(sep);
+        sb.append(String.format(" Unknown Nodes: %d EA, Unknown Node Buffers: %d EA, Unknown Ip Address: %d EA, Duplication Connect: %d EA",
+                this.alarmManager.getUnknownNodeCount(), this.alarmManager.getUnknownNodeBufCount(),
+                this.alarmManager.getUnknownIpAddrCount(), this.alarmManager.getDupConnectCount())).append(sep);
+//        sb.append(heading).append(sep);
         sb.append(String.format(" Channel: %d EA, Session: %d EA", this.sessionManager.getChannelCount(), this.sessionManager.getCount())).append(sep);
         sb.append(heading).append(sep);
 
-        Set<Long> nodeIdSet = new HashSet<>();
-        ConcurrentHashMap<Channel, TsiNodeVo> channelNodeMap = this.sessionManager.getChannelNodeMap();
-        for (Map.Entry<Channel, TsiNodeVo> entry : channelNodeMap.entrySet()) {
-            Channel channel = entry.getKey();
-            TsiNodeVo nodeVo = entry.getValue();
-            Long nodeId = nodeVo.getNodeId();
-
-            TsiNodeVo dbNode = this.nodeManager.getTsiNodeVoMap().get(nodeId);
-            String ip = NettyUtils.getRemoteIpAddress(channel);
-            String dbIp = dbNode == null ? "" : dbNode.getIpAddr();
-
-            if (dbNode == null) {
-                sb.append(String.format("Not Found Node: %d, %s/%s", nodeId, ip, dbIp)).append(sep);
-            }
-            else {
-                if (!dbNode.isConnect()) {
-                    sb.append(String.format("Network state error: %d, %s/%s", nodeId, ip, dbIp)).append(sep);
-                }
-            }
-            if (nodeIdSet.contains(nodeId)) {
-                 sb.append(String.format("Dup Channel: %d %s/%s", nodeId, ip, dbIp)).append(sep);
-            } else {
-                nodeIdSet.add(nodeId);
-            }
-            if (!ip.equals(dbIp)) {
-                sb.append(String.format("IP Not Match: %d,  %s/%s", nodeId, ip, dbIp)).append(sep);
-            }
-        }
+//        Set<Long> nodeIdSet = new HashSet<>();
+//        ConcurrentHashMap<Channel, TsiNodeVo> channelNodeMap = this.sessionManager.getChannelNodeMap();
+//        for (Map.Entry<Channel, TsiNodeVo> entry : channelNodeMap.entrySet()) {
+//            Channel channel = entry.getKey();
+//            TsiNodeVo nodeVo = entry.getValue();
+//            Long nodeId = nodeVo.getNodeId();
+//
+//            TsiNodeVo dbNode = this.nodeManager.getTsiNodeVoMap().get(nodeId);
+//            String ip = NettyUtils.getRemoteIpAddress(channel);
+//            String dbIp = dbNode == null ? "" : dbNode.getIpAddr();
+//
+//            if (dbNode == null) {
+//                sb.append(String.format("Not Found Node: %d, %s/%s", nodeId, ip, dbIp)).append(sep);
+//            }
+//            else {
+//                if (!dbNode.isConnect()) {
+//                    sb.append(String.format("Network state error: %d, %s/%s", nodeId, ip, dbIp)).append(sep);
+//                }
+//            }
+//            if (nodeIdSet.contains(nodeId)) {
+//                 sb.append(String.format("Dup Channel: %d %s/%s", nodeId, ip, dbIp)).append(sep);
+//            } else {
+//                nodeIdSet.add(nodeId);
+//            }
+//            if (!ip.equals(dbIp)) {
+//                sb.append(String.format("IP Not Match: %d,  %s/%s", nodeId, ip, dbIp)).append(sep);
+//            }
+//        }
         return sb.toString();
     }
 

+ 32 - 6
tsi-comm-server/src/main/java/com/tsi/comm/server/repository/TsiAlarmManager.java

@@ -1,7 +1,7 @@
 package com.tsi.comm.server.repository;
 
-import com.tsi.comm.server.xnet.NettyUtils;
 import com.tsi.comm.server.vo.TsiAlarmConfigVo;
+import com.tsi.comm.server.xnet.NettyUtils;
 import com.tsi.common.utils.HexString;
 import io.netty.channel.Channel;
 import lombok.RequiredArgsConstructor;
@@ -9,7 +9,6 @@ import lombok.extern.slf4j.Slf4j;
 import org.slf4j.MDC;
 import org.springframework.stereotype.Component;
 
-import java.util.HashSet;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -21,8 +20,8 @@ public class TsiAlarmManager {
     private final ConcurrentHashMap<String, TsiAlarmConfigVo> tsiAlarmConfigMap = new ConcurrentHashMap<>();
     private final Set<String> UNKNOWN_NODE_SET = ConcurrentHashMap.newKeySet();
     private final Set<String> UNKNOWN_NODE_BUF_SET = ConcurrentHashMap.newKeySet();
-    private final Set<String> UNNKOWN_IPADDR_SET = ConcurrentHashMap.newKeySet();
-
+    private final Set<String> UNKNOWN_IPADDR_SET = ConcurrentHashMap.newKeySet();
+    private final Set<String> DUP_CONNECT_INFO_SET = ConcurrentHashMap.newKeySet();
 
     public TsiAlarmConfigVo get(String code) {
         return this.tsiAlarmConfigMap.get(code);
@@ -40,6 +39,20 @@ public class TsiAlarmManager {
         return (vo != null && vo.isUseYn());
     }
 
+    public int getUnknownNodeCount() {
+        return this.UNKNOWN_NODE_SET.size();
+    }
+    public int getUnknownNodeBufCount() {
+        return this.UNKNOWN_NODE_BUF_SET.size();
+    }
+    public int getUnknownIpAddrCount() {
+        return this.UNKNOWN_IPADDR_SET.size();
+    }
+    public int getDupConnectCount() {
+        return this.DUP_CONNECT_INFO_SET.size();
+    }
+
+
     public void loggingUnknownNode(long nodeId, Channel channel) {
         final String remoteIpAddress = NettyUtils.getRemoteIpAddress(channel);
         if (this.UNKNOWN_NODE_SET.contains(remoteIpAddress)) {
@@ -70,10 +83,10 @@ public class TsiAlarmManager {
     }
 
     public void reportUnknownIp(String ipAddr) {
-        if (this.UNNKOWN_IPADDR_SET.contains(ipAddr)) {
+        if (this.UNKNOWN_IPADDR_SET.contains(ipAddr)) {
             return;
         }
-        this.UNNKOWN_IPADDR_SET.add(ipAddr);
+        this.UNKNOWN_IPADDR_SET.add(ipAddr);
 
         final String fileName = "unknown_ip";
         MDC.put("filename", fileName);
@@ -81,4 +94,17 @@ public class TsiAlarmManager {
         MDC.clear();
     }
 
+    public void alarmDupConnect(Long nodeId, String ipAddr, String remoteIpAddress) {
+        final String dupConnectInfo = nodeId + ":" + ipAddr + ":" + remoteIpAddress;
+        if (this.DUP_CONNECT_INFO_SET.contains(dupConnectInfo)) {
+            return;
+        }
+        this.DUP_CONNECT_INFO_SET.add(dupConnectInfo);
+
+        final String fileName = "dup_connect";
+        MDC.put("filename", fileName);
+        log.info("Duplication Connect: {}", dupConnectInfo);
+        MDC.clear();
+    }
+
 }

+ 11 - 0
tsi-comm-server/src/main/java/com/tsi/comm/server/tcp/codec/CvimServerByteBufMessageDecoder.java

@@ -82,6 +82,16 @@ public class CvimServerByteBufMessageDecoder extends MessageToMessageDecoder<Byt
                     return;
                 }
 
+                // 중복 로그인 체크
+                Channel oldChannel = nodeVo.getChannel();
+                if (oldChannel != null && oldChannel.isActive()) {
+                    // 중복 연결 로깅
+                    if (oldChannel != ctx.channel()) {
+                        this.alarmManager.alarmDupConnect(nodeVo.getNodeId(), nodeVo.getIpAddr(), remoteIpAddress);
+                        oldChannel.close();
+                    }
+                }
+
                 // first connection, save node information to channel attribute map
                 // 채널 맵에 채널에 대한 노드정보를 저장한다.
                 // 채널 목록에 접속 정보 등록
@@ -167,6 +177,7 @@ public class CvimServerByteBufMessageDecoder extends MessageToMessageDecoder<Byt
                 alarm.setAlarmCode(TsiAlarmConfigVo.COMM_01);
                 alarm.setAlarmTarget(Long.toString(nodeId));
                 alarm.setAlarmValue(remoteIpAddress);
+
                 this.dbmsProcess.add(alarm, (int)Thread.currentThread().getId());
             }
         }

+ 13 - 5
tsi-comm-server/src/main/java/com/tsi/comm/server/tcp/handler/CvimServerInboundMessageHandler.java

@@ -94,7 +94,7 @@ public class CvimServerInboundMessageHandler extends ChannelInboundHandlerAdapte
                 packet.setObj(nodeVo);
                 this.packetProcess.add(packet, nodeVo.getPktQIdx());    // 패킷인덱스큐로 데이터 전송
             }
-            log.info("channelInactive: Node {}, {}, sessions: {}", nodeVo.getNodeId(), remoteIpAddr, sessions);
+//            log.info("channelInactive: Node {}, {}, sessions: {}", nodeVo.getNodeId(), remoteIpAddr, sessions);
 
             TsiChannelSession.sessionInactive(nodeVo, remoteIpAddr);
 
@@ -102,11 +102,19 @@ public class CvimServerInboundMessageHandler extends ChannelInboundHandlerAdapte
             ctx.channel().attr(TsiSessionManager.TSI_NODE_ATTRIBUTE_KEY).set(null);
 
             this.queueDistributorService.releaseQueue(nodeVo);    // 작업큐를 할당을 해제한다.
-            nodeVo.setConnect(null);
+            if (nodeVo.getChannel() == ctx.channel()) {
+                // 현재 비활성화되는 채널이 nodeVo에 등록된 활성 채널과 동일한 경우에만
+                nodeVo.setConnect(null);
+                log.info("channelInactive: {}, {}, sessions: {}", nodeVo.getNodeId(), remoteIpAddr, sessions);
+            }
+            else {
+                // 새로운 연결에 의해 강제로 종료되었음
+                log.warn("channelInactive: {}, {}, sessions: {}, Duplicate Connected.", nodeVo.getNodeId(), remoteIpAddr, sessions);
+            }
+        }
+        else {
+            log.info("channelInactive: {}, sessions: {}, Unknown node.", remoteIpAddr, sessions);
         }
-//        else {
-//            log.info("channelInactive: {}, {} Sessions.", remoteIpAddr, sessions);
-//        }
 
         ctx.fireChannelInactive();
     }