ZooKeeper와 Kafka 실습1

2021. 4. 25. 16:07개발/Kafka

구조


구현할 서버 구조

VMware를 이용해 5대의 서버를 생성했다. 서버 생성에서 문제가 있었는데 현재 PC의 메모리로는 5대까지만 가상머신 생성이 가능했다. 덕분에 ZooKeeper 앙상블은 서버3대를 사용해놓고, Kafka 클러스트에는 서버 1대만 사용할 수 밖에 없었다. ( 다음에는 ZooKeeper를 standalone으로 두고 Kafka를 좀 더 괴롭혀봐야겠다... ㅎ )

 

사실 대부분의 테스트 구축에서는 ZooKeeper Server와 Kafka Server를 같은 서버에 두는데 운영과 비슷하게 해보려다 이런 참사(?)가 벌어졌다.

 

아무튼 서버별 기능을 정리해보자면 아래와 같다. ( 5대 )

 

192.168.47.128, 192.168.47.192, 192.168.47.130 서버 3대는 ZooKeeper 서버 역할을 한다. 

192.168.47.131 서버는 브로커(카프카) 서버 역할을 한다. 해당 서버에서 Topic을 생성한다.

192.168.47.132 서버는 Producer이자 Consumer 역할을 하도록 한다. 

 

모든 서버의 운영체제는 Ubuntu 20.04 LTS를 사용했다.

 

 


ZooKeeper 설정셋팅


내려받은 ZooKeeper의 압축을 해제하면  conf 폴더가 있다. 

conf 폴더로 이동해서 zoo.cfg라는 파일을 생성하고 아래와 같이 작성했다. ( 192.168.47.128 서버 기준 )

192.168.47.128 서버는 1번 ZooKeeper 서버로 사용하기 위해 server.1 = 0.0.0.0:2888:3888로 작성한다. 

( 0.0.0.0 부분에 hostname을 작성해도 되는데 실습중에 자꾸 에러나서 직접 주소를 작성했다. )

192.168.47.128서버의 zoo.cfg

그리고 해당 ZooKeeper서버의 유일성을 위해서 myid라는 파일을 만든다. myid파일은 위 파일의 dataDir에 작성한 경로에 위치해야한다.

myid 파일 위치

myid는 다른 서버와 겹치지 않게 자연수를 작성한다. ( 범위가 1~255까지 였던걸로 기억한다. )

myid파일

 

192.168.47.129, 192.168.47.130 서버도 작업한다. 

 

192.168.47.129 서버의 zoo.cfg 파일 내용
192.168.47.129의 myid

 

192.168.47.130
192.168.47.130의 myid


ZooKeeper 실행


zooKeeper의 bin폴더에 zkServer.sh start 명령어를 통해 서버를 실행할 수 있다. 

./zkServer start를 사용하면 백그라운드로 서버가 구동되는데 ./zkServer start-foreground로 실행하면 foregroud로 실행하게 된다. 

 

3개 서버에 모두 ./zkServer.sh start-foreground 명령어를 수행한다. 

 

1개 서버만 올리면 아마 에러로그가 출력될것이다. ZooKeeper는 과반수 이상이 실행되어야 정상실행으로 판단한다. 

2개 이상의 서버가 올라가는 순간부터는 에러로그가 뜨지 않으면서 아래 처럼 로그가 출력되면 정상 실행 되었다는 뜻이다. 

 

혹시 모르니 확인해보자. ./zkServer.sh status 명령어를 사용한다.


Kafka서버 셋팅


192.168.47.131를 주소로 가지는 서버를 브로커(카프카) 서버로 활용한다. 

 

ZooKeeper와 마찬가지로 Kafka에도 설정을 위한 폴더가 있다. 

config폴더로 이동해서 server.properties 파일을 열어보자. 

해당 파일을 Broker서버에 대한 설정을 할 수 있는데 스크롤을 내려보면 ZooKeeper에 대한 셋팅을 작성할 수 있는 영역이 있다. 

zookeeper.connect 셋팅 부분에 지금까지 만든 ZooKeeper 서버(총 3대)에 대한 연결 정보를 작성한다. 

 

그리고 Producer와 Consumer가 브로커에게 접근하기 위한 정보를 작성한다. 

advertised.listeners 셋팅부분을 아래와 같이 작성한다. 만약에 작성하지 않으면 listeners라는 세팅값을 따른다고 되어있다. 

이제 Producer와 Consumer는 192.168.47.131:9092를 통해 브로커에 접근할 수 있게 된다. 

 

./bin/kafka-server-start.sh config/server.properties 명령어를 통해 Kafka 서버를 실행한다. 

 

아래 명령어를 통해 sample-topic1이라는 이름을 가진 Topic을 생성한다. 

replication-factor옵션을 1로 셋팅함으로서 1개의 Topic만 생성하도록한다. 

partitions 옵션을 1로 셋팅함으로써 partition이 1개인 Topic을 생성하도록한다.

zookeeper 옵션을 앞서 작성한 서버(3대)로 작성함으로써 ZooKeeper에 의해 해당 Topic의 정보가 관리되도록한다.

bin/kafka-topics.sh --create --zookeeper 192.168.47.128:2181, 192.168.47.129:2181, 192.168.47.130:2181 --replication-factor 1 --partitions 1 --topic sample-topic1

 

 

아래 명령어를 describe를 통해 Topic이 정상적으로 생성되었는지 확인해보자. 

bin/kafka-topics.sh --describe --zookeeper 192.168.47.128:2181, 192.168.47.129:2181, 192.168.47.130:2181 --topic sample-topic1


Producer, Consumer의 데이터 Pub/Sub


192.168.47.132 서버에서 Kafka가 기본적으로 제공하는 Consumer와 Producer를 생성해서 Pub/Sub 작업을 수행해본다. 

 

Kafka의 bin 폴더에 가면 kafka-console-producer.sh , kafka-console-consumer.sh 쉘 파일이 있는데 이 2개 파일을 통해 손쉽게 Topic을 테스트해볼수 있다.

 

Producer 생성.

broker-list 옵션을 통해 데이터를 publish할 브로커 서버의 list를 정한다.

topic 옵션을 통해 데이터를 publish할 Topic을 정한다.

bin/kafka-console-producer.sh --broker-list 192.168.47.131:9092 --topic sample-topic1

 

Consumer 생성

bin/kafka-console-consumer.sh --bootstrap-server 192.168.47.131:9092 --topic sample-topic1 --from-beginning

Producer(좌측 Terminal)에서 입력한 문자가 Consumer(우측 Terminal)에서 출력되는 모습을 확인할 수 있다.

이렇게 해서 ZooKeeper 서버 구축부터 Kafka pub/sub까지 완료했다. 

다음에는 ZooKeeper 서버를 간소화하고 Kafka에 대해서 좀더 깊이있게 학습해볼 수있도록 환경 구축을 해야겠다.

 

 


삽질


1. ZooKeeper 서버간 Connection문제

ZooKeeper 앙상블 구현하는 과정에서 3개의 서버를 실행했음에도 Zookeeper 1대를 나머지 2개의 서버가 인식하지 못하는 문제가 발생했다. 아무리 봐도 설정에 문제가 없어서 혹시나 싶어 IP를 찍어봤는데 공백으로 출력되었다. 

VMware의 문제로 보이는데 혹시 ZooKeeper 서버간에 connection 문제가 있을때 hostname -I 명령어를 통해 IP를 먼저 확인해보자. (아래처럼 나와야 정상인데 공백으로 나오는 경우 connection에러가 발생했음. ) 재부팅을 통해 IP가 정상 할당되도록 했다. 

노란색 부분이 공백으로 출력된 경우가 있었다.

2. Topic 삭제 문제

Topic을 삭제하기 위해 아래 명령어를 사용했다. 

bin/kafka-topics.sh --delete --zookeeper 192.168.47.128:2181, 192.168.47.129:2181, 192.168.47.130:2181 --topic sample-topic1

분명 삭제를 했는데 Topic이 조회된다. server.properties파일의 delete.topic.enable옵션도 true로 셋팅했지만 삭제 되지 않았다.

 

원인은 간단했는데 Consumer를 종료하지 않은채 delete를 수행하면 Topic이 즉시 삭제되지 않는다. 

 

따라서 Consumer의 실행을 중지하고 다시 --delete 작업을 수행하니 바로 Topic이 삭제 되었다.

 

Producer가 live 상태이고, Consumer를 종료한채로 topic delete를 시도하면 즉시 삭제된다.

반대로 Consumer가 live상태이고, Producer를 종료한채로 topic delete를 시도하면 즉시 삭제되지 않았다. 

 

즉, Consumer가 Topic을 물고 있으면 delete 명령어를 날려도 Topic은 제거되지 않는다. ( delete marking만 수행. )