1

Problem: Suppose there are two services A and B. Service A makes an API call to service B. After a while service A falls down or to be lost due to network errors.

How another services will guess that an outbound call from service A is lost / never happen? I need some another concurrent app that will automatically react (run emergency code) if service A outbound CALL is lost.

What are cutting-edge solutions exist?

My thoughts, for example:

  1. service A registers a call event in some middleware (event info, "running" status, timestamp, etc).
  2. If this call is not completed after N seconds, some "call timeout" event in the middleware automatically starts the emergency code.
  3. If the call is completed at the proper time service A marks the call status as "completed" in the same middleware and the emergency code will not be run.

P.S. I'm on Java stack.

Thanks!

2 Answers2

1

I recommend to look into patterns such as Retry, Timeout, Circuit Breaker, Fallback and Healthcheck. Or you can also look into the Bulkhead pattern if concurrent calls and fault isolation are your concern. There are many resources where these well-known patterns are explained, for instance:

I don't know which technology stack you are on but usually there is already some functionality for these concerns provided already that you can incorporate into your solution. There are libraries that already take care of this resilience functionality and you can, for instance, set it up so that your custom code is executed when some events such as failed retries, timeouts, activated circuit breakers, etc. occur.

E.g. for the Java stack Hystrix is widely used, for .Net you can look into Polly .Net to make use of retry, timeout, circuit breaker, bulkhead or fallback functionality.

Concerning health checks you can look into Actuator for Java and .Net core already provides a health check middleware that more or less provides that functionality out-of-the box.

But before using any libraries I suggest to first get familiar with the purpose and concepts of the listed patterns to choose and integrate those that best fit your use cases and major concerns.

Update

We have to differentiate between two well-known problems here:

1.) How can service A robustly handle temporary outages of service B (or the network connection between service A and B which comes down to the same problem)?

To address the related problems the above mentioned patterns will help.

2.) How to make sure that the request that should be sent to service B will not get lost if service A itself goes down?

To address this kind of problem there are different options at hand.

2a.) The component that performed the request to service A (which than triggers service B) also applies the resilience patterns mentioned and will retry its request until service A successfully answers that it has performed its tasks (which also includes the successful request to service B).

There can also be several instances of each service and some kind of load balancer in front of these instances which will distribute and direct the requests to an available instance (based on regular performed healthchecks) of the specific service. Or you can use a service registry (see https://microservices.io/patterns/service-registry.html).

You can of course chain several API calls after another but this can lead to cascading failures. So I would rather go with an asynchronous communication approach as described in the next option.

2b.) Let's consider that it is of utmost importance that some instance of service A will reliably perform the request to service B.

You can use message queues in this case as follows:

  • Let's say you have a queue where jobs to be performed by service A are collected.
  • Then you have several instances of service A running (see horizontal scaling) where each instance will consume the same queue.
  • You will use message locking features by the message queue service which makes sure that as soon one instance of service A reads a message from the queue the other instances won't see it. If service A was able to complete it's job (i.e. call service B, save some state in service A's persistence and whatever other tasks you need to be included for a succesfull procesing) it will delete the message from the queue afterwards so no other instance of service A will also process the same message.
  • If service A goes down during the processing the queue service will automatically unlock the message for you and another instance A (or the same instance after it has restarted) of service A will try to read the message (i.e. the job) from the queue and try to perform all the tasks (call service B, etc.)

You can combine several queues e.g. also to send a message to service B asynchronously instead of directly performing some kind of API call to it.

The catch is, that the queue service is some highly available and redundant service which will already make sure that no message is getting lost once published to a queue.

Of course you also could handle jobs to be performed in your own database of service A but consider that when service A receives a request there is always a chance that it goes down before it can save that status of the job to it's persistent storage for later processing. Queue services already address that problem for you if chosen thoughtfully and used correctly.

For instance, if look into Kafka as messaging service you can look into this stack overflow answer which relates to the problem solution when using this specific technology: https://stackoverflow.com/a/44589842/7730554

Andreas Hütter
  • 3,288
  • 1
  • 11
  • 19
  • Thank you! I'm on Java stack. If I correctly understand Hystrix is local library and if service A is down/lost then its Hystrix functionality got down/lost as well as Actuator. How another services will guess that an outbound call from service A is lost? I need some another concurrent app that will automatically react (run emergency code) if service A outbound CALL is lost, not service A at whole. Permanent health checking? It looks non-trivial... – Programmer2030 Jul 29 '20 at 05:53
  • Maybe I did not understand your problem completely at first. I think there are two problems you need to address here: the first one is making sure that a request **from service A** to service B is not getting lost if **service B is down**. Here you should apply the retry, timeout, circuit breaker, fallback, etc. patterns so that service A can robustly react to temporal outages of service B. – Andreas Hütter Jul 29 '20 at 06:09
  • Your other problem you are mentioning is that service A itself goes down and the request to service B that should be performed will never happen? Is that right? If so I will update my answer correspondly to address this problem as well. – Andreas Hütter Jul 29 '20 at 06:09
  • Yes, you are right. The first point (service B is down) is not interested to me. It can be solved via Hystrix. But the second point (request for service A will never happen) is theme of my answer. – Programmer2030 Jul 29 '20 at 06:14
  • I updated my answer to also address this problem with some suggestions. I also left my initial answer in place as I think it is also necessary to address the other problem as well. – Andreas Hütter Jul 29 '20 at 06:35
0

There is many way to solve your problem.

I guess you are talk about 2 topics Design Pattern in Microservices and Cicruit Breaker

https://dzone.com/articles/design-patterns-for-microservices

To solve your problem, Normally I put a message queue between services and use Service Discovery to detect which service is live and If your service die or orverload then use Cicruit Breaker methods

Dat Ho
  • 694
  • 3
  • 10