Which microservice ends transaction in Choreography Based Saga Pattern? - microservices

Each microservice sends an event to next microservice to run their local transactions in choreography based saga pattern. So, which microservice ends transaction? Last microservice which has no next ends and aprove transaction or last microservice sends OK to first starting microservice to commit overall process?

The choreography means that services knows about their counterparts and decides from what is outcome of other services. No communication with some "central coordinator".
If we say the A communicates to B which communicates to C (A -> B -> C) then A does some action asks for outcome of B, B does some action and asks for outcome of C and C does some action. The outcomes go in opposite way (A <- B <- C).
Let's expect that all service actions were successful. Thus C persists data and responds to B that the task was successful done and outcome is OK. B knows there is no other services that it waits for and the saga step can be validated as successful at B. Then it responds to A of success and A knows there is no other service to wait for and may ends its saga step with success as well.
The example of two services communicating over queue can be found at https://microservices.io/patterns/data/saga.html

Related

A distributed sequence of actions over services that can horizontally scale

I have a microservice distributed sequence of action. Service A needs to tell service B to do something and once that is complete it will tell service C. The sequence is important so I'm using the saga pattern as you can see.
My issue is that service B can scale and each instance needs to receive the message and complete the action. The action must happen on every service B instance. Then service C should only run once all the service B instances have completed their task.
It is a cache purge that must happen on each instance. I have no control over this architecture so the cache for service B is coupled to each instance. I would have a shared cache for the instances if I could.
I have come up with this orchestration solution but it requires maintaining state and lots of extra code to handle edge cases which I would like to avoid.
service A sends the same message to all service B instances which it knows about
all service B instances send success to service A
On the final service B success, service A messages service C
Is there a better alternative to this?
Assuming that you can't rearchitect service B, you've captured the essential complexity of the operation: A will have to track instances of service B and will have to deal with a ton of edge cases. The process is fundamentally stateful.
If the cache purge command is idempotent (i.e. you don't care if it happens multiple times in the process) you can simplify some of the edge case handling and can get away with the state being less durable (on failure you can start from the beginning instead of needing to reconstruct where you were in the process).

Does each microservice's local transaction affect database immediately in saga pattern?

is each microservice's local transaction persistent in Saga pattern. For example, microservice A completed its transaction and sent an event to microservice B and are microservice A's operations affect database immediately which results with inconsistent state or do they affect after last microservice's OK event?
The point of the Saga pattern is to work with no blocking. If the state of the local transaction of A would be driven by the last microservice outcome (i.e. by B) then the A would be waiting for the result of B. Then the A would be blocked in processing in some way.
For the saga pattern the local transaction is applied immediately when the microservice finishes its work. If failure happens the saga then ensures the A is informed about that outcome and A is responsible to compensate the work being done. That could be for example deleting the persistent record. The microservice A could for example persist the outcome of the local transaction with some flag (like "saga in progress") and does not consider such item until the saga is finished as whole (then switching the flag to something like "finished").

How to make dependent microservice calls async?

How to make microservices call async when microservice B depends on the response of A and microservice C depend on response B?
You should avoid chaining calls from one microservice to another in order to fulfill a client's request. It doesn't matter if the calls are synchronous or asynchronous. This can lead to cascade failures so the availability of the system is affected.
Instead, you should gather all the needed data in background (i.e. using cron or events) before the clients' requests. In this way, if service A is down, service B continues to work.

Microservice deployed - initial data migration

Let's say that we have microservice A (MS A) and Microservice B (MS B).
MS B has data about Products. MS A needs the productnames of MS B.
Each time a product is added, updated or deleted, MS B puts a message on a message queue.
MS A is subscribed to that queue, so it can updated it's own internal state.
Now my question:
How do we fill the internal state of MS A when we deploy it to production the first time?
I couldn't find any documentation about the pros and cons of the possible solutions.
I could think of:
Export/import on database level.
Pros: not much work.
Cons: can miss data if during export/import changes to the data of MS A are made.
Implement calls for GetData and GetDataChangedSince
Pros: failsafe
Cons: a lot of work
Are there any other options? Are there any other pros/cons?
You could use the following workflow:
prepare the microservice B to push the events to the queue or stop it if it is already pushing to the queue; instead, it pushes to a circular buffer (a buffer that is rewritten when full) and waits for a signal from microservice A
deploy the microservice A into production servers but you don't reference it from nowhere; it just runs, waiting for events in the queue
run a script that get all product names from microservice B and push them into the queue as a simulated event; when it finishes the product names it signals the microservice B (optionally telling the date or sequence number or whatever de-duplication technique you have to detect duplicate events)
microservice B then copy the events from the buffer newer that the last pushed by microservice A (or it finds out itself from the queue what is the last one) into the queue and then ignores the buffer and continue to work as normally.
It sounds like there is a service/API call missing from you architecture. Moving a service into production should be no different than recovering from a a failure and should not require any additional steps. Perhaps the messages should be consumed from the queue by another service that can then be queried for the complete list of products.

Spring integration acknowledge message processing back to previous service

In Spring Integration, I have a chain of services, like this:
message -> A -> B -> C -> D -> ... -> output
This works fine. I want to make each of the services asynchronous and to make them pessimistic. Each of them will get a message, process it and send it to the next service in chain. However, it will not wait till the whole chain finishes. It will continue processing the next message and so on. Standard async here.
However, let's say service B is slower than A and that it accumulates 10k messages in its inbound channel queue and at that time the system crashes. I want to be able to restore the system by figuring out where I left and re-processing the messages. For that reason, I want each of the services to know which of the messages it processed was successfully consumed by the following service. The difference between sent vs. processed.
My idea is to do it similar to this (fancy ascii):
-> A --> B -> C -> ...
^ |
| ack |
\-----/
That is, A will send to B, B will process and when it is done successfully it will send an ack to A. A will then remove that particular message from the store, so that the next time it runs, it will not re-process it. I thought I would just put a splitter after B that will call a different method on service A (i.e. ackProcessed).
Is this how it should be done in SI or is there another way I'm missing? I'm primarily asking for a confirmation I'm not missing something supported out-of-the-box or something that will not force me to create a splitter after each of the services.
It wouldn't be a splitter; more likely a pub-sub channel and the ack would probably want to go to a different method in A (i.e. a different service-activator that references the same bean, different method; and the methods share some state).
An easier solution would be to use a persistent message channel (e.g. JMS, RabbitMQ, or a message-store-backed QueueChannel). That way the framework will take care of everything for you.

Resources