Deep understanding of service discovery: from basics to practice

With the widespread application of microservice architecture, service discovery has become an indispensable component. Service discovery is a key issue in microservice architecture, which involves how to manage and coordinate a large number of services in a distributed system. This article will delve into the basic concepts, working principles, and practical applications of service discovery. We will first introduce the basic concepts and working principles of service discovery, then use practical cases to demonstrate the application of service discovery in practice, and finally we will explore the challenges and future development trends of service discovery. We hope that through this article, readers can have a comprehensive and in-depth understanding of service discovery.



1. Introduction to service discovery
1.1. Basic concepts of microservice architecture

Microservices architecture is an architectural style that divides a single application into a set of small services. Each service runs in its own process, and services communicate with each other through a lightweight mechanism (usually HTTP resource API). These services are built around business capabilities and can be deployed independently through a fully automated deployment mechanism. Additionally, these services can be written in different programming languages ​​and use different data storage technologies.
img

1.2. Basic concepts of service discovery

Service discovery is a key component in distributed systems, and its main function is to track the network location of all services in the system. In a microservice architecture, since there are many services and their locations may change frequently, a service discovery mechanism is needed to dynamically find and monitor services.

Service discovery usually includes two main processes: service registration and service lookup. Service registration means registering its own network address to the service registration center when the service starts; service lookup means that when a service needs to call another service, it queries the service registration center to obtain the network address of the called service.

Through service discovery, each service does not need to care about the specific location of other services. It only needs to know the name of the service to communicate, which greatly improves the flexibility and scalability of the system.

1.3. The importance of service discovery in microservice architecture

In the microservice architecture, the importance of service discovery is mainly reflected in the following aspects:

  1. System decoupling: Through service discovery, each service does not need to care about the specific location of other services. It only needs to know the name of the service to communicate, which greatly reduces the coupling between services.
  2. Improve scalability: Since the location information of the service is managed by the service discovery system, when you need to increase or decrease service instances, you only need to update it in the service discovery system without modifying the code that calls the service.
  3. Improve availability: Service discovery systems usually perform health checks on services. When a service fails, it can be quickly removed from the service list to prevent callers from calling the failed service.
  4. Load balancing: The service discovery system can be used with a load balancer to dynamically adjust service calls according to the load of the service.

Therefore, service discovery plays a crucial role in microservice architecture.


2. How service discovery works

The working principle of service discovery mainly includes two steps: service registration and service lookup

2.1. Service registration

Service registration: When a service (for example, a microservice instance) starts, it sends its network address (such as IP address and port number) and possibly other information (such as service name, version number, etc.) to the service registration center. The service registry is responsible for storing and maintaining this information so that when other services need to communicate with the service, they can obtain the network address of the service by querying the service registry. This mechanism enables dynamic discovery and communication between services, improving the flexibility and scalability of the system.

image-20230927154742592

2.2. Service search

Service Lookup: Service lookup is another important step in the service discovery process. When a service (for example, a microservice instance) needs to call another service, it requests the network address of the called service from the service registry. The service registration center will return the address of the called service, and then the caller can communicate directly with the called service. This mechanism enables dynamic discovery and communication between services, improving the flexibility and scalability of the system.

2.3. Load balancing

The service registration center also needs to have load balancing capabilities. In a large distributed system, the service registration center may need to handle a large number of service registration and lookup requests. If all requests are processed by one service registration center, it may become a bottleneck of the system. Therefore, multiple service registration center instances are usually deployed, and requests are distributed to different instances through a load balancing mechanism to improve system processing capabilities and availability.

In addition, the service registration center also needs to provide a mechanism so that when a service has multiple instances, an instance can be selected and returned to the caller according to a certain strategy (such as polling, random, according to load conditions, etc.). This is also a A load balancing method.

Therefore, the service registration center not only needs to manage the registration and search of services, but also needs to have load balancing capabilities to ensure high availability and high performance of the system.

2.4. Service monitoring

Service monitoring: The service registration center needs to monitor registered services, including service availability, response time, error rate and other indicators. These monitoring data can be used to analyze the operating status of the service and detect and solve problems in a timely manner.

Among them, service availability testing is usually implemented through health check:

2.5. Health examination

Health check: The service registration center usually performs health checks on registered services regularly to check whether the service is still available. Health check usually sends a simple request to the service, such as HTTP HEAD request. If the service responds normally, the service is considered healthy; if the service cannot respond or the response is wrong, the service registration center will consider the service unhealthy and will It is removed from the service list, preventing other services from calling the unavailable service.

2.6. Dynamic update

The dynamic update of the service discovery registration center means that when the status of the service changes (such as service online, offline, failure, etc.), the service registration center can update the status information of the service in real time.

Specifically, dynamic updates mainly include the following aspects:

  1. Service registration: When a new service instance starts, it will register its network address and other necessary information to the service registration center, and the service registration center will add this information to the service list.
  2. Service logout: When a service instance stops, it logs itself out of the service registry, and the service registry removes the service from the service list.
  3. Service update: If the service's network address or other information changes, the service can update the registration information in the service registration center.
  4. Health check: The service registration center will regularly perform health checks on the service. If it is found that the service cannot respond normally, the service will be marked as unavailable or removed from the service list.

Through this dynamic update mechanism, the service registration center can reflect the latest status of services in the system in real time, thereby enabling dynamic discovery and communication between services and improving the flexibility and availability of the system.

2.7. Advantages and disadvantages of various protocols

Service discovery can use various protocols, including HTTP, RPC, DNS, etc. Each protocol has its advantages and disadvantages:

HTTP:

  • Advantages: HTTP is a general-purpose, text-based protocol that is easy to understand and debug, can be processed by a variety of tools and libraries, and is suitable for a variety of languages ​​and platforms;
  • Disadvantages: HTTP may not perform as well as binary protocols, especially in large-scale service discovery scenarios. In addition, HTTP is a stateless protocol and is not suitable for scenarios that require long connections.

RPC (such as gRPC, Thrift):

  • Pros: RPC is generally more lightweight and performs better than HTTP. Many RPC frameworks provide service discovery functions, which can be tightly integrated with RPC communication and are more convenient to use;
  • Disadvantages: RPC requires specific client libraries and is not as versatile as HTTP. Additionally, some RPC protocols may not easily pass through network firewalls

DNS:

  • Advantages: DNS is a domain name-based service discovery protocol that can directly use the DNS resolution function of the operating system without the need for additional client libraries. Additionally, DNS supports load balancing and failover well;
  • Disadvantages: DNS update latency is high and is not suitable for frequently changing environments. In addition, DNS does not support service metadata, such as service version, status, etc.

The above are some advantages and disadvantages of using various protocols for service discovery. Which protocol to choose depends on the specific needs and environment of the system.


3. Implementation of service discovery
3.1. Service discovery provider implementation

The service provider implementation of service discovery mainly includes the following steps:

  1. Registration at startup: When the service starts, it will register its own information (such as service name, address, port, etc.) to the service registration center. This is usually achieved by calling the API of the service registry.

  2. Sending heartbeats regularly: In order to let the service registration center know that the service is still available, the service needs to send heartbeats to the service registration center periodically. If the service registration center does not receive a heartbeat from a service within a period of time, it will consider the service to be offline.

  3. Health check: The service may provide a health check interface so that the service registration center can check the health status of the service. If the health status of the service changes, the service needs to update the registration information in the service registration center.

  4. Logout on shutdown: When a service shuts down, it needs to log itself out from the service registry to prevent other services from trying to call the service that is no longer available.

Here is an example of a service provider implemented using Spring Cloud and Eureka:

@SpringBootApplication
@EnableEurekaClient
public class ServiceProviderApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(ServiceProviderApplication.class, args);
    }
}

In this example, @EnableEurekaClientthe annotation enables the Eureka client, which causes the service to automatically register with the Eureka server on startup and send heartbeats periodically. Other information about the service (such as service name, address, port, etc.) can be set in the configuration file.

3.2. Service discovery consumer implementation

The service consumer implementation of service discovery mainly includes the following steps:

  1. Query services: When a service consumer needs to call other services, it first needs to query the service registration center to obtain the service provider's information. This is usually achieved by calling the API of the service registry.

  2. Load balancing: If there are multiple service providers providing the same service, the service consumer needs to choose one of them to call. This is usually achieved through load balancing algorithms (such as round robin, random, least connections, etc.).

  3. Error handling: If the service call fails (such as network error, service unavailability, etc.), the service consumer needs to perform error handling. This may include strategies such as retry, rollback, circuit breaker, etc.

The following is an example of a service consumer implemented using Spring Cloud and Eureka:

@SpringBootApplication
@EnableDiscoveryClient
public class ServiceConsumerApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(ServiceConsumerApplication.class, args);
    }

    @Autowired
    private DiscoveryClient discoveryClient;

    public void doSomething() {
    
    
        List<ServiceInstance> instances = discoveryClient.getInstances("service-provider");
        if (!instances.isEmpty()) {
    
    
            ServiceInstance instance = instances.get(0); // 这里简单地取第一个实例,实际应用中可能需要使用负载均衡算法
            // 使用 instance.getHost() 和 instance.getPort() 获取服务地址和端口,然后进行服务调用
        }
    }
}

In this example, @EnableDiscoveryClientthe annotation enables the service discovery client, which allows the service to query the Eureka server for service provider information. doSomethingIn the method, we first discoveryClient.getInstancesobtain the service provider information through the method, and then make a service call.

The service consumer implementation of service discovery mainly includes the following steps:

  1. Query services: When a service consumer needs to call other services, it first needs to query the service registration center to obtain the service provider's information. This is usually achieved by calling the API of the service registry.

  2. Load balancing: If there are multiple service providers providing the same service, the service consumer needs to choose one of them to call. This is usually achieved through load balancing algorithms (such as round robin, random, least connections, etc.).

  3. Error handling: If the service call fails (such as network error, service unavailability, etc.), the service consumer needs to perform error handling. This may include strategies such as retry, rollback, circuit breaker, etc.

The following is an example of a service consumer implemented using Spring Cloud and Eureka:

@SpringBootApplication
@EnableDiscoveryClient
public class ServiceConsumerApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(ServiceConsumerApplication.class, args);
    }

    @Autowired
    private DiscoveryClient discoveryClient;

    public void doSomething() {
    
    
        List<ServiceInstance> instances = discoveryClient.getInstances("service-provider");
        if (!instances.isEmpty()) {
    
    
            ServiceInstance instance = instances.get(0); // 这里简单地取第一个实例,实际应用中可能需要使用负载均衡算法
            // 使用 instance.getHost() 和 instance.getPort() 获取服务地址和端口,然后进行服务调用
        }
    }
}

In this example, @EnableDiscoveryClientthe annotation enables the service discovery client, which allows the service to query the Eureka server for service provider information. doSomethingIn the method, we first discoveryClient.getInstancesobtain the service provider information through the method, and then make a service call.

3.3. Implementation of service discovery registration center

The registration center implementation of service discovery mainly includes the following steps:

  1. Receiving service registration: The registration center needs to provide an interface so that service providers can register their own information (such as service name, address, port, etc.) to the registration center.

  2. Storing service information: The registration center needs to store the service provider's information so that service consumers can query it. This usually requires the use of some kind of database or in-memory data structure.

  3. Provide service query: The registration center needs to provide an interface so that service consumers can query service provider information.

  4. Receive service heartbeat: The registration center needs to receive the heartbeat of the service provider to understand the survival status of the service provider. If no heartbeat is received from the service provider within a period of time, the registration center will consider the service to be offline.

  5. Provide service logout: The registration center needs to provide an interface so that the service provider can log out from the registration center when shutting down.

Here is an example of a simplified service registry implemented using Spring Boot and HTTP:

@SpringBootApplication
@RestController
public class RegistryCenterApplication {
    
    
    private Map<String, String> services = new ConcurrentHashMap<>();

    public static void main(String[] args) {
    
    
        SpringApplication.run(RegistryCenterApplication.class, args);
    }

    @PostMapping("/register")
    public void register(@RequestParam String serviceName, @RequestParam String serviceAddress) {
    
    
        services.put(serviceName, serviceAddress);
    }

    @GetMapping("/discover")
    public String discover(@RequestParam String serviceName) {
    
    
        return services.get(serviceName);
    }
}

In this example, we use a ConcurrentHashMapto store service information, /registeran interface for service registration, and /discoveran interface for service query. This is just a very simplified example. The actual service registry will be more complex and needs to deal with issues such as concurrency, network communication, error handling, and service health checks.

3.4. Simple case of implementing registration center in Java

Implementing a complete service registration center involves a lot of content, including network programming, multi-thread programming, error handling, etc. The following is a simplified example that uses Spring Boot and HTTP to implement service registration, service lookup and health check functions.

First, we define a ServiceInstanceclass to represent the service instance:

public class ServiceInstance {
    
    
    private String serviceName;
    private String host;
    private int port;

    // 构造函数、getter 和 setter 省略
}

Then, we define a ServiceRegistryclass to implement service registration and discovery functions:

import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class ServiceRegistry {
    
    
    private Map<String, ServiceInstance> services = new ConcurrentHashMap<>();

    public void register(ServiceInstance instance) {
    
    
        services.put(instance.getServiceName(), instance);
    }

    public ServiceInstance discover(String serviceName) {
    
    
        return services.get(serviceName);
    }
}

Next, we define a RegistryControllerclass to handle HTTP requests:

import org.springframework.web.bind.annotation.*;

@RestController
public class RegistryController {
    
    
    private final ServiceRegistry registry;

    public RegistryController(ServiceRegistry registry) {
    
    
        this.registry = registry;
    }

    @PostMapping("/register")
    public void register(@RequestBody ServiceInstance instance) {
    
    
        registry.register(instance);
    }

    @GetMapping("/discover/{serviceName}")
    public ServiceInstance discover(@PathVariable String serviceName) {
    
    
        return registry.discover(serviceName);
    }
}

Finally, we can define a scheduled task to perform service health checks:

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class HealthCheckTask {
    
    
    private final ServiceRegistry registry;

    public HealthCheckTask(ServiceRegistry registry) {
    
    
        this.registry = registry;
    }

    @Scheduled(fixedRate = 60000)
    public void healthCheck() {
    
    
        // 对 registry 中的每个服务进行健康检查,如果检查失败,移除该服务
    }
}

This is just a simplified example, the actual service registry will be more complex. For example, handling concurrency may require the use of locks or other concurrency control mechanisms; network communication may require the use of more complex protocols, such as TCP, UDP, or HTTP/2; error handling may need to consider various network errors, timeouts, service failures, etc.


4. Practical application cases of service discovery
4.1. Service discovery open source software-Eureka

Eureka is an open source product from Netflix that provides service registration and discovery. It is part of the Spring Cloud ecosystem and is mainly used to implement service governance functions in microservice architecture. Key features of Eureka include:

  1. Easy to use: Eureka provides easy-to-use annotations and configuration properties, and developers can easily integrate Eureka into Spring Cloud projects;

  2. Service registration and discovery: Eureka Server provides a service registration function. After each microservice node is started, it will be registered in Eureka Server. Eureka Client can obtain registration information from Eureka Server to realize service discovery;

  3. Client load balancing: Eureka Client has a built-in load balancer, which can well control the distribution of requests to each service node;

  4. High availability: Eureka Server can be configured in high availability mode to form a service registration center cluster by registering with each other;

  5. Self-protection: When a network partition failure occurs (delay, stuck, service does not go offline normally, etc.), Eureka Server will protect the information in the service registry and will not immediately delete the service registration information, so that the microservices are still available.

4.2. Service discovery open source software-Etcd

Etcd was developed by CoreOS and implemented based on the Go language. It is an open source, highly available distributed key-value storage system for shared configuration and service discovery. The main features of Etcd include:

  1. Simple and easy to use: The installation and configuration of Etcd are very simple, it provides HTTP API for interaction, and it is also very convenient to use;
  2. Key-value storage: Etcd is a key-value storage system where data is stored in hierarchically organized directories, just like in a standard file system;
  3. Change monitoring: Etcd can monitor changes in specific keys or directories and react to changes in values, which is very useful for dynamic configuration updates and service discovery;
  4. High performance: According to official benchmark data, a single instance of Etcd supports 2k+ read operations per second, which can meet the needs of most applications;
  5. High availability and consistency: Etcd uses the Raft algorithm to achieve the availability and consistency of distributed system data. Even if some nodes fail, Etcd can still ensure data availability and consistency
4.3. Service discovery open source software-ZooKeeper

ZooKeeper is an open source project of Apache. It is a software that provides consistency services for distributed applications. The functions provided include: configuration maintenance, domain name services, distributed synchronization, group services, etc. Key features of ZooKeeper include:

  1. Simple and easy to use: ZooKeeper's model is a tree-shaped directory structure, very similar to a file system. It provides a set of simple APIs, such as creating nodes, deleting nodes, reading node data, setting node data, etc., which are very convenient to use;
  2. Change notification: ZooKeeper supports the Watcher mechanism. The client can register a Watcher on a node. When the node's data changes, the Watcher will be notified. This is very useful for implementing functions such as dynamic update of configuration, service discovery, etc.;
  3. High performance: ZooKeeper uses a protocol called ZAB to ensure high availability and consistency, which can handle a large number of reads and stable write operations;
  4. High availability and consistency: ZooKeeper uses a replication mechanism to copy data to each working node. As long as more than half of the nodes survive, ZooKeeper can serve normally. At the same time, ZooKeeper ensures that the data that the client can read is the latest.
  5. Sequential consistency: ZooKeeper ensures that transaction requests initiated from the same client will eventually be applied in ZooKeeper in the order in which they were initiated.
4.4. Service discovery open source software-Nacos

Nacos is an easy-to-use platform open sourced by Alibaba for managing, discovering and configuring microservices. Nacos provides a set of simple APIs to implement service registration, discovery and health checking. Key features of Nacos include:

  1. Simple and easy to use: Nacos provides a set of simple and easy-to-use APIs and interfaces, allowing developers to easily manage and operate services.

  2. Service registration and discovery: Nacos provides a service registration center, supports dynamic registration and discovery of services, and supports two service discovery methods: DNS and HTTP.

  3. Dynamic configuration service: Nacos provides a dynamic configuration service that supports configuration version management, configuration update push and other functions, allowing applications to dynamically obtain and update configurations at runtime.

  4. High availability and consistency: Nacos ensures high availability and consistency of service registration and configuration information through built-in cluster mode and data persistence.

  5. Support microservice architecture: Nacos provides integration support with microservice frameworks such as Spring Cloud and Dubbo, allowing developers to easily build microservice architecture.

4.5. Service discovery open source software-K8s

Kubernetes (K8s for short) is Google's open source container orchestration platform for automated deployment, expansion, and management of containerized applications. Key features of Kubernetes include:

  1. Simple and easy to use: Kubernetes provides a rich and easy-to-use API and command line tools, allowing developers to easily manage and operate containers.

  2. Service discovery and load balancing: Kubernetes can automatically assign IP addresses and DNS names to containers, and can perform load balancing among containers.

  3. Automatic deployment and rollback: Kubernetes can automatically deploy and update applications according to predefined policies. If there is a problem with the new version of the application, it can also automatically roll back to the old version.

  4. Horizontal scaling: Kubernetes can automatically scale applications based on CPU usage or other predefined metrics.

  5. Self-healing: Kubernetes can automatically replace, kill, and restart unhealthy containers to ensure service availability.

  6. Key and configuration management: Kubernetes can manage and protect sensitive information such as passwords, OAuth tokens, SSH keys, etc., and update application configurations without rebuilding the image.

Therefore, Kubernetes is a container orchestration platform ideal for building and running distributed systems.

4.6. Future development trends of service discovery

As a key component in microservice architecture, service discovery’s future development trends may include the following aspects:

  1. Automation: With the development of cloud computing and container technology, the deployment and expansion and contraction of services are becoming more and more automated. Service discovery also needs to support automation, and can automatically sense changes in services and update the status of services;

  2. Multi-cloud and hybrid cloud: More and more enterprises are choosing to use multi-cloud or hybrid cloud environments, and service discovery needs to be able to span multiple cloud platforms and data centers to provide a unified service view;

  3. Security: With the widespread application of microservices, communication security between services is becoming more and more important. Service discovery needs to be able to support service authentication and authorization to prevent unauthorized service access;

  4. Scale: As the number of microservices increases, service discovery needs to be able to support large-scale service management and provide efficient service query and update capabilities;

  5. Standardization: Currently, service discovery is implemented in different ways and there is a lack of unified standards. In the future, some standards or specifications for service discovery may emerge to promote interoperability between different service discovery systems;

  6. Integration: Service discovery may be more closely integrated with other system management and monitoring tools to provide more comprehensive service management capabilities.

The above are some predictions of the future development trends of service discovery. The specific development needs to be observed based on changes in technology and market.

Guess you like

Origin blog.csdn.net/weixin_45187434/article/details/133357764
Recommended