1

We deploy microservices in Kubernetes environment.

For providing a solution to a business use-case using microservices,

Is the idea of service registration and service discovery not an anti pattern? where the scenario of starting microservice depends on the availability of other microservice

For example, using API composition, we would need service discovery. We have a usecase in ecommerce, where Front end rest api clients(React or Angular) need to talk to backend(checkout, cart, order, review) services using api composition pattern, to render UI. Not sure, if event based messaging pattern(say using kafka) would be a good option between Front end & Back end services, just to avoid api composition

+++

As mentioned here,

What are microservices?

Microservices - also known as the microservice architecture - is an architectural style that structures an application as a collection of services that are:

  • Independently deployable

  • Loosely coupled

  • Organized around business capabilities

  • Owned by a small team

1
  • Not sure, if event-based messaging pattern(say using kafka) would be a good option between Front end & Back end services, just to avoid API composition Why would you do so? To what end? Who you are trying to impress by making things unnecessarily more complicated? There should be a good reason to go one or the other way and "because strangers on the internet say..." is not a good one.
    – Laiv
    Nov 2, 2023 at 9:11

2 Answers 2

6

Terms change over time, so I think "service discovery pattern" used to mean:

func MyFunc()
{
   var service = serviceRegistry.Find<MyService>();
   service.something
}

This is considered bad because you don't really know whether a service has been registered or not, or when setting up the service registry, what services need to be registered.

The alternative pattern:

func MyFunc(IMyService service)
{
   service.something
}

At least advertises that a IMyService is needed, even if its injected by some container library in much the same way.

However, these days I think the term "service discovery" refers more to the world of container and config management. For example you need a url in config for MyService, but that url isn't a static thing you can just hard code. It depends on what environment you are deploying to, and how that environment is setup in terms of container/nodes/networking etc.

It's now common to simply be able to say url = "myservice" in your config and have that hostname be pointed automagically to the correct place via your container deployment scripts.

This is managed by having MyService "register" its url when its deployed and for other deployments that need MyService query that registry for the underlying url/ip before configuring the hostname-> ip lookup for "http://myservice

This isn't (yet) considered an anti pattern, although personally I think it blurs the line between config and setup and has some dangers.

5
  • we use helm charts for deployment in Kubernetes(as mentioned in query). Can we assess dependencies through helm chart? Oct 31, 2023 at 19:11
  • I couldn't understand your reason(for service discovery) to be considered bad. Finding the dependency service by talking to service registry is doable and reliable, Isn't it? Oct 31, 2023 at 19:13
  • re:helm yes i think you can, but i dont know the deets
    – Ewan
    Oct 31, 2023 at 19:42
  • re: why bad? consider that you still have to pass a IServiceRegistry into everything, mock it in tests, wrap alternative implementations etc. it's just worse than the alternatives#
    – Ewan
    Oct 31, 2023 at 19:43
  • @user1787812 - re: why bad? It's basically the Service Locator antipattern. As the complexity of the system grows, there's a point where it becomes a problem. One issue is that the client classes only implicitly depend on things; the globally visible service registry swipes the necessary preconditions for the use of a class under the rug. This will come back to bite you. Also, you're directly referencing a global that has unbounded number of members and exposes an unbounded number of interfaces. It just invites bad design to proliferate through the codebase. Nov 4, 2023 at 13:39
0

Service discovery (as mentioned in other answers) is just a technique of linking of services without hard coding each with others static address.

The real anti-pattern is making service discovery a startup (static) dependency, instead of a functional (dynamic) dependency.

Startup dependency: When services require for each other at startup and crash if any other is unavailable, the micro-service stack goes into a sort of micro-boot-loop. Here, the system is unresponsive to user requests because things cant get started.

Developers usually end up introducing a startup sequencing, i.e. service A starts first then service B (as it needs A) and so on. Init containers that wait for something, and HTTP probes pointed at other services, many hacks have been used. These are non ideal.

Although many service platforms will just keep restarting those services and eventually the all of them start up somehow. That "somehow" is fine until you need to debug it.

Functional dependency: This is just using service discovery in a more reactive way. All services start up fine, the service discovery only happens when needed for execution of actual service logic in response to a user request:

mailService = await.discovery.get('email');
await mailService.send('welcomeTemplate', welcomeData)

With proper caching of discovery metadata, other services are dynamically located from time to time as needed and the whole thing is not tied to service startup. It just fails user requests if things aren't as expected. By adding a "circuit-breaker", long outages of other services can be handled in a customizable way. The key in this setup is to not couple initialization logic of micro-services with each other.

5
  • For your point : the service discovery only happens when needed for execution of actual service logic.... service discovery for every http call(as service logic) is too much overhead Nov 2, 2023 at 17:52
  • Instead of, using service discovery as functional dependency, does error handling of service logic, make sense? Nov 2, 2023 at 18:01
  • is too much overhead... > That's why local caching is necessary as mentioned in the answer.
    – S.D.
    Nov 3, 2023 at 8:57
  • Late binding will fail at runtime, which is infinitely worse than failing on deployment or design time
    – Basilevs
    Nov 6, 2023 at 16:34
  • How does eager or startup binding prevents other services from going down later ? These are independent distributed services after all.
    – S.D.
    Jan 26 at 17:30

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.