코알못

[로그수집] logstash 큐 타입에 따라 어떤 차이가 있을까? 본문

BIG DATA

[로그수집] logstash 큐 타입에 따라 어떤 차이가 있을까?

코린이s 2022. 2. 20. 23:56
728x90

logstash 의 경우 내부 큐 타입은 2가지로 설정 가능하다.

- memory (메모리)

- persisted (디스크)

두가지 방식에 대한 차이를 구글링 해보았을때 아래와 같다.

구분 memory persisted
장애 발생시 큐에 저장된 데이터 유실 데이터 유실 없음
속도 빠름 느림

현재 회사에 설정된 queue type 은 memory 이며 데이터 유실이 발생할 수 있는 구조이다.

데이터 유실 없이 데이터 수집이 필요하여 persisted 사용시 성능 차이가 얼마나 발생하는지, 얼마나 디스크를 차지하는지를 이번시간에는 파악해보기로 한다.

우선 결과부터 말하자면 아래와 같다.

방식 데이터 건수 소요 시간 사용 메모리 사용 CPU 샤용 디스크
memory 3,000,000 5분 750MB 90% 0GB
persisted 3,000,000 8분 250MB 60% 1GB
memory 10,000,000 20분 750MB 90% 0GB
persisted 10,000,000 27분 250MB 60% 1GB

결론,

- 300만건 : (8-5) % 5 = 메모리 방식이 3% 빠름

- 1000 만건 : (27-20) % 20 = 메모리 방식이 7% 빠름

속도와 데이터 유실은 trade-off 관계 이기에 둘 중 더 중요하게 생각하는 부분에 가중치를 두어야 할 것이다.

데이터 유실보다 속도가 중요하다면 memory 방식, 데이터 누락이 없어야 한다면 presisted 방식을 택한다.

테스트는 아래와 같이 진행했다.

logstash 의 queue 설정에 따른 성능 차이만 보기 위한 작업이기에 아래와 같이 심플한 구조로 테스트를 진행한다. (테스트 진행시 kafka 가 계속적으로 죽고 err 메세지도 없어 원인을 찾기에는 조금 시간이 걸려 우선 해당 테스트에는 꼭 필요한 부분은 아니라고 생각하기에 빼고 진행하였다. 추후에 원인은 찾아볼예정이다.)

로그 행 수 100,000
로그 사이즈 2MB

결과는 아래와 같다.

방식 메모리 디스크 최종 output 데이터 행수 소요 시간
memory 100M 증가 변함 없음 100,000 12분
persisted 100M 증가 최대 1G 100,000 5분

// kibana 건수 확인

테스트를 진행하였으나 뭔가 예상한 결과랑 달랐다. 테스트가 잘못 되었을까?

저자의 경우 일일히 free 명령어를 통해 계속적으로 모니터링 하였는데 정확하고 편리하게 모니터링을 위해 모니터링 툴을 설치해본다.

Ec2 이용시 cloud watch 로 모니터링 가능하나 메모리를 확인하기 위해서는 추가 작업이 필요하나 해당 작업중 IAM 서비스를 이용할수 있는 권한이 필요하나 회사에서 공유 받은 계정에는 IAM 권한이 부여되지 않았다.

IAM 서비스는 권한을 부여하는 서비스로 관련 권한을 요청 하기 어려울것 같다는 생각에 다른 모니터링 툴(VisualVM)을 우선 이용해보기로 했다. 

아래 사이트를 참고하여 visualVM을 설치 및 셋팅한다.

- https://co-de.tistory.com/75

 

서버 모니터링 툴(visualVM) 을 붙여보자!

서버의 메모리와 CPU를 모니터링 할일이 생겨 모니터링 툴이 필요했다. 여러 모니터링툴중 오픈 소스인 visualVM 을 사용해보자! java 프로세스 띄울시 jvm 옵션에 설정을 주어 해당 자바 어플리케이

co-de.tistory.com

모니터링 툴을 연동하기 위해서는 jvm 옵션을 변경하는 부분이 있는데 logstash 의 JVM 옵션은 아래 경로에서 가능하다.

$ vi logstash-7.6.0/config/jvm.options

이제 테스트를 진행해본다!

우선 아무 요청이 안들어왔을시 260MB 정도, cpu 는 1% 미만 사용한다.

다시 위와 같은 테스트를 진행하였고 재 테스트 결과 이다. (혹시 몰라서 2번 테스트 진행 하였으며 동일한 결과가 나왔다. 아마 앞전 결과는 잘못 테스트 진행 한것으로 보인다.)

방식 메모리 CPU 디스크 최종 output 데이터 행수 소요 시간
memory 최대 280MB 최초 70%/ 그외 20% 미만 변함 없음 100,000 9분
persisted 최대 300MB사용 최초 100%/ 그외 20% 미만 최대 1G 100,000 14분

// 데이터

// 메모리 방식

// 디스크 방식

결과를 봐서는 메모리가 조금 더 빨리 처리 되었으나 차이는 거의 없어 보여 로그 건수가 많다면 더 확연한 차이가 있지 않을까? 하여 

10배, 30배 로그건수를 늘려서 추가 테스트를 진행해본다.

테스트 도중에 elastic search 에서 아래와 같은 오류가 발생하는것을 발견하였다. (이전 10만건 테스트시에도 오류 발생 했으나 무시 했었다.)

메모리 부족하면 해당 오류가 발생한다고 하여 서버 메모리를 1G > 16G로 올리고 elastic search 할당 메모리도 10 G 로 올려본다. 

$ curl -XGET 'localhost:9200/servicelog-2022.02.19/_count'
[circuit_breaking_exception] [parent] Data too large, data for [<http_request>] would be [108235192/103.2mb], which is larger than the limit of [104035123/99.2mb], real usage: [108235192/103.2mb], new bytes reserved: [0/0b], usages [request=0/0b, fielddata=650/650b, in_flight_requests=0/0b, accounting=82466/80.5kb], with { bytes_wanted=108235192 & bytes_limit=104035123 & durability=\"PERMANENT\" }

 

서버(kibana, es 있는 서버)의 스펙을 늘리는 방법은 아래 링크를 참고한다.

- https://co-de.tistory.com/74

 

[AWS] 서버 인스턴스 유형(스펙)을 변경해보자!

서버 운영중에 서버 자원을 늘려야 하는 경우가 생긴다. 만약 직접 서버를 운영한다면 디스크나 메모리 카드를 사다가 교체해야 할 것이다. 그러나 EC2 로 운영한다면 기존 데이터를 유지하고 서

co-de.tistory.com

서버 스펙을 16G 로 올렸으니 elastic search 의 사용 가능 메모리를 10G 로 셋팅한다. 

$ vi elasticsearch-7.6.0/config/jvm.options
-Xms10g
-Xmx10g
:wq!

이제 다시 테스트를 진행해보자!

로그 행 수 1,000,000
로그 사이즈 18MB

// 데이터

아래와 같이 elastic search 를 호출하여 확인 가능하며

$ curl -XGET 'localhost:9200/servicelog-2022.02.19/_count'
{"count":1000000,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0}}

kibana 를 이용하여 좀 더 쉽게 확인도 가능하다.

// 메모리 방식

방식 메모리 CPU 디스크 최종 output 데이터 행수 소요 시간
memory 최대 300MB 최초 95.9%/ 그외 70% 미만 변함 없음 1,000,000 2분 소요

10배 가량 많은 로그를 보냈으나 빠르게 처리 되었다. 당연한 이야기지만 output 서비스의 성능도 로그 이동 시간에 중요한 영향을 끼친다.  

그럼 es 의 메모리를 더 올리면 성능이 더 좋아질까? (디스크 방식을 테스트 하기전 궁금한 부분 부터 확인 하도록 한다.)

elastic 설정 10G > 13G 로 변경해본다. 

$ vi elasticsearch-7.6.0/config/jvm.options
-Xms13g
-Xmx13g
:wq!

그리고 재기동을 진행하고 테스트를 진행해보면 아래와 같다.

방식 메모리 CPU 디스크 최종 output 데이터 행수 소요 시간
memory 최대 312MB 52% 미만 변함 없음 1,000,000 2분 소요

위 결과로 추측 되는것은 10G 이하로 메모리를 사용한다는것이다. 확인을 위해 elastic 도 visualVM 을 붙여보고 돌려본다.

$ vi elasticsearch-7.6.0/config/jvm.options
# visualVM
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.port=9901
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Djava.rmi.server.hostname=[ec2 public ip]
-Dcom.sun.management.jmxremote.rmi.port=9901
:wq!

메모리는 700MB 이하로 사용하고 오히려 CPU 를 많이 사용한다. 

여기서 궁금한점은 그럼 처음에 성능이 나오지 않았던것(10만건/8분)은 CPU 문제가 아니였을까?(실제 메모리 뿐만아니라 CPU 도 2>4 개로 증가 하였다.) 하여 메모리를 원래 설정대로 1G 로 변경하여 돌려본다. 

그결과, 

메모리를 1G 로 변경하여도 정상적으로 돌아간다.

정확한 테스트를 위해 CPU 2개 유지하고 메모리만(2G > 4G) 늘려서 테스트 해본다.

위 결과를 보아 성능이 동일하게 나와 메모리 이슈가 맞다.

그러나 es 에 할당한 메모리 이슈가 아닌서버 메모리 부족에 대한 이슈라는것을 테스트를 통해 알 수 있다.

이제 다시 위에 진행하던 테스트를 해보자

영구 큐로 변경하고 테스트를 진행 한다.

방식 메모리 CPU 디스크 최종 output 데이터 행수 소요 시간
memory 최대 300MB 최초 95.9%/ 그외 70% 미만 변함 없음 1,000,000 2분 소요
persisted 최대 300MB 최초 95.9%/ 그외 85% 미만 최대 1G 1,000,000 3분 소요

로그수를 더 늘려서 테스트를 진행해본다.

로그 행 수 3,000,000
로그 사이즈 52M

// 데이터

// 메모리 방식

// 디스크 방식

방식 메모리 CPU 디스크 최종 output 데이터 행수 소요 시간
memory 그래프 확인 변함 없음 3,000,000 8분
persisted 최대 1G 3,000,000 8분

차이가 없다. 큐 사이즈가 작아서 일까?

큐 사이즈에 대해 찾아보니 in-memory 큐는 영구 큐와 다른 설정을 바라본다고 한다. (큐 사이즈가 같은줄 알았으나 아니였다. 어쩐지.. 메모리 사용량이 비슷하여 이상했다.) 

in memory 의 경우 아래 공식 사이트에서 알 수 있듯이 큐사이즈를 직접적으로 조절하는것은 불가능 하고

파이프 라인 설정을 통해(병렬처리) pipeline.workers(기본값 cpu 갯수) * pipeline.batch.size(기본값 125) 로 설정 가능하다고 한다.

- https://www.elastic.co/guide/en/logstash/current/memory-queue.html

 

Memory queue | Logstash Reference [8.0] | Elastic

Each pipeline has its own queue.

www.elastic.co

아래와 같이 영구큐과 동일하게 맞춰본다.

구분 기존 변경
memory queue (1 worker * 125MB) * (2 pipeline) = 250MB queue (1 worker * 64MB) * (16 pipeline) = 1G
persisted queue (16 worker * 64MB) * (1 pipeline)  = 1G queue (16 worker * 64MB) * (1 pipeline)  = 1G

메모리 방식만 영구 큐와 동일하게 맞추고 진행한다.

// 메모리 방식

// 디스크 방식

방식 메모리 CPU 디스크 최종 output 데이터 행수 소요 시간
memory 그래프 확인 변함 없음 3,000,000 5분
persisted 최대 1G 3,000,000 8분

이번에는 디스크 방식을 메모리 방식과 비슷하게 맞춰 본다. 저자 생각은 pipeline 설정으로 병렬처리 하는것도 어느정도 이점이 있을것 같아 최대한 비슷하게 맞춘다.

구분 기존 변경
memory queue (1 worker * 125MB) * (2 pipeline) = 250MB queue (1 worker * 64MB) * (16 pipeline) = 1G
persisted queue (16 worker * 64MB) * (1 pipeline)  = 1G queue (1 worker * 64MB) * (16 pipeline)  = 1G

// 디스크

방식 메모리 CPU 디스크 최종 output 데이터 행수 소요 시간
memory 그래프 확인 변함 없음 3,000,000 5분
persisted 최대 1G 3,000,000 8분

두 설정 모두 디스크 방식 소요 시간은 동일하다. 그러나 메모리와 CPU 사용율이 적은 설정은 파이프 라인을 1개 두고 큐를 여러개 두는 방식이므로 해당 방식으로 테스트 하기로 한다.

300만건으로는 많은 차이가 없어 더 많은 데이터로 테스트 해본다.

// 메모리 

// 디스크

방식 메모리 CPU 디스크 최종 output 데이터 행수 소요 시간
memory 그래프 확인 변함 없음 10,000,000 20분
persisted 최대 1G 10,000,000 27분

결론,

- 300만건 : (8-5) % 5 = 메모리 방식이 3% 빠름

- 1000 만건 : (27-20) % 20 = 메모리 방식이 7% 빠름

방식 속도 자원 데이터 유실
memory - 300만건 : (8-5) % 5 = 메모리 방식이 3% 빠름
- 1000 만건 : (27-20) % 20 = 메모리 방식이 7% 빠름
처리해야할 데이터가 늘어날수록 속도 차이는 더 날 것으로 보인다.
디스크를 최대 1G 사용 유실될 가능성 있음 (1G 가 아니라 125MB 일것으로 현재 로그 사이즈 기준 약 ?개 누락 가능성 존재)
persisted - 메모리를 최대 1G 사용 유실 되지 않음

속도와 데이터 유실은 trade-off 관계 이기에 둘 중 더 중요하게 생각하는 부분에 가중치를 두어야 할 것이다.

데이터 유실보다 속도가 중요하다면 memory 방식, 데이터 누락이 없어야 한다면 presisted 방식을 택한다.

<참고>

logstash queue type 이 persisted 방식이라면 아래 설정에 따라 디스크를 사용한다.

$ vi logstash-7.6.0/config/logstash.yml
// 큐 저장 방식
queue.type: persisted
// 아래 경로에 큐 데이터 저장
path.queue: /home/ec2-user/lib/logstash-7.6.0/queue-data
// 아래 큐 데이터는 최대 1GB 사용
queue.max_bytes: 1024mb
// 하나의 큐 데이터 파일 크기
queue.page_capacity: 64mb

위와 같이 설정시 아래와 같이 저장 된다.

// 큐 저장소
$ cd /home/ec2-user/lib/logstash-7.6.0/queue-data
$ ll
합계 857212
-rw-rw-r-- 1 ec2-user ec2-user       34  2월 19 08:02 checkpoint.73
-rw-rw-r-- 1 ec2-user ec2-user       34  2월 19 08:02 checkpoint.74
-rw-rw-r-- 1 ec2-user ec2-user       34  2월 19 08:02 checkpoint.75
-rw-rw-r-- 1 ec2-user ec2-user       34  2월 19 08:02 checkpoint.76
-rw-rw-r-- 1 ec2-user ec2-user       34  2월 19 08:02 checkpoint.77
-rw-rw-r-- 1 ec2-user ec2-user       34  2월 19 08:02 checkpoint.78
-rw-rw-r-- 1 ec2-user ec2-user       34  2월 19 08:02 checkpoint.79
-rw-rw-r-- 1 ec2-user ec2-user       34  2월 19 08:02 checkpoint.80
-rw-rw-r-- 1 ec2-user ec2-user       34  2월 19 08:02 checkpoint.81
-rw-rw-r-- 1 ec2-user ec2-user       34  2월 19 08:02 checkpoint.82
-rw-rw-r-- 1 ec2-user ec2-user       34  2월 19 08:02 checkpoint.83
-rw-rw-r-- 1 ec2-user ec2-user       34  2월 19 08:02 checkpoint.84
-rw-rw-r-- 1 ec2-user ec2-user       34  2월 19 08:02 checkpoint.85
-rw-rw-r-- 1 ec2-user ec2-user       34  2월 19 08:02 checkpoint.head
-rw-rw-r-- 1 ec2-user ec2-user 67108864  2월 19 08:01 page.73
-rw-rw-r-- 1 ec2-user ec2-user 67108864  2월 19 08:02 page.74
-rw-rw-r-- 1 ec2-user ec2-user 67108864  2월 19 08:02 page.75
-rw-rw-r-- 1 ec2-user ec2-user 67108864  2월 19 08:02 page.76
-rw-rw-r-- 1 ec2-user ec2-user 67108864  2월 19 08:02 page.77
-rw-rw-r-- 1 ec2-user ec2-user 67108864  2월 19 08:02 page.78
-rw-rw-r-- 1 ec2-user ec2-user 67108864  2월 19 08:02 page.79
-rw-rw-r-- 1 ec2-user ec2-user 67108864  2월 19 08:02 page.80
-rw-rw-r-- 1 ec2-user ec2-user 67108864  2월 19 08:02 page.81
-rw-rw-r-- 1 ec2-user ec2-user 67108864  2월 19 08:02 page.82
-rw-rw-r-- 1 ec2-user ec2-user 67108864  2월 19 08:02 page.83
-rw-rw-r-- 1 ec2-user ec2-user 67108864  2월 19 08:02 page.84
-rw-rw-r-- 1 ec2-user ec2-user 67108864  2월 19 08:02 page.85
-rw-rw-r-- 1 ec2-user ec2-user 67108864  2월 19 08:02 page.86
// 하나의 큐 페이지 파일 크기 64MB
$ du -sh /home/ec2-user/lib/logstash-7.6.0/queue-data/main/page.85
64M	/home/ec2-user/lib/logstash-7.6.0/queue-data/main/page.85
// 전체 큐 크기 설정한대로 1G 이며 나머지 0.1GB 는 체크포인트 파일 크기
// 체크 포인트 파일 크기는 페이지수 * 14KB 로 크지는 않다.
$ du -sh queue-data/
1.1G	queue-data/
// 전송 완료시 아래와 같이 마지막 파일만 남는다.
$ ll
합계 5452
-rw-rw-r-- 1 ec2-user ec2-user       34  2월 19 08:07 checkpoint.head
-rw-rw-r-- 1 ec2-user ec2-user 67108864  2월 19 08:06 page.131

 

728x90
Comments