REDIS 정리
RedisConnectionFactory 역할 : 레디스 서버와의 연결 통로 만드는 역할, 커넥션 풀 같은 거라고 생각하면 된다.
RedisMessageListener Container
: 별도의 스레드에서 동작, 서버가 처음 올라갈 때 설정한 채널에 대해 subcribe 처리
안에 메시지 리스너를 등록하는데 특정 채널의 메시지가 오면 어떤 로직을 실행할지 정의하게 된다. 메시지 리스너의 defaultLisenerMethod는 onMessage이다.
@Bean
public RedisMessageListenerContainer redisMessageListenerContainer(
@Qualifier("chatPubSub") RedisConnectionFactory factory,
MessageListenerAdapter listenerAdapter
) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(factory);
container.addMessageListener(listenerAdapter, new PatternTopic("chat"));
return container;
}
package com.example.chatserver.chat.service;
import com.example.chatserver.chat.dto.ChatMessageDto;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.stereotype.Service;
import java.nio.charset.StandardCharsets;
@Service
public class RedisPubSubService implements MessageListener {
private static final Logger logger = LoggerFactory.getLogger(RedisPubSubService.class);
private final StringRedisTemplate stringRedisTemplate;
private final SimpMessageSendingOperations messageSendingOperations;
public RedisPubSubService(@Qualifier("chatPubSub") StringRedisTemplate redisTemplate,
SimpMessageSendingOperations messageSendingOperations) {
this.stringRedisTemplate = redisTemplate;
this.messageSendingOperations = messageSendingOperations;
}
/**
* 메시지를 발행하고, 수신한 구독자 수를 로그로 출력합니다.
* @param channel 발행할 채널
* @param message 보낼 메시지
*/
public void publish(String channel, String message) {
//execute를 사용하여 네이티브 publish 명령 실행 및 결과 확인
Long subscriberCount = stringRedisTemplate.execute((RedisConnection connection) ->
connection.publish(
channel.getBytes(StandardCharsets.UTF_8),
message.getBytes(StandardCharsets.UTF_8)
)
);
logger.info("✅ Message published to channel '{}'. Received by {} subscribers.", channel, subscriberCount);
}
@Override
public void onMessage(Message message, byte[] pattern) {
try {
String topic = new String(message.getChannel());
String payload = new String(message.getBody(), StandardCharsets.UTF_8);
logger.info("Received message from topic '{}': {}", topic, payload);
ChatMessageDto chatMessageDto = new ObjectMapper().readValue(payload, ChatMessageDto.class);
messageSendingOperations.convertAndSend("/topic/" + chatMessageDto.getRoomId(), chatMessageDto);
} catch (JsonProcessingException e) {
logger.error("Error processing message on topic", e);
throw new RuntimeException(e);
}
}
}
Last updated