2

I’m reading about microservices and a consistent message I’m getting is that microservices should communicate via asynchronous means only. But I don’t see how this can work while also providing feedback to the user?

Taking an e-commerce application as an example, we may have an OrderService and a PaymentService. The client makes a request to the order service to complete the order, which in turn makes a request to the payment service to process the charge.

However, if the request to the payment service from the order service is asynchronous, how do we tell the user whether their order was successful, as the client is expecting a synchronous response from the order service?

2
  • 2
    microservices should communicate via asynchronous means only Says who? Can you share some links? Maybe I am out of touch but that strikes me as absurd.
    – John Wu
    Commented Aug 2, 2019 at 0:01
  • There was a famous tweet starting this discussion. See here for a more in-depth clarification. Meanwhile, you can find good resources discussing pros and cons of both approaches
    – claasz
    Commented Aug 2, 2019 at 8:33

4 Answers 4

2

All communication to web servers is already asynchronous... Because they are using a computer network. The client makes a request, it goes to the network, and eventually, a response arrives.

You can have asynchronous code be multithreaded, and you can have it single threaded. You could convert something synchronous into something asynchronous by using continuations, coroutines, or a second thread. Usually accessing an external system is asynchronous, being the main example anything across the network. However, it is also possible to access permanent storage asynchronously, and similarly inter-process communication. Furthermore, if you need timers, it also makes sense to make them asynchronous (otherwise, you just have a thread sleep).

Furthermore, if you are using a second thread, you can convert something asynchronous into something synchronous by having a thread block until a response is ready.

Why don't we do that for the network? If we were talking of a multithreaded environment, we could afford to have one block on the network. Right? Well, we don't do that because we want to Keep the UI responsive, that means that the UI thread will keep running, and... wait, it needs to talk with the network thread... and it will do it asynchronously.

So, you can design your microservices as synchronous. However, due to the network, they will eventually be asynchronous, usually without any extra effort on the microservices part.

Finally, if the user is expecting a response, do not block the browser... make the browser put a up something that says please wait, loading, or something like that, and when the browser receives the response it can take it out and display the response.

Note: Promises on JavaScript are based on continuations. On the other hand the async/await pattern converts the code into continuations. With these and similar tools, writing asynchronous code is easier.


Should you use WebSockets? Not necessarily. You can perfectly implement this over Ajax Fetch on a traditional Web API. I would only recommend WebSockets if the server needs to initiate an action (for example if the client needs to receive notifications). However, if everything the server sends is in response to a request of the client, then there is no need for that.

Note: If you need a quick notification of something being received over the web... first remember that if it cannot reach your server, it will have neat error HTTP status, and second, if you insist, the server can send partial responses. So ti can say HTTP status 200, but keep the connection open for more data until it is available.


By the way, you can implement continuations over the network. Evidently you cannot send a function over the network, however, you can send and id of a function... so, if the application allows you to – for example – write a product review regardless of whatever or not you are logged in, and when the user press submit, it checks and sends the user to log in... you can store submitting the product review in a continuation, so that after the user logged in, the product review can be submitted.

For more on that idea, see Defunctionalize the continuation (The Best Refactoring You've Never Heard Of)

1

I think you have a misconception about what asynchronous means. Almost all communication to web servers from browsers is already done asynchronously, because JavaScript only has one thread. Yes, the request and response are correlated together, but any number of things can happen between the request and the response, and while the response is outstanding, it consumes no threads and no CPU time. Just a tiny amount of memory. Likewise on the server, while it is waiting for a response from other microservices, very few resources are consumed.

There is a more decoupled form of asynchronous architecture called event-driven programming that is gaining popularity in microservices applications. From the user client point of view, there is very little difference, though. Instead of a completeOrder function being called when the original request is acknowledged, a completeOrder function gets called when a CompleteOrder event is received later over another channel.

2
  • 2
    Almost all communication to web servers is already asynchronous, because JavaScript only has one thread. -- That's not the correct correlation. Single-threaded-ness is not what makes something asynchronous. Commented Aug 2, 2019 at 1:59
  • Single-threadedness doesn't force something to be asynchronous, but it does make it very annoying to use synchronous network calls. I'm using "because" in the sense that it's a compelling reason why programmers nearly universally choose to make their applications async. It's a human preference "because", not a technical requirement "because". Commented Aug 2, 2019 at 2:35
0

Typically you'd want to use something like WebSockets to send your request from the OrderService to the PaymentService.

The PaymentService would immediately send back a reply saying it received the request for payment. It would then (for example) forward the request to the bank, and probably send the OrderService another message saying the payment request was submitted to the bank. Eventually it gets a reply from the bank saying either the payment cleared or it didn't. It then sends another message back to the OrderService to tell it that final status.

Presumably, the OrderService would be forwarding those updates to the client, and some code on the user's machine would be updating his display from "received" to "sent to bank" to either "paid" or "failed" (or whatever). Might happen too fast to actually see all those, but then again, it might not.

0

how do we tell the user whether their order was successful, as the client is expecting a synchronous response from the order service?

In case of a web application, you could e.g. have a text "Payment: pending" being displayed when the order service responses. Then, you would use a JavaScript poll function periodically asking the order service whether payment is complete. Once it returns "completed", turn the text into "Payment: accepted".

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.