Invoking dependent microservice

Viewed 276

Let's say that I have 2 microservices: Service1 and Service2. Each one of them has its own database. Service1 has EntityA and Service2 has EntityB

EntityA {
    Long id;
    //other fields
    EntityB entity;
}

EntityB{
     //other fields
}

I'm using Spring's RestTemplate for retrieving and saving data. The problem is : when retrieving EntityA from Service1's database I don't have data of EntityB as they are held in Service2's db, I understand that I should make a rest call via RestTemplate to retrieve EntityB from Service2's db, but what about relationship between the entities - should EntityA still have the whole EntityB object inside even though its fields are null most of the time except id ? What am I missing? Thank you in advance.

3 Answers

From a technical perspective, your problem can be fixed via an API Gateway.

In a nutshell, you should define a new microservice, say gateway service, that will be called by your API clients. The gateway service would then:

  1. Invoke Service1 to get Entity1 along with the id for Entity2
  2. Invoke Service2 to get Entity2 based on the id from step 1.
  3. Aggregate the two responses (in you case, setting the Entity2 values inside Entity1).
  4. Return the aggregated response to the client.

Two thing to keep in mind while you design:

  • Your API client should not be aware his data is fetched by two services.
  • It is generally cleaner to aggregate client response in the gateway, since it allows a higher level of decoupling between your microservices. For example, you could model your entities as follows (and remove the data model dependency between Service1 and Service2, allowing the two services to evolve independently).

See the below snippet:

// In Service1
EntityA {
    Long bId; 
}

// In Service2
EntityB{

}

// In Gateway
Response {
    EntityA a;
    EntityB b;
}

The decision of weather Entity1 should reference Entity2 is not dependent on how your data is distributed but on your business needs. If you would have a monolithic application and in that context it would make sense for Entity1 to reference Entity2, it still makes sense to do so in a microservice environment.

The two solutions that come to my mind are both easy and complicated in the same time.

Duplicate data

In between of MS's, there's usually a highly available pub-sub or message queue clustered system. When the EntityB is saved in Service2 you send an event into the queue or pub-sub system. Service1 can subscribe to that particular event and store the information about EntityB in its own database.

Group domain logic

Maybe, there's just too big correlation between domain of Service1 and Service2. In that case, you might want to have your services grouped into a single service.

I came across this pattern and I think it useful for your situation.
The pattern is called CQRS (Command Query Responsibility Segregation, a mouthful)

The pattern assumes that you have an event sourcing system in place, which there is a high change you have since you are working with microservices.

When any EntityA from Service1 is changed, Service1 publishes an event. The same goes for Service2, when any EntityB si changed it will also publish an event.

Then we have Service3 which subscribes to the events coming from Service1 and Service2 aggregates the data and stores it in its local database. Now all you have to do is call Service3 to get the agregated data from Service1 and Service2.

Of course this pattern comes with its downside like eventual consistency but it some scenarios it may actually be the best fit.

The idea comes mostly from here: https://microservices.io/patterns/data/cqrs.html. I would also read at least the "when to use this pattern" section from here: https://docs.microsoft.com/en-us/azure/architecture/patterns/cqrs

Related