Featured in
Architecture & Design

Mini-talks: The Machine Intelligence Landscape: A Venture Capital Perspective by David Beyer. The future of global, trustless transactions on the largest graph: blockchain by Olaf Carlson-Wee. Algorithms for Anti-Money Laundering by Richard Minerich.

Featured in
Process & Practices

In-App Subscriptions Made Easy

There are various types of subscriptions: recurring, non-recurring, free-trial periods, various billing cycles and any possible billing variation one can imagine. But with lack of information online, you might discover that mobile subscriptions behave differently from what you expected. This article will make your life somewhat easier when addressing an in-app subscriptions implementation.

Featured in
Operations & Infrastructure

Mini-talks: The Machine Intelligence Landscape: A Venture Capital Perspective by David Beyer. The future of global, trustless transactions on the largest graph: blockchain by Olaf Carlson-Wee. Algorithms for Anti-Money Laundering by Richard Minerich.

Featured in
Enterprise Architecture

Mini-talks: The Machine Intelligence Landscape: A Venture Capital Perspective by David Beyer. The future of global, trustless transactions on the largest graph: blockchain by Olaf Carlson-Wee. Algorithms for Anti-Money Laundering by Richard Minerich.

Implementing Pub/Sub based on AWS technologies

AWS provides two services - Amazon Simple Notification Service and Amazon Simple Queue Service -that combined can be used as the foundation of a complete pub/sub service.

Existing AWS capabilities

Amazon Simple Notification Service (Amazon SNS) is a web service that enables applications, end-users, and devices to instantly send and receive notifications from the cloud. A very simplified SNS architecture looks like the following: (Figure 1):

(Click here to enlarge)

Figure 1 Amazon SNS based architecture

Here multiple publishing applications can talk to multiple subscribing applications using the SNS topic as an intermediary. The advantage of this implementation is that publishers and subscribers do not need to know about each other and, as a result, SNS supports fully dynamic integration between applications. SNS supports multiple transports for notification delivery, including HTTP, HTTPs, Email, SMS and Amazon Simple Queue.

Amazon Simple Queuing Service (Amazon SQS) offers reliable and scalable hosted queues for storing messages as they travel between computers. By using Amazon SQS, you can move data between distributed components of your applications that perform different tasks without losing messages or requiring each component to be always available. Combining SQS with SNS offers two additional advantages not provided by SNS alone – removing temporal coupling and supporting symmetric load balancing of specific consuming applications. The latter can be done by having multiple instances of the same application read messages from the same queue. The overall architecture for combined SNS/SQS implementation is presented below (Figure 2). Here we show one of the subscribing applications as load balanced.

(Click here to enlarge)

Figure 2 Combining SNS with SQS

The main drawback of this implementation is that both publishers and subscribers need to explicitly agree on the names of SNS topics. Additionally, if a given consumer wants to get information from multiple topics, he needs to register his queue to the multiple topics.

Desired Pub/Sub implementation

A typical solution for this problem is a tree-based topic organization implemented by the majority of pub/sub engines. The main principles of such an organization are outlined at OASIS specification Web Services Topics 1.3.

This specification defines topics

“… as a way to organize and categorize a set of Notifications. The Topics mechanism provides a convenient means by which subscribers can reason about Notifications of interest… a Publisher may associate [publication] with one or more Topics. When a Subscriber creates a Subscription, it may supply a Topic filter expression, associating the Subscription with one or more Topics… Each Topic… can have zero or more child Topics, and a child Topic can itself contain further child Topics. A Topic without a parent is termed a root Topic. A particular root Topic and all its descendants form a hierarchy (termed a Topic Tree).”

An example of the topic tree for cell phone sales is presented below (Figure 3).

Figure 3 Example Topic tree

Here a topic tree root represents sales. Sales can be broken down by regions (North America, Europe and Asia Pacific, in our example). Sales for a given region can be further broken down by the phone type, and so on.

The reason why such a structure is important in a pub/sub system is the fact that a tree reflects an organization of data. If a consumer is interested in events about smartphone sales in North America, he is listening on this specific topic. If he is interested in events about all sales in North America, he is listening on the topic North America with the assumption that he will get all of the notifications from the child topics.

Of course, this approach does not solve all the problems. For example, if a consumer wants to listen to the events about all smartphone sales, he needs to explicitly subscribe to smartphone sale events for all regions. This situation is typically reflected in the appropriate topic tree design. A tree is designed based on the information organization and typical usage patterns. In some cases, multiple topics are design to satisfy different internal needs (see topics namespaces in Web Services Topics 1.3). Another important feature of modern pub/sub architectures is content-based message filtering:

“In a content-based system, messages are only delivered to a subscriber if the attributes or content of those messages match constraints defined by the subscriber. The subscriber is responsible for classifying the messages.”

In other words, in this case, subscribers can explicitly specify the content of the messages that they are interested in, using a list of regular expressions.

The combination of this filtering and a hierarchical topic structure allows for the creation of very flexible and powerful pub/sub implementations.

In this article we will show how this type of system can be easily built using AWS components.

Proposed Pub/Sub architecture

The proposed architecture is presented in the picture below (Figure 4). In this architecture Pub/Sub server is implemented as a web application running inside a Tomcat container. Here we are also leveraging AWS Elastic Load Balancer, which allows us to dynamically expand and contract the size of the Pub/Sub server cluster based on the current load. In addition, it uses the Relational Data Service to store the current configuration to enable dynamic creation of additional Pub/Sub instances. To improve the overall performance, we are trying to minimize the amount of database access by keeping the current topology in memory. This makes the actual message routing very fast. This solution does though require a mechanism to notify all the servers of any topology change (which due to load balancer usage can be processed on any server). This can be easily done using Amazon SNS. Finally, we are leveraging Amazon SQS for delivering notifications to the consumers. Note that a given consumer can be listening on multiple queues.

(Click here to enlarge)

Figure 4 Proposed overall Architecture

Pub/Sub Server

At the heart of this implementation is a custom Pub/Sub server. The server implementation comprises three main layers – persistence, domain and services.

Persistence

A topic entity (Listing 1) describes information stored about a specific topic, including topic id (internal id for the database), topic name (a string identifying topic), a Boolean variable (defining whether this topic is a root topic), a reference to topic parent and children (allowing the traversal of a topic hierarchy), and a list of subscriptions associated with a given topic.

We also define two named queries here that are used to access the topic – RootTopics gets a topic structure starting from the root and AllTopics gets all existing topics.

This entity provides a complete topic definition and can also support multiple topic trees (not part of the example implementation).

A subscription entity (Listing 2) describes information stored about a specific subscription, including subscription id (internal id for the database), name of the queue (SQS queue ARN) to which this subscription should be delivered, a reference to a topic that this subscription is associated with, and a list of semantic filters. Notification will be delivered to a given queue (client) only if all the filters accept the message (see below). If a notification does not contain semantic filters, all the messages from associated topics will be directly passed to the queue.

We also define here a named query that is used for getting all existing subscriptions.

Finally, a semantic filter entity (Listing 3) describes information stored about a specific semantic filter, including the semantic filter id (internal id for the database), the name of the attribute that this semantic filter tests, a regular expression that is used, and a reference to a subscription that this semantic filter is associated with.

Domain Model

A responsibility of domain model objects is to support service operations including the subscription to and publication of data, as well as the actual publishing of the notifications to subscribers’ queues. Although, in our simple implementation, we could have merged the domain and persistence models, we chose to separate them. The data model for both layers is the same, but there are additional methods on domain objects that explicitly support Pub/Sub implementation.

Publication implementation (Listing 5) is a method on the subscription class. Note that this method is implementing “ORing” of the semantic filters. This limitation can be overcome by having multiple subscriptions for a given client or extending the subscription implementation to support Boolean functions.

When using SNS it is important to remember that subscribing to the topic does not mean that you are ready to listen on the topic. SNS subscription is a two-step process. When you send a subscribe request to SNS, it will return a reply saying that it is necessary to confirm the subscription. That is why Listing 8 has both subscribe and confirmSubscription methods. A single schema:

describes both message types - confirm request and actual notification. The two can be distinguished by examining the Type element. If the element value is “SubscriptionConfirmation” then it is a request for subscription confirmation, if it is "Notification" it is an actual notification.

Topic class implements two methods (Listing 8) to support publications.

The processPublications method creates a list of topics that are associated with a given message. It does this by taking a tokenized topic tree string and adding itself on to the list if a token corresponds to its name. A topic publish method takes a map of message attributes and, for every subscription associated with this topic, it tries to publish a message.

The above methods are brought together by the publish method in the Domain manager class (Listing 9). This method first tokenizes topic string and then (using the processPublications method) builds a list of topics to whose subscribers this message is of interest. Once the list is created, it builds a map of message attributes (we assume an XML message) and publishes it to every topic in the list.

These services are used by the message publisher (publish methods), service subscriber (create/delete semantic filters and subscriptions, as well as associating filters to subscriptions and subscriptions to topics), Pub/Sub implementation internally (get synch service) and admin applications.

Conclusion

The simple implementation presented here builds a very powerful, extensible, pub/sub implementation, whilst leveraging a lot of existing AWS capabilities with a minimal amount of custom Java code. It also fully takes advantage of existing AWS deployment support for load balancing and failover.

About the Author

Dr Boris Lublinsky is a Principal Architect at Nokia, where he is actively participating in Big Data, SOA, BPM and middleware implementations. Prior to this Boris was a Principal Architect at Herzum Software, where he was designing large-scale SOA systems for the clients, an Enterprise Architect at CNA Insurance where he was involved in design and implementation of CNA’s integration and SOA strategy, building application frameworks and implementing service-oriented architectures, Boris has over 25 years experience in enterprise and technical architecture and software engineering. He is an active member of OASIS SOA RM committee, coauthor of Applied SOA: Service-Oriented Architecture and Design Strategies book and author of numerous articles on Architecture, programming, Big Data, SOA and BPM.