-1

I'm working on a big C# application that is currently under development so we have some room for structural refactoring.

The application is divided into 10 microservices, which some of them communicate with each other.

That intercommunication is done via 2 different approaches at the moment: A) using Apache Kafka as an event bus and B) creating an internal facade/service-object approach when need to request some data from another microservice. I want to focus in the later approach.

This facade/service is done by literally copying all the important data types definition and having the HTTP requests hard-coded inside each project (ie. we have local copies - duplicated - of each type related to a given microservice request/response inside each microservice project that needs to communicate with it).

I'm not very well versed in microservices and Rest API, but this seems to me a recipe for disaster. If microservice A is requested by 5 other microservices, and we change A's API, now we need to update all other 5 microservices projects with all the new data types or changes that was made rather than having some sort of shared library with that facade or something like that.

I know managing API versioning is difficult and painful, but this certainly doesn't seem right to me.

I didn't find a straight forward guide that addresses a problem like this.

Can anyone shed some light on this? How should we manage those duplicated data type definitions? And lastly how should we manage versioning properly between those different APIs?

7
  • 2
    What you normally do is if you have breaking changes in your API you make a new version and support the old version for a while until all microservices had the change to switch to the new API version.
    – Darem
    Commented Jul 14, 2021 at 5:40
  • 2
    I would suggest being very careful with inter micro-service communication. One point of microservices are independence, if they are not independent you loose many of the advantages, while still suffering the disadvantages. I would also suggest thinking about your actual goals with using microservices. The pattern is sometimes used because it is trendy and not for any actual advantages.
    – JonasH
    Commented Jul 14, 2021 at 9:49
  • Thanks for the useful information, but what about the actual duplication of code. Is there any better way around that? Commented Jul 14, 2021 at 11:40
  • You should not share dtos between microservices because this would lead to strong coupling. If you can´t avoid inter micro-service communication you normally (AFAIK) copy the dtos in every project. This has the advantage that every service can decide which properties are relevant and furthermore you are programming language independent.
    – Darem
    Commented Jul 14, 2021 at 11:47
  • 1
    @andresantacruz Updating APIs of microservices is supposed to be painful, especially backwards incompatible changes. This is done to make the APIs as stable as possible, so that teams can work without constantly needing to update their code due to other teams changing the API.
    – JonasH
    Commented Jul 16, 2021 at 9:57

2 Answers 2

0

I'm a little confused by your description of the code base. You say its a microservice architecture with duplicated code across the services. That is by definition not a service. It also violates the definition of a facade as a facade should not have any hard coded requesting within it. The implementation of the interfaces function calls should be decoupled from the interface itself. The only time you should have to make a change across microservices is if you change the function call or API call reference name (for components vs services respectively). If done as intended, the new implementation updates should be followed by all microservices when you update the implementation.

Services are (should be) essentially containerized apps with their dependencies locally hosted so that if another service changes, then no redeployment is necessary for sister services. This is used for distributed architectures where the services may not be on the same machine and shared libraries are impossible.

Components use shared libraries so that duplication is minimized across an application for storage reasons. Mostly useful in monolithic applications. But if one component requires a certain version of a library and another component uses another version of the same library then you get the matrix from hell situation.

I believe your quickest solution is to add an event queue and event log and message broker to so that no calls are made FROM the services but all events are sent TO the services. And keep in mind that an event can be anything, so you just keep your http logic just send it to the queue instead of to another microservice. You could even preempt the broker with an event processor that could have encoding logic so that you could backward compatibalize any API changes.

This gives you the benefit of adding and deleting any services in a central location easily and future proofs (HA!) your API

See these diagrams: (Not Mine) Mediator Topology Broker Topology

5
  • We already use a message broker (Apache Kafka, specifically). The problem I described occurs when one microservice needs to retrieve data (ie. make a request) from another microservice. I can't see how to do that flow using pub/sub in a maintainable way. Commented Jul 14, 2021 at 16:29
  • I misunderstood then a bit. Microservices tend to be stateless mechanisms. Usually communicating with some sort of database management system as a dependency. If you need the output of the microservice to become the input of another microservice (the same or different) you'll have to route the output into another event queue for processing. If there is static data inside the service, possibly in a standalone database, then youll have to create events messages on changes within that database. If you need the data even if no change, then there's no getting round the request/response model.
    – JesseRigon
    Commented Jul 14, 2021 at 16:48
  • But I did find this online. Never used this system but it's specific to kafka. dzone.com/articles/…
    – JesseRigon
    Commented Jul 14, 2021 at 16:50
  • Also this framework might inspire a solution. It's for UI http requests but the architecture ideas could help in your project. Obviously I couldn't help you in what you needed but hopefully this helped.
    – JesseRigon
    Commented Jul 14, 2021 at 17:21
  • You could also look into service meshes like linkerd or istio. But works best with kubernetes.
    – JesseRigon
    Commented Jul 15, 2021 at 15:01
0
  • Each service should store its own data.

If you take that principle, you should be using events to populate each service with the data it needs from other services. Therefore no direct calls will be needed.

The only time I ever introduce direct API calls is when I have to call something outside of my architecture.

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.