0

I'm dealing with a system where:

  1. A number of around 50 microservices are available
  2. Depending on their needs, clients design their deployment choosing which of those microservices they need
  3. Most of them are not usable in isolation, but require others to be available, which is perfectly understandable.

Now the situation I'm trying to solve is: When a service A is deployed, some configuration needs to be added to service B, and only then. For example, when deploying a service A to perform backups, then a Localization service B needs to be configured to be able to translate the names of the backup operations, which are then queried by a UI service C. That is, deploying A involves changing the configuration to B.

Right now, when deploying A, a number of REST calls are made to B to add this configuration, but somehow feels cumbersome.

In this system, there's a number of these situations, to the point where I'm thinking there's probably a generic known solution lying around. I've talking a look at configuration servers like microconfig, but I have no experience with them or with microservices for that matter. So the question is:

Is a configuration server the default option for this ? Or does this simply smell like an architectural problem for there is a different solution.

1 Answer 1

2

When a service A is deployed, some configuration needs to be added to service B, and only then. For example, when deploying a service A to perform backups, then a Localization service B needs to be configured to be able to translate the names of the backup operations, which are then queried by a UI service C. That is, deploying A involves changing the configuration to B.

That's not the microservice way.

It's perfectly fine for one microservice (A) to make use of another (B), but it's not okay to have to manually configure B to be able to serve A. That breaks B's independence.

  1. A number of around 50 microservices are available
  2. Depending on their needs, clients design their deployment choosing which of those microservices they need
  3. Most of them are not usable in isolation, but require others to be available, which is perfectly understandable.

I'm assuming a tenanted situation here to simplify the explanation, but the gist (and specifically the part I think you need answered) is the same even if not in a tenanted setup.

It's perfectly fine to setup your system to tell the tenant that if they want to have microservice A, that they're also going to need microservice B. There are several way to go about this:

  1. Provisioning A automatically provisions B, the customer doesn't have to think about it.
  2. You expect the customer to know that B needs to be provisioned, and to explicitly provision B before A.
  3. You write your A service so that it has a fallback behavior if B is not provisioned, effectively making the provisioning of B optional.

I'm not a fan of option 2, as it's not a great experience for the customer. It's a mandated hoop for them to jump through that you could have easily automated since you knew in advance that it needed to be done.

In cases where A can optionally depend on B, I'd favor option 3. Otherwise I'd favor option 1.

Similarly, if they provision a C microservice which would query B if it exists, I'd offer option 3, where C can graciously handle the case where there is no B, e.g. a clear message to the user that the C features relating to B are not available because there is no B.

If B is not optional, and the customer only provisions A and C, then A and C's B-dependent features will not work. This is not a problematic situation from a development perspective. At best, you graciously handle the subsequent errors/exceptions, but A and C can do nothing more than report that they "cannot find a B that my own feature needs".
Usually, this is no different from already handling an unexpected outage of B, as both scenarios look the same from the perspective of A: it cannot successfully interact with B.

Or does this simply smell like an architectural problem for there is a different solution.

The main issue here is that if B is a microservice, you should be able to deploy B before you even know who will be consuming it.

The only exception here is if A "registers" itself to B (e.g. pubsub scenario). But that is not a configuration setting, that's an actual interaction between A and B where A calls the "subscribe" endpoint of an already operational B microservice.

Your example is light on concrete reasons why B must be reconfigured, but it seems to me like you've not properly defined B the way a microservice should be defined. It's much too dependent on knowledge who will specifically consume it, which means it's not independent.

That is, deploying A involves changing the configuration to B.

If I assume that you're not in a tenanted situation, but rather that there is only one of each (A, B, C), then it's important to define "configuration".

If by "configuration" you mean things like consumers registering/subscribing to the service, that's not configuration. The ability to register is part of the responsibility of the app itself, so needing to register is just "using the app", in that sense. You could go about this in several ways:

  • A can register itself in B by having the end user call the correct A endpoint.
  • A automatically registers itself with B on startup.
  • A automatically registers itself with B on startup, and internally stores a reminder that it doesn't need to re-register when it next starts up.
  • As part of the A release pipeline, after A is deployed you then call the appropriate A endpoint which makes A register itself with B.

However, if by "configuration" you mean app configuration, i.e. config files, a bulk data upload behind the scenes, or other data needed for the service to even work, then you're doing it wrong.

7
  • with configuration I mean app configuration as you define it in your last paragraph. I am convinced we're doing it wrong, that's why I'm looking for a better way. The 'concrete reasons' why 'B' needs to be reconfigured on the example is the described above: If A is deployed, new localization strings (in a specific language, let's say) need to be available at B, how should this additional configuration made available to B ? B can be deployed independentaly, but won't have A's configuration at the beginning, how to put it there if not by pushing together when pushing A
    – Chirlo
    Commented Mar 23, 2021 at 15:21
  • @Chirlo Note how my answer disassociates config files from features. If uploading localization strings were a feature of B rather than an internal configuration, then it's something that A can upload to B.
    – Flater
    Commented Mar 23, 2021 at 15:25
  • C is the one that needs B to be configured (because of A being available, yes). A uploading to B would 'pollute' A with the functionality of uploading to B, the way I'm looking at it rn. Imagine X,Y,Z,T services, that would all cause some localization strings to be available at B, should they all upload it themselves to B ?
    – Chirlo
    Commented Mar 23, 2021 at 15:39
  • @Chirlo: C depending on B being configured because of A is precisely what fails to meet the independence criteria of microservices. But this is not something you can fix using a universal solution. You need to redesign your implementation to enable that independence, which requires in-depth discussions on the requirements and how (not) to implement them. That is not something StackExchange's Q&A format is appropriate for.
    – Flater
    Commented Mar 23, 2021 at 15:54
  • 1
    @Chirlo Just to offer another thought (among many possible ideas here), maybe B shouldn't be a microservice, but rather a nuget package that is included into A, C, Y, X, Z, and T, meaning it individually runs inside the runtime of each service that is using it (and then C queries those services directly). Whether this is viable or not depends on specific requirements that we can't fleece through here, but it's important to remember that just because you're using microservices, doesn't mean everything needs to be a microservice.
    – Flater
    Commented Mar 23, 2021 at 15:58

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.