The original address: microservices. IO/patterns/cl…

Services need to call each other, and in a singleton architecture, calls between services are done directly through method calls at the programming language level. In the deployment of traditional distributed applications, service addresses and ports are fixed and predicted in advance, so simple HTTP/REST calls or other RPC mechanisms can be invoked directly. However, in the current cloud native microservice system, microservices are mostly run under a certain virtual machine or a certain container, and the number of service instances and the address and port of the service are not fixed. It can be understood that these service instances are temporary. Therefore, mechanisms need to be implemented to enable service clients to make requests to a dynamically changing set of AD hoc service instances.

Ask questions

How does a client of a service, API gateway, or some other service that needs to discover service instances know the location of service instances?

consideration

  • Each instance of a service exposes a remote API, such as HTTP/REST or Thrift, at a specific location (host and port)
  • The number of service instances and their locations change dynamically
  • VMS and containers are usually assigned dynamic IP addresses
  • The number of service instances can change dynamically. For example, AN AWS EC2 autoscaling group can dynamically adjust the number of instances based on LOAD.

The solution

When requesting a Service, the client queries a public Service Registry (commonly referred to as a Registry) to find out what instances of the Service to invoke are and where they are located. As shown below:

For example,

The Scala language, Spring Boot and Spring Cloud framework are used here. For example, the service discovery of Spring Cloud is mainly based on client service discovery.

RegistrationServiceProxy is a component of the application used to register users:

@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])
       ...
}

Copy the code

This class injects the RestTemplate and user_Registration_url. When the application is deployed, user_Registration_url is actually http://REGISTRATION-SERVICE/user, Registration-service is the name of the SERVICE used by the client for SERVICE discovery. Service discovery is implemented through Netflix OSS components, including Eureka as a registry and the Ribbon that queries Eureka for instances to make Http requests.

Client 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 }Copy the code

The @enableEurekaclient annotation enables the Eureka client. The @loadBalanced annotation configures the RestTemplate to be called remotely using the Ribbon configured for service discovery with Eureka clients. Therefore, the RestTemplate will get the service name by resolving to http://REGISTRATION-SERVICE/user, and then make the request by querying Eureka for the network location of the available service instances.

Analysis of the

Advantages of client service discovery:

  • There are fewer network intermediate components and network hops than server-side service discovery

Shortcomings found in client services:

  • Coupled with registries, different registries have different registration logic.
  • Client service discovery logic needs to be implemented in different languages.

Related design patterns

  • Service Registry (or Registry)
  • Microservices infrastructure framework
  • Server-side service discovery is an alternative to this design pattern