Redis Pub Sub Example Java
Overview:
In this article, I would like to show Redis PubSub with Spring Boot which can be used to broadcast messages across multiple services in a Microservices architecture. I assume you have basic knowledge on Redis + Spring Boot integration. If you are new to Spring Boot Redis, check the below article.
- Spring WebFlux Redis Integration
Redis PubSub:
PubSub is an asynchronous messaging model for service-to-service communication in Microservices architecture. That is, a service ( Publisher ) instead of sending a message to a specific recipient, it publishes the message to a Topic/Channel , through which interested parties ( S ubscribers ) receive the message.
Advantages | |
---|---|
One-To-Many Communication | A Publisher can publish a single message where N number of subscribers can receive and react to the message. |
Loose Coupling | Services are not tightly coupled. Any service can consume / ignore the message |
Better Performance | Publisher does not have to call N number of services. Instead it just publishes a message into a topic. It does not have to have any knowledge on the subscribers. It is not blocked. |
The PubSub model also has some limitations.
Limitations |
---|
PubSub is fire-forget model. If the receivers are offline, they might not receive the message. (Take a look at Redis Stream for this use case) |
PubSub is fan-out model. That is, multiple instances of the same service will receive the message. (Take a look at Redis Stream for this use case) |
Sample Application:
We are going to create a 2 simple Spring Boot applications. 1 will be acting like a publisher and other one will be a subscriber .
- Publisher: this application will periodically publish Jokes
- Subscriber: There could be N number of subscribers. In our case we will have 1 subscriber.
- This subscriber will be notified as and when a new joke is published.
- Subscriber could do anything with the joke. In our case we will just print on the console.
Jokes API:
We will be using below URL to get random jokes. That is our publisher will use the below URL to get random jokes and publish it. It is a simple GET request without any authentication.
https://joke.deno.dev/
The response payload is as shown below. Jokes are in the Q & A format.
{ "id":120, "type":"general", "setup":"How do hens stay fit?", "punchline":"They always egg-cercise!" }
Project Set Up:
- Create a Spring Boot project with below dependencies.
- I create a multi-module maven project as shown here
Common – DTO:
Let's first create a DTO for the joke. We are interested only in the 'setup' and the 'punchline' from the Joke API.
@Data public class Joke implements Serializable { private static final String JOKE_FORMAT = "Q: %s \nA: %s"; private String setup; private String punchline; @Override public String toString() { return String.format(JOKE_FORMAT, this.setup, this.punchline); } }
Redis PubSub – Publisher:
- Create a bean for ReactiveRedisOperations
@EnableScheduling @SpringBootApplication public class RedisPublisherApplication { public static void main(String[] args) { SpringApplication.run(RedisPublisherApplication.class, args); } @Bean public ReactiveRedisOperations<String, Joke> jokeTemplate(LettuceConnectionFactory lettuceConnectionFactory){ RedisSerializer<Joke> valueSerializer = new Jackson2JsonRedisSerializer<>(Joke.class); RedisSerializationContext<String, Joke> serializationContext = RedisSerializationContext.<String, Joke>newSerializationContext(RedisSerializer.string()) .value(valueSerializer) .build(); return new ReactiveRedisTemplate<String, Joke>(lettuceConnectionFactory, serializationContext); } }
- Then we autowire the ReactiveRedisOperation to publish the message periodically every 3 seconds.
@Service public class PublisherService { private static final String JOKE_API_ENDPOINT = "https://joke.deno.dev/"; private WebClient webClient; @Autowired private ReactiveRedisOperations<String, Joke> redisTemplate; @Value("${topic.name:joke-channel}") private String topic; @PostConstruct private void init(){ this.webClient = WebClient.builder() .baseUrl(JOKE_API_ENDPOINT) .build(); } @Scheduled(fixedRate = 3000) public void publish(){ this.webClient.get() .retrieve() .bodyToMono(Joke.class) .flatMap(joke -> this.redisTemplate.convertAndSend(topic, joke)) .subscribe(); } }
Redis PubSub – Subscriber:
This subscriber is another Spring Boot application. The subscriber part is relatively very simple. Here we subscribe to the channel and we print the value on the console as and when we receive the message. We can include multiple channel names if we are interested.
@Service public class SubscriberService { @Autowired private ReactiveRedisOperations<String, Joke> reactiveRedisTemplate; @Value("${topic.name:joke-channel}") private String topic; @PostConstruct private void init(){ this.reactiveRedisTemplate .listenTo(ChannelTopic.of(topic)) .map(ReactiveSubscription.Message::getMessage) .subscribe(System.out::println); } }
Dockerizing Infrastructure:
- I use below Dockerfile to dockerize both publisher and subscriber applications.
# Use JRE11 slim FROM openjdk:11.0-jre-slim # Add the app jar ADD target/*.jar redis-pubsub.jar ENTRYPOINT java -jar redis-pubsub.jar
- docker-compose file with all the dependencies
version: '3' services: redis: image: redis ports: - 6379:6379 publisher: build: ./redis-publisher image: vinsdocker/redis-publisher depends_on: - redis environment: - SPRING_REDIS_HOST=redis subscriber: build: ./redis-subscriber image: vinsdocker/redis-subscriber depends_on: - redis environment: - SPRING_REDIS_HOST=redis
Redis PubSub Spring Boot – Demo:
Once everything is ready, I run these commands one by one.
- Build the project
mvn clean package -DskipTests
- Build the docker images
docker-compose build
- Run the applications
docker-compose up
Output:
When I start my subscriber and publisher, I start seeing my subscriber printing all the jokes it receives on the console.
Summary:
We were able to successfully demonstrate Redis PubSub with Spring Boot by developing 2 simple Microservices. As we had seen above the publisher & the subscriber are not tightly coupled, but they still were able to communicate via Redis PubSub feature.
Instead of printing this on a console, how to show this message in a browser? Check this out –Spring WebFlux Streaming
Learn more about Redis.
- Redis Stream With Spring Boot – Real Time Data Processing
- Redis Master Slave With Spring Boot
- Priority-Queue Pattern With Spring Boot + Redis
The source code is available here.
Happy learning 🙂
Source: https://www.vinsguru.com/redis-pubsub-spring-boot/
0 Response to "Redis Pub Sub Example Java"
Post a Comment