[Seeking advice] RESTful backend on top of distributed microservices

Hi, there!

First of all, I hope this is the adequate subreddit for this post. If it's not, please pardon my inexperience.

​

I'm looking for help for architectural / pattern design for a concrete use case I'm facing at work. I work as sw. architect in the frontend team of a large company which is building a financial cloud platform. However, we will be leading and probably building a new backend or design a solution for the problem at hand:

​

We currently have several distributed services which expose RESTful microservices in the platform (one for resources scaffolding, another one for deployments and deployment control, another for monitoring clusters/resources, logging and alarms, another one provides aggregated platform status, etc). Security IS a pain but it's already been sorted out, as well as connectivity. We are building a modular web RIA with very complex UI which we want to be showing lots of aggregated data and provide a rich UX (all sorts of filtering, sorting, heterogeneous trees, paging/buffered lists, charts, etc.).

​

Right now every module has been deployed as an isolated app and connected to "its own" backend or set of microservices, and their functionality has been limited in most cases in line with the amount of data already exposed by such microservices.

We now need to build a backend/proxy/layer/whatever that can connect with the rest or (we would like this one better) even replace them.

However, there is a unique source of truth but distributed among many services (for example, one service might yield an array with the IDs of the project a user has access to, while another might provide us with the details for a project given its id). Currently, one of our backend's endpoints first retrieves the list of IDs, then fires a request for every ID, and then aggregates the result as a single JSON. This is suboptimal. Furthermore, when we want to implement sorting, it is not feasible for someone with access to 200 projects to wait for 200 requests and then sort (in frontend, if you don't want to overload the server with every page request). We can and will have to (regardless of the solution chosen, probably) ask our colleagues in every team to create new endpoints with listing and sorting whenever possible. However, this means going case by case and, sometimes, maybe 3 services/teams can be involved to generate a JSON result with data sparse among them.

​

Given that we cannot rewrite the platform, and you have N systems and your data might be distributed across microservices on such systems, would anyone be able to suggest a pattern or any ideas on how to create RESTful services that compose larger JSONs (likely not reusable) to be consumed by our RIA/s and be able to perform things like sorting, paging and filtering?

​

I'm sorry for the wall of text, and thanks a lot for your time and attention.

Posted Feb 5, 2019, 9:29 PM UTC · edited

38
chipstastegood•

Wow, a question on Reddit that I am finally ideally suited to answer!

In short, yes, there is a solution for this. It's a common problem when you go from a monolith to a microservice architecture on the back-end. The whole point of microservices is to make them isolated from each other. That, of course, causes problems like what you're running into. As you start to layer microservices on top of each other, dependencies become difficult to manage and can cause performance problems.

The solution is simple but can be tricky to implement if it's your first time doing it. You need to implement an event-based architecture. And then create projections and read models. That will solve your performance issues.

If you don't already have an event-based architecture, you can retrofit it. It's not too hard.

Here is how this works in a nutshell. Microservices emit events on a state change. Other microservices listen to events emitted by microservices they depend on. They then project those events onto a data model that is read-only. Finally, when a higher-level microservice some data from a lower-level microservice, it doesn't need to necessarily call the dependent service. Instead, it can immediately get the data it needs from its local read model projection.

Let me know if you have questions. I love talking about this. I have a blog, too, that talks about event-based architectures. Don't want to advertise here but if you're interested, let me know and I'll send you the link to it via DM.

Source: Principal software architect for a ride-sharing company and founder of an event-sourcing platform as a service.

4
crimson117•

It sounds like your domain modeling went overboard and split up things way too aggressively.

Before you switch technologies, try to correct your domain modeling by identifying data that is often needed simultaneously by your users but which you have isolated in separate services.

Once you have done that, elasticsearch is a good recommendation.

3
chipstastegood•

Perhaps, but not necessarily. There are plenty of ways that someone like OP can find themselves in a situation where data needs to be aggregated from outputs of several microservices. Well-designed systems exhibit this problem as well. It's a perfectly valid question

2
enderfxOP•

By the way, we are considering a modular backend written in NodeJS (most of our modules' backends are written in NodeJS but not with common architecture), and we would love to implement GraphQL, but since there is no "master database", distributed or not, we don't know if this well be possible.

1
takuhi•

GraphQL itself doesn’t need a “master database”, in fact in a lot of use cases it doesn’t do any of the heavy lifting and resolves queries by calling out to other services. I’d say it’s very well suited to act as a gateway for your backend services, but you probably still need to use some sort of API gateway to do things like load balancing and rate limiting.

I’d also recommend looking at something like gRPC or Apache Thrift for your backend services, especially if you’re looking to use GraphQL. We found that GraphQL and gRPC played really nicely because they’re fairly opinionated (good for speed and time to market) and enforce data types. gRPC has official libraries for loads of languages, which means you can use multiples languages to implement your services and they can all talk to each other seamlessly.

1
enderfxOP•

Thanks for your reply. I will definitely take a look at gRPC and Thrift. I still, however, don’t know what to do with the disseminated data :/

1
takuhi•

Yep, so that’s where something like GraphQL can help. You can have a single schema definition which encompasses all your different data sources / services. GraphQL let’s you resolve each node in the schema separately, which makes aggregating data from multiple sources dead easy.

I’ll try and illustrate an example using a bit of pseudo code. Your GraphQL schema types might look something like this;

User
  - Name 
  - Address 
    - Line 1 
    - Line 2 
    - Postcode 
  - Playlists[]
    - Playlist 
      - Title 
      - Songs[] 
        - Title 
        - Artist

As far as the client is concerned, it could request as much or as little as it wants from this schema. In some cases they might just want the user’s name and the playlist titles, in others it might just want the user’s postcode. Each node in this schema can be resolved to different services (asynchronously) and then aggregated into one response. So for example, GraphQL might resolve this schema like this;

User -> UserService
  - Name 
  - Address 
    - Line 1 
    - Line 2 
    - Postcode 
  - Playlists[] -> PlaylistService
    - Playlist 
      - Title 
      - Songs[] -> SongService
        - Title 
        - Artist -> ArtistService

Edit: Formatting

1
patelpriyank•

Depending on how real time data you want on UI, you can index data from all those microservices into something like Solr/elasticsearch and server your "GET" queries from there. You can build a notification system to update it or reindex every fix intervals. Searching, facades, auto complete and auto correct all come out of box with Solr/elasticsearch. For sorting, you may have to do some tricks and POC to get it working as per your need.

1