[문제해결] RabbitMQ Headers Exchange

YeonJi·2025년 5월 6일
1

문제해결

목록 보기
19/24

Headers Exchange는 라우팅 키 대신 헤더 속성 값을 기반으로 라우팅한다.

❓ 문제

메시지가 "x-api-key"라는 헤더를 가지고 있을 경우, queue6으로 전송하도록 설정하였다.
하지만 "x-api-key"라는 헤더 없이 요청을 보내도 메시지를 수신할 수 있다.

"x-api-key" 헤더가 없으면 queue6으로 전달되면 안 되는데 queue6에 메시지가 저장되는 부분이 문제가 된다.

@Configuration
public class RabbitmqConfig {
...
    @Bean
    HeadersExchange headersExchange() {
        return  new HeadersExchange("exchange.headers");
    }

    @Bean
    Queue queue6() {
        return new Queue("queue6", false);
    }

    @Bean
    Binding headersBinding(HeadersExchange headersExchange, Queue queue6) {
        return BindingBuilder
                .bind(queue6)
                .to(headersExchange)
                .where("x-api-key")
                .exists();
    }
...

2025-05-06T20:56:54.065+09:00  INFO 23988 --- [ntContainer#3-1] rabbitmq.demo.service.ConsumerService    : queue6 결과: {"title":"headers message title","message":"headers message"}

💥 원인

헤더 설정 로직이 없어서 바인딩 조건이 안 맞아도 헤더 상관없이 queue6과 바인딩 돼 메시지 수신이 가능했던 것 같다.

⭕ 해결

@Service
@RequiredArgsConstructor
@Slf4j
public class ProducerServiceImpl implements ProducerService {
...
    @Override
    public void headersSendMessage(MessageDto messageDto, String header) {
        try {
            if (header == null) {
                log.warn("x-api-key 헤더 없음");
                return;
            }

            ObjectMapper objectMapper = new ObjectMapper();
            String objectToJSON = objectMapper.writeValueAsString(messageDto);

            // 메시지 헤더 설정
            MessageProperties props = new MessageProperties();
            props.setHeader("x-api-key", header);

            rabbitTemplate.convertAndSend("exchange.headers", "", objectToJSON, message -> {
                message.getMessageProperties().setHeaders(props.getHeaders());

                return message;
            });
        } catch (JsonProcessingException jpe) {
            log.error("파싱 오류 발생");
        }
    }
...
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/api/v1/producers")
public class ProducerController {
...
    @PostMapping("/headers")
    public ResponseEntity<String> headersSendMessage(@RequestBody MessageDto messageDto,
                                                     HttpServletRequest request) {
        String header = request.getHeader("x-api-key");
        producerService.headersSendMessage(messageDto, header);

        return new ResponseEntity<>("메시지 전송 성공", HttpStatus.OK);
    }
...
profile
문제해결 위주로 기록

0개의 댓글