Link: github.com/oopsguy/mic… Translator: Oopsguy
Chapter 4 of this book focuses on building applications using microservices. Chapter 1 has already introduced the microservices architecture pattern and discussed the advantages and disadvantages of using microservices. Chapter two and Chapter three introduce the communication between micro services and compare different communication mechanisms. In this chapter, we’ll explore service Discovery.
4.1. Why use service discovery
Let’s say you’re writing some code that calls a service that has a REST API or a Thrift API. To send a request, your code needs to know the network location (IP address and port) of the service instance. In traditional applications running on physical hardware, the network location of service instances is relatively static. For example, your code could read the network location from an occasionally updated configuration file.
However, this is a more difficult problem to solve in modern cloud-based microservices applications, as shown in Figure 4-1.
Service instances have dynamically allocated network locations. In addition, the entire set of service instances changes dynamically due to automatic scaling, failures, and upgrades. Therefore, your client code needs to use a more precise service discovery mechanism.
Figure 4-1 client or API gateway that requires services to find help
There are two main modes of service discovery: client-side discovery and server-side discovery. Let’s take a look at client discovery first.
4.2 Client discovery mode
When using the client discovery pattern, the client is responsible for determining the network location and request load balancing of available service instances. The client queries the Service Registry, which is a database of available service instances. The client then uses a load balancing algorithm to select an available service instance and make a request.
Figure 4-2 shows the structure of this pattern
The client can undertake the task of discovering services
The network location of the service instance is registered when the service registry is started. When the instance terminates, it is removed from the service registry. A heartbeat mechanism is typically used to periodically refresh the registration information of a service instance.
Netflix OSS provides a good example of the client-side discovery pattern. Netflix Eureka is a service registry that provides a REST API for managing service instance registrations and querying available instances. Netflix Ribbon is an IPC client that can be used with Eureka to load balance requests between available service instances. Eureka is discussed later in this chapter.
The client-side discovery pattern has various advantages and disadvantages. This pattern is relatively simple, with no moving parts other than the service registry. In addition, because clients can discover available service instances, intelligent, application-specific load balancing decisions can be made, such as using consistent hashing. An important disadvantage of this pattern is that it couples the client to the service registry. You must implement client-side service discovery logic for each programming language and framework used by the service client.
Now that we’ve looked at client-side discovery, let’s look at server-side discovery.
4.3 Server discovery Mode
Another approach to service discovery is the server-side discovery pattern. Figure 4-3 shows the structure of this pattern:
Inter-server processing can also handle service discovery
The client makes a request to the service through the load balancer. The load balancer queries the service registry and routes each request to an available service instance. As with client discovery, service instances are registered and destroyed by the service registry.
AWS Elastic Load Balancer (ELB) is an example of server route discovery. ELB is used to load balance external traffic from the Internet. However, you can also use ELB to load balance traffic within a virtual private cloud (VPC). The client sends the request (HTTP or TCP) using its DNS name via ELB. ELB load balances traffic between a group of registered Elastic Compute Cloud (EC2) instances or EC2 Container Service (ECS) containers. There is no separate service registry visible here. Instead, EC2 instances and ECS containers are registered by the ELB itself.
HTTP servers and load balancers (such as NGINX Plus and NGINX) can also discover load balancers as servers. For example, this blog post describes dynamically reconfiguring an NGINX reverse proxy using Consul Template. Consul Template is a tool that periodically regenerates arbitrary profiles from configuration data stored in the Consul service registry. Whenever the file is changed, it runs arbitrary shell commands. In the example described in the listed blog post, Consul Template generates an nginx.conf file that configures the reverse proxy and then tells Nginx to reload the configuration by running a command. A more sophisticated implementation could dynamically reconfigure NGINX Plus using its HTTP API or DNS.
Some deployment environments, such as Kubernetes and Marathon, run an agent on each host in the cluster. These agents act as server-side discovery load balancers. To make a request to the service, the client uses the IP address of the host and the assigned port of the service to route the request through the proxy. The broker then transparently forwards the request to an available service instance running somewhere in the cluster.
The server-side discovery pattern has several advantages and disadvantages. A big advantage of this pattern is that the details of discovery are abstracted from the client side. The client simply makes a request to the load balancer. This eliminates the need to implement discovery logic for every programming language and framework used by the service client. In addition, as mentioned above, some deployment environments provide this functionality for free. However, there are some drawbacks to this model. Unless the load balancer is provided by a deployment environment, you need to import, set up, and manage this high availability system component.
4.4. Service Registry
The Service Registry is a key part of service discovery. It is a database that contains the network location of the service instance. The service registry must be highly available and up to date. Although the client can cache the network location obtained from the service registry, this information will eventually expire and the client will not be able to discover the service instance. Thus, a service registry consists of clusters of servers that use the Replication Protocol to maintain consistency.
As mentioned earlier, Netflix Eureka is a good example of a service registry. It provides a REST API for registering and querying service instances. A service instance registers its network location using a POST request. It must use PUT requests every 30 seconds to refresh its registration information. Remove registration information by using HTTP DELETE requests or instance registration timeouts. As you might expect, clients can use HTTP GET requests to retrieve registered service instances.
Netflix achieves high Availability by running one or more Eureka servers in each Amazon EC2 Availability Zone. Each Eureka server runs on an EC2 instance with an Elastic IP address. The DNS TEXT record is used to store the Eureka cluster configuration, which is a mapping of the list of network locations from availability zones to Eureka servers. When the Eureka server starts, it will query DNS to retrieve the Eureka cluster configuration, find its peer, and assign it an unused Elastic IP address.
Query DNS through Eureka client – Service and Service client – to discover the network location of the Eureka server. The client preferentially uses the Eureka server in the same availability zone or, if none is available, uses the Eureka server in another availability zone.
Other service registries are listed below:
- Etcd – a highly available, distributed, and consistent key-value store for shared configuration and service discovery. Two notable projects using ETCD are Kubernetes and Cloud Foundry.
- Consul – a discovery and configuration service tool. It provides an API for client registration and discovery services. Consul performs a health check on a service to determine its availability.
- Apache ZooKeeper – a high-performance coordination service widely used in distributed applications. Apache ZooKeeper was originally a Hadoop subproject, but is now a standalone top-level project.
In addition, as mentioned earlier, some systems, such as Kubernetes, Marathon, and AWS, do not have an explicit service registry. Instead, a service registry is just a built-in part of the infrastructure.
Now that we understand the concept of a service registry, let’s look at how a service instance is registered in a service registry.
4.5 Service registration method
As mentioned earlier, service instances must be registered and unregistered in the service registry. There are several different ways to handle registration and logout. One is self-registration of service instances, that is, self-registration mode. The other is to use other system components to manage the registration of service instances, a third-party registration pattern. Let’s look at self-registration mode first.
4.6 self-registration mode
When using self-registration mode, the service instance is responsible for registering and unregistering itself in the service registry. In addition, if necessary, the service instance will prevent its registration information from expiring by sending a heartbeat request.
Figure 4-4 shows the structure of this pattern.
Figure 4-4. The service can register itself
A good example of this approach is the Netflix OSS Eureka client. The Eureka client handles all aspects of service instance registration and unregistration. Spring Cloud projects that implement multiple patterns, including service discovery, can easily use Eureka to automatically register service instances. You simply apply the @enableeurekaclient annotation to the Java Configuration class.
There are good and bad self-registration modes. One benefit is that it is relatively simple and does not require any other system components. However, the main disadvantage is that it couples service instances to service registries. You must implement the registration code for each programming language and framework used by the service.
An alternative to separating services from service registries is the third-party registry pattern.
4.7 Third-party registration mode
When using the third-party registry mode, the service instance is no longer responsible for registering itself with the service registry. Instead, another system component, known as the Service Registrar, will handle the job. The service registry keeps track of changes to the set of running instances by polling the deployment environment or subscribing to events. When it detects a new available service instance, it registers the instance with the service registry. In addition, the service registry can unregister terminated service instances.
Figure 4-5 shows the structure of this pattern:
Figure 4-5. A single service registry is responsible for registering other services
An example of a service registry is the open source Registrator project. It can automatically register and unregister service instances deployed as Docker containers. The registry supports multiple service registries, including ETCD and Consul.
Another example of a service registry is NetflixOSS Prana. Primarily used for services written in non-JVM languages, it is a side-application that runs in parallel with the service instance. Prana uses Netflix Eureka to register and unregister service instances.
The service registry is a built-in component in some deployment environments. EC2 instances created by the Autoscaling Group can be automatically registered with the ELB. The Kubernetes service will automatically register and provide discovery.
The third-party registration model also has its pros and cons. A major benefit is decoupling between services and service registries. You do not need to implement service registration logic for every programming language and framework used by developers. Instead, service instance registration needs to be handled centrally in a dedicated service.
One disadvantage of this pattern is that unless the deployment environment is built in, you also need to introduce, set up and manage such a highly available system component.
4.8,
In a microservice application, the set of running service instances changes dynamically. Instances have dynamically allocated network locations. Therefore, in order for a client to make a request to a service, it must use the service discovery mechanism.
A key part of service discovery is the service registry. A service registry is a database of available service instances. The service registry provides the functionality of an administrative API and a query API. Service instances are registered or unregistered from the service registry using the administration API. System components use query apis to discover available service instances.
There are two main modes of service discovery: client discovery and server discovery. In a system that uses client-side service discovery, the client queries the service registry, selects an available instance and makes a request. In a system that uses server discovery, the client makes the request through the router, which queries the service registry and forwards the request to the available instance.
There are two main ways to register and unregister a service instance in a service registry. One is that a service instance registers itself with the service registry, that is, in self-registration mode. The other is to use other system components to register and unregister services on behalf of the service, that is, third-party registration mode.
In some deployment environments, you need to use a service registry such as Netflix Eureka or Apache ZooKeeper to set up your own service discovery infrastructure. In other deployment environments, service discovery is built in, such as Kubernetes and Marathon, which handle registration and unregistration of service instances. They also run an agent on each cluster host that acts as a server discovery router.
An HTTP reverse proxy and load balancer (such as NGINX) can also be used as a server-side discovery load balancer. The service registry can push routing information to NGINX and invoke a normal configuration update; For example, you can use Consul Template. NGINX Plus supports additional dynamic reconfiguration mechanisms – it can use DNS to extract information about service instances from registries and provides an API for remote reconfiguration.
Microservices: NGINX’s flexibility
by Floyd Smith
In a microservice environment, your back-end infrastructure may be constantly changing due to automated scaling, failures, and upgrades, including the creation, deployment, and extension of services. As described in this chapter, a service discovery mechanism is required in an environment that dynamically reallocates services.
Part of the benefit of applying NGINX to microservices is that you can easily configure it to automatically respond to changes made by the back-end infrastructure. NGINX configuration is not only simple and flexible, but also compatible with the templates used by Amazon Web Services, making it easier to manage specific service changes and groups of load-balanced change Services.
NGINX Plus has an instant reconfiguration API that enables you to sense changes to load balanced service groups without restarting NGINX Plus or manually reloading the configuration. In NGINX Plus Release 8 and later, you can configure the changes you make to the API to remain unchanged during a reboot and configuration reload. (Reloading does not require a reboot, do not disconnect.) NGINX Plus Release 9 and later supports service discovery using DNS SRV records for tighter integration with existing server discovery platforms such as Consul and ETCD.
We created a model for managing service discovery in NGINX:
- Docker containers that run separately for several applications, including service discovery applications such as ETCD, service registration tools, one or more back-end servers, and NGINX Plus itself for load balancing other containers.
- The registry tool monitors new Docker containers and registers new services using the service discovery tool. In addition, missing containers can be deleted.
- Containers and the services they run are automatically added to or removed from load balancing upstream servers.
This Demo application can be used with multiple service discovery applications: Consul API, DNS SRV records from Consul, ETCD, and ZooKeeper.