G
G
Gennady Kruglov2021-10-06 10:18:12
C++ / C#
Gennady Kruglov, 2021-10-06 10:18:12

Can anyone help me figure out asynchronous communication between microservices?

I will give a spherical example from my head to make it clearer:

Let's say we have two microservices with their own databases. The first one is used to fill in the data, the second one is used to form a PDF for printing from this data.

The first microservice creates a student card, fills it with personal data and attaches a photo. In other words, there is a WEB API and three methods that are called in the next. in order:

1. CreateStudentCard()
2. PutPersonalData()
3. PutPhoto()

In the first CreateStudentCard() method, a student card is created, its ID is generated and saved to the database with this ID as a primary key.
In the remaining two methods, using the received student card ID as a foreign key, we save in other resp. tables personal data and photos.

In each of these three methods, after saving to the database, an event is sent to the RabbitMQ bus using the MassTransit library. In the first method, after the card is saved to the database, the StudentCardCreated message is sent, which contains the card ID and creation date. In the second method, respectively, sending the PersonalDataUpdated event with the student's data, in the third PhotoUpdated with a photo.

In the secondmicroservice, we are subscribed to all these three events. In other words, there are three asynchronous Consumers that will receive these three messages asynchronously in order to create a student card in their database with the same ID as in the source microservice, and attach personal data and photos to it.

And here the crux of the matter begins:

Each asynchronous consumer-consumer in its implementation has methods for accessing the data context that are also asynchronous (in particular, the LINQ methods of EntityFramework).
And here is the first consumer that listens for the StudentCardCreated event and receives the message. Inside it, before immediately taking and saving the incoming card, we call some kind of asynchronous method to check something in the database using await (let's say AnyAsync). As soon as await is called in this consumer, control will return to the calling thread, which will immediately pick up the next event from the queue and call the consumer for the second PersonalDataUpdated message.
In this case, there is a risk that the consumer for PersonalDataUpdated will reach saving to the database before the student card itself is created in the consumer for StudentCardCreated, which, of course, will lead to an error, since we need the card ID as a foreign key, because we We cannot attach data and photos to a card that does not exist in the database.

I think that I do not fully understand the logic of working with a broker or how asynchrony works in this case. Maybe someone will be able to suggest how such situations are resolved correctly and maybe such an approach is generally fundamentally wrong?

I sketched in paint a diagram of what I mean. The arrows and numbers indicate the procedure as I see it:
615d65c280b84125174838.png

Answer the question

In order to leave comments, you need to log in

2 answer(s)
S
Sanes, 2014-11-16
@Sanes

add http: often helps

D
Dima Pautov, 2014-11-16
@bootd

How do you specify the icon itself?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question