Communication between two microservices
Asked Answered
C

6

50

I am creating a project with microservices architecture. And I created two microservices.

One of them is for product entity, the other is for bill entity. They have their own endpoints and they are connected together with the gateway (i am using jhipster microservices architecture).

The bill-ms should access to list of products. I'm wondering how I can communicate between those two ms. I have three approaches in my mind:

  1. Send a request from bill-ms to queue - like rabbitMQ, to get these products with these ids from product-ms (I don't know what is bottleneck of this)

  2. Send a request to gateway for product service and get the product from there (I'm worried about the latency because of the data size between them and in this way I'm not touching the database directly so I always depend on the gateway)

  3. I can duplicate the repositories, services and entities in bill-ms (it's an ugly way, and I think it breaks the rule of ms-architecture and the maintenance is very difficult)

If you have any other approaches, I appreciate you to share it with me.

Edit

  1. Now I know what the bottleneck is: say that there are 3 instance of bill-ms and how does rabbitMQ decide which instance to respond? or how should I say to ribbon "give me the free instance of bill-ms to subscribe to the request from rabbitMQ" for load balancing.
Christenechristening answered 18/4, 2016 at 17:58 Comment(5)
You could also reconsider your services boundaries, maybe your services are too fine grain. Also duplication may not be bad thing, if you consider that your products may disappear or may be modified in their database while in the bill you want them to stay unchanged for a long time, in this case I would nto consider this a s a duplication but only storing the immutable infomration about product that your bill need.Appliance
"i am using jhipster microservices architecture"..JHipster is just a library which hasn't its own architecture..Quarrier
Jhipster is not a library, it's an application generator which happens to implement microservices architecture on top of spring cloud netflix.Appliance
So the bigger question is here: why do you want to go the microservice way when you actually have the problem of making data available to each other? I'd rather suggest start with a properly modularized monolith. Never do option 3 cause then you don't need microservices at all. And don'T get afraid of option 2, the spring netflix world has a ton of solutions to the upcoming problems (eureka, feign, ribbon, hystrix, ...)Tumid
Either using a load balanced (by Ribbon) discovery client to fetch an instance of product-service, or option 3 mentioned above seems better options. Duplicating data should be fine as long as only one service (owner) modifies it, and other services keep immutable copy of the same. Rabbit MQ can be used to keep the duplicate data in sync.Oft
S
47

I'm not sure if what I am going to answer is thé right way. I'm still learning myself.. But I can tell you how I've implemented my microservices attempts..

First, I started with HTTP communication based microservices using this blog. This works fine, but the problem is, that you create dependendies between your services. Service A needs to be aware of a service B and needs to call it directly (via service discovery etc of course). This is what you generally are trying to avoid when developing microservices.

Another approach that I've started with lately, is using a message bus. It's actually the 3rd option that you touched in your question.

I have a service A, which stores persons (just an example). What the service does when it creates a new person is: It sends an event on a RabbitMQ bus: personCreatedEvent. If there are any other services interested in events like this, they can subcribe to them. These interested services keep the relevant information that they are interested in, in their own datastores.

With this last approach, there is not really a dependency between your services, because they don't communicate with each other directly. Service A is not aware of service B, because B just sends events to RabbitMQ to whichever service is interested to these events and vice versa.

Of course, you have duplications between datastores over the service. But this can be profitable as well, e.g. service B doesn't need to use the same schema or data store mechanism as service A. It only stores the relevant information in the way that is best for this service.

Shien answered 18/4, 2016 at 18:22 Comment(4)
This publish/subscribe Design Pattern is a very good approach.Pathogen
As I understood from your suggestion, I will use just the attributes of the product entity which I need. That's why I'm planning to create a DTO for this, and the product entity is held in product-ms. Is it a good approach to keep all the data in one microservice and get the data as dto from rabbitMQ? Did I understand you correctly? @LuxoChristenechristening
If your bill-ms needs access to the products. The product-ms needs to publish events on the RabbitMQ bus like "ProductCreated", containing the product itself. Since the bill-ms is subscribed to these events, it will receive the events, and save the parts of the entities (of the product in this example) in it's own datastore. @ChristenechristeningShien
@Shien If the point is to develop each microservice in isolation, how does this work for developers? If bill-ms depends on product-ms, in development bill-ms would never receive these events. Pretty sure I'm missing something important here.Glower
H
2

Have you looked at http://stytex.de/blog/2016/03/25/jhipster3-microservice-tutorial/ Part 2: inter-service communication section. It walks you through a specific example of how it is achieved

Hammurabi answered 10/5, 2016 at 6:37 Comment(0)
T
2

In general, you have two good options to communicate microservices and also several more to avoid as possible:

  • Don't use shared db's
  • Don't use FTP file sharing
  • Don't use in-memory shared databases
  • Don't use CSV or the kind

What to use:

  • Option 1 (the best): Use a queue system to share messages, so if Microsoervice B needs some information from Microservice A, A will send a message to the queue and B will consume it. This is the most resilient solution as, if B is down, it will consume the message anyway when it recovers.
  • Option 2: Use a RESTFul endpoint, you can call from A to inform B or from B to get information from A. The problem is that, if the receiver is down or failing, the request will break and you will desync. You need to implement a circuit-breaker then to avoid losing it.

You may find more information on how to communicate microservices properly in my article on Communicating microservices the proper way.

Tunny answered 20/2, 2023 at 8:17 Comment(0)
B
0

Let me try and add some more details to this scenario to stress what may or may not qualify as an event in the context of Product and Biiling. The Billing-MS would need to talk to Product-Ms only in case an Order is placed. Placing an Order would mostly be for a separate MS let's say Order-MS. When an order is created or placed, it will contain information of Products as line items.

Creation of an Order can be considered as an event. When Order creation event occurs, it can be pushed to a Queue for the Billing service. Queue should be implemented as a Work-queue in RabbitMQ. This way, multiple instances of the Billing-MS can subscribe to the same Queue but it'll be processed by one and only one Worker. There is no role of RIBBON in registering a service as a Worker to RabbitMQ. Each instance registers to a Queue and RabbitMQ decides RoundRobin which instance of Billing Service gets to process this event.

Getting details of Products in an Order for the Billing-Ms should be a Service-to-Service call load balanced via Ribbon (if that's what you are using). Getting Product details is not really an event, placing an Order is, hence the difference.

Also, Gateway should be used for exposing your Edge services. For Service-to-Service calls, it would not be ideal to hop via Gateway service.

Biocatalyst answered 18/5, 2016 at 3:44 Comment(0)
H
0

One option is sending a request to bill microservice using it's registred name on the eureka registry.

Hettiehetty answered 22/6, 2018 at 9:4 Comment(0)
A
0

you can use below solution : Microservice A (i.e UAA-SERVICE), and Microservice B. Microservice B want to connect microservice A and call services with Feign client.

1)This code for Microservice B

@AuthorizedFeignClient(name = "UAA-SERVICE")

public interface UaaServiceClient {

@RequestMapping(method = RequestMethod.GET, path = "api/users")
public List<UserDTO> getUserList();

@RequestMapping(method = RequestMethod.PUT, path = "api/user-info")
public String updateUserInfo(@RequestBody UserDTO userDTO);

}

UAA-SERVICE : find this name with running Application Instances with registry.

2) In Microservice B (application.yml) Increase feign client connection Time Out------> feign: client: config: default:
connectTimeout: 10000 readTimeout: 50000 enter image description here Increase hystrix Thread time out-------->

hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 60000 shareSecurityContext: true

enter image description here 3) add @EnableFeignClients in main @SpringBootApplication class.-------> This solution is working fine for me.

Antecedency answered 3/7, 2021 at 9:39 Comment(1)
Provide relevant descriptions for the images attached for better clarity for the reader on what they are going to seeJamiejamieson

© 2022 - 2025 — McMap. All rights reserved.