현장 사례집
「이렇게 하세요」가 아니라 「이렇게 됐고 이렇게 풀었다」의 기록입니다. 2026년 2월부터 9월까지 실제 현장에서 겪고 해결한 것만 담았습니다.
1. 현장 설치 · 네트워크
PLC 에 ping 이 안 되고 데이터를 못 주고받음
- 증상 현장 설치 후 PLC 와 통신 불가. ping 무응답.
- 원인 PLC IP 와 엣지 PC 에 할당할 IP 를 구분하지 않았습니다.
- 조치 엣지 PC IP 를 PLC 와 같은 대역 · 다른 호스트 · 동일 마스크로 설정합니다. 출장 전 표에 두 IP 를 채워 서로 다른 값인지 확인하고 출발하세요.
- 확인 양쪽 통신이 동시에 끊기면 IP 충돌을 먼저 의심합니다.
ping→ 포트 → read 순으로 좁힙니다.
미쓰비시 포트를 몰라 엔지니어 대기만 함
- 증상 MC 프로토콜 포트를 몰라 작업이 멈춤.
- 원인 미쓰비시는 공식 고정 포트가 없습니다. GX Works 의 「오픈 설정」에서 지정하는 값입니다.
- 조치 엔지니어에게 네 가지만 지정해 요청합니다 — ① 오픈 설정 화면 ② 프로토콜·오픈 방식·자국 포트 ③ MC 프로토콜용 설정 여부 ④ 접속 허용 IP 제한. 「통신 설정 어떻게 하나요」로 열어 묻지 않습니다.
- 참고 관행값은 내장 이더넷 1025 · 모듈 2001 이고 5001·5002 는 예약입니다. 5007 은 라이브러리 기본값이지 미쓰비시 기본값이 아닙니다.
ping·포트는 되는데 값이 안 읽힘
- 증상 연결은 되는데 메모리 값이 안 들어옴.
- 원인 PLC DB 블럭 메모리 주소값 문제.
- 조치 PLC 엔지니어에게 DB 블럭 주소값 확인을 요청합니다. 주소가 맞고 연결 옵션에 이슈가 없으면 엣지 측 스캔 문제는 없다는 것이 현장 자료로 증명돼 있습니다. 그 선부터는 PLC 측 조치입니다.
판넬 문을 닫으면 통신이 불안정해짐
- 증상 판넬 문을 닫으면 네트워크가 매우 불안정하고, 열어두면 양호.
- 원인 두꺼운 판넬 내부에 엣지 PC·LTE 라우터·안테나까지 전부 넣은 구성.
- 조치 안테나를 판넬 외부로 설치합니다. 타공 위치는 전기실 담당이 지정합니다. 외부 설치 시 접합부 실리콘 처리가 필수입니다 — 고정 불량을 막습니다.
실사에서 확인 항목을 놓쳐 현장에서 막힘
- 증상 준비했다고 생각했는데 현장에서 변수가 계속 나옴.
- 조치 실사 6항목을 고정합니다 — 판넬 구조·함체 종류 / PLC 모델·상태 / 네트워크 통신 방식 / AP 구역 ping 상태 / 엣지 PC 설치 위치 / 안테나 위치. 함체는 엣지 미니 PC + LTE 라우터 + 2구 멀티탭 구성이며 전원 어댑터 위치를 반드시 고려합니다.
엣지 PC 설치 대수를 확정할 수 없었음
- 증상 실사를 마쳤는데 장비 수량이 안 나옴.
- 원인 수집 태그 수가 확보되지 않았습니다. 태그 수와 수집 주기가 있어야 장비당 부하를 잡고 대수를 정할 수 있는데 목록이 없었고, 설치 위치도 제한적이라 추가 설치가 어려웠습니다. 1:1 매핑을 전제했으나 고객사는 1:N 을 요구했습니다.
- 조치 실사 전에 ① 사업장별 PLC 태그 목록·수 ② 설치 정보 양식(PLC/SCADA · IP/PORT · 프로토콜) ③ 신규 구간 네트워크 구성 방안을 먼저 받습니다.
PLC 에 이더넷 포트가 없거나 SCADA PC 경유를 요구받음
- 증상 이더넷 TCP 직결 전제가 성립하지 않음. 「PLC 에 연결된 PC 에서 가져가면 되지 않냐」는 요구, 또는 PLC 다수가 SCADA PC 의 DB 에만 기록되는 구조.
- 조치 실사 시 PLC 이더넷 포트 유무 / SCADA 경유 여부 / SCADA DB 종류·기록 방식을 반드시 확인해 수집 방식을 사전에 결정합니다.
테스트 도구를 붙였다가 수집이 깨짐
- 증상 검증 도구 접속 후 기존 수집이 거부되거나 교란됨.
- 원인 MELSEC 같은 단일 연결 슬롯 장비에 두 번째 TCP 연결을 열었습니다.
- 조치 세 가지를 금합니다.
- 수집 중인 PLC 에 두 번째 연결 금지 — 해당 OPC 를 먼저 정지합니다.
- write 금지 — 도구 인자 하나로 write 가 됩니다.
- 프로브 타임아웃 1초 금지 — 장비 accept 지연 실측이 약 2.6초입니다. 3~5초로 잡습니다.
2. 부팅 · 기동
부팅 후 모든 endpoint 무응답 + ping retry 로그 도배
- 증상 요청이 전부 timeout(code=000).
- 원인
dev.mode=EDGE인데 외부 플랫폼 웹 포트가 죽어 부팅이 차단됐습니다. - 조치
dev.mode=STANDALONE으로 바꿔 재기동하고, 외부가 회복되면 원복합니다.server.host도 함께 확인합니다.
웹 화면이 3~4분마다 먹통
- 증상 주기적으로 웹이 죽고 되살아남.
- 원인 플랫폼 미연결. 붙지 못하면 웹 컨텍스트가 3~4분마다 리로드 루프에 빠집니다. 연결되면 멈춥니다. 웹 자체 문제가 아닙니다.
- 조치 플랫폼 연결 복구가 근본입니다.
인증 키를 바꾼 뒤 NPE 무한 폭주
- 증상 로그에
dm is nullNPE 가 끝없이 쌓이고 DB 관련 기능이 전부 죽음. - 원인 키가 틀리면 API client 초기화가 403 으로 hard-fail 하고, 그 결과
DatalakeManager가 초기화되지 않아 DB 계층이 무너집니다. 정상 키일 때는 폴백으로 올라옵니다. - 조치 원래 키로 원복 후 재기동합니다. 부팅 로그의
DataSource initialized — ready줄로 확인합니다.
3. 플랫폼 상행(전송) 끊김
엣지 웹·수집은 정상인데 플랫폼에 데이터가 안 올라옴
가장 자주 마주친 형태입니다.
-
증상 현장 수집과 웹은 멀쩡한데 상행만 멈춥니다. 웹포트 TIME-WAIT 이 100개 이상 폭주합니다.
-
원인 회선 순단 후 MQTT 재연결 CONNECT 에 인증정보가 빠져 플랫폼이 거부하고 무한 재연결에 빠집니다. 최초 기동 경로에는 인증정보가 들어가므로, 한 번 끊기면 앱이 스스로 복구하지 못합니다.
-
조치 웹앱 재시작으로 세션이 복구됩니다. 재발 방지는 아래 watchdog 입니다.
-
확인 지문은 「플랫폼 웹포트는 열리는데 MQTT 세션이 없다」입니다.
nc -z -w2 <플랫폼IP> <웹포트> && echo ROUTE_OKss -tan | grep -c "ESTAB.*<플랫폼IP>:<MQTT포트>" # 1 정상 / 0 끊김
순단은 몇 초인데 며칠간 상행 중단
- 증상 7초 순단 후 3시간 중단, 순단 한 번으로 11일 중단.
- 원인 위와 같습니다. 웹·PLC 수집·회선이 전부 정상이라 아무도 인지하지 못했습니다.
- 조치 자동복구(watchdog)를 배포합니다. 순단 길이와 중단 길이는 무관하므로 감시자 없는 장비를 먼저 처리합니다.
플랫폼에 적재가 안 되는데 엣지를 계속 파고들었음
- 증상 상행은 되는데 플랫폼에 데이터가 남지 않음.
- 원인 엣지가 아니라 플랫폼 저장 경로였습니다. 브로커 전 토픽 캡처로 엣지 발행은 정상임을 확인했고, 진짜 차단점은 플랫폼 저장 초기화가 DB 쿼리 타임아웃으로 영구 미초기화된 것이었습니다.
- 조치 플랫폼 서버를 재기동합니다. 최종 복구는 여러 원인을 동시에 해소한 것이었습니다 — 브로커 인증 파일 누락 + 태그 description null + 플랫폼 저장버퍼 정지.
- 확인 적재 성공은 SSTable 생성이 아니라 대상 태그의 실재로 판정합니다. 생성만 보고 통과로 오판한 이력이 있습니다.
watchdog 자동복구 구성
- 증상 상행 끊김을 사람이 발견해야만 복구됐습니다.
- 조치 watchdog 세 종을 각각 독립 서비스로 배포합니다 — 회선(로그만) · 설비망(로그만) · 플랫폼 세션(웹앱 재시작). 하나가 죽어도 나머지가 살아야 하므로 하나로 합치지 않습니다.
- 판정 30초 간격 4회 연속(약 2분) 지문 확정 → 재시작 → 15분 재발동 금지.
- 결과 6대 배포에 오탐 0건. 실전 복구는 순단 05:27 → 발동 05:39 → 복구 05:40 이었습니다.
watchdog 을 깔았는데 자동복구가 안 됨
- 증상 11일간 중단됐는데 watchdog 이 아무 동작도 안 함.
- 원인 관찰 전용(
DRY_RUN=1) 상태였습니다.would restart가 1,013회 기록만 남았습니다. 판정은 정확했고 실패 지점은 이것 하나였습니다. - 조치 관찰 배포 → 1대 실재시작 검증 → 정상 상태에서 실행 모드로 전환합니다. 끊긴 상태에서 전환하면 즉시 재시작이 발동합니다.
수동 재시작 명령이 자기 셸을 죽임
- 증상 재시작 명령 실행 후 셸이 즉사하고 웹앱이 3분 34초간 다운.
- 원인
pkill -9 -ef tomcat의 커맨드라인에 「tomcat」 이 들어 있어 자기 자신을 매치했습니다. 뒤에 이어붙인 startup 이 실행되지 않았습니다. - 조치 kill 과 startup 을 별도 실행으로 분리합니다. 상태 확인은
pgrep -f 'catalina[.]startup'처럼 대괄호로 자기 매치를 피합니다. - 주의
restart.sh는 끝에 로그 tail 이 있어 자동화에서 호출하면 멈춥니다.
PLC 는 정상인데 watchdog 이 서비스 DOWN 이라고 함
- 증상 세션이 살아 있는데 오탐 1,422건.
- 원인 ① 판정 패턴이 IPv6-mapped 표기(
[::ffff:<PLC_IP>]:<PLC포트>)를 놓쳤습니다. ② 폴백으로 쓴nc가 단일 세션 장비에서 거부됐습니다. - 조치 ① 패턴을 대괄호 유무 양쪽을 받도록 고칩니다. ② 판정 순서를
ss ESTAB패시브 우선, 없을 때만nc로 바꿉니다.
watchdog 을 재시작했더니 수집이 2분 끊김
- 증상 watchdog 설정을 바꾸자 웹앱이 함께 종료됨.
- 원인 watchdog 이 띄운 웹앱은 watchdog 서비스의 cgroup 에 편입되어 함께 죽습니다.
- 조치 90초 뒤 재감지·재기동으로 자가치유되지만 2분 중단이 생깁니다. watchdog 설정 변경은 조업 영향 없는 시간에 합니다.
진단 채널 401 이 반복 기록됨
- 증상 진단 포트가 만성 SYN-SENT, 로그에 진단 인증 401 이 2~3초마다 찍힘.
- 원인 플랫폼 측 사안이며, 401 은 진단 전송기가 키를 싣지 않는 세대 차 때문에 정상 동작 조합에서도 똑같이 발생합니다.
- 조치 엣지 재시작으로 해결되지 않으므로 watchdog 트리거에서 제외합니다. 연동 정상 여부는 60초 안에 실제 태그 데이터가 들어오는지로 판정합니다.
4. PLC 수집 안정성
통신이 잠깐 흔들릴 때마다 수집이 중지·재시작을 반복
-
증상 일시적 통신 변동에 수집이 멈추고 다시 붙기를 반복.
-
원인 ping 1회 실패로 즉시 수집기를 멈췄습니다.
-
조치 유예를 멈춤과 복구 쪽에 두었습니다. NOT_COLLECT 판정 자체에는 유예가 없습니다.
무엇 값 ping 주기 · ICMP 타임아웃 5초 · 800ms ping 연속 실패 몇 회에 수집기를 멈추나 (성공하면 리셋) 3회 최근 읽기가 성공해 신선하면 ping 을 건너뛰는 창 15초 또는 수집 주기 ×3 중 긴 쪽 NOT_COLLECT 로 떨어지는 조건 유예 없음 — 한 주기에 오류가 1건이라도 있거나 값을 하나도 받지 못하면 그 주기에 바로 NOT_COLLECT 가 얼마나 이어져야 복구(재연결)를 요청하나 60초 넘게 설정으로 바꿀 수 없습니다ping 3회 · 복구 60초를 비롯해 위 값은 모두 코드에 박힌 상수입니다.
app.properties에 해당 키가 없습니다 — 바꾸려면 제품 변경이 필요합니다. 예전 자료에 설정 키처럼 적힌 것이 있는데 사실이 아닙니다.함께 태그별 재시도를 없앴습니다. 연결이 끊기면 모든 태그가 동시에 실패하므로 재시도는 스캔만 지연시킵니다. 대신 태그별 읽기 타임아웃을 두어 한 태그의 지연이 전체 스캔을 묶지 않게 했습니다.
연결 실패에는 연결별 재접속 백오프가 걸립니다(2026-10-01). 1초부터 두 배씩, 최대 60초까지 기다렸다가 다시 붙습니다. 접속에 성공하거나 IP·포트를 바꾸면 기다리지 않고 바로 다시 시도합니다.
-
결과 잠깐의 흔들림은 화면에 NOT_COLLECT 로 잠깐 보일 수 있습니다. 그래도 수집기를 멈추거나 재연결을 일으키지는 않습니다 — ping 이 3회 연속 실패하기 전엔 멈추지 않고, 복구는 NOT_COLLECT 가 60초 넘게 이어질 때만 요청합니다.
감시층 ICMP 오탐으로 멀쩡한 수집이 정지됨
- 증상 수집은 되고 있는데 감시가 수집기를 멈춤.
- 원인 감시층이 ping 결과만으로 판단했습니다.
- 조치 감시 기준을 **「트래픽이 곧 생존 증거」**로 바꿉니다. 최근 read 가 성공했고 신선하면 프로브를 생략합니다.
소켓 누수로 PLC 가 50분간 전면 거부
- 증상 수집·프로브·복구 모든 연결이 거부됨.
- 원인 드라이버를 폐기할 때 close 없이 버려 소켓이 누수됐고, 단일 슬롯 장비라 그 소켓이 슬롯을 영구 점유했습니다.
connected=false는 논리 플래그일 뿐 TCP 소켓과 별개입니다. - 조치 드라이버를 제거·교체하는 코드에 close 를 반드시 동반시킵니다.
프로브 타임아웃 때문에 복구가 영영 열리지 않음
- 증상 슬롯이 비어 있는데도 복구가 안 됨.
- 원인 장비 accept 지연이 약 2.6초인데 프로브 타임아웃이 1초라 영구 실패로 판정했습니다.
- 조치 타임아웃을 4초로 올립니다. 새 장비를 붙일 때는 연결 소요를 로그로 실측하고 여유를 검증합니다.
바로 위 세 사례는 같은 증상에 원인이 세 겹이었습니다. 하나를 고칠 때마다 「해결됐다」고 판단했지만 다음 원인이 남아 있었습니다.
사고는 대부분 부팅 후 1분 안에 나타납니다. 초기 3분을 집중해 관찰하고, 통과 판정은 부팅 결정 구간 + 15분 무정지 + 로그 0건을 모두 채웠을 때만 줍니다.
통신 불안정의 원인이 회선인지 확인이 안 됨
- 증상 간헐적 수집 실패의 원인 구간을 못 짚음.
- 관측 실사례에서 연결 지연이 평균의 6배(6,125ms) 로 뛴 뒤 며칠에 걸쳐 링크가 끊겼고, 무조치로 자동 복구되어 수집이 재개됐습니다. 지연 급증이 전조입니다.
- 조치 상시 품질 감시를 둡니다. 1초 ping 을 10분 단위로 요약(손실률 · RTT 최소·평균·최대)하고, 손실률 5% 이상이면 인터페이스 에러 카운터와 라우팅을 스냅샷으로 동시 기록합니다. 판정은 정상 / 주의 5% / 위험 10% 이고 로그는 15일 보관합니다.
패킷 손실 상황을 재현할 수 없었음
-
증상 현장 증상을 사내에서 재현하지 못해 검증이 막힘.
-
조치
tc/netem으로 특정 PLC IP 통신에만 손실을 겁니다. SSH 나 다른 통신에는 영향이 없습니다.tc qdisc del dev <NIC> root 2>/dev/null # 항상 먼저 제거tc qdisc add dev <NIC> root handle 1: htb default 30tc class add dev <NIC> parent 1: classid 1:1 htb rate 100mbittc class add dev <NIC> parent 1:1 classid 1:10 htb rate 100mbittc qdisc add dev <NIC> parent 1:10 handle 10: netem loss 5%tc filter add dev <NIC> protocol ip parent 1:0 prio 1 u32 match ip dst <PLC_IP> flowid 1:10tc qdisc del dev <NIC> root # 종료
watchdog 로그 판독
상태가 바뀔 때만 이벤트 블록이 남습니다. grep "EVENT" 로 사건만 봅니다.
| 갈래 | 신호 | 뜻 |
|---|---|---|
| LTE | CABLE_DISCONNECTED | 물리 링크 |
| LTE | ROUTER_DOWN | 라우터 ping 실패 |
| LTE | LTE_NO_RETURN_TRAFFIC | 송신은 있는데 수신 0 — 상행 단절 |
| LTE | LTE_SIGNAL_LOST | 외부 ping 실패 |
| PLC | LINK_DOWN · ARP_L2_ISSUE | 링크·L2 |
| PLC | PHYSICAL_LAYER_ISSUE | CRC 증가 — 케이블·포트 물리 |
| PLC | PLC_NO_RESPONSE · PLC_SERVICE_DOWN | 무응답 · 포트 닫힘 |
⚠ 일부 NIC 은 rx_crc_errors 를 지원하지 않습니다. CRC:+0 은 폴백값이므로 물리 판정에 쓰지 마세요.
5. 값이 안 나오거나 이상함
HMI 화면 값과 엣지 수집 값이 다름
- 원인 HMI 값은 이미 로직이 적용된 값일 수 있습니다.
- 조치 3단으로 좁힙니다 — PLC 메모리 원본 → HMI 판넬(로직 적용) → 엣지(데이터 타입·수집주기·수식). 먼저 PLC 원본과 비교하고, 그다음 엣지의 타입·주기·수식을 확인해 최종 비교합니다.
카운터에 간헐적으로 이상한 중간값이 섞임
- 원인 PLC 스캔 주기 중 카운터 갱신 타이밍과 읽기 시점이 겹치면 상·하위 워드의 정합성이 깨진 중간값이 읽힙니다. 장애가 아니라 타이밍 특성입니다.
태그 주소를 넣었는데 계속 빈 값
-
원인 JSON 계열 주소에서 PATH 모드 표기(
$.)를 빠뜨려 KEY 모드로 떨어졌습니다. KEY 모드는 경로를 따라가지 않고 최상위 키 이름 그대로 찾습니다. 해당하는 것은 Kafka · MQTT · WebSocket 이고 HTTP 는 아닙니다. -
조치 세 가지를 확인합니다.
- 배열 인덱스는 점과 숫자(
.0.)이고 대괄호 표기는 지원하지 않습니다. - 필드명은 대소문자까지 정확해야 합니다(
agvid실패 /agvId성공). - 와일드카드와 배열 전체 펼침은 지원하지 않습니다.
TOPIC:$.body.list.0.battery ✅TOPIC:body.list[0].battery ❌ - 배열 인덱스는 점과 숫자(
특정 태그만 계속 빈 값
- 원인 발신 측 페이로드의 필드명이 오타였습니다(
status→stutaus). 정상 스펠링으로 등록하면 에러 없이 빈 값만 나옵니다. - 조치 등록 전에 실제 페이로드의 필드명 원문을 눈으로 확인합니다.
- 함께 알아 둘 것 빈 문자열은 아예 적재되지 않습니다(알람 없는 시간대에 데이터 공백이 생깁니다). JSON
null은 문자열"null"로 적재되므로 숫자 타입으로 등록하면 파싱에 실패합니다.
발행 건수보다 수집 건수가 훨씬 적음
- 원인 설계상 정상입니다. 드라이버가 메시지를 마지막 값으로 덮어쓰고, 읽기는 큐 소비가 아니라 마지막 값 폴링 샘플입니다. 브로커 LAG 이 0 이면 다 받고 있는 것입니다.
- 조치 전수집이 필요하면 큐 기반 재설계가 필요합니다. 계약 변경 사안입니다.
등록 직후 옛 데이터가 쏟아지거나 반대로 안 들어옴
- 원인 Kafka 의
auto-offset방향입니다(기본latest).latest는 컨슈머 그룹 생성 뒤에 발행해야 잡히고,earliest는 등록 순간 쌓여 있던 기존 메시지를 일괄 소비합니다. 두 값 외에는 조용히latest로 떨어집니다. - 주의 이건 Kafka 만 해당합니다. MQTT 에는 offset 개념이 없습니다 — 비슷한 자리가
clean-session입니다. - 조치 검증은 실시간 발행으로 합니다.
데이터 추출이 0건인데 에러 로그도 없음
- 원인 jar 충돌 — 재패키징된 JSON 라이브러리가 표준 라이브러리와 충돌해 필요한 생성자가 없었습니다.
- 조치 표준 jar 로 교체하고 충돌 jar 를 백업 이동한 뒤 캐시를 정리하고 재기동합니다.
- 확인 정상은 조용한 성공입니다. 폴링 스레드가 살아 있고 LAG 이 0 이며
VALUE_NULL로그가 멈추면 정상입니다. 성공 로그는 나오지 않습니다.
타입 예외가 납니다
- 증상
NumberFormatException또는Invalid tag data type. - 원인 등록할 때 타입을 일괄 Integer 로 넣었습니다.
- 조치 값 성격대로 다시 나눕니다 — Double 은 전류·온도·전압·중량·속도·좌표, String 은 알람·상태·구역·방향·색, Integer 는 배터리·에러코드입니다. 엣지 태그 타입과 플랫폼 타입이 일치해야 합니다. 값이 문자열로 와도 선언 타입만 맞으면 정확히 파싱됩니다.
메타데이터를 바꿨는데 반영되지 않음
- 원인 캐시 reload 를 하지 않았습니다.
- 조치 세 곳을 모두 다시 읽힙니다 — 플랫폼 서버, OPC-UA 플러그인, 엣지. 하나만 빠져도 정합성이 깨집니다. OPC 를 다시 등록해 태그 ID 가 재발급되면 플랫폼의 태그 잔재를 지우고 OPC 를 정지했다 시작해 재동기화합니다.
REST 로 등록했더니 드라이버가 브로커 접속조차 안 함
- 증상 「PLC 연결 timeout」 처럼 보이지만 TCP 는 정상이고 컨슈머 그룹조차 생기지 않음.
- 원인 OPC 생성 요청 본문에 필수 필드가 빠져 내부에서 예외가 나고 주소 맵 스캔이 실패했습니다. 화면으로 등록하면 화면이 채워 주므로 REST 경로에서만 터집니다.
- 조치 필수 필드 여덟 개를 모두 채웁니다 —
opc_id·opc_name·opc_type·site_id·opc_agent_ip·opc_agent_port·timecycle·async. 주소 표기와 offset 방향도 함께 확인합니다. - 바뀐 것 예전에는
PUT이 미지정 필드를 비워 버려 「삭제 후 재생성」이 안전했습니다. 2026-07-20 에 부분 병합으로 고쳐졌습니다 — 이제 보낸 필드만 바뀝니다. 다만 그래서 필드를null로 지울 수는 없습니다.
ping 은 되는데 수집이 0
- 원인 ping 은 되고 ARP 도 정상인데 TCP 포트만 닫혀 있었습니다. 읽기 에러 카운터가 480만인데 성공은 0 이었습니다.
- 조치 PLC 측 통신 포트·모듈 조치 대상이며 watchdog 으로 해결되지 않습니다. 설비 담당에게 넘깁니다.
최신값을 조회했는데 옛 데이터가 나옴
- 원인
SELECT * ... LIMIT 5는 파티션 순서라 옛 데이터가 먼저 나옵니다. 실시간 적재는 정상이었습니다. - 조치
WHERE tag_id=... ORDER BY timestamp DESC로 확인합니다.
6. 자원 고갈 · 로그
30일마다 온갖 오류가 동시에 터짐
-
증상 30일 가동 후 전방위 오류 폭발.
-
원인 감시 타이머가 10초마다 docker ping 을 시도하는데 docker 가 없으면 실패 경로에서 파일 디스크립터 2개가 회수되지 않습니다. 예외를 로그로 남기지 않아 무증상으로 쌓입니다. 산수가 맞아떨어집니다 — 30.3일을 10초로 나누면 261,700회, 곱하기 2 는 523,400 이고 실측이 523,690 이었습니다.
-
조치 정상 대조 장비와 같은 버전 docker 를 고정 설치합니다. 재부팅만 하면 30일 뒤에 재발합니다.
-
확인
P=$(pgrep -f catalina.startup.Bootstrap | head -1)ls /proc/$P/fd | wc -l # 정상 ~600, 누수 시 50만+wc -l < /proc/net/unix # 정상 ~200, 누수 시 50만+ls /var/run/docker.sock # 없으면 누수 진행 확정
/proc/stat 실패, Mount point not found, JMX NPE, 「열린 파일이 너무 많음」, 큐 WAL 예외
(수집 데이터 유실 구간), 로그 폭증은 전부 파일 디스크립터 고갈에서 파생된 것입니다.
고갈 이전 로그에는 ERROR 가 0건이었습니다.
스레드·FD 가 계속 늘어나고 OOM 발생
- 원인 죽은 대상에 대한 무한 재연결. 대상이 ping 은 되는데 프로토콜 포트는 죽은 상태에서 OPC 수십 종이 1초 주기로 재연결하며 시도마다 클라이언트를 만듭니다. 실측 초당 2.25개 순증이었고 상시 스레드의 76% 가 그것이었습니다. 다른 장비에서는 드라이버 스레드가 40,900개까지 늘어 OOM 이 났고 수집이 3일 정지됐는데 종료 로그조차 없어 인지하지 못했습니다.
- 조치 쓰지 않는 OPC 는 반드시 정지합니다. PLC 가 다운되면 같은 누수가 재현되므로 장기 가동 장비에서 특히 주의합니다.
같은 로그가 수만 건 쌓임
- 원인 폴링 주기가 하드코딩이라 끄는 설정이 없습니다.
- 조치 클래스를 패치하지 말고 로깅 설정에 해당 패키지 WARN 로거를 추가해 억제합니다.
7. 배포 · 초기화
고객사 장비에 설치 흔적을 남기지 않아야 했음
-
조치 파일을 올리는 대신 표준입력으로 스크립트를 투입합니다.
ssh <호스트> 'bash -s' < install.sh서버에 설치본 파일이 아예 생기지 않습니다.
-
확인 임시 디렉터리에 잔재가 없고 백업 파일이 생기지 않았으며, 24시간 내 새 파일은 의도한 산출물뿐인지 봅니다. 백업 원본은 로컬 보고서에 보존합니다.
한 줄 설치 명령이 404
- 원인 배포 경로가 개편됐고 도메인 최상위가 달랐습니다.
- 함께 걸린 것
- 심링크는 404 가 됩니다 — 포인터는 하드링크로 겁니다.
curl | bash로 실행하면 스크립트 안의read가 EOF 를 만나 전체가 중단됩니다. 터미널을 물려 해결합니다.- 한 단계 실패가 이후 방화벽·튜닝·SSL·서비스 등록을 전부 건너뛰게 만들어, 해당 단계를 비필수로 바꿨습니다.
박스를 OS 만 남기고 초기화
- 조치 순서 컨테이너 삭제를 엔진 제거보다 먼저 합니다. 재세팅 소스가 있는지를 0번 안전장치로 두고 없으면 중단합니다.
원격 접속 중에 방화벽을 리셋하면 SSH 가 끊겨 콘솔 없이는 복구할 수 없습니다. 재세팅 스크립트는 필요한 포트를 다시 열 뿐 닫지 않습니다.
- 의도적으로 안 건드리는 것 호스트명·로케일·타임존·부수 패키지입니다. 재세팅이 다시 설정합니다.
server.host 를 바꿨는데 데이터 방향이 안 바뀜
- 원인 그 장비는 pull 방식이었습니다. 플랫폼이 엣지의 태그 값 API 를 직접 읽어 갑니다. 엣지의 push 대상을 바꿔도 방향이 바뀌지 않습니다.
- 조치 다른 플랫폼으로 받으려면 그쪽에 엣지 주소와 키로 pull 설정을 합니다.
엣지·플랫폼 세대가 달라 연동 불가
- 증상
API server is not responding무한 반복. 포트는 전부 열려 있어 네트워크는 무죄. - 원인 신규 플랫폼이 새 API 만 여는데 구형 엣지가 옛 경로를 하드코딩으로 호출했습니다. 핸드셰이크가 선행돼야 발행이 시작됩니다.
- 조치 엣지를 플랫폼과 같은 릴리스로 업그레이드합니다. 설정으로는 안 됩니다 — 핸드셰이크가 컴파일되어 있습니다.
- 토큰 함정 저장과 배포는 다릅니다(화면에서 「배포」를 눌러야 합니다). 허용 IP 지정이 필요하고, 공개 ping 의 200 은 인증 증거가 아닙니다.