Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to deal with shared models in micro service architectures

My goal is to create an architecture in which services should be able to deploy independent of each other and are completely autonomous, but what do you do when you have 2 services that reads from DB the same object type?

In my case I have a socket server (micro service 1) and a http server (micro service 2). Using the http server my users creates an asset called: A, this asset gets stored on a DB and a mongoID is returned. Then, using another protocol and the ID, there are calls to the socket server that needs to check that validity of that ID, thus, needs to read from DB. This two services will have to share the model of A in order to map it to an object, but this means the 2 services will have to share code, and that's not ok.

Do I need another service? or should I make only service1 able to read from DB and then make the second one talks to service 1?

like image 963
DomingoSL Avatar asked Jul 24 '16 16:07

DomingoSL


People also ask

Should microservices share models?

They should not share any data between them, aside from an ID used for correlating the Authentication context's "User" with the other context's "User". They can each have their own representation of what a "User" is, and their own domain model, which just the information needed to perform their business responsibility.

Can microservices have shared database?

In the shared-database-per-service pattern, the same database is shared by several microservices. You need to carefully assess the application architecture before adopting this pattern, and make sure that you avoid hot tables (single tables that are shared among multiple microservices).


3 Answers

Microservices help solve the issue of coupling, to achieve that you need to keep your services/components autonomous, which means they can't share anything, not code assemblies or any resources, especially not the database.

If you need a read only copy of the data you can use patterns like publish subscribe to save a local copy of some information your component needs (subscribe to an event like NewUserCreatedEvent: new user was created and his id is this guid for example), there should be only one owner of the user data in the system and the owner is the only one who can modify the state of the data he owns, the rest of the components in the system can keep a local copy of reference data for read only purposes.

this asset gets stored on a DB and a mongoID is returned. Then, using another protocol and the ID, there are calls to the socket server that needs to check that validity of that ID, thus, needs to read from DB

In your scenario the client that creates the user should provide the id (a guid), the component that owns the user (therefore it's the one that creates it) will publish an event the other component (service) subscribes to and stores the data it needs in it's own database.

Does that make sense?

like image 177
Sean Farmar Avatar answered Oct 22 '22 11:10

Sean Farmar


... there are calls to the socket server that needs to check that validity of that ID, thus, needs to read from DB. This two services will have to share the model of A in order to map it to an object, ...

Well - no, they do not need to share code! The only thing they actually need, is a common understanding of the schema of the DB (I assume you're using MongoDB). Whether that understanding is coming from shared class definitions in shared libraries or from duplicated class definitions in separate libraries does not really matter. Many developers will now start screaming at me for violating the DRY (Don't repeat yourself) principle, but with microservices many things are different to what we're used to!

In her answer, Priti Singh states that:

Two microservices should not share same data model

which in correct in a microservice context and considered good practice! Let me show you why:

In the microservice pattern, services should be independant of other sevices and have well-defined interfaces. Having two different services reading the same DB makes that DB another "service" (I KNOW, weird, right?!?). By definition this database now needs a well-defined interface - which is kind of difficult in a schemaless DB ;-) Another reason not to make a DB act like a service is, that changes in one service will always have some influence on the other service accessing the data. This means, changing the "schema" on one service might force you to change another service as well, just to keep your system running! That's a headache when you consider a full-blown microservice system with >100 services.

That is why your second idea:

... or should I make only service1 able to read from DB and then make the second one talks to service 1?

is much better. Keep your database hidden behind a service with a well-defined interface that can be versioned. Like this you can refactor inside service 1 as your heart desires without necessarily influencing other services. Once you need to make a breaking change on your interface - give it a new version and start migrating other services to use the new interface.

The underlying controversy in your question is the one of Coupling vs. Duplication. Sharing an interface definition and database is coupling (the wakes-you-up-at-night-after-a-small-change kind of coupling) but duplicating the database schema to both services is duplication. I believe that coupling will kill you long before duplication does, but taking your second approach, having the http-service access the socks-service which then accesses the database should remove duplication as well as reduce coupling!

Let me know if this was helpfull!

like image 30
enzian Avatar answered Oct 22 '22 11:10

enzian


Two microservices should not share same data model. You can create a service which is solely responsible for managing data persistence, and can use it in other services.

like image 42
Priti Singh Avatar answered Oct 22 '22 10:10

Priti Singh