3

I am coming from a typical monolithic background and I've been experimenting a lot with Spring Framework. I have also build some simple microservices communicating with each other etc. Now I want to go a step forward and build my one more complex app based on microservices. Right now I am on the phase where I am doing my research on how to do that. I have a simple idea of composing an online shop app with, let's say , two microservices:

  1. Customer Relationship Service
  2. Order Management Service

What I don't still understand is how could those two services exchange information about customers. In a typical monolithic project I would have just relate a Customer entity with a Order Entity over a @OneToMany relationship, assuming a customer can have more than one order active. But how would this relationship work in a microservice environment without having to read the same data base ?

3
  • To whoever down voted my post, please state your critic, otherwise it doesn't bring much to the discussion and me personally. I would be more than happy to read your critical comment!!!! Mar 22, 2020 at 20:28
  • Just curious, are you trying to make the services communicate with each other to exchange information, or do you mean that the services hit the same data source, and you want to eliminate hitting the same data source twice? Mar 22, 2020 at 20:56
  • In other word, can two different entities in two different microservices have a relationship like @OneToMany and locate each one in different data bases? Or should just the Order entity communicate with the customer service just to get the details of a customer like name etc. ? Mar 23, 2020 at 15:28

3 Answers 3

1

A company might have a People table in which those people's social security number (or any other government-issued identifier) is listed. That identifier is the PK (or functional equivalent) of some government database somewhere. But the company does not have access to the government database. The company's application uses the identifier without direct access to the fovernment's database, and you really wouldn't want everyone who uses that identifier to all have access to the government's database, right?

So how can it trust that the identifier that the user entered exists and is correct? Well, it could fire off a request to the government API to verify the identifier.
While this maybe does not fit the current example scenario very well, your frontend UI could also have asked the government API a list of all people (with their identifiers), had the user select the correct person, and then the frontend would know which identifier to send to its backend service.

Your Customer and Order microservices will behave very similarly to the above example.

What I don't still understand is how could those two services exchange information about customers.

Only the customer microservice deals with customer information. That's why it's the customer microservice.

The order microservice does not deal with customer information except an identifier, something that uniquely identifies a particular customer. While a PK seems to fit the bill here, it's generally advised to not use a DB-related value as it causes tight coupling.

Let's say you're on the webpage where (eventually) an order will be created. You'll already know who your customer is. So when you click the "Place Order" button, obviously you should be able to POST a request to the order microservice and include the customer's identifier. The order microservice then uses that identifier as simple data that it adds to its order entity.

If, for whatever reason, the order microservice needs to know the full name of the customer who placed order 123, then it will have to query the customer microservice using the customer identifier in order to find out the customer's details.

But how would this relationship work in a microservice environment without having to read the same data base ?

I hope the above explanation already helps shift your expectation here. There should not be any FK constraint between the Customer and Order tables, because they're in different microservices.

What's more, you shouldn't even be using the same database for multiple microservices. Each microservice manages its own data and therefore it should be given a private data storage that cannot be directly accesses by anyone but the microservice. If anyone else needs to know any of that data, they need to come through the microservice's API and have the microservice be the one who interacts with its database.


Overall, I think you need to read up on microservices to a greater extent than you already have. You seem to understand the separation of different contexts well (Customer vs Order), but your implicit reliance on an underlying shared datastore suggests that you don't really understand what microservices aim to achieve and how they achieve it.

A total separation of each microservice's private resources lies at the heart of the microservice architecture. If you infringe that core concept, which is technically perfectly possible to do, you will lose out on the major benefit of having a microservice architecture. Your not-really-a-microservice approach will most likely end up being something that cost you more effort than the benefits you gained from it.

This answer is a basic reframing of your interpretation of a microservice, a proper readthrough of an actual learning resource will tell you more than I can in this answer.

0

Based on our brief comments, I believe that I have more of an understanding of what you are trying to achieve. In short, yes you can have them as two separate databases.

The part that might be making it confusing is that you are trying to look at this from the perspective of the services first. The piece is defining how to relate the data based on two or more data sources.

Working with Orders and Customers, it makes sense that an Order can hold some reference to a Customer. If the intent is that the Order data source should not know about the Customer data source, then there is an extra layer/lookup concept to define.

That could look something like:

Order database/data source

CREATE TABLE Orders
(
    OrderId
    , OrderCustomerId
    -- other relevant order information
)
CREATE TABLE OrderCustomerLookup
(
    OrderCustomerId
    , ExternalCustomerId
    -- whatever makes sense here
)

Customer database/data source

CREATE TABLE Customer
(
    CustomerId -- this would be ExternalCustomerId in the Order database/data source
    -- other relevant customer information
)

If that was a route that you did not want to go, then you could still have the Customer Id being read into the Order database where it would look like:

Order database/data source

CREATE TABLE Orders
(
    OrderId
    , CustomerId
    -- other relevant order information
)

Customer database/data source

CREATE TABLE Customer
(
    CustomerId -- this would be CustomerId in the Order database/data source
    -- other relevant customer information
)

You can do this explicitly from the databases, but that might be a whole other discussion itself. One thing I see due to corporate/policy type limitation is having the calling application handle the link/relation, and this can bridge into incorporating those services. One of the ways, as you brought up, is having the the service for Orders making a call to the service for Customer data, and that gets into a chained pattern of using services.

That may feel a bit coupled, but it can be the right solution depending on the overall requirements as a product which could be a little out of scope here. If there are any requirements to incorporate more separation, then I would be wary to not fall back into the same monolithic design. For instance, having the application call the Order service then make a call to the Customer service based on the data retrieved in the Order service response. You are pretty much back to the monolithic design, but the entities are now services instead of plain objects.

Let me know if I misunderstood anything, or anything appears to be misstated.

0

TL;DR: couple to API's not databases. Turn transactions into business problems and err on the side of inconsistency (unless you're a bank).

To answer the question you asked exactly: you can initiate a remote db connection, and lock another db row or table(s). But you shouldn't. That isn't a microservice - it's a distributed monolith, and that is worse than a non-distributed monolith.

Part of microservices is about loose coupling and high cohesion (at a macro level) - so the goal is to have things that belong together in the same Microservice (to reduce the number of times where you need something that looks like a lock on two tables in difference services.

You can do a simple query but then you still couple yourself temporally to between services - so I believe best practices now is reactive microservices which communicate through message passing/ eventing.

But this makes our previous model of monolithic software development more complicated because you if you think in terms of CustomerA must update at the same time as OrderA for that customer, then you are thinking in terms of transactions and distributed transactions open a whole can of worms and issues with distribution - availability - even the software development of services being coupled to one another. The last sentence might not make much sense, but I'm trying to say that with microservices you want to also be able to have development each service loosely coupled to the development of other ones.

This is part of the conversation that DDD tries to address as well. They say that you should avoid distributed locks - and make sure that absolute consistency is completely necessary. For instance, for making orders - what happens if two people from the same customer order two different items exactly the same time? Our history is inconsistent, maybe we have a loyalty program that will incorrectly calculate points. As developers we often think in binary - "That would be wrong" but in fact it's a business question. It's easy to ask "Is this problem in our system worth 40 thousand dollars?" Because that may be how much extra dev work it takes to create and maintain this extra constraints because coupling will have a permanent consequences.

In reality if the business bonuses everyone who complains with $10 in free credit, it might happen 10 times - cost the business $100 and you'll not have to fix that problem ever. This isn't an article but maybe I'll take more time and write one instead - since this requires more thought to articulate well.

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.