1

I'm currently working on a project which is build as a microservice architecture.

We have one "Gateway" which aggregates the data coming from the different microservices to return one aggregated result to the frontend. The "Gateways" exposes GraphQL queries and mutations to CRUD data.

The microservices are build using java and spring boot and expose several REST API endpoints.

The problem I'm currently facing happens when it comes to generate a aggregate report.

For example:

  1. Fronted queries all orders within a time span
  2. Orders microservice returns a List of orders containing a list of products and a customer reference
  3. Now for each product in one order a GET to the product micro services is invoked to get the product data. That means if an order contains 10 products 10 GET requests are created to get the data.
  4. Same goes to the customer reference. A GET request is invoked to get the concrete data of the customer from the customer micro service

Now if we imagine we want to query all orders of the last month this ends up in a long-running query which might run in a timeout.

I know that microservices in general do not claim to be fast and that this is not their main purpose. But the current situation is not sustainable.

Are there any ideas to improve the performance without re-implementing the whole project?

Sorry if this is the wrong stack network for such questions.

  • 1
    How are you doing the internal requests in the gateway? One at a time or asynchronously/parallel? There is no particular reason why ten requests have to take ten times as long. Of course, Erno's suggestion of using batch requests is even better because it allows you to avoid overhead at all stages, incl the actual database queries. – amon Feb 12 at 8:31
  • 2
    there is no direct fix when the data is distributed among silos. you can create a data warehouse that contains all the data together, or reshape the microservices so the data is colocated and can be retrieved with a single query. – Martin K Feb 12 at 10:52
4

One way to 'solve' this is by re-designing or extending the REST interfaces to support batches next to single item requests.

E.g.:

Next to the GET server/products/314 you could implement a POST server/products/filter and post a body containing the ids of multiple products.

This would reduce the number of round-trips (assuming that these are the costly part of the current design)

| improve this answer | |
  • That was also one of my considerations. But this was too obvious to me. Possibly there are other solutions, which are not known to me or are not accessible to me. Actually I have solved this with Batch requests. I assume that this improves the performance because the following is currently happening: Order has a list of products. For every single product within an order a GET request is sent to retrieve the product from the database. There may also be references to other objects in the product, so this will add up. – Michael Schulz Mar 12 at 6:33
2

We can probably redesign the Order Microservice to store and return a tailored amount of Product data along with Product reference (same for Customer data), which is needed for "Order Summary" view/response; It's not very uncommon to have same data residing in multiple systems, especially since this by nature is mostly static (i.e. Ordered Product details won't change post-Order) and need not be updated for a change in Source system; So a sync-up of this data with it's Source-Of-Truth ideally may not be needed..

Product reference can be used to fetch individual Product details from Products microservice based on further User action for fetching individual Product(s);

| improve this answer | |
  • So you mean that I / We should store a minimalistic ShadowProduct entity inside the Order Microservice which represents the real Product but with lesser data? Would this go hand in hand with the Bounded Context concept? As far as I understand the Bounded Context concept knows more than one Product entity, for example. However, the data differs according to the context. – Michael Schulz Mar 12 at 6:29
  • 1
    Yes. I would think that Product Microservice can be API provided by Product Management System, that handles complete Lifecycle of a Product; and the Order Microservice can store a Ordered product detail in a shallow product representation needed to represent it only in the context of the Order and an internal reference of the Original Product from Product Management System. – Divs Mar 12 at 6:45
1

In principle, each logical set of data should have its own microservice that has exclusive access to that data (encapsulation). However, sometimes it cannot be avoided to have a complex query on multiple sets of data implemented in one service, for performance reasons. In most relational database systems, you can define a 'view' to decouple the query from the physical database structure.

You could extend the REST interface to generate a report by one 'microservice' in one call. Design a URI for the report, e.g. mydomain.xx/reports/orders and then use http method GET on this URI to let a special reporting service generate the report.

| improve this answer | |
0

This is reminiscent of historic code: queries and then loops inside loops doing queries themselves.

Move the frontend methods with heavy microservice usage to the backend. Then there the prior microservice calls can be immediate calls, and all in the same transaction.

This kind of refactoring can be done step-wise, parallel to the working system.

Such batch services require some care, as you pass larger data object models. A version in data and code for maintenance of the data, especially if more than one team is involved. JSON might be an easy readable format, but there are binary formats too (Hessian, ASN defined). Binary data has one advantage: no conversion back and forth. If versioned, no problem.

The data model can be optimized for streaming, so that I/O can immediately start. In order of the queries, and the queries in order of the front end usage. This should be realized in a special kind of Test Driven Model, testing such transfer of the data only, listing it in text for comparison; a long developed unit test.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.