What is microservices service discovery?
In a microservices-based application, the backend environment constantly changes. In order to keep up with these changes, the client needs a way to identify the available service instances. This is where a service discovery mechanism is useful.
Service discovery involves automatically discovering and locating services and devices on the network. The networking standard used is SDP (service discovery protocol), which can help clients identify resources on a network.
Historically, service discovery helped facilitate configuration efforts by helping users find compatible resources like bluetooth-enabled devices in their proximity. More recently, this concept has extended to treat distributed container-based resources as services, which can be dynamically discovered and accessed.
Why you need service discovery
A microservice must know the location (port and IP address) of all other services it communicates with. Without a service discovery system, the service locations are coupled, resulting in a system that is challenging to scale and maintain. You can wire the addresses of services or inject them using configurations, but this isn’t recommended in modern cloud-based distributed applications.
Dynamically identifying the location of application services can be challenging. It becomes more complicated in an environment where instances of services are constantly created and destroyed. For example, a cloud-based application might continuously change due to horizontal autoscaling to accommodate changing loads. Modern service discovery mechanisms must deal with these complex use cases.
Service discovery patterns
A service discovery pattern enables locating microservices within the network. It uses a service registry (a centralized server) to keep a global record of all microservices’ network locations.
All microservices must register and disclose their locations to the central service registry at set intervals. Clients (service consumers) can retrieve the locations of each microservice by connecting to the service registry, after which they can directly call the various services to complete a task.
Here are the two primary service discovery patterns:
Client-side discovery pattern
Here is how a client-side discovery pattern works:
- A service consumer tries to locate a specific service provider by searching the service registry.
- The service consumer selects a suitable, available service instance with the help of a load balancer.
- The service consumer makes a request.
Once the service initiates, its instance’s location is recorded in the service registry. When the instance is terminated, this information should be deleted from the registry.
Since the consumer of a given service is aware of all service instances available, the pattern can make intelligent decisions to implement load balancing. However, in some cases, the discovery service might not be behind an API gateway. If that happens, you must reimplement authentication, cross-cutting, and balancing concerns for the discovery service.
Here are the main advantages of a client-side discovery pattern:
- Enables the service consumer to make intelligent decisions based on requirements.
- Facilitates application-specific decisions for load balancing, such as hashing.
- This pattern is less complicated.
- Does not require using a load balancer or router to route client applications or requests.
- Avoids extra middle steps to achieve a quick turnaround.
Here are the main disadvantages of a client-side discovery pattern:
- Tightly couples the client and the service registry, requiring you to implement the client-side service discovery logic for every programming framework and language the service clients use.
- Since microservices architecture consists of disparate tools, technologies, languages, and frameworks, this pattern makes application management highly complex.
- Forces a client to make two calls to reach a target microservice.
Server-side discovery pattern
Here is how a server-side discovery pattern works:
- The client-side service consumer does not know about the service registry. Instead, it makes requests through a router.
- The router looks for an available, suitable service instance in the service registry and reroutes the request.
In this pattern, clients do not do service discovery or load balancing. Instead, the API gateway works to select a suitable endpoint for a given client-side request.
A server-side discovery pattern is language-agnostic and framework-agnostic. However, it requires the deployment environment to provide a load balancer and to remain highly available.
Here are the main advantages of server-side service discovery:
- The client doesn’t need to look for available service instances. As a result, they do not need to make more than one call when requesting services.
- Creates an abstraction between the client and server-side.
- Eliminates the need to implement the discovery logic for each framework and language the service client uses.
- Available for free with several deployment environments.
Here are the main disadvantages of a server-side discovery:
- If the deployment environment doesn’t provide it, you must set it up and manage it.
- Requires implementing load balancing for the central server.
- Does not allow the client to choose a service instance.
3 ways to implement service discovery
Here are several common approaches to implementing service discovery.
DNS-based implementation
When using the DNS-based approach to implementing service discovery, you use a standard DNS library as the client. There is an entry for each microservice in the DNS zone file. The service discovery system locates instances by performing DNS lookups. Alternatively, you can configure a microservice to discover services periodically using a proxy like NGINX to check the DNS.
This approach is suitable for all programming languages and doesn’t require any (or significant) code changes. However, DNS-based service discovery also has some disadvantages that you should consider, such as a lack of real-time visibility. It also lacks sufficient support if multiple clients use different caching semantics.
The DNS approach can be expensive because it requires operational overhead to manage zone files while you add or remove new services. You must set up additional infrastructure to support periodic health checks and caching to a local machine when the system cannot reach the central DNS server.
Sidecar and key/value store
This approach uses a consistent key/value data store like Zookeeper or Consul as a central mechanism to perform service discovery. This mechanism communicates using a sidecar proxy and key/value store—a microservice connects to the service discovery system via a local proxy. It obtains the information needed to configure the sidecar proxy and retrieve results.
You can use an interface like REST or DNS with the sidecar process. This process is fully transparent to the coder, allowing you to write the code in any language. There is no need to consider the interaction between the microservices.
However, the sidecar approach is limited for host discovery and cannot route to fine-grained schemes and resources. Another drawback is the additional step required for each microservice (the sidecar process). The sidecar proxy requires critical maintenance, tuning, and deployment with all microservices.
Library-based service discovery
This approach uses a library to communicate with the service discovery solution, enabling specialized solutions like Eureka. It directly exposes the functionality to the end developer, so it’s important to understand that you code the microservice via API calls.
Library-based service discovery allows you to discover any type of resource because it’s not limited to the host. There is a clear, straightforward deployment function, and you deploy the client library alongside other client libraries. Ideally, the set of libraries is broad to support more programming languages.
Microservices service discovery with Gloo Mesh
A service mesh enables service-to-service communication and typically plugs in with a service discovery mechanism for a specific cluster or network. But a service mesh doesn’t automatically solve the multi-network problem. A service mesh can route to services outside of its network, but how does it know which services exist and to where to route them?
That’s where Gloo Mesh, an open-source service-mesh management plane, helps.
Gloo Mesh can register clusters (and non Kubernetes workloads) and build a global registry across networks. Gloo Mesh can then orchestrate each mesh (potentially deployed 1:1 with a cluster or network) by updating the mesh with vital cross-network service discovery information. For example, with Istio, a very popular service mesh implementation built on Envoy Proxy, Gloo Mesh can discover which services run on what clusters and build that information for each Istio control plane (istiod) by creating ServiceEntry resources that point to services in other clusters. That gives a single Istio mesh awareness of services running in other clusters. Gloo Mesh can do this for all of the Istio control planes across multiple networks and create the illusion of a “VirtualMesh” where all of the meshes are working on concert together to provide routing and service discovery across any networks.