첫 번째와 두 번째 클라이언트는 첫 번째 서버와 SSE 연결을 맺었기 때문에, 두 번째 서버는 이 두 클라이언트와의 SSE 연결 정보를 가지고 있지 않습니다.
만약에 A 파드에서 알림이 발생했을 경우에는 첫번째 클라이언트와 두번째 클라이언트에게 SEE 를 사용해서 알림을 보낼 수 있습니다.
하지만 B 파드에서 알림이 발생했을 경우에는 ?
첫번째 클라이언트와 두번째 클라이언트의 SSE 정보가 없기 때문에 전송할 수 없습니다.
그래서 레디스의 Sub/Pub 기능을 이용해서 알림 상태를 모든 Pod 에게 전달하기로 했습니다.
Redis Config 에 RedisMessageListenerContainer, MessageListenerAdapter 빈등록을 해줍시다.
일단 "알림"이라는 채널을 생성을 했습니다.
@Bean
public RedisMessageListenerContainer redisContainer(RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter, new PatternTopic("알람"));
return container;
}
@Bean
public MessageListenerAdapter messageListener(RedisMessageSubscriber subscriber) {
return new MessageListenerAdapter(subscriber);
}
( MessageListener 는 하단에 구현 하겠습니다. )
그리고 모든 파드들은 "알림" 채널을 구독합니다.
RedisMessageListenerContainer 에 addMessageListener 를 해주고 PatternTopic 생성자에 채널명을 전달해주면 구독이 완료됩니다.
"알람" 이라고 명시하면 "알람" 에 대한 채널을 구독하겠다는 의미이고,
"알람*" 이라고 명시하면 "알람" 으로 시작하는 패턴을 가진 채널을 구독하겠다는 의미입니다.
MessageListener 를 상속받아서 메세지가 왔을 경우에 이벤트를 받아낼 수 있도록 합니다.
@Service
@RequiredArgsConstructor
public class RedisMessageSubscriber implements MessageListener {
private final SseService sseService;
/**
* 메세지가 발행되면 이벤트를 받는 역활
*/
@Override
public void onMessage(Message message, byte[] pattern) {
String channel = new String(message.getChannel());
// 메세지 내용
String messageContent = new String(message.getBody());
// SSE 로 메세지를 전송
sseService.sendSseEmitter(messageContent);
}
}
그럼 이제 아래와 같은 순조로운 시나리오대로 알림이 전송됩니다.
클라이언트와 API 는 각각 SSE 관계를 맺는다.
그렇기 때문에 모든 API 에 모든 SSE 정보는 있을 수 없다.
( 기왕이면 SSE 를 REDIS 에 저장하면 나이스라고 생각했으나, SEE 객체 특성상 직렬화/역직렬화가 자유롭지 못하다. )
모든 API 파드들은 REDIS 와 Pub/Sub 관계를 맺어 실시간으로 채널을 구독하는 관계를 만들고
모든 API 파드들은 메세지가 발행되면 Client 에게 SEE 를 통해 메세지를 전달한다.
여기서 한가지 모순이 있는데,
REDIS > API > Client 이 단방향으로 메세지가 전달되는 구조기 때문에
혹시라도 Client 1 의 정보를 가지고 있는 API 파드가 KILL 되고 재생성된 경우에는 Client 1 의 정보가 사라질 수 밖에 없다.
너무 슬픈일이다.
이런 경우에는 어떡할까
'개발중 > Spring Boot & Redis' 카테고리의 다른 글
Spring Boot 기반 Redis Pub/Sub 구현: 분산 환경에서 Pod 간 이벤트 처리 (2) | 2024.11.16 |
---|---|
Spring Boot 3와 Redis: 로컬 도커 환경에서 시작하기 (0) | 2024.05.08 |
Spring Boot 3.x 및 Security 6.x를 이용한 중복 로그인 관리 방법 (0) | 2024.05.03 |
Spring Boot와 Redis를 사용한 데이터 저장 및 관리 (0) | 2024.05.03 |
Spring Boot 2.x.x에서 3.x.x로 업그레이드 후 Redis에 Java 객체 저장 문제 발생 (0) | 2024.04.16 |