33

I have the following application:

enter image description here

This application receives an API call (HTTP), does some internal work that usually includes reading or writing to a database that has 5 different tables, generates an XML file and then sends it to another system via a REST interface. This has around 5K lines of codes.

I'm now studying the microservice architecture and see how my application would/should look like if I was using it. After reading a lot of stuff, I came to two different solutions:

  1. In the first one, each microservice only serve one or a very few HTTP requests. This is good because if one microsevice is down, only a small part of my previous big app is down, but the rest is still working. However, there is a lot of code duplication between each microservice. For example, each of them has more or less the same code to generate an XML template or send request to the southbound system. I know it can be overcome by using a shared library, but then each microservice needs to use the same programming language.

    enter image description here

  2. Splitting the part of my app to smaller services. Here, I avoid code duplication and each service can use a different programming language, but if a single microservice is down, everything stops working. Moreover, this looks like a monolithic architecture, because I'm just separating the layer with HTTP request instead of a class/functions interface. It seems maybe a bit easier to understand and maintain, but not really giving anything more.

    enter image description here

I would like to have your opinion on my personal use case as I really struggle to understand how an application in a microservice world should be designed without a concrete example.

1
  • 6
    If you are looking for the tule of thumb to split a system into a Microservice ecosystem, I'm afraid of you won't find it because the split or the design depends entirely on the needs. On concrete and real needs. MS or not, designs must serve to a real purpose. Given your 2 examples, which one solves/fits best in your strategy for the business. As you mentioned, it's all about trade-offs. There're not silver bullets here.
    – Laiv
    Jun 5, 2020 at 12:12

2 Answers 2

24

The objective of microservices is to provide independently deployable, loosely coupled, lean services. This means that you shall be able to change one of the microservices however you want, and can deploy it in production without changing the others.

Your scenario 1 indeed breaks the monolith down into smaller pieces. But these are not independently deployable:

However, there is a lot of code duplication between each microservice. (...) I know it can be overcome by using a shared library,

If you change some functionality in the shared code, you no longer are sure that it's interoperable with the other service. And if shared library is changed, you're no longer sure that the other service still compiles and could be patched for an emergency issue within minutes.

Your focus seems to be reliability and continuity of the microservices that you have extracted from your legacy monolith. But the common code weakens the independent continuity of services: if you have for example a vulnerability in your shared library, both services could easily be disrupted by the same hacker. Or suffer from the same nasty UB bug.

The reliability achieved with microservice is based on true independence on the functional axis. The focus is also more on scalability (see the scale cube): microservices can offer horizontal duplication (i.e. several service instances for the same API - if one breaks down, the clones continue to work), not to speak about partitioning.

For scenario 2, you could consider implementing fault tolerance by implementing horizontal scalability, i.e. having several instances of the same service running on different nodes. It's a tough change since the services have to find each other dynamically. But then, if one of the service instance is down in the chain, the other services upstream can find another working instance. A trick for achieveing this is to move from a synchronous communication to asynchronous communication via event queues or a message broker.

It's difficult based on the few elements you provide to confirm if approach 2 is the best one. Perhaps another decomposition strategy could result in even lower coupling.

I could for example think of this one, which combines both of your approaches: migrating your common XML generator features into a "Service Proxy" (the name is arbitrary: it seemed to be a relay between your new microservices and other applications), splitting the core of the monolith into highly cohesive but loosely coupled capabilities, and hiding the details of the split to the outside world behind an API gateway:

enter image description here

2
  • 3
    Your "common code" argument isn't wrong but it does depend on a subjective line of acceptability. It's perfectly fine for both services to have a dependency on a third party library, regardless of whether you wrote that third party library or e.g. got it off NuGet. For example NodaTime - no harm in using that in both microservices. However, if the majority of the microservices' purpose is encapsulated by that one library, then you've mostly just deployed the same library twice, at which point you're not really working microservice oriented and are just putting a facade on your monolith.
    – Flater
    Jun 8, 2020 at 13:38
  • 1
    @Flater I think we can agree on this topic. In this other answer I even bring some arguments defending code sharing, but with a couple of conditions. The first condition is indeed a strong version management, so that different microservices can safely rely on different versions. I discouraged it here, because the reason and purpose of the code sharing was not so clear and I suspect possible hidden coupling (e.g. if service X is still based on some functions that belong to service A that are for convenience moved to the lib).
    – Christophe
    Jun 8, 2020 at 14:22
1

You should start with writing down the problems you want to fix, and the goals you want to achieve. Then look at the possible solutions, and check if they help achieve your goals and solve the problems.

I really like the Micro service architecture, but it has got a bad reputation because of cargo culting.

Not the answer you're looking for? Browse other questions tagged or ask your own question.