plantpulse-messaging (메시징 계층)
역할
PlantPulse 의 신경계 역할을 하는 메시지 브로커 계층입니다. 산업 현장에서 들어오는 센서 데이터를 수집하고, 모듈 간 이벤트를 전달합니다. 브로커는 둘입니다 — Kafka 와 HiveMQ(MQTT).
| 항목 | 값 |
|---|---|
| 모듈명 | plantpulse-messaging |
| 설치 경로 | /opt/kopens/plantpulse-platform/plantpulse-messaging/ |
| 데이터 위치 | /data1/pp-data/kafka/kraft_combined_logs |
pd 서비스 | messaging — MASTER 노드에서만 |
| 계정 | PP_MQ_USER / PP_MQ_PASSWORD — Kafka 와 HiveMQ 가 한 값을 공유합니다 |
브라우저 실시간 푸시가 SSE 로 바뀌면서 STOMP 브로커가 이미지에서 빠졌습니다. 61000 / 61004 포트와 PP_STOMP_* 는 더 이상 서비스되지 않습니다. 옛 방화벽 규칙에 남아 있다면 정리하세요.
구성
Kafka
KRaft 모드(ZooKeeper 없음)의 단일 브로커가 컨트롤러를 겸합니다.
| 항목 | 값 |
|---|---|
| 포트 | 9092 (SASL_PLAINTEXT) · 9093 (controller, 내부) · 9094 (SASL_SSL) |
| 인증 | SASL/PLAIN — 정적 JAAS(config/jaas.conf). 계정 PP_MQ_USER |
| 광고 주소 | PP_KAFKA_ADVERTISED_HOST — 기동 때 호스트 주소로 유도됩니다 |
| 토픽 접두사 | PP_TOPIC_PREFIX (기본 pp) |
브로커가 읽는 파일은 하나입니다
plantpulse-messaging/kafka/config/kafka.properties 가 브로커 설정이고, 호스트의 /etc/kopens/conf/kafka.properties.template 에서 렌더됩니다. 같은 디렉터리의 broker.properties · server.properties · controller.properties 는 아파치 카프카 배포판이 들고 오는 예제 파일이라 아무도 읽지 않습니다. 컨테이너 안에서 advertised.listeners=PLAINTEXT://localhost:9092 같은 값을 보고 놀라지 마세요.
템플릿의 핵심 줄(자리표시자는 렌더 때 채워집니다):
process.roles=broker,controller
listeners=SASL_PLAINTEXT://0.0.0.0:${PP_KAFKA_PORT},CONTROLLER://0.0.0.0:${PP_KAFKA_CONTROLLER_PORT:9093},SASL_SSL://0.0.0.0:${PP_KAFKA_TLS_PORT}
advertised.listeners=SASL_PLAINTEXT://${PP_KAFKA_ADVERTISED_HOST}:${PP_KAFKA_PORT},…
sasl.enabled.mechanisms=PLAIN
allow.everyone.if.no.acl.found=false
log.dirs=${PP_DATA_DIR}/kafka/kraft_combined_logs
log.retention.ms=3600000 # 1시간 — 버퍼이지 보관소가 아닙니다
log.segment.bytes=10485760 # 10MB
num.partitions=4
default.replication.factor=1 # 단일 브로커
message.max.bytes=157286400
auto.create.topics.enable=true
브로커 기본 보존은 1시간입니다. 데이터의 보관소는 Cassandra · 시계열 엔진 · Iceberg 이고, Kafka 는 그 사이의 버퍼입니다. 토픽별 보존과 «누가 그 값을 정했나» 는 pd retention 이 보여 줍니다.
주요 토픽
접두사 pp(PP_TOPIC_PREFIX) 가 붙습니다. 아래는 플랫폼 코드가 쓰는 대표 토픽입니다.
| 토픽 | 용도 |
|---|---|
event · event-row | 서버 ↔ 엔진 이벤트 버스 |
pp-tag-point | 태그 값 스트림 — 태그마다 «Kafka 발행» 을 켜야 채워집니다 |
pp-tag-alarm · pp-asset-alarm · pp-asset-event | 알람 · 에셋 이벤트 |
pp-asset-data · pp-asset-aggregation · pp-asset-health-status | 에셋 데이터와 집계 |
pp-batch | 배치 잡 |
pp-edge-status · pp-opc-status · pp-diagnostic | 엣지 · OPC · 진단 상태 |
pp-domain-changed-event | 메타데이터 변경 |
pp-production-oee · pp-production-ram · pp-production-ems | 생산 지표 |
운영 명령
docker exec plantpulse-datalake pd status messaging # UP (advertised <주소>:9092 answered ApiVersions)
docker exec plantpulse-datalake pd flow # 컨슈머 그룹별 lag
docker exec plantpulse-datalake pd node topic # 토픽 "event" describe (비밀번호 자동 주입)
docker exec plantpulse-datalake pd retention # 토픽별 보존과 세그먼트 크기
docker exec plantpulse-datalake pd restart messaging
Kafka 배포판의 도구를 직접 쓰려면 SASL 자격을 클라이언트 설정 파일로 넘겨야 합니다. pd flow · pd node topic 은 그것을 대신해 주니 먼저 쓰세요.
브로커는 요청 처리를 켜기 약 10초 전에 9092 를 엽니다. 그래서 pd 의 헬스체크는 포트가 아니라 «광고 주소로 ApiVersions 요청을 보내 답을 받나» 를 봅니다. 기동 직후 DOWN (port 9092 is bound but … did not answer) 는 30초 뒤 다시 보세요.
튜닝 포인트
전부 /etc/kopens/conf/kafka.properties.template 에서 고치고 restart-datalake.sh 로 반영합니다.
| 항목 | 기본 | 비고 |
|---|---|---|
log.retention.ms | 1시간 | 소비자가 오래 멈출 수 있는 사이트라면 늘립니다. 디스크를 그만큼 씁니다 |
num.partitions | 4 | 새 토픽의 파티션 수. 소비자 스레드 수와 맞춥니다 |
num.io.threads · num.network.threads | 8 · 3 | NVMe 라면 io 를 16 까지 |
message.max.bytes | 150MB | 큰 메시지(파일 큐)를 위해 크게 잡혀 있습니다 |
HiveMQ (MQTT)
경량 IoT 디바이스 · 센서와 Edge 에이전트가 붙는 표준 MQTT 브로커입니다(Community Edition).
| 항목 | 값 |
|---|---|
| 포트 | 1883 (평문) · 1884 (TLS) — 프록시 컨테이너가 호스트에 발행하고 데이터레이크로 넘깁니다 |
| 인증 | username / password — 시큐리티 익스텐션이 conf/auth.properties 를 읽습니다 |
| 계정 | PP_MQ_USER / PP_MQ_PASSWORD (Kafka 와 같은 값) |
| 설정 | mqtt/conf/config.xml ← /etc/kopens/conf/hivemq.xml.template |
TLS 리스너는 플랫폼 공용 keystore(/var/security/plantpulse/master/master.keystore.jks)를 쓰고 클라이언트 인증서는 요구하지 않습니다(NONE).
# 외부에서 발행 · 구독 (디버깅)
mosquitto_pub -h <서버IP> -p 1883 -u mq -P '<PP_MQ_PASSWORD>' -t test/topic -m "hello"
mosquitto_sub -h <서버IP> -p 1883 -u mq -P '<PP_MQ_PASSWORD>' -t 'test/#'
로그
docker exec plantpulse-datalake pd logs --lines 100 messaging
| 브로커 | 파일 |
|---|---|
| Kafka | plantpulse-messaging/kafka/logs/ |
| HiveMQ | plantpulse-messaging/mqtt/logs/hivemq.log (event.log 는 메시지 단위 감사 로그라 pd logs 가 일부러 뺍니다) |
자주 발생하는 문제
| 증상 | 원인 | 조치 |
|---|---|---|
| 다른 박스의 클라이언트가 bootstrap 뒤 끊김 | 광고 주소가 컨테이너 내부 주소 | 노드 파일 PP_MASTER_IP → 설정 바꾸는 법 |
pd status messaging 이 DOWN (advertises 127.0.0.1…) | 노드 파일에 주소 없음 | 같은 조치. 렌더 exit 8 과 같은 원인 |
| 컨슈머 lag 증가 | 소비자 느림 · 멈춤 | pd flow 의 MEMB · LAG, 소비자 컨테이너 로그 |
| 디스크 가득 | 보존 늘렸는데 소비자 정지 | pd retention 의 kafka 표, log.retention.ms |
| MQTT TLS handshake 실패 | 인증서 만료 · SAN 누락 | 보안 설정 — plantpulse-certs 가 재발급 |
| 회전 뒤 Kafka 만 인증 실패 | PP_MQ_PASSWORD 는 두 브로커 공용 | passwd.sh PP_MQ_PASSWORD 로 둘을 함께 → 비밀번호 |
보안 / 외부 노출
| 포트 | 권장 |
|---|---|
| 9092 (Kafka SASL 평문) | 사설망 only |
| 9094 (Kafka SASL_SSL) | 외부 노출 시 사용 |
| 1883 (MQTT 평문) | 사설망 only |
| 1884 (MQTT TLS) | 외부 노출 시 사용 |