Redis는 DB,Cache 기능 외에 Pub/Sub기능을 제공한다. SpringBoot에서 Redis의 Pub/Sub을 어떻게 활용하는지 알아보고자 한다.
Redis Pub/Sub의 특징을 간단히 다음과 같다
- 가볍고 빠르다
- 메시지 전송에 대한 보장을 못한다(Subscriber가 실시간으로 메시지를 받지 못하면 그 메시지는 버려진다)
- 간단하고 가벼운 실시간 pub/sub 처리에 적합
SpringBoot에서 Redis Pub/Sub을 사용하기 위한 설정부터 알아보자
1. SpringBoot 설정
build.gradle에 redis 의존성을 추가한다.
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
application.yml에 redis 접속정보를 설정한다.
spring:
redis:
host: 127.0.0.1
port: 6379
# password: 'xxxx' # 비밀번호 있을 경우 설정
RedisConfig파일을 작성한다. RedisMessageListenerContainer빈을 등록하면서 redis연결정보, 메시지 리스너, 토픽을 설정한다.
@RequiredArgsConstructor
@Configuration
public class RedisConfig {
// applicaton.yml redis 설정
private final RedisProperties redisProperties;
// redisSubscriber(아래 내용에 빈 선언 있음)
private final RedisSubscriber redisSubscriber;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(redisProperties.getHost(), redisProperties.getPort());
}
@Bean
public RedisMessageListenerContainer redisMessageListener(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(redisSubscriber, myTopic()); // listener 및 토픽 등록
return container;
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(connectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
// Jackson2JsonRedisSerializer 설정
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(String.class));
return redisTemplate;
}
@Bean
public ChannelTopic myTopic() {
return new ChannelTopic("myTopic");
}
테스트를 위한 간단한 도메인 객체를 생성한다.
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Member {
private String id;
private String fName;
private String lName;
private Address address;
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Address {
private String address;
private String etc;
}
메시지를 전송한 Publisher를 작성한다. 메소드는 일단 String 메시지와 객체 전송을 위한 메소드 2개로 작성했다.
@Service
@AllArgsConstructor
public class RedisPublisher {
private final RedisTemplate<String, Object> redisTemplate;
public void publish(ChannelTopic topic, String message) {
redisTemplate.convertAndSend(topic.getTopic(), message);
}
public void publishPojo(ChannelTopic topic, Member member) {
redisTemplate.convertAndSend(topic.getTopic(), member);
}
}
메시지를 수신해서 처리할 Subscriber를 작성한다. MessgeListener를 implements 해야한다.
@Service
@AllArgsConstructor
public class RedisSubscriber implements MessageListener {
private final ObjectMapper objectMapper;
private final RedisTemplate redisTemplate;
@Override
public void onMessage(Message message, byte[] pattern) {
try {
// simple message 테스트
// String msg = (String) redisTemplate.getStringSerializer()
// .deserialize(message.getBody());
// String data = objectMapper.readValue(msg, String.class);
// System.out.println(data);
// pojo 메시지 테스트
Member member = objectMapper.readValue(message.getBody(), Member.class);
System.out.println(member);
System.out.println(member.getFName());
System.out.println(member.getLName());
} catch (Exception e) {
e.printStackTrace();
}
}
}
테스트를 위한 Controller를 작성하고 실행해본다.
@RestController
@RequestMapping("pubsub")
@AllArgsConstructor
public class PubSubController {
private final ChannelTopic myTopic;
private final RedisPublisher redisPublisher;
@PostMapping("/topics/myTopic")
public void pushMessage(@PathVariable String name) {
// simple message
//redisPublisher.publish(myTopic, message);
// pojo
Address address = new Address("Korea Seoul", "kangnam");
Member member = new Member(null, "kildong", "hong", address);
redisPublisher.publishPojo(myTopic, member);
}
}
POST방식으로 http://localhost:8080/pubsub/topics/myTopic 호출하면 myTopic이라는 채널로 메시지를 Publish하고, myTopic 채널을 Subscribe하고 있는 RedisSubscriber가 메시지를 수신하여 아래와 같은 콘솔 로그를 출력하는 것을 볼수 있다.
'개발 > SpringBoot' 카테고리의 다른 글
SpringBoot3 - GraalVM Native Image Support (0) | 2023.02.01 |
---|---|
SpringBoot RabbitMQ 활용(Simple Queue, Pub/Sub) (0) | 2022.12.23 |
SpringBoot Redis 활용 - RedisTemplate, RedisRepository (0) | 2022.12.16 |
SpringBoot Redis 세션 사용 (0) | 2022.09.06 |
SpringBoot SpringDoc(OpenAPI)을 이용한 Swagger 그룹화, 전역인증&Parameter 설정 (0) | 2022.08.03 |
댓글