← 전체 글
OPC UA/약 11분 읽기/ 조회

OPC UA 클라이언트가 빠른 태그 변화를 놓치는 이유와 queue 설정

OPC UA monitored item queue, discard policy, Overflow 상태 비트가 SCADA 클라이언트가 모든 빠른 변화를 받을지 최신 값만 받을지를 어떻게 정하는지.

OPC UASCADAHMI태그문제 해결

PLC의 reject counter가 12에서 19로 뛰었는데, SCADA 트렌드는 12 → 19로 한 번에 올라간 것으로 보였다. 회선에서 값이 유실된 게 아니다. 클라이언트가 중간 값을 남겨 달라고 요청하지 않았을 뿐이다. 이 동작은 monitored item의 숫자 세 개가 정하는데, 대부분은 아무도 일부러 설정하지 않는다.

OPC UA Part 4(Services 규격)는 이 값들을 MonitoringParameters라고 부른다. samplingInterval, queueSize, discardOldest 플래그, 그리고 DataChangeFilter다. Sampling과 publishing은 사람들이 흔히 다투는 설정이고, queue는 빠른 전환을 조용히 삼키는 설정이다.

같은 숫자가 아닌 숫자 세 개

Sampling, publishing, queue size를 "더 빠르게"로 뭉뚱그리면 위의 reject counter 문제가 나온다. 셋은 다른 질문에 답한다.

파라미터의미답하는 질문
samplingInterval(item별)서버가 source value를 확인하는 주기서버/PLC가 이 속도를 실제로 감당하는가
Publishing interval(subscription별)subscription이 notification을 내보내는 주기클라이언트가 고르게 받는가, burst로 받는가
queueSize(item별)publish 사이에 대기할 notification 개수중간 값이 필요한가
discardOldest(item별)queue가 찼을 때 무엇을 버릴지최신 값을 남길지, 순서를 남길지
DataChangeFilter어떤 변화만 notification으로 만들지노이즈와 의미 있는 변화를 나눴는가

값이 빠진다고 queueSize를 1로 둔 채 publishing interval만 줄이면 publish 사이의 burst에는 아무 소용이 없다. Queue는 여전히 값 하나만 담는다. 클라이언트가 더 자주 publish할 뿐이다. Publish 두 주기 사이에 변화 열 개가 들어오고 queue가 하나만 담으면, publish를 아무리 빨리 해도 아홉 개는 사라진다.

위 표의 "item별"에 주의한다. samplingIntervalqueueSize는 subscription이 아니라 각 monitored item에 설정한다. 같은 subscription 안에서도 빠른 counter와 탱크 레벨에 다른 파라미터를 줄 수 있고, 줘야 한다.

Live 값은 queue size 1이 맞는 기본값이다

대부분의 SCADA 포인트는 live 상태값이다. 운전자는 지난 화면 갱신 이후의 모든 값이 아니라 지금 값과 그 품질을 본다. 이런 값은 queueSize 1이 맞다. 더 키우면 서버 메모리만 쓴다. 다음이 해당한다.

  • Overview 화면의 탱크 레벨.
  • 현재 운전 여부만 쓰는 모터 running feedback.
  • 천천히 움직이는 온도.
  • 어차피 히스토리언이 별도로 수집하는 HMI 표시용 값.

queueSize 1에서도 물리는 게 하나 있다. Quality다. 통신이 5초 끊겼다가 들어온 새 Good 값이, 그 사이 값이 Bad/Uncertain이었다는 사실까지 지워서는 안 된다. 히스토리언이 기록이라면 StatusCode 변화도 notification으로 잡히도록 구독해야 한다. DataChangeFilter의 Trigger 설정(StatusValueStatusValueTimestamp냐)이 이걸 정한다.

순서가 실제로 중요한 태그만 queue를 키운다

'최신 값'만으로 부족한 태그는 몇 개뿐이다. 모든 포인트를 부풀리지 말고 그런 태그에만 깊은 queue를 준다.

  • Reject가 몰릴 때 튀는 counter(도입부의 그 값).
  • Auto cycle 시작 중 여러 상태를 지나가는 step number.
  • 1초 안에 warning → fault → reset으로 바뀌는 diagnostic word.
  • MES나 report가 읽는 batch phase 전환.
  • 시운전 중 지켜보는 고속 test tag.

각각 최악의 burst를 숫자로 적어 둔다. 설비가 2초에 상태를 20번 바꿀 수 있고 publish가 1초에 한 번이면 queueSize 2로는 못 담는다. publish 사이 예상 변화 하나당 슬롯 하나에 여유를 더한 정도가 필요하다. 그리고 서버가 실제로 준 값을 확인한다. CreateMonitoredItemsRevisedQueueSizeRevisedSamplingInterval을 반환하고, 서버는 요청보다 적게 줄 수 있다. 요청값이 아니라 revised 값을 기록한다.

Discard policy: discardOldest는 진짜 결정이다

Queue가 차면 서버는 무언가를 버린다. discardOldest = true(기본값)는 queue에서 가장 오래된 notification을 버리고, false는 들어오는 값을 버린다.

discardOldest맞는 경우대가
true(기본값)현재값을 좇는 live 표시중간 이력이 사라진다
falsesequence의 앞 순서 보존클라이언트가 실제 공정보다 늦어질 수 있다

대부분의 live HMI 값은 true가 이해하기 쉽다. 화면이 최신 상태로 수렴한다. SOE(sequence of events) 작업에서는 false가 첫 fault 전환을 남기지만, 복구가 느리면 화면이 오래돼 보인다. 어느 쪽이든 중요 태그라면 이유 없이 벤더 기본값에 두지 않는다.

사람들이 놓치는 부분: 서버가 버렸다는 걸 알려 준다. Data change가 버려지면 OPC UA는 해당 queue에서 다음에 전달되는 값의 StatusCode에 Overflow InfoBit을 세운다(Part 4의 DataChangeNotification 처리). 클라이언트는 별도 서버 카운터 없이도 monitored item별로 손실을 감지할 수 있다. 단, StatusCode를 Good/Bad로 뭉개지 않고 InfoBits를 실제로 읽어야 한다. 드라이버가 severity만 남기고 나머지를 버리면 overflow 플래그를 못 보고, 버려진 값이 깨끗한 데이터처럼 보인다.

"가끔 값이 빠진다"를 실제 티켓으로 만드는 진단

Queue 문제는 재현 안 되는 간헐적 데이터 손실처럼 보인다. 다음을 시운전 화면이나 유지보수 문서에 남기면 추적된다.

  • Subscription 개수와 monitored item 개수(서버가 광고하는 MaxMonitoredItemsPerSubscription과 비교).
  • Revised publishing interval과 keep-alive count.
  • 늦은 PublishResponse 또는 늘어나는 publish request backlog.
  • 서버가 제공하는 queue overflow counter, 그리고 Overflow InfoBit을 달고 온 값의 수.
  • 거절된 CreateMonitoredItems 요청(서버가 MaxMonitoredItemsPerCall이나 세션 한도에 걸림).
  • 클라이언트 수신 queue 깊이 또는 처리 지연.
  • Source timestamp와 client receive time 차이.

부하 시험은 태그 하나가 아니라 실제 조합으로 한다. 빠른 test value를 바꾸면서 가장 무거운 HMI 화면을 열고 히스토리언 수집도 같이 돌린다. 화면 여러 개를 열 때만 overflow가 늘면 PLC 태그가 아니라 클라이언트 처리 경로가 못 따라오는 것이다.

Alarm은 빠른 Boolean이 아니다

알람의 active/inactive Boolean을 data change로 구독하면 상태는 얻지만 event는 못 얻는다. Condition ID, acknowledge, 전환 detail 같은 알람 이력에 필요한 정보는 담기지 않는다. 그건 Event 모델(Part 9, Alarms & Conditions)에 있고, DataChangeFilter가 아니라 EventFilter를 쓰는 event monitored item으로 전달된다.

알람이 많은 사이트에서는 다음을 확인한다.

  • Event subscription을 data subscription과 별도로 잡았는가.
  • Acknowledge, return-to-normal, shelving이 모두 timestamp와 함께 남는가.
  • Event queue 동작과 historical event가 단절을 견디는가(시험할 것).
  • HMI alarm summary가 sampled Boolean 하나에 기대지 않는가.

알람 순서가 중요하면 알람 경로를 알람 경로로 시험한다.

느낌이 아니라 기록을 남기는 시운전 시험

Test tag 두 개면 대부분 잡힌다.

  1. 1초마다 1씩 증가하는 태그.
  2. 최대한 빠르게 10번 증가하는 burst 태그.
  3. 운영에 쓸 파라미터 그대로 구독한다(요청값이 아니라 revised 값).
  4. Source timestamp, value, StatusCode(InfoBits 포함), receive time을 기록한다.
  5. 가장 무거운 HMI 화면과 히스토리언 collector를 동시에 켠다.
  6. Reconnect 복구가 요구 사항이면 시험 중 client를 끊고 다시 붙인다.
  7. 예상 증가 횟수와 실제 수신 횟수를 비교하고, Overflow 비트를 달고 온 값의 수를 센다.

결과에는 어떤 변화가 의도적으로 버려졌고 어떤 것이 문제인지가 적혀야 한다. "화면에서 대충 맞아 보였다"는 시운전 기록이 아니다.

결국 핵심은 queue 동작을 각 태그의 용도에 맞추는 일이다. Live 표시, 히스토리언 수집, 알람/event, sequence 진단은 서로 다른 파라미터를 원한다. Class로 나누고 각 class에 부하를 걸어 시험한다. 기본값은 당신의 공정이 아니라 서버 벤더가 고른 값이기 때문이다.