1

We are working on a suite of Python 'services' each of which is basically an application that does some calculations based on a domain (data) model and returns the results. These services are designed to be called individually by only providing a domain model. We also have one large "main" service, MainService, that orchestrates these other services, and collects all the output and returns a decision based on the output of all the other services.

Say, service CustomerService depends on the output of service StatisticalService (it uses the probability calculated by the StatisticalService), that is no problem since CustomerService can just call StatisticalService.

However, MainService also depends on the output of StatisticalService (it uses an explanation of how the probability was calculated by StatisticalService). In this case, I see a problem (?), in that if MainService also calls StatisticalService, then StatisticalService will be called twice within MainService, once in MainService itself, and once in CustomerService.

Overview

I don't want CustomerService to output anything related to the StatisticalService, only use it, and I also don't want CustomerService to take StatisticalService output as input (which could be managed by MainService). The thing is StatisticalService has to execute the model inside before it can provide any output, so we can't really split it up into different independent "methods".

My question is, what would be a good way to handle these dependencies? I don't have much experience with this, I have thought up one possible solution though;

Caching the output of StatisticalService it is called the first time, and then dont call StatisticalService if there is output stored in the cache, CustomerService being called by MainService would then check if the StatisticalService output is in the cache. Would that be a sensible and stable approach to take?

Hope that makes sense, thank you in advance!

1
  • Would that be a sensible and stable approach to take? it depends. Is StatisticalService output deterministic? In other words, given the same input, do you get always the same result no matter which service makes the request first? If yes, then sounds fairly good. If not, the cache will make things even more complicated.
    – Laiv
    Mar 14, 2023 at 21:08

3 Answers 3

3

As long as you have micro services calling each other directly, you will have hard dependencies between services. With your current design, the statistics service is a active participant in the business process.

Instead, consider asynchronous messaging. The MainService and CustomerService would send messages to a queue for the StatisticalService. The StatisticalService can process these messages independently of the other two services. The challenge here is making sure that downstream services requiring statistical data are programmed to wait for some result or message from the stats service. This is called Eventual Consistency in micro services.

You could flip the communication around. Instead of services pushing messages to a queue used by the StatisticalService, the MainService and CustomerService would push messages onto some outgoing queues of their own. The StatisticalService would subscribe to those message queues, making the StatisticalService a passive participant in the business process. You still need to program other services requiring statistical data to use Eventual Consistency — perhaps the StatisticalService publishes its own event when new stats are available. Other services needing this data would subscribe to this message queue.

Breaking hard dependencies, and especially chained dependencies, involves decoupling services from each other. They should not know about each other directly, and instead should rely on message queues. This complicates the business process, because certain parts of the process are calculated independently of other parts. This is the cost of decoupling your services.

1
  • Hi Greg, thank you for your response. Since only MainService will actually be callable from outside the application and I only strive for this independent design, for the purpose of design, this approach will probably be too complicated to implement "just for design". I think I will attempt to use caching since the other services are exclusive to the MainService. Nonetheless, I will try to employ Eventual Consistency on the larger scale services, so thank you for that.
    – Mathias A.
    Mar 17, 2023 at 14:55
0

In addition to Greg's answer, see if you can separate the Statistical service function consumed by Customer service as another service. This new service will be meant only for Customer service.

1
  • Hi Amit thank you for your response, unfortunately any meaninful interaction with the statistical service required the underlying model to be evaluated so that won't be possible.
    – Mathias A.
    Mar 17, 2023 at 14:58
0

In addition to Greg's and Amit's answer, at first place we have to look into bounded context while working on microservices architecture. May be defining clear boundary and responsibility of each service reduce inter services dependency to some extent.

Secondly, caching will work better of data you are fetching from other serivices is kind of constant or update less frequently. if this is not the case than you have to add an additionla layer of complexity to write some cron or serivce to periodically update your cache. Otherwise you cache will have older version of data.

There are two type of communication usually happens in microservices architecture, async and sync. For async communication best possible approach is using message broker or queue. You can use AWS SQS or Kafka depending on the use case. For sync communication you can use RESTful APIs, gRPC or serivce mesh as per your requirement.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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