Kaynağa Gözat

update region center dual ip address apply

shjung 1 gün önce
ebeveyn
işleme
bd8f8c0c89

+ 7 - 0
moct-utic-server/src/main/java/com/utic/its/moct/utic/server/service/ApplicationService.java

@@ -5,6 +5,7 @@ import com.utic.its.asn1.utils.ItsAsn;
 import com.utic.its.common.dto.CenterDto;
 import com.utic.its.common.entity.TbCenter;
 import com.utic.its.common.repository.ApplicationRepository;
+import com.utic.its.common.utils.IpUtils;
 import com.utic.its.moct.utic.server.cluster.ClusterConfig;
 import com.utic.its.moct.utic.server.config.SchedulingConfig;
 import com.utic.its.moct.utic.server.dao.repository.MoctUticServerRepository;
@@ -104,6 +105,12 @@ public class ApplicationService {
 
             ApplicationRepository.CENTER_MAP.put(dto.getCenterId(), dto);
             ApplicationRepository.IPADDRESS_MAP.put(dto.getIpAddress(), dto);
+            String ipAddress2 = dto.getIpAddress2();
+            if (IpUtils.isUsableIp(ipAddress2) && !dto.getIpAddress().equals(ipAddress2)) {
+                ApplicationRepository.IPADDRESS_MAP.put(ipAddress2, dto);
+                log.info("ApplicationService.loadLocalCenter: dual ip address: [{}], {}/{}.",
+                        dto.getCenterId(), dto.getIpAddress(), dto.getIpAddress2());
+            }
         }
         return true;
     }

+ 3 - 2
moct-utic-server/src/main/resources/mybatis/mapper/MoctUticServerMapper.xml

@@ -25,13 +25,14 @@
         <![CDATA[
         SELECT SUBSTR(CENTERID,   1, 10) AS centerid,
                SUBSTR(CENTERINFO, 1, 20) AS centerInfo,
-               IPADDRESS                 AS ipAddress,
+               TRIM(IPADDRESS)           AS ipAddress,
                COMMPORT                  AS commPort,
                DATEXUSER                 AS datexUser,
                DATEXPASSWD               AS datexPasswd,
                HEARTBEATCYCLE            AS heartbeatCycle,
                RESTIME                   AS resTime,
-               DATAGRAMSIZE              AS datagramSize
+               DATAGRAMSIZE              AS datagramSize,
+               TRIM(IPADDRESS2)          AS ipAddress2
         FROM CENTER_MOCT
         WHERE CENTERFLAG = 'L'
           AND EXEYN      = 'Y'

+ 3 - 2
rota-utic-client/src/main/resources/mybatis/mapper/RotaUticClientMapper.xml

@@ -24,13 +24,14 @@
         <![CDATA[
         SELECT SUBSTR(CENTERID,   1, 10) AS centerid,
                SUBSTR(CENTERINFO, 1, 20) AS centerInfo,
-               IPADDRESS                 AS ipAddress,
+               TRIM(IPADDRESS)           AS ipAddress,
                COMMPORT                  AS commPort,
                DATEXUSER                 AS datexUser,
                DATEXPASSWD               AS datexPasswd,
                HEARTBEATCYCLE            AS heartbeatCycle,
                RESTIME                   AS resTime,
-               DATAGRAMSIZE              AS datagramSize
+               DATAGRAMSIZE              AS datagramSize,
+               TRIM(IPADDRESS2)          AS ipAddress2
         FROM CENTER
         WHERE CENTERFLAG = 'L'
           AND EXEYN      = 'Y'

+ 7 - 0
rota-utic-server/src/main/java/com/utic/its/rota/utic/server/service/ApplicationService.java

@@ -4,6 +4,7 @@ import com.its.common.utils.TimeUtils;
 import com.utic.its.common.dto.CenterDto;
 import com.utic.its.common.entity.TbCenter;
 import com.utic.its.common.repository.ApplicationRepository;
+import com.utic.its.common.utils.IpUtils;
 import com.utic.its.rota.utic.server.cluster.ClusterConfig;
 import com.utic.its.rota.utic.server.config.SchedulingConfig;
 import com.utic.its.rota.utic.server.dao.repository.RotaUticServerRepository;
@@ -116,6 +117,12 @@ public class ApplicationService {
 
             ApplicationRepository.CENTER_MAP.put(dto.getCenterId(), dto);
             ApplicationRepository.IPADDRESS_MAP.put(dto.getIpAddress(), dto);
+            String ipAddress2 = dto.getIpAddress2();
+            if (IpUtils.isUsableIp(ipAddress2) && !dto.getIpAddress().equals(ipAddress2)) {
+                ApplicationRepository.IPADDRESS_MAP.put(ipAddress2, dto);
+                log.info("ApplicationService.loadRegionCenterInfo: dual ip address: [{}], {}/{}.",
+                        dto.getCenterId(), dto.getIpAddress(), dto.getIpAddress2());
+            }
         }
         return true;
     }

+ 3 - 2
rota-utic-server/src/main/resources/mybatis/mapper/RotaUticServerMapper.xml

@@ -24,13 +24,14 @@
         <![CDATA[
         SELECT SUBSTR(CENTERID,   1, 10) AS centerid,
                SUBSTR(CENTERINFO, 1, 20) AS centerInfo,
-               IPADDRESS                 AS ipAddress,
+               TRIM(IPADDRESS)           AS ipAddress,
                COMMPORT                  AS commPort,
                DATEXUSER                 AS datexUser,
                DATEXPASSWD               AS datexPasswd,
                HEARTBEATCYCLE            AS heartbeatCycle,
                RESTIME                   AS resTime,
-               DATAGRAMSIZE              AS datagramSize
+               DATAGRAMSIZE              AS datagramSize,
+               TRIM(IPADDRESS2)          AS ipAddress2
         FROM CENTER
         WHERE CENTERFLAG = 'L'
           AND EXEYN      = 'Y'

+ 1 - 0
utic-its-common/src/main/java/com/utic/its/common/dto/CenterDto.java

@@ -43,6 +43,7 @@ public class CenterDto implements Serializable {
     private String centerId;
     private String centerInfo;
     private String ipAddress;
+    private String ipAddress2;
     private Integer commPort;
     private String datexUser;
     private String datexPasswd;

+ 2 - 0
utic-its-common/src/main/java/com/utic/its/common/entity/TbCenter.java

@@ -29,6 +29,7 @@ public class TbCenter {
     private Integer datagramSize;
     private String trafficYn;
     private String incidentYn;
+    private String ipAddress2;
 
     public CenterDto toDto() {
         return CenterDto.builder()
@@ -38,6 +39,7 @@ public class TbCenter {
                 .centerId(this.centerId)
                 .centerInfo(this.centerInfo)
                 .ipAddress(this.ipAddress)
+                .ipAddress2(this.ipAddress2)
                 .commPort(this.commPort)
                 .datexUser(this.datexUser)
                 .datexPasswd(this.datexPasswd)

+ 35 - 0
utic-its-common/src/main/java/com/utic/its/common/utils/IpUtils.java

@@ -0,0 +1,35 @@
+package com.utic.its.common.utils;
+
+public class IpUtils {
+
+    private static final String IPV4_REGEX =
+            "((25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)\\.){3}" +
+                    "(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)";
+
+    private IpUtils() {
+        throw new RuntimeException("");
+    }
+
+    /**
+     * 주어진 문자열이 유효한 IPv4 주소인지 확인합니다.
+     *
+     * @param ip 검사할 IP 문자열
+     * @return 유효한 IPv4 주소이면 true, 아니면 false
+     */
+    public static boolean isValidIPv4(String ip) {
+        if (ip == null || ip.isEmpty()) {
+            return false;
+        }
+        return ip.matches(IPV4_REGEX);
+    }
+
+    /**
+     * IP 주소가 유효하고, 공백이 아닌지 확인합니다.
+     *
+     * @param ip 검사할 IP 문자열
+     * @return 유효한 IPv4 주소이고 공백이 아니면 true
+     */
+    public static boolean isUsableIp(String ip) {
+        return ip != null && !ip.trim().isEmpty() && isValidIPv4(ip.trim());
+    }
+}

+ 6 - 1
utic-its-common/src/main/java/com/utic/its/common/utils/StringUtils.java

@@ -59,5 +59,10 @@ public class StringUtils {
 
         return input.substring(0, charIndex);
     }
-
+    private boolean isValidIp(String ip) {
+        if (isEmpty(ip)) {
+            return ip.matches("((25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)\\.){3}(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)");
+        }
+        return false;
+    }
 }

+ 15 - 3
utic-its-common/src/main/java/com/utic/its/common/xnet/client/handler/ItsAsnClient.java

@@ -2,6 +2,7 @@ package com.utic.its.common.xnet.client.handler;
 
 import com.utic.its.common.dto.CenterDto;
 import com.utic.its.common.repository.ApplicationRepository;
+import com.utic.its.common.utils.IpUtils;
 import com.utic.its.common.xnet.client.ItsAsnClientBootstrapFactory;
 import com.utic.its.common.xnet.client.ItsAsnCommClient;
 import com.utic.its.common.xnet.client.codec.ItsAsnClientDecoder;
@@ -44,6 +45,7 @@ public class ItsAsnClient implements Callable<Object> {
     private Bootstrap bootstrap = null;
     private ChannelFuture channelFuture = null;
     private String ipAddress;
+    private String prevIpAddress;
     private int port;
 
     private NioEventLoopGroup eventLoopGroup = null;
@@ -71,7 +73,16 @@ public class ItsAsnClient implements Callable<Object> {
 
             this.ipAddress = this.center.getIpAddress();
             this.port = this.center.getCommPort();
-
+            String ipAddress2 = this.center.getIpAddress2();
+            if (IpUtils.isUsableIp(ipAddress2) && !this.center.getIpAddress().equals(ipAddress2)) {
+                // 이중화 IP Address 가 존재함
+                if (this.ipAddress.equals(this.prevIpAddress)) {
+                    // 이전에 사용한 IP Address 가 첫번째 주소였다면 이번에는 2번째 주소를 할당해서 연결을 시도한다.
+                    this.ipAddress = ipAddress2;
+                }
+                log.info("ItsAsnClient >>>>>>>>Start: Dual Ip Address: [{}], ipAddress1/2: {}/{}",
+                        this.center.getCenterId(), this.center.getIpAddress(), this.center.getIpAddress2());
+            }
             if (this.clusterId > 0) {
                 log.info("ItsAsnClient >>>>>>>>Start: [{}, {}], {}, clusterId {}, realClusterId: {}",
                         this.center.getCenterId(), this.ipAddress, this.port, this.center.getClusterId(), this.center.getRealClusterId());
@@ -146,7 +157,7 @@ public class ItsAsnClient implements Callable<Object> {
 
     /**
      * 연결 성공시 처리 이벤트
-     * @param channel
+     * @param channel: Opened netty channel
      */
     protected void channelOpen(Channel channel) {
         MDC.put("id", this.center.getLogKey());
@@ -167,12 +178,13 @@ public class ItsAsnClient implements Callable<Object> {
 
     /**
      * 연결 종료시 처리 이벤트
-     * @param channel
+     * @param channel: Closed netty channel
      */
     protected synchronized void channelClosed(Channel channel) {
         try {
             MDC.put("id", this.center.getLogKey());
 
+            this.prevIpAddress = this.ipAddress;    // 현재 연결한 ip address 를 백업받아 놓는다.
             log.warn("ItsAsnClient channelClosed: [{}, {}], {}, Channel: {}, RetryConnectSeconds: {} seconds.",
                     this.center.getCenterId(), this.center.getIpAddress(), this.center.getCommPort(), channel, this.retryConnectSeconds);
 

+ 14 - 2
utic-its-common/src/main/java/com/utic/its/common/xnet/server/handler/ItsAsnCommServerInitializer.java

@@ -3,6 +3,7 @@ package com.utic.its.common.xnet.server.handler;
 import com.its.common.network.NettyUtils;
 import com.utic.its.common.dto.CenterDto;
 import com.utic.its.common.repository.ApplicationRepository;
+import com.utic.its.common.utils.IpUtils;
 import com.utic.its.common.xnet.server.codec.ItsAsnServerDecoder;
 import com.utic.its.common.xnet.server.codec.ItsAsnServerEncoder;
 import io.netty.channel.Channel;
@@ -61,8 +62,19 @@ public class ItsAsnCommServerInitializer extends ChannelInitializer<Channel> {
             ApplicationRepository.setCenterObject(channel, center);
             center.setRealClusterId(this.clusterId);
 
-//            long idleTime = center.getResTime(); // CENTER Table RESTIME 으로 설정
-            long idleTime = center.getHeartbeatCycle() / 2; // CENTER Table HEARTBEATCYCLE 으로 설정
+            String ipAddress2 = center.getIpAddress2();
+            if (IpUtils.isUsableIp(ipAddress2) && center.getIpAddress2().equals(ipAddress)) {
+                // 이중화 IP Address 가 존재하고 첫번째 IP가 아닌 2번째 IP에서 접속한 경우
+                // 메모리상의 IP Address 주소를 변경해서 업데이트 해 놓는다.
+                String tmpIpAddress1 = center.getIpAddress();
+                center.setIpAddress(ipAddress2);
+                center.setIpAddress2(tmpIpAddress1);
+                log.info("       ItsAsnCommServerInitializer.----initChannel: [{}, {}]. change primary ip address: {} -> {}",
+                        center.getLogKey(), ipAddress, center.getIpAddress(), center.getIpAddress2());
+            }
+
+            // long idleTime = center.getResTime(); // CENTER Table resTime 으로 설정
+            long idleTime = center.getHeartbeatCycle() / 2; // CENTER Table HeartbeatCycle 으로 설정
             IdleStateHandler idleStateHandler = new IdleStateHandler(idleTime, 0, 0, TimeUnit.SECONDS);
             ChannelPipeline pipeline = channel.pipeline();
             //        pipeline.addLast(new LoggingHandler(LogLevel.INFO));