|
@@ -11,6 +11,7 @@ import com.tsi.comm.server.protocol.AbstractTsiPacket;
|
|
|
import com.tsi.comm.server.protocol.TsiCpuDisconnected;
|
|
|
import com.tsi.comm.server.protocol.TsiCpuPacket;
|
|
|
import com.tsi.comm.server.vo.TsiNodeVo;
|
|
|
+import lombok.Getter;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.slf4j.MDC;
|
|
|
|
|
@@ -18,6 +19,7 @@ import java.util.concurrent.LinkedBlockingQueue;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
@Slf4j
|
|
|
+@Getter
|
|
|
public class TsiCvimPacketWorker extends AbstractTsiCvimWorker implements Runnable {
|
|
|
|
|
|
//private ConcurrentLinkedQueue<AbstractTsiPacket> DATA_QUEUE;
|
|
@@ -30,40 +32,75 @@ public class TsiCvimPacketWorker extends AbstractTsiCvimWorker implements Runnab
|
|
|
this.idx = idx;
|
|
|
this.qSize = qSize;
|
|
|
this.kafkaProducer = kafkaProducer;
|
|
|
- this.loggingService = (TsiCvimLoggingProcess) AppUtils.getBean(TsiCvimLoggingProcess.class);
|
|
|
this.DATA_QUEUE = new LinkedBlockingQueue<>(qSize);
|
|
|
+ this.loggingService = (TsiCvimLoggingProcess) AppUtils.getBean(TsiCvimLoggingProcess.class);
|
|
|
this.cvimServerConfig = (TsiCvimServerConfig) AppUtils.getBean(TsiCvimServerConfig.class);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void run() {
|
|
|
- log.info("{} Start. QSIZE: {}", Thread.currentThread().getName(), this.qSize);
|
|
|
- while (true) {
|
|
|
- Object packet = null;
|
|
|
- try {
|
|
|
- packet = this.DATA_QUEUE.take();
|
|
|
- if (packet != null) {
|
|
|
- process(packet);
|
|
|
- }
|
|
|
- else {
|
|
|
- Thread.yield();
|
|
|
- }
|
|
|
- }
|
|
|
- catch (Exception e) {
|
|
|
- if (packet != null) {
|
|
|
- TsiCpuPacket cpuPacket = (TsiCpuPacket)((AbstractTsiPacket)packet);
|
|
|
- TsiNodeVo nodeVo = (TsiNodeVo)cpuPacket.getObj();
|
|
|
- if (nodeVo != null) {
|
|
|
- log.warn(" Node: {}, Network Conn: {}", nodeVo.getKey(), nodeVo.isConnect());
|
|
|
+ log.info("PacketWorker({}): {} Start. QSIZE: {}", this.idx, Thread.currentThread().getName(), this.qSize);
|
|
|
+ try {
|
|
|
+ while (!Thread.currentThread().isInterrupted()) {
|
|
|
+ Object packet = null;
|
|
|
+ try {
|
|
|
+ packet = this.DATA_QUEUE.poll(1, TimeUnit.SECONDS); // 인터럽트 감지 가능
|
|
|
+ if (packet != null) {
|
|
|
+ process(packet);
|
|
|
+ } else {
|
|
|
+ Thread.yield(); // 대기 중 CPU 양보
|
|
|
+ }
|
|
|
+ } catch (InterruptedException ie) {
|
|
|
+ log.warn("PacketWorker({}): {} Interrupted. Exiting...", this.idx, Thread.currentThread().getName());
|
|
|
+ Thread.currentThread().interrupt(); // 상태 복구
|
|
|
+ break;
|
|
|
+ } catch (Exception e) {
|
|
|
+ if (packet != null) {
|
|
|
+ TsiCpuPacket cpuPacket = (TsiCpuPacket)((AbstractTsiPacket)packet);
|
|
|
+ TsiNodeVo nodeVo = (TsiNodeVo)cpuPacket.getObj();
|
|
|
+ if (nodeVo != null) {
|
|
|
+ log.warn("PacketWorker({}): {} Node: {}, Network Conn: {}", this.idx, Thread.currentThread().getName(), nodeVo.getKey(), nodeVo.isConnect());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ log.error("PacketWorker({}): {} Exception: {}", this.idx, Thread.currentThread().getName(), e.getMessage());
|
|
|
}
|
|
|
- }
|
|
|
- else {
|
|
|
- log.error("Exception(PacketWorker while): {}", e.getMessage());
|
|
|
}
|
|
|
}
|
|
|
+ } finally {
|
|
|
+ log.info("PacketWorker({}): {} Stopped.", this.idx, Thread.currentThread().getName());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// @Override
|
|
|
+// public void run() {
|
|
|
+// log.info("{} Start. QSIZE: {}", Thread.currentThread().getName(), this.qSize);
|
|
|
+// while (true) {
|
|
|
+// Object packet = null;
|
|
|
+// try {
|
|
|
+// packet = this.DATA_QUEUE.take();
|
|
|
+// if (packet != null) {
|
|
|
+// process(packet);
|
|
|
+// }
|
|
|
+// else {
|
|
|
+// Thread.yield();
|
|
|
+// }
|
|
|
+// }
|
|
|
+// catch (Exception e) {
|
|
|
+// if (packet != null) {
|
|
|
+// TsiCpuPacket cpuPacket = (TsiCpuPacket)((AbstractTsiPacket)packet);
|
|
|
+// TsiNodeVo nodeVo = (TsiNodeVo)cpuPacket.getObj();
|
|
|
+// if (nodeVo != null) {
|
|
|
+// log.warn(" Node: {}, Network Conn: {}", nodeVo.getKey(), nodeVo.isConnect());
|
|
|
+// }
|
|
|
+// }
|
|
|
+// else {
|
|
|
+// log.error("Exception(PacketWorker while): {}", e.getMessage());
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
/*
|
|
|
* 작업큐에 데이터 추가
|
|
|
*/
|
|
@@ -71,18 +108,18 @@ public class TsiCvimPacketWorker extends AbstractTsiCvimWorker implements Runnab
|
|
|
boolean offer = false;
|
|
|
AbstractTsiPacket packet = (AbstractTsiPacket)object;
|
|
|
try {
|
|
|
- //offer => full -> return
|
|
|
- //add => full -> wait
|
|
|
- offer = this.DATA_QUEUE.offer(packet);
|
|
|
+ offer = this.DATA_QUEUE.offer(packet); //offer => full -> return, add => full -> wait
|
|
|
if (!offer) {
|
|
|
MDC.put("id", Long.toString(packet.getNodeId()));
|
|
|
- log.error("Packet Queue.offer: {}/{}, {}, Queue Full: {} EA, {}, {}",
|
|
|
- packet.getNodeId(), this.DATA_QUEUE.size(), this.idx, this.qSize, TimeUtils.elapsedTime(packet.getRcv()), Thread.currentThread().getName());
|
|
|
+ log.error("PacketWorker({}): Queue.offer(Full): {}, {}/{}/{}, {}, {}",
|
|
|
+ this.idx, packet.getNodeId(),
|
|
|
+ this.DATA_QUEUE.size(), this.qSize, this.DATA_QUEUE.remainingCapacity(),
|
|
|
+ TimeUtils.elapsedTime(packet.getRcv()), Thread.currentThread().getName());
|
|
|
MDC.clear();
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
MDC.put("id", Long.toString(packet.getNodeId()));
|
|
|
- log.error("Packet Queue.offer: Exception: {}, {}, {}", packet.getNodeId(), Thread.currentThread().getName(), e.getMessage());
|
|
|
+ log.error("PacketWorker({}): Queue.offer: Exception: {}, {}, {}", this.idx, packet.getNodeId(), Thread.currentThread().getName(), e.getMessage());
|
|
|
MDC.clear();
|
|
|
}
|
|
|
return offer;
|
|
@@ -92,9 +129,10 @@ public class TsiCvimPacketWorker extends AbstractTsiCvimWorker implements Runnab
|
|
|
AbstractTsiPacket packet = (AbstractTsiPacket)object;
|
|
|
TsiCpuPacket cpuPacket = (TsiCpuPacket)packet;
|
|
|
TsiNodeVo nodeVo = (TsiNodeVo)cpuPacket.getObj();//TsiNodeManager.getInstance().get(packet.getNodeId());
|
|
|
+ long nodeId = packet.getNodeId();
|
|
|
if (nodeVo == null) {
|
|
|
// 노드 정보가 없는 경우
|
|
|
- log.error("Packet process NodeVo is null: {}, {}", packet.getNodeId(), Thread.currentThread().getName());
|
|
|
+ log.error("Packet process NodeVo is null: {}, {}", nodeId, Thread.currentThread().getName());
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -102,25 +140,31 @@ public class TsiCvimPacketWorker extends AbstractTsiCvimWorker implements Runnab
|
|
|
|
|
|
long curr = System.nanoTime();
|
|
|
if (TimeUnit.MILLISECONDS.convert(curr - packet.getRcv(), TimeUnit.NANOSECONDS) > 3000) {
|
|
|
- log.error("Packet skip::: {}, {} ms.", packet.getNodeId(), TimeUnit.MILLISECONDS.convert(curr - packet.getRcv(), TimeUnit.NANOSECONDS));
|
|
|
+ log.error("Packet skip::: {}, {} ms.", nodeId, TimeUnit.MILLISECONDS.convert(curr - packet.getRcv(), TimeUnit.NANOSECONDS));
|
|
|
return;
|
|
|
}
|
|
|
packet.setPop(curr);
|
|
|
|
|
|
if (packet.getOpCode() == (byte) eOpCode.TSI_CPU_DISCONNECTED.getValue()) {
|
|
|
- TsiCpuDisconnected disconnected = (TsiCpuDisconnected)packet;
|
|
|
- disconnected.parsing(nodeVo);
|
|
|
- if (nodeVo.isSendCvim() && disconnected.getCvimData() != null) {
|
|
|
- this.kafkaProducer.sendCvim(disconnected.getNodeId(), disconnected.getCvimData());
|
|
|
- }
|
|
|
+ MDC.put("id", nodeVo.getKey());
|
|
|
+ try {
|
|
|
+ TsiCpuDisconnected disconnected = (TsiCpuDisconnected) packet;
|
|
|
+ disconnected.parsing(nodeVo);
|
|
|
+ if (nodeVo.isSendCvim() && disconnected.getCvimData() != null) {
|
|
|
+ this.kafkaProducer.sendCvim(disconnected.getNodeId(), disconnected.getCvimData());
|
|
|
+ }
|
|
|
|
|
|
- if (disconnected.getAddNodes() != null) {
|
|
|
- // 연등지 인 경우
|
|
|
- for (int ii = 0; ii < disconnected.getAddNodes().size(); ii++) {
|
|
|
- this.kafkaProducer.sendCvim(disconnected.getAddNodes().get(ii).getNodeId(), disconnected.getAddNodes().get(ii).getCvimData());
|
|
|
+ if (disconnected.getAddNodes() != null) {
|
|
|
+ // 연등지 인 경우
|
|
|
+ for (int ii = 0; ii < disconnected.getAddNodes().size(); ii++) {
|
|
|
+ this.kafkaProducer.sendCvim(disconnected.getAddNodes().get(ii).getNodeId(), disconnected.getAddNodes().get(ii).getCvimData());
|
|
|
+ }
|
|
|
}
|
|
|
+ this.loggingService.add(packet, loggingIdx);//(int)Thread.currentThread().getId());
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("Disconnect Packet parsing error: {}, {}, {}", nodeId, Thread.currentThread().getName(), e.getMessage());
|
|
|
}
|
|
|
- this.loggingService.add(packet, loggingIdx);//(int)Thread.currentThread().getId());
|
|
|
+ MDC.clear();
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -128,10 +172,15 @@ public class TsiCvimPacketWorker extends AbstractTsiCvimWorker implements Runnab
|
|
|
// 20250425: packet parsing 의 로그를 노드별 로그파일에 저장되도록 MDC 위치 변경
|
|
|
// 20250425: parsing 함수에 packet-check 여부를 같이 넘겨줘서 CRC 체크여부 확인
|
|
|
MDC.put("id", nodeVo.getKey());
|
|
|
- if (!cpuPacket.parsing(nodeVo, this.cvimServerConfig.isCheckPacket())) {
|
|
|
- // MDC.put("id", nodeVo.getKey());
|
|
|
- log.error("Packet parsing failed: {}", packet.getNodeId());
|
|
|
- // MDC.clear();
|
|
|
+ try {
|
|
|
+ if (!cpuPacket.parsing(nodeVo, this.cvimServerConfig.isCheckPacket())) {
|
|
|
+ // MDC.put("id", nodeVo.getKey());
|
|
|
+ log.error("Packet parsing failed: {}", nodeId);
|
|
|
+ // MDC.clear();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception e) {
|
|
|
+ log.error("Cpu Packet parsing error: {}, {}, {}", nodeId, Thread.currentThread().getName(), e.getMessage());
|
|
|
}
|
|
|
MDC.clear();
|
|
|
|
|
@@ -139,13 +188,13 @@ public class TsiCvimPacketWorker extends AbstractTsiCvimWorker implements Runnab
|
|
|
|
|
|
// 카프카 전송
|
|
|
if (nodeVo.isSendNode() && packet.getNodeData() != null) {
|
|
|
- this.kafkaProducer.sendNode(Long.toString(packet.getNodeId()), packet.getNodeData());
|
|
|
+ this.kafkaProducer.sendNode(Long.toString(nodeId), packet.getNodeData());
|
|
|
}
|
|
|
if (nodeVo.isSendTest()) {
|
|
|
- this.kafkaProducer.sendTest(packet.getNodeId(), packet.getTestData());
|
|
|
+ this.kafkaProducer.sendTest(nodeId, packet.getTestData());
|
|
|
}
|
|
|
if (nodeVo.isSendCvim() && packet.getCvimData() != null) {
|
|
|
- this.kafkaProducer.sendCvim(packet.getNodeId(), packet.getCvimData());
|
|
|
+ this.kafkaProducer.sendCvim(nodeId, packet.getCvimData());
|
|
|
}
|
|
|
|
|
|
if (cpuPacket.getAddNodes() != null) {
|
|
@@ -182,7 +231,11 @@ public class TsiCvimPacketWorker extends AbstractTsiCvimWorker implements Runnab
|
|
|
}
|
|
|
|
|
|
public void report() {
|
|
|
- long avgTime = 0;
|
|
|
- log.info("Packet: Remain Q: {}, Average: {}, {}", this.DATA_QUEUE.size(), TimeUtils.elapsedTimeStr(avgTime), Thread.currentThread().getName());
|
|
|
+ log.info("PacketWorker({}), Queue Total/Size/Remain: {}/{}/{}, Average: {}, {}",
|
|
|
+ this.idx,
|
|
|
+ this.qSize, this.DATA_QUEUE.size(), this.DATA_QUEUE.remainingCapacity(),
|
|
|
+ TimeUtils.elapsedTimeStr(this.avgTime),
|
|
|
+ Thread.currentThread().getName());
|
|
|
}
|
|
|
+
|
|
|
}
|