Service Discovery: Consul Support in Judge-d (Part 1)
We introduce you (both in theory and in practice) to the subject of service discovery, Consul as a sample tool implementing it, and how it can be used with Judge-d.
Join the DZone community and get the full member experience.Join For Free
Service discovery is a mechanism allowing to automatically detect services in complex ecosystems utilizing microservices architecture. Consul is one of the most popular tools offering service discovery. Therefore, it is a perfect match for Judge-d, an open source tool providing contract testing, to become one of the available sources of information about the state of the environment, which is under Judge-d jurisdiction.
In this article, we would like to introduce you (both in theory and in practice) to the subject of service discovery, Consul as a sample tool implementing it, and how it can be used with Judge-d as a source of truth about the environment where contract tests are required.
Microservices architecture relies on many applications cooperating together to deliver business value. Each of them is a separate deployment unit and is responsible for a separate piece of functionality as expected by the single responsibility principle. An application can provide a particular functionality — the application is called a provider of the service. At the same time, it can rely on functionality provided by other applications — the application is called a consumer of the service.
In order to cooperate together, both consumers and providers need to be able to communicate together. There are many different ways of facilitating such communication, both synchronous and asynchronous.
The number of services in the microservices ecosystem might grow in time. Additionally, in order to provide scalability, there might be multiple instances of the same application providing a particular service and inbound traffic might be split among multiple instances. Such horizontal scaling might be managed by specific orchestrators like Kubernetes. Moreover, typically, production environments are replicated in multiple locations to provide failover handling.
In such complex architectures, it would be troublesome to handle routing of traffic between applications by manually setting static IP addresses and ports so that the applications know where should they sent their requests. Additionally, orchestration tools like Kubernetes might scale services horizontally — instances might be constantly created or deleted. IP addresses are subject to constant changes. Manually addressing such changes might be troublesome, especially in big ecosystems.
Therefore, the service discovery concept was created. It encompasses automatic detection of services in complex ecosystems. There are 2 types of service discovery — client-side service discovery and server-side service discovery. For more details on service discovery principles and patterns, please refer to the Nginx blog post.
Consul is a tool offering many functionalities, one of them being service discovery. A service can register itself in Consul and afterward any consumer is able to localize it, allowing it to utilize the service offered by the provider.
Moreover, Consul is able to take care of monitoring the state of registered services. Services might have health checks associated with them and in case of failed subsequent checks, the service is marked as unavailable. It allows the consumers to avoid sending requests to unhealthy instances which in turn avoids cascading failures.
There 2 basic logical units in Consul: agent and server. The consul server is responsible for data storing and replication. In a production environment, there is more than one instance of the server, therefore the leader election process is in place. Consul suggests setting 3 to 5 servers in production environments for each data center. Information like availability of services, the health of these services are kept in 'catalogs.' The Consul agent is responsible for checking the health of the applications registered in Consul. Moreover, the agent redirects any request it gets to the Consul server. More details to be found here.
Judge-d requires information about services available in the whole environment to be able to perform contract testing after a change is introduced to the service. This information is periodically sent to the Judge-d server by Judge-d agents and the information stored by the Judge-d server is subject to updates. Judge-d agent currently supports fetching state of the environment from Kubernetes and from Consul. However, any other source might be added in the future as Judge-d is designed to be easily extended and developed further.
In order to fetch data from Consul, the Judge-d agent requires each service to contain a version tag as the Judge-d server distinguishes between services using their name and version. The version tag is specified by the service during registration in the Consul server.
Judge-d agent periodically asks Consul agent or server for the services contained in the catalog owned by Consul servers in this environment. Afterward, service names and versions are extracted. Moreover, the health of services is verified, and unhealthy (i.e., not available) services are not included. Judge-d server is updated with filtered service names and versions.
Consul needs to maintain the state of the whole environment to be able to perform service discovery, therefore it was a perfect match for Judge-d to provide information about the state of the environment. If you use Judge-d to perform contract testing in your system and you use Consul for service discovery, you can simply combine both without much effort as proven in the demo section in this article.
The second part of the article (demo) is available here.
Opinions expressed by DZone contributors are their own.