본문 바로가기

리눅스 인프라/Kafka

Virtualbox 포트 포워딩 Kafka 호스트 PC 연결 오류 해결

관련 내용

[리눅스 인프라/Kafka] - [Spring]Kafka를 활용한 이메일 인증 기능 구현하기

개요와 목적

(호스트 Window) 환경에서 실행하는 Spring Server와, Window 내부의 VirtualBox-포트포워딩 - Ubuntu)에서 실행되는 Kafka가 연결이 되지 않는 문제가 발생했다. 이번 글에서는 (Virtualbox-포트포워딩) Kafka와 호스트 Window Spring Server 연결을 시키는 설정 방법에 대해서 알아보겠다.

기본 카프카 설정(실패 했을 때)

연결을 담당하는 카프카 기본 소켓 서버의 설정을 아래와 같다.

이 설정에서 카프카와 호스트WindowSpringServer와 연결 했더니, 아래와 같은 에러가 발생했다.

kafka/config/server.properties

문제 해결 세팅

설정 코드 먼저 공개

(호스트Window)SpringServer와 (VirtualBox-포트포워딩)Kafka 연결에 성공한 Kafka 설정을 먼저 공개 하겠다.

그리고 각 설정 값이 어떤 역할을 수행하고, 이러한 설정 값들이 연결을 성공으로 이끌었는지 알아보겠다.

listeners= INTERNAL://10.0.2.7:9092, EXTERNAL://0.0.0.0:9093
listener.security.protocol.map=EXTERNAL:PLAINTEXT,INTERNAL:PLAINTEXT

advertised.listeners= INTERNAL://10.0.2.7:9092, EXTERNAL://127.0.0.7:9093
inter.broker.listener.name=INTERNAL

설정에 대한 설명

lieteners란 무엇인가

listeners의 정보는 서버 소켓을 만드는데 사용할 URI 정보이다. 리스너의 이름과 포트 번호는 고유해야 한다. 그래서 INTERNAL와 EXTERNAL의 포트 번호를 다르게 하기 위해서, 9093 포트를 새로 개설해 주었다. 왜 리스너를 INTERNAL와 EXTERNAL로 나누었는지는 잠시 후 설명한다.

그리고 모든 인터페이스에 바인딩 하려면 URI를 0.0.0.0으로 지정해줘야 한다. 그래서 외부 호스트 Window Spring Server와 연결하는 EXTERNAL을 0.0.0.0:9093으로 설정했다. 왜 advertiesed.listeners의 EXTERNAL은 0.0.0.0:9093이 아닌지는 잠시 후 설명한다.

listener이름이 보안 프로토콜이 아닌 경우, listener.security.protocol.map에 설정을 해줘야 한다. 그래서 listener.security.protocol.map=EXTERNAL:PLAINTEXT,INTERNAL:PLAINTEXT 를 설정해 주었다.

 

INTERNAL과 EXTERNAL을 나눈 이유

현재 나의 상황은 VirtualBox 내부에서 통신하는 internal ip와 호스트 Window 외부와 통신하는 external ip 총 두 가지를 사용하므로, listeners에 두 개의 이름 주소를 지정해줘야 한다.

 

advertiesed.listeners란 무엇인가

advertised를 지정하지 않으면 listeners가 그대로 사용된다.

advertised을 지정하는 이유는 브로커가 바인드하는 인터페이스와 클라이언트의 접속 주소가 다를 때 클라이언트의 요청 수락을 위해 zookeeper에 게시 할 주소를 지정하는 것이다.

나의 상황은 포트 포워딩을 통해서, 127.0.0.7로 외부와 연결을 한다. 그 이후 머신으로 들어오면서, 10.0.2.7로 변환 되므로 브로커가 바인드하는 인터페이스와 클라이언트 접속 주소가 다르게 된다. 그래서 advertiesed EXTERNAL에 외부와 연결되는 포트 포워딩 주소 127.0.0.7를 입력한 것이다.

그리고, listeners와 달리 advertised에는 0.0.0.0 메타 주소를 사용할 수 없다.

사용 결과

테스트를 위해 controller와 service 코드를 추가해서 produce와 consume이 잘 이루어지는 것을 확인 할 수 있다.

IgnorantEnglish\API\src\main\java\hello\api\controller\KafkaTestController.java

@RestController
@Slf4j
@RequiredArgsConstructor
public class KafkaTestController {
    private final KafkaTemplate<String, KafkaEmailDto> kafkaTemplate;

    @GetMapping("/kafkaTest")
    public String kafkaTest() {
        log.info("kafka Test 진입");
        kafkaTemplate.send("test", new KafkaEmailDto("emailTest"));
        return "kafka produce success";
    }
}

IgnorantEnglish\PlusAPI\src\main\java\hello\plusapi\service\EmailAuthService.java

@Service
@RequiredArgsConstructor
@Slf4j
public class KafkaTestService {

    @KafkaListener(topics = "test", groupId = "foo", properties = {
        "spring.json.value.default.type:hello.plusapi.dto.KafkaEmailDto"})
    public void sendEmailAuth(KafkaEmailDto kafkaEmailDto) {
        log.info("kafka consumer 집입");
        log.info("kafka test emailDto={}", kafkaEmailDto);
    }
}

 


Reference

https://theserverside.tistory.com/630

https://medium.com/@eun9882/kafka-trouble-shooting-remote-connect-error-a7970b00ffca

https://kafka.apache.org/documentation/#brokerconfigs