Diagrams of How AEM Solr/Mongo UGC (MSRP) Works

Diagrams of How AEM Solr/Mongo UGC (MSRP) Works

May 21, 2020 1 By Tad Reeves

When the AEM 6.1 Communities functionality was first released about 4 years ago, I’d just created my first blog post with AEM architecture diagrams for the Rackspace blog, and promised all my teammates that I would TOTALLY create some great diagrams of how the Adobe Experience Manager / Solr / Mongo / Sling Distribution setup worked.

Well, now here we are a few versions later, and in the intervening years I’ve made still further promises to co-workers to make some understandable diagrams of how this all works. Well, sorry team, I’m finally catching up my backlog.

First: Understanding the Problem of UGC on AEM

In AEM (with the exception of the new AEM as a Cloud service) each Publish instance keeps an entire copy of ALL of the content a user could possibly want to see, with the exception of things like – say – a custom on-site search engine like Sinequa or Solr, or a Commerce engine like Hybris.

So, if you wanted to implement some social features like comments, blog posts, likes, ratings, bookmarks, blog “follow” functionality, etc, that all needs to be stored somewhere that all users can get to.

In the old days (i.e. AEM 6.0 and earlier) your only option was to have all of your publicly logged-in users to be REAL AEM users, and a comment or a “like” posted on one AEM publisher would then have to get reverse-replicated back to the Author (which is not supposed to be taking public traffic) which then forward-replicates it out to the other publishers. This setup was EXCEPTIONALLY brittle, and with its multiple redundant points of failure could handle FAMOUSLY little traffic before falling over dead. The most problematic AEM site I ever worked on, causing me more heartache and grief than virtually anything else I’ve ever touched in my career was AEM 6.0 with such a setup.

And don’t ask me for a diagram of it, I won’t do it.

Adobe had to design an entirely separate system for handling both User profiles and access, as well as handling the user-generated content itself. From that AEM Communities was born.

AEM UGC Infrastructure Choices

Since AEM 6.1, Adobe has maintained four separate mechanisms for storing UGC in AEM. They are:

  • MSRP – Mongo Storage Resource Provider: Persists UGC in MongoDB, and uses Solr as a caching and search mechanism to quickly serve it up to the publishers. Suitable for high traffic sites with a lot of UGC, but does take a fair bit of DevOps muscle.
  • DSRP – Relational Database: Same as MSRP, but uses a relational database like MySQL to persist the UGC, and still uses Solr as a read cache. Slower than MSRP but works for those with a lot of DBA muscle around.
  • ASRP – Adobe Storage Resource Provider: This is where you use Adobe’s Cloud-Hosted AEM Communities endpoints, which are really just MSRP under the covers, but you just don’t need to provision the infrastructure for them. If you have the option of moving your UGC out of your org’s ops footprint, this is a great option.

    Also, this will be the only option available for AEM as a Cloud Service once AEM communities is released for AEMaaCS.
  • JSRP – Java Storage Resource Provider: This is for dev use only, and NOT for production, and persists all UGC into the local JCR of the publish instance, and can’t share it with another instance. Just for developing on your local.

Today, we’re going to be talking about MSRP.

User Profile Data vs User Generated Content

The first distinction to make when understanding this setup is that there are two very different types of user data to handle on a Communities setup:

  • User Generated Content: This would consist of blog posts, comments, ratings, post likes, comment likes, author follows, bookmarks, and other user-generated content, much of which is in a constant state of flux, and which could be rapidly changing with every page refresh.
  • User Profile data: This would be seldomly-updated and user-specific data for a given user, like username, password, display name, email address, etc. It is data with infrequent updates, but also must be persisted as part of the AEM application as it can be they key for things like Closed User Groups and user-specific content access. But because it’s not in a state of constant, high-volume flux, it gets persisted differently than UGC.

For user profile data, AEM uses Sling Distribution user sync to take updated user data from one publisher and ensure it gets to all other publish instances in the farm.

Simple diagram of Sling User Sync on AEM

The link above gives the instructions for setting up user sync on AEM 6.5. Setting up User Sync on AEM can be a brittle process, as it does require that the Author environment be in the loop and be the via for any user changes that happen in the publish environment.

NOTE: It is, presently, the only part of a modern AEM site where the loss of the Author environment would impact the user experience and full availability of your public-facing website.

Generally, an Author instance can be taken offline on the weekends without any effect at all on your publish environment (aside from no new content getting published) but with Sling user sync in the loop, taking down the author means that if someone changes their display name or profile image on one publisher, that change will not be reflected in the other publishers while the Author is down. Adobe recommends that if this is an issue, or if you are not able to implement sticky sessions (i.e. if users can hop from publisher to publisher at any time) it’s recommended to go with a separate SSO solution to establish your user sessions rather than use Sling user sync.

Storing & Serving User Content with Mongo / Solr

Now, for storing & serving user-generated content itself. I’m focusing here on MSRP, as it’s the most robust platform you can host yourself.

First off, just know that setting up MSRP is NOT FAST AND EASY. This document talks about how to do it in detail, but if you’re looking at doing this for the first time, recommend that you hit up some DevOps muscle to help you with automating that setup.

There are two ends of this to talk about, how data is written to the system, and how it’s read back & displayed.

For writes, the system-of-record for AEM Communities UGC here is MongoDB:

How a user action resulting in a write of UGC to the system gets persisted.

In the example above, a user on the website clicks the “Like” button on a blog post. That call then goes through a load balancer where he’s assigned to a dispatcher, the dispatcher passes that request back to the publisher.

The AEM Publisher does not persist this “Like” anywhere in the JCR locally, but instead hands it off to the MSRP setup, where it makes a write to your MongoDB cluster, where it will be permanently stored.

Solr in this case will pull its data from Mongo to be used for later refreshes of that page, or for other users to see that the page has a “Like”.

To restate: the system of record for the UGC setup is Mongo. If Solr data becomes inconsistent, or if you upgrade Solr and need to wipe it out and start from scratch, there is a Solr Reindex job you run from the Author which vaporizes Solr and pulls all the data newly from Mongo.

Then, for reads, let’s look at Solr:

In the example above, the user loads an AEM page that contains user comments on it. After passing through the dispatcher, the AEM publisher would go to attempt to render the page. On-page components that come from the JCR get spat out directly, but components that contain the user-generated content go to the MSRP connector.

Now, Adobe supports both going with a stand-alone Solr server, or with full SolrCloud Solr/Zookeeper setup. For high-availability and speed, you’d want SolrCloud.

In the case above, the first thing that happens is the AEM Zookeeper client kicking off to talk to your Zookeeper ensemble and ask it what Solr servers it should be talking to for a given Solr Collection. If a Solr server is being restarted or is not responding, Zookeeper will handle the load-balancing and failover for you.

After AEM gets what Solr server it should talk to, it reaches out to talk to Solr (usually port 8983) to query and get the data it needs (i.e. “give me all the blog posts for a page with this id” etc).

Once it gets the data back from Solr, AEM can return the page.

About the Cover Photo: Taken on a lovely sunset in June 2018 on the Donnersbergerbruecke in Munich, Germany while on a business trip. I’m forever envious of how easy it is to get around Munich without a car. Original: Sunset Trains Coming from Munich Haubtbahnhof | Tad Reeves | Flickr

Sunset Trains Coming from Munich Haubtbahnhof