mirror of https://github.com/status-im/consul.git
Website: GH-730 and cleanup for docs/guides/leader-election.html.
This commit is contained in:
parent
bca0e55770
commit
42a7251f27
|
@ -3,45 +3,44 @@ layout: "docs"
|
||||||
page_title: "Leader Election"
|
page_title: "Leader Election"
|
||||||
sidebar_current: "docs-guides-leader"
|
sidebar_current: "docs-guides-leader"
|
||||||
description: |-
|
description: |-
|
||||||
The goal of this guide is to cover how to build client-side leader election using Consul. If you are interested in the leader election used internally to Consul, you want to read about the consensus protocol instead.
|
This guide describes how to build client-side leader election using Consul. If you are interested in the leader election used internally to Consul, please refer to the consensus protocol documentation instead.
|
||||||
---
|
---
|
||||||
|
|
||||||
# Leader Election
|
# Leader Election
|
||||||
|
|
||||||
The goal of this guide is to cover how to build client-side leader election using Consul.
|
This guide describes how to build client-side leader election using Consul. If you
|
||||||
If you are interested in the leader election used internally to Consul, you want to
|
are interested in the leader election used internally by Consul, please refer to the
|
||||||
read about the [consensus protocol](/docs/internals/consensus.html) instead.
|
[consensus protocol](/docs/internals/consensus.html) documentation instead.
|
||||||
|
|
||||||
There are a number of ways that leader election can be built, so our goal is not to
|
There are a number of ways that leader election can be built, so our goal is not to
|
||||||
cover all the possible methods. Instead, we will focus on using Consul's support for
|
cover all the possible methods. Instead, we will focus on using Consul's support for
|
||||||
[sessions](/docs/internals/sessions.html), which allow us to build a system that can
|
[sessions](/docs/internals/sessions.html). Sessions allow us to build a system that
|
||||||
gracefully handle failures.
|
can gracefully handle failures.
|
||||||
|
|
||||||
Note that JSON output in this guide has been pretty-printed for easier
|
Note that JSON output in this guide has been pretty-printed for easier
|
||||||
reading. Actual values returned from the API will not be formatted.
|
reading. Actual values returned from the API will not be formatted.
|
||||||
|
|
||||||
## Contending Nodes
|
## Contending Nodes
|
||||||
|
|
||||||
The first flow we cover is for nodes who are attempting to acquire leadership
|
Let's imagine we have a set of nodes who are attempting to acquire leadership
|
||||||
for a given service. All nodes that are participating should agree on a given
|
for a given service. All nodes that are participating should agree on a given
|
||||||
key being used to coordinate. A good choice is simply:
|
key to coordinate. A good pattern is simply:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
service/<service name>/leader
|
service/<service name>/leader
|
||||||
```
|
```
|
||||||
|
|
||||||
We will refer to this as just `<key>` for simplicity.
|
We'll abbreviate this pattern as simply `<key>` for the rest of this guide.
|
||||||
|
|
||||||
The first step is to create a session. This is done using the [/v1/session/create endpoint][session-api]:
|
The first step is to create a session using the
|
||||||
|
[Session HTTP API](/docs/agent/http/session.html#session_create):
|
||||||
[session-api]: http://www.consul.io/docs/agent/http.html#_v1_session_create
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
curl -X PUT -d '{"Name": "dbservice"}' \
|
curl -X PUT -d '{"Name": "dbservice"}' \
|
||||||
http://localhost:8500/v1/session/create
|
http://localhost:8500/v1/session/create
|
||||||
```
|
```
|
||||||
|
|
||||||
This will return a JSON object contain the session ID:
|
This will return a JSON object containing the session ID:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
{
|
{
|
||||||
|
@ -49,35 +48,38 @@ This will return a JSON object contain the session ID:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The session by default makes use of only the gossip failure detector. Additional checks
|
The next step is to acquire a session for a given key from this node
|
||||||
can be specified if desired.
|
using the PUT method on a [KV entry](/docs/agent/http/kv.html) with the
|
||||||
|
"?acquire=\<session\>" query parameter. The `<body>` of the PUT should be a
|
||||||
Create `<body>` to represent the local node. This value is opaque to
|
JSON object representing the local node. This value is opaque to
|
||||||
Consul and should contain whatever information clients require to
|
Consul, but it should contain whatever information clients require to
|
||||||
communicate with your application (e.g., it could be a JSON object
|
communicate with your application (e.g., it could be a JSON object
|
||||||
that contains the node's name and the application's port).
|
that contains the node's name and the application's port).
|
||||||
|
|
||||||
Attempt to `acquire` the `<key>` by doing a `PUT`. This is something like:
|
Attempt to `acquire` the `<key>`. This will look something like (note that
|
||||||
|
`<session>` is the ID returned by the call to
|
||||||
|
[`/v1/session/create`](/docs/agent/http/session.html#session_create)):
|
||||||
|
|
||||||
```text
|
```text
|
||||||
curl -X PUT -d <body> http://localhost:8500/v1/kv/<key>?acquire=<session>
|
curl -X PUT -d <body> http://localhost:8500/v1/kv/<key>?acquire=<session>
|
||||||
```
|
```
|
||||||
|
|
||||||
Where `<session>` is the ID returned by the call to
|
This will either return `true` or `false`. If `true`, the lock has been acquired and
|
||||||
`/v1/session/create`.
|
the local node is now the leader. If `false` is returned, some other node has acquired
|
||||||
|
the lock.
|
||||||
This will either return `true` or `false`. If `true` is returned, the lock
|
|
||||||
has been acquired and the local node is now the leader. If `false` is returned,
|
|
||||||
some other node has acquired the lock.
|
|
||||||
|
|
||||||
All nodes now remain in an idle waiting state. In this state, we watch for changes
|
All nodes now remain in an idle waiting state. In this state, we watch for changes
|
||||||
on `<key>`. This is because the lock may be released, the node may fail, etc.
|
on `<key>`. This is because the lock may be released, the node may fail, etc.
|
||||||
The leader must also watch for changes since it's lock may be released by an operator,
|
The leader must also watch for changes since its lock may be released by an operator
|
||||||
or automatically released due to a false positive in the failure detector.
|
or automatically released due to a false positive in the failure detector.
|
||||||
|
|
||||||
Watching for changes is done by doing a blocking query against `<key>`. If we ever
|
Note that the session by default makes use of only the gossip failure detector. That
|
||||||
notice that the `Session` of the `<key>` is blank, then there is no leader, and we should
|
is, the session is considered held by a node as long as the default Serf health check
|
||||||
retry acquiring the lock. Each attempt to acquire the key should be separated by a timed
|
has not declared the node unhealthy. Additional checks can be specified if desired.
|
||||||
|
|
||||||
|
Watching for changes is done via a blocking query against `<key>`. If we ever
|
||||||
|
notice that the `Session` of the `<key>` is blank, there is no leader, and we should
|
||||||
|
retry lock acquisition. Each attempt to acquire the key should be separated by a timed
|
||||||
wait. This is because Consul may be enforcing a [`lock-delay`](/docs/internals/sessions.html).
|
wait. This is because Consul may be enforcing a [`lock-delay`](/docs/internals/sessions.html).
|
||||||
|
|
||||||
If the leader ever wishes to step down voluntarily, this should be done by simply
|
If the leader ever wishes to step down voluntarily, this should be done by simply
|
||||||
|
@ -89,10 +91,11 @@ curl -X PUT http://localhost:8500/v1/kv/<key>?release=<session>
|
||||||
|
|
||||||
## Discovering a Leader
|
## Discovering a Leader
|
||||||
|
|
||||||
The second flow is for nodes who are attempting to discover the leader
|
Another common practice regarding leader election is for nodes to wish to identify the
|
||||||
for a given service. All nodes that are participating should agree on the key
|
leader for a given service.
|
||||||
being used to coordinate, including the contenders. This key will be referred
|
|
||||||
to as just `key`.
|
As with leader leader election, all nodes that are participating should agree on the key
|
||||||
|
being used to coordinate. This key will be referred to as just `key`.
|
||||||
|
|
||||||
Clients have a very simple role, they simply read `<key>` to discover who the current
|
Clients have a very simple role, they simply read `<key>` to discover who the current
|
||||||
leader is:
|
leader is:
|
||||||
|
@ -112,11 +115,12 @@ curl http://localhost:8500/v1/kv/<key>
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
If the key has no associated `Session`, then there is no leader.
|
If the key has no associated `Session`, then there is no leader. Otherwise, the value of
|
||||||
Otherwise, the value of the key will provide all the
|
the key will provide all the application-dependent information required as a Base64 encoded
|
||||||
application-dependent information required as a base64 encoded blob in
|
blob in the `Value` field.
|
||||||
the `Value` key. You can query the `/v1/session/info` endpoint to get
|
|
||||||
details about the session:
|
You can query the [`/v1/session/info`](/docs/agent/http/session.html#session_info) endpoint
|
||||||
|
to get details about the session:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
curl http://localhost:8500/v1/session/info/4ca8e74b-6350-7587-addf-a18084928f3c
|
curl http://localhost:8500/v1/session/info/4ca8e74b-6350-7587-addf-a18084928f3c
|
||||||
|
@ -135,5 +139,5 @@ curl http://localhost:8500/v1/session/info/4ca8e74b-6350-7587-addf-a18084928f3c
|
||||||
```
|
```
|
||||||
|
|
||||||
Clients should also watch the key using a blocking query for any changes. If the leader
|
Clients should also watch the key using a blocking query for any changes. If the leader
|
||||||
steps down, or fails, then the `Session` associated with the key will be cleared. When
|
steps down or fails, the `Session` associated with the key will be cleared. When
|
||||||
a new leader is elected, the key value will also be updated.
|
a new leader is elected, the key value will also be updated.
|
||||||
|
|
Loading…
Reference in New Issue