14

I am dealing with communication between microservices.

For example (fictive example, just for the illustration):

  • Microservice A - Store Users (getUser, etc.)
  • Microservice B - Store Orders (createOrder, etc.)

Now if I want to add new Order from the Client app, I need to know user address. So the request would be like this:

Client -> Microservice B (createOrder for userId 5) -> Microservice A (getUser with id 5)

The microservice B will create order with details (address) from the User Microservice.

PROBLEM TO SOLVE: How effectively deal with communication between microservice A and microservice B, as we have to wait until the response come back?

OPTIONS:

I don't know what will be better for the performance. Is call faster via RabbitMQ, or RestAPI? What is the best solution for microservice architecture?

David Pavelka
  • 373
  • 1
  • 5
  • 11
  • It depends on the requirement for this application. Hard to answer from a fictive example. To me it sounds like add order could be async. It could also be the case that service B already knows about the users in the system - from say reading events, then it is just an in memory lookup. – Jocke May 21 '18 at 20:56
  • 1
    In my opinion, storing users in some memory might be memory consuming. And isn't it anti-pattern to store other microservices data? Do you think, that with this being said, the best option is HTTP? – David Pavelka May 22 '18 at 05:55
  • Yes, in that case. HTTP. – Jocke May 22 '18 at 18:41
  • 1
    If you want to do it with API, i strongly recommend you to use gRPC instead of http. It's very faster. But also AMQP is very fast, because of the always-connected nature. – Amin Shojaei Aug 12 '20 at 10:08

3 Answers3

9

In your case using direct REST calls should be fine.

Option 1 Use Rest API :

When you need synchronous communication. For example, your case. This option is suitable.

Option 2 Use AMQP :

When you need asynchronous communication. For example when your order service creates order you may want to notify product service to reduce the product quantity. Or you may want to nofity user service that order for user is successfully placed.

I highly recommend having a look at http://microservices.io/patterns/index.html

Foolish
  • 3,952
  • 33
  • 46
5

It all depends on your service's communication behaviour to choose between REST APIs and Event-Based design Or Both.

What you do is based on your requirement you can choose REST APIs where you see synchronous behaviour between services and go with Event based design where you find services needs asynchronous behaviour, there is no harm combining both also.

Ideally for inter-process communication protocol it is better to go with messaging and for client-service REST APIs are best fitted. Check the Communication style in microservices.io

REST based Architecture

  • Advantage

    1. Request/Response is easy and best fitted when you need synchronous environments.

    2. Simpler system since there in no intermediate broker

    3. Promotes orchestration i.e Service can take action based on response of other service.

  • Drawback

    1. Services needs to discover locations of service instances.

    2. One to one Mapping between services.

    3. Rest used HTTP which is general purpose protocol built on top of TCP/IP which adds enormous amount of overhead when using it to pass messages.

Event Driven Architecture

  • Advantage

    1. Event-driven architectures are appealing to API developers because they function very well in asynchronous environments.

    2. Loose coupling since it decouples services as on a event of once service multiple services can take action based on application requirement. it is easy to plug-in any new consumer to producer.

    3. Improved availability since the message broker buffers messages until the consumer is able to process them.

  • Drawback

    1. Additional complexity of message broker, which must be highly available
    2. Debugging an event request is not that easy.
Yogendra Mishra
  • 2,399
  • 2
  • 13
  • 20
3

Personally I am not a fan of using a message broker for RPC. It adds unnecessary complexity and overhead.

How do you host your long-lived RabbitMQ consumer in your Users web service? If you make it some static singleton, in your web service how do you deal with scaling and concurrency? Or do you make it a stand-alone daemon process? Now you have two User applications instead of one. What happens if your Users consumer slows down, by the time it consumes the request message the Orders service context might have timed-out and sent another message or given up.

For RPC I would suggest simple HTTP.

There is a pattern involving a message broker that can avoid the need for a synchronous network call. The pattern is for services to consume events from other services and store that data locally in their own database. Then when the time comes when the Orders service needs a user record it can access it from its own database.

In your case, your Users app doesn't need to know anything about orders, but your Orders app needs to know some details about your users. So every time a user is added, modified, removed etc, the Users service emits an event (UserCreated, UserModified, UserRemoved). The Orders service can subscribe to those events and store only the data it needs, such as the user address.

The benefit is that is that at request time, your Orders service has one less synchronous dependency on another service. Testing the service is easier as you have fewer request time dependencies. There are also drawbacks however such as some latency between user record changes occuring and being received by the Orders app. Something to consider.

UPDATE If you do go with RabbitMQ for RPC then remember to make use of the message TTL feature. If the client will timeout, then set the message expiration to that period. This will help avoid wasted work on the part of the consumer and avoid a queue getting backed up under load. One issue with RPC over a message broker is that once a queue fills up it can add long latencies that take a while to recover from. Setting your message expiration to your client timeout helps avoid that.

Regarding RabbitMQ for RPC. Normally we use a message broker for decoupling and durability. Seeing as RPC is a synchronous communication, that is, we are waiting for a response, then durability is not a consideration. That leaves us decoupling. The question is does that decoupling buy you anything over the decoupling you can do with HTTP via a gateway or Docker service names?

Vanlightly
  • 1,389
  • 8
  • 10
  • Thank you for your submission. RabbitMQ is as standalone microservice in Docker. But you are right, that for the timeouts, and these things, HTTP might be worth using. I like the idea about catching events, but there is problem, that microservice order could shut down, and than he doesn't have that user inside his database. Also it is quite anti-pattern in terms of microservice, which is ment to do only one thing. – David Pavelka May 22 '18 at 04:59
  • Well, RabbitMQ is a durable message system. That is one of the points of using it. If one service is down then no problem, you can consume the event when the service comes back up. We get reliable messaging in the face of transient consumers. – Vanlightly May 22 '18 at 07:16
  • Also this "anti-pattern" is quite a common pattern in microservices. I'm not sure where you got that idea. I would say a larger anti-pattern is to have direct coupling with multiple other services, you're on the road to a distributed monolith. Also think about what happens when the Users service is unavailable, sure you can use your retries and circuit breakers, but that won't help if it is down for a few minutes. When the data is already local to your service, you get better reliability and lower latency. It has trade-offs but I don't think you could call it an anti-pattern. – Vanlightly May 22 '18 at 07:20
  • Ok, that sounds reasonable. I am fighting with duplicating databases over the microservices. I don't know if it is the best idea. If you think of what have to be done is, that models from Users must be in the Order and also there have to be event handling. If there is more services like order, that need some data from Users, than this might be a nightmare. Not counting other services that might have data as users. And not counting that Users datacontext might be changed over time. – David Pavelka May 22 '18 at 08:11
  • If the service goes down, there is load balancer, that recognize that and redirect communication to the other instance. So, hopefully everything is good to go with synchronous calls. For these calls is better HTTP? – David Pavelka May 22 '18 at 08:15
  • Let's come at it from another angle. It's about weighing the trade-offs. So identify what a message broker offers you that HTTP cannot, and vice-versa. With a list of benefits and drawbacks make the decision. So what does a message broker give you in this scenario that HTTP does not? – Vanlightly May 22 '18 at 09:18
  • Yes, it does give me everything as HTTP. If I want to call something synchronous, I can do it via RPC (supported by RabbitMQ). What is important for me is speed. I don't know, which one will response faster (HTTP, or RPC). So you would preffer RPC? I need to decide between these two. – David Pavelka May 22 '18 at 10:02
  • 1
    The last thing I'll say this is. Forgetting all the other trade-offs, if speed is your number one priority then I'd recommend running a benchmark to see which one is faster in your case. Make sure you use non-persistent messages for RabbitMQ. I have used ZeroMQ on a previous project and the performance was phenonmenal at the cost of some extra complexity. Also look at GRPC if your tech stack supports it. – Vanlightly May 22 '18 at 10:51