MergeContent · MergeRecord 프로세서 앞 큐에 FlowFile 이 쌓인 채 다음 단계로 넘어가지 않는 현상을 진단한 기록이다. 병합 프로세서는 "빈(bin) 배출 조건" 이 충족돼야만 결과를 내보내므로, 조건이 영원히 충족되지 않는 설정이 대부분의 원인이다. Cloudera(CFM/CDP) 환경에서는 설정 위치가 Ranger · NiFi UI · Cloudera Manager 세 곳으로 나뉘는 점도 정리한다.
들어온 FlowFile 은 즉시 병합되지 않고 힙 메모리상의 빈에 배정된다. Correlation Attribute Name 을 지정하면 그 속성값이 같은 것끼리 별도 빈으로 묶이고, 미지정 시 하나의 빈에 순서대로 쌓인다.
Merge Strategy 는 두 가지다. Bin-Packing Algorithm 은 조건만 채우면 순서 보장 없이 묶고, Defragment 는 fragment.identifier 로 그룹을 묶어 fragment.index 순으로 정렬하며 fragment.count 개수가 전부 모여야 병합한다(SplitText · SplitContent · UnpackContent 가 붙인 속성을 그대로 이용해 원본을 복원하는 용도).
빈 배출 조건은 다음과 같다.
| 조건 | 동작 |
|---|---|
Minimum Number of Entries, Minimum Group Size |
모두 충족해야 병합 시작 |
Maximum Number of Entries, Maximum Group Size |
하나라도 걸리면 즉시 병합 |
Max Bin Age |
시간이 지나면 최소 조건 미달이어도 강제 배출 (Defragment 는 미완성 그룹이 failure 로 감) |
Maximum number of Bins (기본 100) |
빈이 가득 차면 가장 오래된 빈을 강제로 밀어냄 |
병합 포맷은 Binary Concatenation(+Header/Footer/Demarcator) · TAR · ZIP · FlowFile Stream v3/v2 · Avro 이며, Binary Concatenation 은 content claim 을 이어 붙이는 방식이라 가장 가볍다. 결과는 merged, 원본 FlowFile 은 original 릴레이션으로 나간다.
Max Bin Age 미설정 — 최소 조건을 못 채운 빈이 무한 대기한다. 가장 흔한 원인이며 1 min 정도 넣어 흘러나오는지 보면 원인 특정이 빠르다.merged 다음 커넥션이 빨간색이면 프로세서가 멈춘다. original 릴레이션을 연결하지도 auto-terminate 하지도 않은 경우가 특히 많다.Single Node 또는 Attribute 기반으로 건다."안 돈다" 와 "돌지만 안 내보낸다" 는 원인이 다르다. 프로세서 박스의 Tasks / Time (5 min) 이 0 / 00:00:00 이면 스케줄 자체가 안 걸린 것이고, 숫자는 도는데 Out 이 0 이면 빈 조건 미충족이다. 좌상단 아이콘이 ▶ 이면 Stopped, 노란 느낌표면 Invalid(툴팁에 원인이 뜬다), ■ 이면 Running 이다.
큐에 FlowFile 이 1개인데 크기가 0 byte 인 경우는 Minimum Group Size 를 절대 충족하지 못한다. MergeRecord 는 레코드 0건이라 failure 로 가고, failure 가 자기 자신으로 루프백돼 있으면 무한 순환한다. 임시 해소는 Max Bin Age 설정이고, 근본 대응은 MergeContent 앞에 RouteOnAttribute 를 두고 ${fileSize:gt(0)} 조건으로 빈 FlowFile 을 걸러내는 것이다. 왜 0 byte 가 생겼는지는 List Queue → Attributes 와 Provenance 로 출처를 거슬러 확인한다.
| 대상 | 위치 |
|---|---|
| System Diagnostics / Summary 접근 권한 | Ranger → cm_nifi repo → /system READ (Controller Settings 는 /controller READ,WRITE, UI 접근은 /flow READ) |
| Max Timer Driven Thread Count | NiFi UI ☰ → Controller Settings → General (flow 정의에 저장되므로 CM 에서 못 바꿈, 재시작 불필요) |
| JVM 힙 · nifi.properties | Cloudera Manager → NiFi → Configuration (Java Heap Size of NiFi Node, 없는 키는 Safety Valve 로 key=value 추가, Stale → Restart) |
| 로그 | CM → NiFi → Instances → 노드 → Log Files → Role Log Details (NiFi UI 권한 없이도 nifi-app.log 열람 가능) |
Summary → System Diagnostics 가 안 보이면 전역 정책 view the system diagnostics 권한이 없는 것이다. 권한 없이 스레드 고갈 여부를 볼 때는 Running 중인 프로세서 좌상단의 스레드 배지 숫자, View Status History 의 Task Count · Task Duration, 우클릭 메뉴에 Terminate 가 활성화되는지(실행 중 스레드가 물려 있음)를 본다.
프로세서 UUID 로 grep 하는 것이 가장 정확하다. 로그에는 MergeContent[id=xxxx] 형태로 찍힌다.
grep "<UUID>" nifi-app.log
grep -i "thread pool\|has not finished\|still running\|Terminating" nifi-app.log
grep -i "bin" nifi-app.log | grep -i merge # Migrating bin / Merged / due to Max Bin Age
grep -i "back pressure\|is full" nifi-app.log
grep -i "OutOfMemory\|content repository\|disk usage" nifi-app.log
grep -i "primary node\|disconnected" nifi-app.log
UUID 흔적이 아예 없으면 스케줄 자체가 안 걸린 것이고, 흔적은 있는데 Merged 가 없으면 빈 조건 미충족이다. 콘텐츠 리포지토리 디스크가 임계치를 넘으면 전체 플로우가 정지하며 Unable to write flowfile content 가 대량으로 찍힌다.
빈은 노드 로컬 힙에 상주하므로 Maximum number of Bins 를 크게 잡으면 OOM 위험이 있다. 순서가 중요하면 Bin-Packing 대신 Defragment 를 쓰거나 EnforceOrder 를 앞에 둔다. 스레드 고갈은 마지막에 의심할 항목이며, 실제 원인은 Max Bin Age 미설정이나 original 릴레이션 미처리인 경우가 압도적으로 많다.