Notes
  • Blockchain
  • About this repository
  • References
  • Carret Position
  • Loggia and Balcony
  • automobile
    • Motorbike
  • computer
    • Kubernetes Event-driven Autoscaling (KEDA)
    • Protobuf
    • [[Amazon]] [[Identity and Access Management]] ([[IAM]])
    • Apdex
    • Architecture Decision Record
    • Audio
    • [[Amazon Web Services]] (AWS) Lambda
    • Blockchain
    • C/C++
    • Cache line
    • Caching strategies
    • Database
    • Design Patterns
    • Docker compose
    • Event Driven Design
    • False sharing
    • Git
    • [[Go]] common mistakes
    • [Go] [[subtests]]
    • Go
    • Janus
    • Jest
    • Kubernetes
    • Log-Structured Merge-tree
    • Media server
    • MySQL: Charset, Collation and UCA
    • Netflix
    • Opus Codec
    • Process, Thread
    • ReDoS - [[Regular expression]] Denial of Service
    • Rust
    • ScyllaDB
    • Shell Functions
    • Signals (The GNU Library)
    • Solidity
    • Sources
    • SQL
    • Transmission Control Protocol (TCP)
    • Ten design principles for Azure applications
    • Transient Fault Handling
    • twemproxy
    • Video
    • Web2 vs Web3
    • WebRTC
    • Microservice architecture
      • 3rd party registration
      • Command Query Responsibility Segregation (CQRS)
      • Access token
      • Aggregate
      • API Composition
      • API gateway/Backends for Frontends
      • Application metrics
      • Audit logging
      • Circuit Breaker
      • Client-side discovery
      • Client-side UI composition
      • Consumer-driven contract test
      • Consumer-side contract test
      • Database per Service
      • Decompose by business capability
      • Decompose by subdomain
      • Distributed tracing
      • Domain event
      • Domain-specific
      • Event sourcing
      • Exception tracking
      • Externalized configuration
      • Health check API
      • Log aggregation
      • Log deployments and changes
      • Messaging
      • Microservice architecture
      • Microservice Chassis
      • Multiple Service instances per host
      • Polling publisher
      • Remote Procedure invocation
      • Saga
      • Self-contained service
      • Self registration
      • Server-side discovery
      • Server-side page fragment composition
      • Serverless deployment
      • Service Component test
      • Service deployment platform
      • Service instance per Container
      • Service instance per VM
      • Service mesh
      • Service per team
      • Service registry
      • Service template
      • Shared database
      • Single Service instance per host
      • Transaction log tailling
      • Transactional outbox
  • food-and-beverage
    • Cheese
    • Flour
    • Japanese Plum liqueur or Umeshu
    • Sugar
  • management
    • Software Engineering processes
  • medic
    • Desease, disorder, condition, syndrome
    • Motion Sickess
  • others
    • Elliðaey
    • ASCII art
    • Empirical rule
    • Hindsight bias
    • Outcome bias
    • Tam giác Reuleaux
    • Luật Việt Nam
  • soft-skills
    • Emotional intelligence
Powered by GitBook
On this page
  • Context
  • Problem
  • Forces
  • Solution
  • Examples
  • Resulting context
  • Related patterns
  1. computer
  2. Microservice architecture

Client-side discovery

PreviousCircuit BreakerNextClient-side UI composition

Last updated 2 years ago

Context

Services typically need to call one another. In a monolithic application, services invoke one another through language-level method or procedure calls. In a traditional distributed system deployment, services run at fixed, well known locations (hosts and ports) and so can easily call one another using HTTP/REST or some RPC mechanism. However, a modern microservice-based application typically runs in a virtualized or containerized environments where the number of instances of a service and their locations changes dynamically.

Consequently, you must implement a mechanism for that enables the clients of service to make requests to a dynamically changing set of ephemeral service instances.

Problem

How does the client of a service - the API gateway or another service - discover the location of a service instance?

Forces

  • Each instance of a service exposes a remote API such as HTTP/REST, or Thrift etc. at a particular location (host and port)

  • The number of services instances and their locations changes dynamically.

  • Virtual machines and containers are usually assigned dynamic IP addresses.

  • The number of services instances might vary dynamically. For example, an EC2 Autoscaling Group adjusts the number of instances based on load.

Solution

When making a request to a service, the client obtains the location of a service instance by querying a [[Service Registry]], which knows the locations of all service instances.

The following diagram shows the structure of this pattern.

This is typically handled by a [[Microservice chassis]] framework

Examples

RegistrationServiceProxy is a component of that application. In order to register a user, it invokes another service using the Spring Framework's RestTemplate:

@Component
class RegistrationServiceProxy @Autowired()(restTemplate: RestTemplate) extends RegistrationService {

  @Value("${user_registration_url}")
  var userRegistrationUrl: String = _

  override def registerUser(emailAddress: String, password: String): Either[RegistrationError, String] = {

      val response = restTemplate.postForEntity(userRegistrationUrl,
        RegistrationBackendRequest(emailAddress, password),
        classOf[RegistrationBackendResponse])
       ...
}

It is injected with the RestTemplate and the user_registration_url, which specifies the REST endpoint.

Client-side service discovery is configured using various [[Spring Cloud]] annotations:

@Configuration
@EnableEurekaClient
@Profile(Array("enableEureka"))
class EurekaClientConfiguration {

  @Bean
  @LoadBalanced
  def restTemplate(scalaObjectMapper : ScalaObjectMapper) : RestTemplate = {
    val restTemplate = new RestTemplate()
    restTemplate.getMessageConverters foreach {
      case mc: MappingJackson2HttpMessageConverter =>
        mc.setObjectMapper(scalaObjectMapper)
      case _ =>
    }
    restTemplate
  }
}

The @EnableEurekaClient annotation enables the [[Eureka]] client. The @LoadBalanced annotation configures the RestTemplate to use [[Ribbon]], which has been configured to use the [[[Eureka]]] client to do service discovery. As a result, the RestTemplate will handle requests to the http://REGISTRATION-SERVICE/user endpoint by querying [[Eureka]] to find the network locations of available service instances.

Resulting context

Client-side discovery has the following benefits:

  • Fewer moving parts and network hops compared to [[Server-side Discovery]]

Client-side discovery also has the following drawbacks:

  • This pattern couples the client to the [[Service Registry]]

Related patterns

  • [[Service Registry]] - an essential part of service discovery

  • [[Microservice chassis]] - Client-side service discovery is the responsibility the microservice chassis framework

  • [[Server Side Discovery]] is an alternative solution to this problem.

The is an example of an application that uses client-side service discovery. It is written in Scala and uses [[Spring Boot]] and [[Spring Cloud]] as the [[Microservice chassis]]. They provide various capabilities including client-side discovery.

When the application is deployed user_registration_url is set to this URL http://REGISTRATION-SERVICE/user - see the docker-compose.yml file. REGISTRATION-SERVICE is the logical service name that is resolved to a network location using client-side service discovery. The service discovery is implemented using [[Netflix OSS]] (http://netflix.github.io/) components. It provides [[Eureka]] ([https://github.com/Netflix/eureka/wiki/Eureka-at-a-glance]) , which is a [[Service Registry]], and , which is an HTTP client that queries Eureka in order to route HTTP requests to an available service instance.

You need to implement client-side service discovery logic for each programming language/framework used by your application, e.g Java/Scala, JavaScript/NodeJS. For example, provides an HTTP proxy-based approach to service discovery for non-JVM clients.

Microservices Example application
Ribbon
Netflix Prana