성능 튜닝
개요
PlantPulse 의 성능은 수집 → 처리 → 저장 의 각 계층 병목을 차례로 제거해야 향상됩니다. 무조건 모든 값을 키우는 것이 아니라, 모니터링 지표를 보고 병목 지점만 조정하는 것이 핵심입니다.
튜닝 원칙 3가지
- 한 번에 하나만: 동시에 여러 변수를 바꾸면 어떤 변경이 효과를 냈는지 알 수 없습니다.
- 운영 데이터 기반: stage 환경 + 실제 트래픽 재현 후 변경.
- 기록 남기기: 변경한 값, 변경 전후 지표를 GitOps / 운영 wiki 에 남기세요.
운영 환경별 권장 출발점
| 환경 | CPU | 메모리 | 디스크 | 권장 PIPELINE_THREADS | 권장 PIPELINE_RATELIMIT |
|---|---|---|---|---|---|
| 개발 | 16 vCPU | 64 GB | SSD | 16 | 10,000 MPS |
| 표준 | 32 vCPU | 128 GB | NVMe | 36 | 40,000 MPS |
| 대규모 | 48+ vCPU | 200+ GB | NVMe | 64 | 100,000 MPS |
env.sh 기반 핵심 튜닝 변수
운영 환경에서 가장 자주 조정하는 변수는 호스트의 bin/env.sh 와 compose/docker-compose.yml 에서 관리됩니다 → 환경 변수 레퍼런스
| 변수 | 기본 | 영향 |
|---|---|---|
PP_CLUSTER_CORES | 30 | Spark / 분석 코어 할당 |
PP_CLUSTER_MEMORY_BY_CORE | 2G | Spark executor 메모리/코어 |
PP_LANG / PP_TZ | ko / Asia/Seoul | JVM locale / timezone |
JAVA_TOOL_OPTIONS | 자동 생성 | 모든 자식 JVM 에 자동 적용 |
상세 변수는 프로퍼티 레퍼런스 의 env.sh 변수 인덱스 참고.
측정 도구
튜닝 전후를 비교할 수 있는 도구:
cd /opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin
./status.sh # 모듈별 CPU / 메모리(PSS) 요약
./ops-check.sh # 헬스 + critical log
./memory-check.sh # 모듈별 메모리 상세
./memory-rank.sh # 메모리 순위
./pd node tpstats # Cassandra 스레드풀
./pd node compactionstats # Cassandra 컴팩션
./pd node table-stats # 테이블별 통계
./pd node proxyhistograms # Cassandra 지연 히스토그램
# Kafka consumer lag
./pd node topic
# JVM Heap / GC (컨테이너 진입 후)
./shell.sh
jcmd <pid> GC.heap_info
jcmd <pid> GC.heap_dump /tmp/heap.hprof
외부 모니터링 (Grafana / Prometheus) 은 시스템 모니터링 페이지 참고.
안내: 성능 튜닝은 서버 사양, 데이터 규모, 사용 패턴에 따라 최적값이 달라질 수 있습니다. 아래의 권장 설정을 기준으로 시작하시고, 모니터링 결과를 확인하면서 점진적으로 조정해 나가시는 것을 권장합니다.
엔진 파이프라인 튜닝
설정 파일: plantpulse-server/config/plantpulse-engine.properties
안내: 엔진 파이프라인은 센서에서 수집된 데이터가 처리되는 핵심 경로입니다. 이 설정을 통해 데이터의 처리 속도와 용량을 조절할 수 있습니다.
파이프라인 핵심 파라미터
| 파라미터 | 기본값 | 설명 | 튜닝 가이드 |
|---|---|---|---|
engine.pipeline.threads | 36 | 파이프라인 워커 스레드 수 | 호스트 코어 수의 70~80%를 권장합니다 (검증 환경 48코어 → 36) |
engine.pipeline.ratelimit | 40000 | 초당 최대 처리 메시지 수 (MPS) | 서버 사양에 맞게 조정해 주세요 |
engine.pipeline.queue.size | 1200000 | 파이프라인 큐 최대 크기 | 메모리 여유분에 맞게 조정해 주세요 |
engine.pipeline.queue.o3.delay | 50 | Out-of-Order 지연 처리 (ms) | 네트워크 지연에 따라 조정해 주세요 |
engine.pipeline.task.mode | SINGLE | 파이프라인 태스크 모드 | SINGLE 또는 MULTI |
engine.async.parallelism | 256 | 비동기 병렬 처리 수 | CPU 코어의 8~16배를 권장합니다 |
스트리밍 설정
| 파라미터 | 기본값 | 설명 |
|---|---|---|
engine.stream.processor | DIRECT | 스트림 처리 모드 |
engine.streaming.messaging.warning.ms | 5000 | 메시지 지연 경고 기준 (ms) |
engine.streaming.messaging.timeout.ms | 10000 | 메시지 타임아웃 (ms) |
engine.streaming.messaging.timeout.store.type | FILE_QUEUE | 타임아웃 메시지 저장 방식 |
engine.streaming.messaging.timeout.recovery.type | DB | 타임아웃 복구 방식 |
작업 스레드
| 파라미터 | 기본값 | 설명 |
|---|---|---|
engine.job.thread.asset | 8 | 에셋 작업 스레드 수 |
engine.job.thread.point | 8 | 포인트 작업 스레드 수 |
사양별 권장 설정
아래 표는 서버 사양에 따른 권장 설정값입니다. 운영 환경의 사양에 맞는 열을 참고하여 설정해 주세요.
| 항목 | 소규모 (8코어/64GB) | 중규모 (16코어/128GB) | 대규모 (32코어/256GB) |
|---|---|---|---|
pipeline.threads | 16 | 36 | 64 |
pipeline.ratelimit | 10,000 | 40,000 | 100,000 |
pipeline.queue.size | 300,000 | 1,200,000 | 3,000,000 |
async.parallelism | 64 | 256 | 512 |
Cassandra 튜닝
설정 파일: plantpulse-storage/db/cassandra/conf/cassandra.yaml
안내: Cassandra는 시계열 데이터를 저장하는 핵심 데이터베이스입니다. 데이터 규모가 커질수록 Cassandra 튜닝이 전체 성능에 큰 영향을 미치므로, 운영 환경에 맞게 조정해 주시는 것을 권장합니다.
메모리 설정
| 파라미터 | 기본값 | 설명 |
|---|---|---|
memtable_heap_space | 2GiB | Memtable 힙 메모리 |
memtable_offheap_space | 2GiB | Memtable Off-Heap 메모리 |
memtable_allocation_type | offheap_objects | 메모리 할당 타입 |
memtable_flush_writers | 8 | Memtable 플러시 스레드 수 |
동시성 설정
| 파라미터 | 기본값 | 설명 | 튜닝 가이드 |
|---|---|---|---|
concurrent_reads | 256 | 동시 읽기 스레드 | 디스크 수 x 16을 권장합니다 |
concurrent_writes | 256 | 동시 쓰기 스레드 | CPU 코어 x 8을 권장합니다 |
concurrent_counter_writes | 256 | 동시 카운터 쓰기 | concurrent_writes와 동일하게 설정해 주세요 |
concurrent_compactors | 8 | 동시 컴팩션 스레드 | CPU 코어 수의 1/4을 권장합니다 |
커밋로그
| 파라미터 | 기본값 | 설명 |
|---|---|---|
commitlog_sync | periodic | 동기 방식 |
commitlog_sync_period | 10000ms | 동기 주기 |
commitlog_segment_size | 320MiB | 세그먼트 크기 |
commitlog_total_space | 32GiB | 전체 커밋로그 공간 |
타임아웃
| 파라미터 | 기본값 | 설명 |
|---|---|---|
read_request_timeout | 10000ms | 읽기 타임아웃 |
write_request_timeout | 60000ms | 쓰기 타임아웃 |
counter_write_request_timeout | 10000ms | 카운터 쓰기 타임아웃 |
cas_contention_timeout | 1000ms | CAS 경합 타임아웃 |
truncate_request_timeout | 600000ms | Truncate 타임아웃 |
컴팩션 전략
PlantPulse는 시계열 데이터 특성에 맞는 **UCS(Unified Compaction Strategy)**를 사용합니다.
안내: 컴팩션(Compaction)은 Cassandra가 디스크에 저장된 데이터 파일(SSTable)을 정리하고 병합하는 작업입니다. 적절한 컴팩션 전략을 사용하면 디스크 공간을 절약하고 읽기 성능을 향상시킬 수 있습니다.
storage.properties 설정:
| 파라미터 | 기본값 | 설명 |
|---|---|---|
storage.table.compaction.strategy | UCS | 컴팩션 전략 (UCS 또는 TWCS) |
storage.table.compaction.strategy.ucs.scailing_parameter | T8 | 스케일링 파라미터 |
storage.table.compaction.strategy.ucs.min_sstable_size | 128MiB | 최소 SSTable 크기 |
storage.table.compaction.strategy.ucs.target_sstable_size | 512MiB | 목표 SSTable 크기 |
storage.table.compaction.strategy.ucs.base_shard_count | 8 | 베이스 샤드 수 |
storage.table.compaction.strategy.ucs.max_sstables_to_compact | 6 | 최대 컴팩션 SSTable 수 |
압축
ZStandard 딕셔너리 압축을 사용합니다:
| 파라미터 | 기본값 | 설명 |
|---|---|---|
storage.compression.zstd.type | ZstdDictionaryCompressor | 압축 방식 |
storage.compression.zstd.level | 3 | 압축 레벨 (1~22, 높을수록 압축률은 올라가지만 속도는 느려집니다) |
TTL (데이터 보존 기간)
storage.properties에서 테이블별 TTL을 설정합니다. TTL이 지나면 해당 데이터는 자동으로 삭제되므로, 데이터 보존 요구사항에 맞게 설정해 주세요.
| 파라미터 | 기본값 | 설명 |
|---|---|---|
storage.tag.point.ttl | 62 (일) | 태그 포인트 원본 데이터 |
storage.tag.point.map.ttl | 1 (일) | 태그 포인트 맵 |
storage.tag.point.sampling.ttl | 93 (일) | 샘플링 데이터 |
storage.tag.point.snapshot.ttl | 93 (일) | 스냅샷 데이터 |
storage.tag.point.aggregation.ttl | 93 (일) | 집계 데이터 |
storage.tag.point.archive.ttl | 365 (일) | 아카이브 데이터 |
storage.tag.blob.ttl | 93 (일) | BLOB 데이터 |
storage.asset.data.ttl | 10 (일) | 에셋 데이터 |
storage.asset.data.sampling.ttl | 31 (일) | 에셋 샘플링 데이터 |
Cassandra 성능 점검 명령어
아래 명령어를 사용하여 Cassandra의 성능 상태를 점검하실 수 있습니다:
# 컴팩션 상태 확인
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node compactionstats
# 테이블별 통계 확인
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node table-stats
# 테이블 히스토그램 (읽기/쓰기 지연)
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node table-histograms
# SSTable 크기 확인
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node sstable-size
# 스레드풀 통계
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node tpstats
Spark 튜닝
설정 파일: plantpulse-analytics/spark/conf/spark-defaults.conf
안내: Apache Spark는 대용량 데이터 분석을 위한 분산 처리 엔진입니다. 분석 작업의 속도와 안정성을 높이기 위해 아래 설정을 참고해 주세요.
리소스 할당
| 파라미터 | 기본값 | 설명 |
|---|---|---|
spark.cores.max | 16 | Spark 최대 사용 코어 |
spark.driver.cores | 2 | 드라이버 코어 수 |
spark.driver.memory | 4g | 드라이버 메모리 |
spark.executor.cores | 1 | Executor 코어 수 |
spark.executor.memory | 2G | Executor 메모리 |
spark.executor.memoryOverhead | 2g | Executor 오버헤드 메모리 |
동적 할당
| 파라미터 | 기본값 | 설명 |
|---|---|---|
spark.dynamicAllocation.enabled | true | 동적 Executor 할당 |
spark.dynamicAllocation.minExecutors | 2 | 최소 Executor 수 |
spark.dynamicAllocation.maxExecutors | 16 | 최대 Executor 수 |
spark.dynamicAllocation.executorIdleTimeout | 30 | 유휴 Executor 해제 시간 (초) |
셔플 및 병렬도
| 파라미터 | 기본값 | 설명 |
|---|---|---|
spark.default.parallelism | 64 | 기본 병렬도 |
spark.sql.shuffle.partitions | 128 | SQL 셔플 파티션 수 |
spark.sql.adaptive.enabled | true | Adaptive Query Execution |
spark.sql.adaptive.coalescePartitions.enabled | true | 파티션 자동 병합 |
JVM 설정
Spark 드라이버/Executor 모두 ZGC를 사용합니다:
-XX:+UseZGC
-XX:+AlwaysPreTouch
-XX:+UseTLAB
-XX:+ResizeTLAB
-XX:+DisableExplicitGC
S3 (MinIO) 연동 설정
| 파라미터 | 기본값 | 설명 |
|---|---|---|
spark.hadoop.fs.s3a.connection.maximum | 400 | 최대 S3 연결 수 |
spark.hadoop.fs.s3a.threads.max | 128 | 최대 S3 스레드 |
spark.hadoop.fs.s3a.max.total.tasks | 1024 | 최대 비동기 작업 |
spark.hadoop.fs.s3a.fast.upload | true | 빠른 업로드 활성화 |
spark.hadoop.fs.s3a.fast.upload.buffer | disk | 업로드 버퍼 타입 |
spark.hadoop.fs.s3a.block.size | 128MB | S3 블록 크기 |
Iceberg 설정
| 파라미터 | 기본값 | 설명 |
|---|---|---|
spark.sql.iceberg.write.target-file-size-bytes | 256MB | 대상 파일 크기 |
spark.sql.iceberg.column-stats.enabled | true | 컬럼 통계 활성화 |
spark.sql.iceberg.vectorization.enabled | true | 벡터화 읽기 활성화 |
spark.sql.iceberg.manifest.merge.enabled | true | 매니페스트 병합 |
spark.sql.parquet.compression.codec | zstd | Parquet 압축 코덱 |
Kafka 튜닝
설정 파일: plantpulse-messaging/kafka/config/server.properties
안내: Kafka는 센서 데이터를 실시간으로 전달하는 메시지 브로커입니다. 데이터 양이 많아지면 Kafka 설정을 조정하여 처리 성능을 높일 수 있습니다.
핵심 설정
| 파라미터 | 기본값 | 설명 |
|---|---|---|
num.network.threads | 3 | 네트워크 처리 스레드 |
num.io.threads | 8 | I/O 처리 스레드 |
socket.send.buffer.bytes | 102400 | 소켓 전송 버퍼 |
socket.receive.buffer.bytes | 102400 | 소켓 수신 버퍼 |
socket.request.max.bytes | 104857600 | 최대 요청 크기 (100MB) |
num.partitions | 1 | 기본 파티션 수 |
log.retention.hours | 168 | 로그 보존 기간 (7일) |
log.segment.bytes | 1073741824 | 로그 세그먼트 크기 (1GB) |
대용량 처리 튜닝
대량의 IoT 데이터를 처리하실 경우, 아래 설정을 참고하여 조정해 주세요:
# 파티션 수 증가 (메시지 병렬 처리)
num.partitions=4
# I/O 스레드 증가
num.io.threads=16
# 네트워크 스레드 증가
num.network.threads=8
# 소켓 버퍼 증가
socket.send.buffer.bytes=1048576
socket.receive.buffer.bytes=1048576
메시징 설정
설정 파일: plantpulse-server/config/plantpulse-mq.properties
Kafka DDS 토픽
| 파라미터 | 기본값 | 용도 |
|---|---|---|
mq.dds.kafka.topic.tag.point | pp-tag-point | 태그 포인트 값 |
mq.dds.kafka.topic.tag.alarm | pp-tag-alarm | 태그 알람 |
mq.dds.kafka.topic.asset.data | pp-asset-data | 에셋 데이터 |
mq.dds.kafka.topic.asset.alarm | pp-asset-alarm | 에셋 알람 |
mq.dds.kafka.topic.asset.event | pp-asset-event | 에셋 이벤트 |
mq.dds.kafka.topic.asset.aggregation | pp-asset-aggregation | 에셋 집계 |
mq.dds.kafka.topic.domain.changed.event | pp-domain-changed-event | 메타데이터 변경 |
MQTT DDS 토픽
| 파라미터 | 기본값 | 용도 |
|---|---|---|
mq.dds.mqtt.topic.tag.point | tag/point/{tag_id} | 태그별 포인트 값 |
mq.dds.mqtt.topic.tag.alarm | tag/alarm/{tag_id} | 태그별 알람 |
mq.dds.mqtt.topic.asset.data | asset/data/{asset_id} | 에셋별 데이터 |
mq.dds.mqtt.topic.asset.command | asset/command/{asset_id} | 에셋 제어 명령 |
스케줄러 설정
설정 파일: quartz.properties (웹앱 내부 클래스패스 리소스 — 외부화 대상 아님)
| 파라미터 | 기본값 | 설명 |
|---|---|---|
org.quartz.threadPool.threadCount | 8 | 스케줄러 스레드 수 |
org.quartz.threadPool.threadPriority | 5 | 스레드 우선순위 |
메일 / 알림 설정
설정 파일: plantpulse-server/config/plantpulse-mail.properties
| 파라미터 | 기본값 | 설명 |
|---|---|---|
mail.smtp.host | 192.168.0.41 | SMTP 서버 주소 |
mail.smtp.port | 25 | SMTP 포트 |
mail.smtp.auth | false | 인증 사용 여부 |
mail.smtp.starttls.enable | false | TLS 사용 여부 |
애플리케이션 설정
application.properties 파일은 2026.06 에 제거되었습니다. 테마 / 홈페이지 등 콘솔 동작 설정은 콘솔의 시스템 > 설정 관리 (PostgreSQL mm_config 테이블)에서 관리하고, alarm.duplicate.check.minutes(중복 알람 체크 간격, 분)는 plantpulse-server/config/plantpulse-engine.properties 로 이관되었습니다.
성능 병목 진단
성능 문제가 발생했을 때 아래 증상별 진단 방법과 해결책을 참고해 주세요.
1. 파이프라인 큐 적체
증상: 파이프라인 대기 큐가 지속적으로 증가합니다
# Grafana 대시보드에서 "파이프라인 대기 큐" 패널을 확인해 주세요
# 또는 JMX: pipeline.queue.size 값을 확인해 주세요
해결:
engine.pipeline.threads값을 늘려 주세요engine.pipeline.ratelimit값을 상향 조정해 주세요- Cassandra 쓰기 성능을 확인해 주세요
2. Cassandra 쓰기 지연
증상: 쓰기 타임아웃 또는 WriteTimeoutException이 발생합니다
# 컴팩션 상태 확인
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node compactionstats
# Memtable 플러시
/opt/kopens/plantpulse-platform/plantpulse-datalake-cli/bin/pd node flush
해결:
concurrent_writes값을 늘려 주세요compaction_throughput값을 늘려 주세요- 디스크 I/O 성능을 점검해 주세요 (SSD 사용을 권장합니다)
3. 메모리 부족
증상: JVM GC가 빈번하게 발생하거나 OutOfMemoryError가 발생합니다
해결:
- 서비스 모듈의
bin/start.sh에서-Xmx값을 늘려 주세요 engine.pipeline.queue.size값을 줄여 메모리 사용을 절약해 주세요- 불필요한 캐시를 비활성화해 주세요
4. 네트워크 지연
증상: 데이터 수신 지연이 증가합니다 (Grafana "네트워크 지연" 패널에서 확인 가능)
해결:
- OPC 서버와 PlantPulse 간 네트워크 상태를 확인해 주세요
engine.streaming.messaging.timeout.ms값을 조정해 주세요- MQTT QoS 레벨을 확인해 주세요
기술 지원
성능 튜닝 관련 문의: webmaster@kopens.com