Infra/Kafka, MQTT

[Kafka] 카프카 브로커 하나씩 다운시킨 후 메시지 전송 테스트 (고가용성 테스트, replication test)

Nellie Kim 2024. 6. 10. 17:04
728x90

kafka1, kafka2, kafka3 중에 하나씩 브로커를 죽여보고 메시지를 전송해보려고 한다. 

업무에 kafka 를 적용하여 운영할 예정이라, 브로커 서버가 죽었을 때 메시지가 정상적으로 전송 되는지 고 가용성 테스트를 해보기로 했다. 

 

목차

1. directTest 토픽의 partition 3들의 복제 상태 확인

2. 프로듀서 메시지 전송 확인

3. 브로커 하나씩 죽여보기

4. 브로커 하나씩 다시 살리기

결론

✅ 1. directTest 토픽의 partition 3들의 복제 상태 확인

현재 토픽의 복제 상태를 확인하는 명령어

kafka-topics.sh --bootstrap-server kafka1:9092 --topic directTest --describe --command-config /opt/bitnami/kafka/config/sasl_client.properties

토픽 정보

  • Topic: directTest
  • TopicId: ve1NQTn4SNCf-lV-qVwDqA
  • PartitionCount: 3 (총 3개의 파티션)
  • ReplicationFactor: 3 (각 파티션이 3개의 브로커에 복제됨)
  • Configs: (특별한 설정 없음)

파티션 정보

  1. Partition 0:
    • Leader: 브로커 1 (ID : 1) (데이터 읽기/쓰기 작업을 주도하는 브로커)
    • Replicas: 1, 2, 3 (이 파티션의 데이터를 복제하는 브로커 목록)
    • Isr (In-Sync Replicas): 2, 1, 3 (현재 동기화 상태인 복제본 목록)
  2. Partition 1:
    • Leader: 브로커 2 (ID : 2)
    • Replicas: 1, 2, 3
    • Isr: 2, 1, 3
  3. Partition 2:
    • Leader: 브로커 2 (ID : 2)
    • Replicas: 1, 2, 3
    • Isr: 2, 1, 3

요약

모든 파티션의 복제본이 브로커 1, 2, 3에 고르게 분포되어 있습니다. 각 파티션의 리더는 특정 브로커가 담당하고 있으며, 현재 모든 복제본이 동기화 상태에 있습니다. 이제 파티션 2번도 정상적으로 복제되어, 각 파티션의 복제본이 브로커 1, 2, 3에 고르게 분포된 것을 확인할 수 있습니다.

 

✅ 2. 프로듀서 메시지 전송 확인

카프카 프로듀서 KafkaProducerTest

import org.apache.kafka.clients.producer.*;

import java.util.Properties;

public class KafkaProducerTest {
    /**
     * SASL 인증을 위한 JAAS Template
     */
    private static final String JAAS_TEMPLATE = "org.apache.kafka.common.security.scram.ScramLoginModule required username=\\"admin\\" password=\\"admin-secret\\";";

    public static Object test() {
        // 1. 설정 세팅
        Properties prop = new Properties();
        prop.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "123.143.255.255:9092"); // kafka host 및 server 설정
        prop.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");   // serialize 설정
        prop.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer"); // serialize 설정

        // 1-1) SASL 설정 추가 (프로듀서 생성 전에 추가해야 함)
        prop.put("security.protocol", "SASL_PLAINTEXT");
        prop.put("sasl.mechanism", "SCRAM-SHA-256");
        String jaasConfig = String.format(JAAS_TEMPLATE, "admin", "admin-secret");
        prop.put("sasl.jaas.config", jaasConfig);

        // 2. producer 생성
        KafkaProducer<String, String> producer = new KafkaProducer<>(prop);

        // 3. message 전달
        producer.send(new ProducerRecord<>("directTest", "key1", "1"));
        producer.send(new ProducerRecord<>("directTest", "key2", "12"));
        producer.send(new ProducerRecord<>("directTest", "key3", "123"));
        producer.send(new ProducerRecord<>("directTest", "key4", "1234"));
        producer.send(new ProducerRecord<>("directTest", "key5", "12345"));
        producer.send(new ProducerRecord<>("directTest", "key6", "123456"));
        producer.send(new ProducerRecord<>("directTest", "key7", "1234567"));
        producer.send(new ProducerRecord<>("directTest", "key8", "12345678"));
        producer.send(new ProducerRecord<>("directTest", "key9", "123456789"));
        producer.send(new ProducerRecord<>("directTest", "key10", "1234567890"));

        // 종료
        producer.flush();
        producer.close();
        return 1;
    }
}

포스트맨으로 send 해보았다. 

 

골고루 잘 들어갔다.

 

✅ 3. 브로커 하나씩 죽여보기

1) kafka 2 죽이기

docker stop kafka2

컨트롤러 브로커가 원래 2번이었는데 3번이 되었다.

메시지 전송

마찬가지로 포스트맨으로 전송 테스트를 했다.

파티션 별로 들어가는 메시지는 동일한 것을 확인.

파티션 별로 리더는 누가 됐는지 확인

파티션 0 번의 리더는 1번 브로커

파티션 1번의 리더는 2번 브로커

파티션 2번의 리더는 2번 브로커 였는데,

2번 브로커가 죽음으로서, 모든 파티션의 리더는 1번으로 바뀌었다.

2) kafka 1 죽이기

docker stop kafka1

컨트롤러 브로커가 원래 3번이었으니 1번을 죽여도 여전히 3번이 컨트롤러 브로커이다.

1번 브로커는 아예 자취를 감췄다.

메시지 전송

마찬가지로 포스트맨으로 전송 테스트 함.

파티션 별로 들어가는 메시지는 동일한 것을 확인.

파티션 별로 리더는 누가 됐는지 확인

kafka1은 죽었으니까 bash 접속도 튕겼다. 그래서 kafka3으로 들어갔다.

들어가서 아래 명령어로 이제 각각의 파티션 리더가 있는 브로커가 어디인지 확인하자.

kafka-topics.sh --bootstrap-server kafka3:9094 --topic directTest --describe --command-config /opt/bitnami/kafka/config/sasl_client.properties

파티션 리더가 모두 1번 브로커였는데 이제는 3번 브로커로 다 바뀌었다. 3번 브로커 밖에 없기때문.

3) kafka 3 죽이기

1개 남은 kafka3 도 죽여보겠다.

docker stop kafka3

카프카 ui 는 물론 메시지 전송은 당연히 안된다.

 

 

✅ 4. 브로커 하나씩 다시 살리기

1) kafka3 살리기

kafka3 부터 다시 살리자.

docker start kafka3

바로 ui 에 잘 뜬다. 컨트롤러 브로커도 당연히 3번 브로커가 되었다.

메시지 전송

마찬가지로 포스트맨으로 전송 테스트 함. 들어가는 순서는 조금 바뀌었지만, 정해진 파티션에 잘 들어간다.

파티션 별로 리더는 누가 됐는지 확인

kafka-topics.sh --bootstrap-server kafka3:9094 --topic directTest --describe --command-config /opt/bitnami/kafka/config/sasl_client.properties

예상대로 브로커 3번이 리더가 되었다.

2) kafka1 살리기

docker start kafka1

파티션 별로 리더는 누가 됐는지 확인

여전히 리더는 3번 브로커이다. 원래 1번이었는데 그냥 1번으로 다시 안바뀌고, 3번으로 가는 것 같다.

3) kafka2 살리기

docker start kafka2

컨트롤러 브로커도 여전히 3이다.

메시지 전송

메시지도 전송해보자. 같은 방식으로 잘 간다.

파티션 별로 리더는 누가 됐는지 확인

kafka2 살렸는데도 여전히 파티션들의 리더는 3으로 고정이다. 굳이 바꿀 이유가 없으면 파티션 리더는 바꾸지 않는다.

 

 

✅ 결론

브로커를 하나씩 죽이고 메시지를 보내보았다. 다시 브로커를 살릴때는 20~30분 후에 살렸다.

카프카 3개 브로커 중에 2개를 죽이고 메시지를 보낸 상황에서도 메시지는 성공적으로 전송이 되었다.

 

아파치 카프카는 replication(복제) 기능이 잘 되어있기 때문에 카프카 브로커 서버가 한두개 다운되어도 데이터는 안전한 전송을 보장 받을 수 있다.

 

모두 다운되더라도 컨트롤러 브로커 (리더 브로커)와 리더 파티션을 자동으로 선출하고 메시지를 받을 준비를 해준다. 아주 굿이다!!!! (물론 카프카 브로커 서버가 모두 다운된다면 메시지는 보낼 수 없다)