We use cookies to improve your experience on our website. By browsing this website, you agree to our use of cookies. More info Ok, I understand!

17 March 2016

Consul Service Discovery. Part 1

Consul Service Discovery. Part 1

When developing an application you need to pay special attention to the architecture. If you don’t do it from the beginning, the scaling problems can appear all of a sudden (sometimes they don’t even have a solution). Application scaling and efficient resources use at the setting stage – can save months in future.

Distributed architecture (with a possibility of horizontal scaling of all components) is often used for preventing such problems. Unfortunately, at SOA implementing the new problems can occur, like: cohesion and complexity of service configuration.

In this article we will look at discovery service called Consul, with the help of which we can find solutions to the above stated problems and also to make the architecture more transparent and clear.

Distributed architecture (SOA) and implementation challenges

While designing application as weak linked feature set, we got the opportunity to scale every component from the beginning.

SOA (Service Oriented Architecture https://en.wikipedia.org/wiki/Service-oriented_architecture) – is an architectural pattern, describing application architecture as self-contained components with weak linking, that communicate by using standard transfer protocols (ex. REST). The SOA follow-up (or domain) is microservice architecture. It is based on services increase instead of functionality increase of a certain server (reflection of Single Responsibility in architecture) and deep integration with continuous-processes.

When you implement microservice architecture - responsibility for services interaction falls on infrastructure solution of our application. Services, which correspond the principle of Single Responsibility can only receive a request and return a response. At the same time it is important to balance the traffic load within the system nodes, to connect (even though it’s a weak connection) services dependent on each other. And, of course, it is necessary to act on the configuration change of our system:

  • Services are constantly added.
  • Some services stop to respond to Healthcheck.
  • New components appear in the system and it is necessary to effectively share information on them.
  • Versions of certain components have updates – backward compatibility fails.

In any system this is a continuous and complex process, but with the help of discovery we can control and make it clear.

What is discovery?

Discovery -- is a tool (or set of tools) for providing connection between architecture components. By using discovery we provide coherence between application components, but not linking. Discovery can be considered as some metainformation registry of distributed architecture that keeps data of all components. This allows to realize components interaction with minimal manual intervention (according to the principle of ZeroConf https://en.wikipedia.org/wiki/Zero-configuration_networking).

Discovery role in the process of building distributed architecture

Discovery-service has three main functions on which cohesion is based in terms of distributed architecture:

  • Consistence of metainformation about services in cluster.
  • Mechanism for registration and monitoring components availability.
  • Mechanism for components discovery.

Let’s look at the meaning of each point in detail:

Consistence

Distributed architecture means that components can be scaled horizontally. At the same time they have to be aware of actual cluster state. Discovery-service provides decentralized storage and gives access to the storage for any node. Components can save their data; information will be transferred to all interested cluster participants.

Registration and monitoring

Once more added servers should report themselves, and running servers should be permanently checked on availability. This is a necessary condition for automatic cluster configuration. Traffic balancers and dependant nodes mandatorily should have information on cluster actual configuration for effective resources use.

Discovery

Discovery - is a technique for services search (for example, according to the roles they have). We can request the location for all services of a certain role, knowing only discovery-service address and not knowing their exact number and particular address.

Consul.io as discovery implementation

In this article we will talk about discovery implementation based on Consul.

Consul -- is a decentralized fault-tolerant service from HashiCorp Company (that develops such products as Vagrant, TerraForm, Otto, Atlas and others).

Consul is a decentralized service. It means that Consul agent is installed to every host and it is a first-class cluster participant. So servers don’t need to know discovery address in our network, all requests to discovery are processed to local address 127.0.0.1.

Additional information about Consul:

Leader – is a server that receives all requests for information change. If we draw an analogy with database, then it’s a master in the context of master/slave-replication. All other servers replicate data from the leader. The main difference from database replication is that in case leader fails all other servers start process of choosing a new leader. After they make a choice, they start to replicate from the new leader.

Every instance can work in two modes: agent and server. The difference is that agent – is a point of spreading information, while server – is a point of registration. So, agents receive requests only for reading but server can change already existing information (service registration and removal). In fact, we make a request to local address any way. The difference is that the request for reading will be processed on local host while the request for data change will be readdressed to the leader, which saves and spreads data among the whole cluster. If our local agent is not a leader at the moment then our request for change will be fully processed locally and spread among the cluster.

Using Consul in Cluster

Consul cluster is a network of connected nodes with running services registered in discovery. Consul guarantees that cluster information will be distributed among all cluster participants and will be available on demand. Also there is not only peer support but also multizoned cluster (in Consul terminology called “datacenters”). With the help of Consul it is possible both: to work with certain datacentres and to perform an action on any others. Datacentres are not isolated from each other in terms of discovery. Agent in one datacenter can get information from other datacenter that can help in building effective solution for distributed system.

Using Consul in Cluster

Consul agents running in server mode besides their main role, get the role of a potential cluster leader. It is recommended to use in cluster not less than 3 agents in server mode for providing fault tolerance. Using server mode doesn’t place any restrictions on the main agent functionality.

When adding new node to the cluster we need to know the address of any node in cluster. By running the following command:

consul join node_ip_address

we register a new node in cluster and after some time information about cluster state will be available to that node. So, the new node will be available for other nodes requests.

Node types: internal, external

In Consul we can register our service in two ways:

  1. Using HTTP API or agent configuration file only in case the service communicates with Consul independently.
  2. Register service as 3d-party component in case it can’t communicate with Consul.

Let’s look at both ways in detail.

With the help of HTTP API, offered by Consul, there is a possibility to make a correct component registration and service removal in discovery. Besides these 2 modes we can use maintenance mode. In this mode service is marked as unavailable and is stopped mapping in DNS and API requests.

Let’s consider request sample for component registration (JSON should be transferred in PUT-request):

http://localhost:8500/v1/agent/service/register

{
"ID": "redis1",
"Name": "redis",
"Tags": [
"master",
"v1"
],
"Address": "127.0.0.1",
"Port": 8000,
"Check": {
"Script": "/usr/local/bin/check_redis.py",
"HTTP": "http://localhost:5000/health",
"Interval": "10s",
"TTL": "15s"
}
}

Here is an example for component removal from the catalog:

http://localhost:8500/v1/agent/service/deregister/<ServiceID>

Here is an example for service transferring in maintenance mode.

http://localhost:8500/v1/agent/service/maintenanse/<ServiceID>?enable=true|false

With the help of enable flag we can switch the status and add an optional parameter reason, which has text description for cause of component transferring to maintenance mode.

If we need to register some external service and to “teach” it to self-register in Consul, then we can register it not as a service-provider but as an external service. After registration we can receive external service data by DNS:

$ curl -X PUT -d '{"Datacenter": "dc1", "Node": "google",
"Address": "www.google.com",
"Service": {"Service": "search", "Port": 80}}'
http://127.0.0.1:8500/v1/catalog/register

Besides HTTP API you can use agent configuration files with services description.

In the second part we will finish our review of Consul service, and we will especially stop at the following functions:

  • DNS interface
  • HTTP API.
  • Health Checks.
  • K/V storage.

And, of course, we will summarize the work with Consul.