The following is an excerpt from the chapter on “Push Notifications with Amazon MQ” from the eBook “Stratospheric – From Zero to Production with Spring Boot and AWS” I’m currently writing together with Tom Hombergs and Philip Riecks.
You can get the eBook over at Leanpub.
Push Notifications With Amazon MQ
As discussed in the chapter “Sharing Todos with SQS and SES” we might want to share our Todos with others. Being able to share Todos is already quite helpful for working on tasks collaboratively. Receiving real-time feedback whenever a collaborator makes changes to a Todo, however, would be even more useful.
This is where push notifications come into play. In this chapter, we’ll explore the benefits, ins-and-outs, and strategies of push notifications and the required AWS infrastructure for implementing those.
What Are Push Notifications Anyway?
Having originated in the mobile app space in 2009 when Apple coined that specific term, push notifications usually refer to a backend server pushing information to the user interface of a mobile application rather than the application itself initiating a request – or pulling – in order to acquire information or an updated application state.
The main benefit of this approach is that, rather than continuously polling for new information – and hence using a lot of network and system resources (which on mobile devices typically equates to reduced battery life) a client only ever gets notified if and when there’s an update that’s relevant to that specific client.
While the term was originally coined for mobile apps the general pattern applies to any kind of distributed client-server or multi-tier application, especially if there are multiple clients involved, which in turn might need to communicate with each other.
This pattern comes in several flavours and implementations. A common design pattern for implementing such behavior is the observer pattern as outlined in this sequence diagram:
With this design pattern multiple observers subscribe to a subject (or: observable), which in turn will notify each of its subscribers (calling a
next(value) method) once there’s an update available.
To take both scalability and easier management of subscribers into account, message brokers such as Apache ActiveMQ generalize this idea following the publish-subscribe pattern. This pattern allows us to have an n:m relationship between publishers and subscribers with multiple publishers publishing messages to a topic (also called “channel”) and multiple subscribes receiving messages from that topic:
We will apply this general concept of a server notifying its clients whenever there’s a relevant update to a Todo in our application. In our case, we will be notifying users in their browser window when another user has accepted their request to collaborate on a Todo.
In order to do so, we’ll be using WebSocket and STOMP as protocols on top of an ActiveMQ message broker running on Amazon MQ. While implementing a publish-subscribe pattern is certainly possible with other protocols such as HTTP, WebSocket and STOMP particularly lend themselves to this scenario since WebSocket – in contrast to HTTP – allows for bi-directional, full-duplex communication.
Although technically not required, these two properties greatly simplify implementing a publish-subscribe pattern. There are alternative approaches such as HTTP Polling, HTTP Streaming, or Server-Sent Events, each of which comes with its own upsides and trade-offs.
Still, WebSocket not only fits the bill in terms of what we need for our particular use case but it also sports better performance and lower latency than HTTP.
Push Notifications for Live Updates
In the previous chapter on “Sharing Todos with SQS and SES” we’ve seen how we can communicate and collaborate with other users with Amazon Simple Queue Service (SQS)and Amazon Simple Email Service (SES).
So far, however, that communication has been one-way only: we allow a user to share their Todos with other users but the Todo’s owner won’t receive a notification yet in case their collaborators made progress on a shared Todo. In order to amend that situation, we’ll be implementing a notification feature that’ll inform us of such updates.
While using Spring’s embedded in-memory message broker might seem like an obvious – and simple – solution, this doesn’t work here because we want to run (at least) two instances of our Spring Boot application for reliability. In this setting, only clients connected to a specific instance would be able to exchange messages with each other. Hence, to be able to communicate across instances we need a stateful service that enables message sharing across application instances.
Therefore, we’ll employ an AWS service for doing so. Within the AWS ecosystem there are quite a few services that allow us to implement notifications with a publish-subscribe pattern. Each of those services is targeted at different use cases or even different industries with different requirement usage patterns.[…]
So, have we run out of options? Fortunately, no, we haven’t. With Amazon MQ, there’s still one option left that might help us with our PubSub scenario:
“Amazon MQ is a managed message broker service for Apache ActiveMQ and RabbitMQ that makes it easy to set up and operate message brokers on AWS.“
Amazon MQ is different from the services discussed before in that it doesn’t provide a high-level, serverless API for specific use cases but rather a traditional service instance, on which to run our own message broker. The benefit of this approach is that we’re not constrained by a particular API’s or platform’s limitations but rather we’re able to use the full range of features those message brokers provide us with, particularly when it comes to the WebSocket protocol, which both ActiveMQ and RabbitMQ support. A demerit of this is that setting up the requisite infrastructure is more involved than with the AWS services mentioned before.
In contrast to the other PubSub options provided by AWS Amazon MQ operates under a pay-per-hour business model, which means that it’ll incur costs even when we’re not actively using it.
While both the potentially higher costs, and the more complex infrastructure setup can be considered major downsides, Amazon MQ is the only service of those mentioned that natively supports the WebSocket protocol.
Hence, it’s the only one that meets our specific requirements, which is why we’ll be using Amazon MQ for implementing our “push notifications” feature.
Using Amazon MQ as Message Broker Infrastructure
Having settled for Amazon MQ, the next decision to make is the one between the two message broker options available:
Both come with a similar set of features and a roughly similar performance profile. Therefore, deciding which to use boils down to specific requirements for your particular project or environment.
However, ActiveMQ not only natively supports the WebSocket and STOMP protocols but also the Java Message Service (JMS) API and the MQTT and AMQP protocols as well. So, it seems like the more versatile solution, particularly in a Java-based environment. Should the need arise to directly connect the message broker to our Spring Boot application via JMS we could do so without swapping the underlying message broker technology.
For these reasons we’ll be using ActiveMQ for our push notifications feature.[…]
Again, if you like what you’ve read so far you can get the eBook over at Leanpub.
With each version of the book the price will go up. If you decide to buy the eBook now you’ll get all future updates for free.
If you join the mailing list you’ll get an additional 50% discount on the current price.