[docs] Leader Election Guide Updates (#5654)
* Updating the Leader Election guide. * Update website/source/docs/guides/leader-election.html.md * updating key name * Update website/source/docs/guides/leader-election.html.md Co-Authored-By: kaitlincarter-hc <43049322+kaitlincarter-hc@users.noreply.github.com> * Update website/source/docs/guides/leader-election.html.md Co-Authored-By: kaitlincarter-hc <43049322+kaitlincarter-hc@users.noreply.github.com>
This commit is contained in:
parent
6cbd67f9df
commit
64a2e486f5
|
@ -1,74 +1,83 @@
|
|||
---
|
||||
layout: "docs"
|
||||
page_title: "Leader Election"
|
||||
page_title: "Application Leader Election with Sessions"
|
||||
sidebar_current: "docs-guides-leader"
|
||||
description: |-
|
||||
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
|
||||
# Application Leader Election with Sessions
|
||||
|
||||
This guide describes how to build client-side leader election using Consul. If you
|
||||
For some applications, like HDFS, it is necessary to set one instance as
|
||||
a leader. This ensures the application data is current and stable.
|
||||
|
||||
This guide describes how to build client-side leader elections for service
|
||||
instances, using Consul. Consul's support for
|
||||
[sessions](/docs/internals/sessions.html) allows you to build a system that can gracefully handle failures.
|
||||
|
||||
If you
|
||||
are interested in the leader election used internally by Consul, please refer to the
|
||||
[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
|
||||
cover all the possible methods. Instead, we will focus on using Consul's support for
|
||||
[sessions](/docs/internals/sessions.html). Sessions allow us to build a system that
|
||||
can gracefully handle failures.
|
||||
## Contending Service Instances
|
||||
|
||||
-> **Note:** JSON output in this guide has been pretty-printed for easier reading. Actual values returned from the API will not be formatted.
|
||||
|
||||
## Contending Nodes
|
||||
|
||||
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
|
||||
Imagine you have a set of MySQL service instances who are attempting to acquire leadership. All service instances that are participating should agree on a given
|
||||
key to coordinate. A good pattern is simply:
|
||||
|
||||
```text
|
||||
service/<service name>/leader
|
||||
```
|
||||
|
||||
We'll abbreviate this pattern as simply `<key>` for the rest of this guide.
|
||||
This key will be used for all requests to the Consul KV API.
|
||||
|
||||
The first step is to create a session using the
|
||||
[Session HTTP API](/api/session.html#session_create):
|
||||
We will use the same, simple pattern for the MySQL services for the remainder of the guide.
|
||||
|
||||
```text
|
||||
curl -X PUT -d '{"Name": "dbservice"}' \
|
||||
http://localhost:8500/v1/session/create
|
||||
service/mysql/leader
|
||||
```
|
||||
|
||||
### Create a Session
|
||||
|
||||
The first step is to create a session using the
|
||||
[Session HTTP API](/api/session.html#session_create).
|
||||
|
||||
```sh
|
||||
$ curl -X PUT -d '{"Name": "mysql-session"}' http://localhost:8500/v1/session/create
|
||||
```
|
||||
|
||||
This will return a JSON object containing the session ID:
|
||||
|
||||
```text
|
||||
```json
|
||||
{
|
||||
"ID": "4ca8e74b-6350-7587-addf-a18084928f3c"
|
||||
}
|
||||
```
|
||||
|
||||
The next step is to acquire a session for a given key from this node
|
||||
### Acquire a Session
|
||||
|
||||
The next step is to acquire a session for a given key from this instance
|
||||
using the PUT method on a [KV entry](/api/kv.html) with the
|
||||
`?acquire=<session>` query parameter. The `<body>` of the PUT should be a
|
||||
JSON object representing the local node. This value is opaque to
|
||||
`?acquire=<session>` query parameter.
|
||||
|
||||
The `<body>` of the PUT should be a
|
||||
JSON object representing the local instance. This value is opaque to
|
||||
Consul, but it should contain whatever information clients require to
|
||||
communicate with your application (e.g., it could be a JSON object
|
||||
that contains the node's name and the application's port).
|
||||
|
||||
Attempt to `acquire` the `<key>`. This will look something like (note that
|
||||
`<session>` is the ID returned by the call to
|
||||
[`/v1/session/create`](/api/session.html#session_create)):
|
||||
|
||||
```text
|
||||
curl -X PUT -d <body> http://localhost:8500/v1/kv/<key>?acquire=<session>
|
||||
```sh
|
||||
$ curl -X PUT -d <body> http://localhost:8500/v1/kv/service/mysql/leader?acquire=4ca8e74b-6350-7587-addf-a18084928f3c
|
||||
```
|
||||
|
||||
This will either return `true` or `false`. If `true`, the lock has been acquired and
|
||||
the local node is now the leader. If `false` is returned, some other node has acquired
|
||||
the local service instance 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
|
||||
on `<key>`. This is because the lock may be released, the node may fail, etc.
|
||||
### Watch the Session
|
||||
|
||||
All instances now remain in an idle waiting state. In this state, they watch for changes
|
||||
on the key `service/mysql/leader`. This is because the lock may be released or the instance could fail, etc.
|
||||
|
||||
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.
|
||||
|
||||
|
@ -76,37 +85,38 @@ By default, the session makes use of only the gossip failure detector. That
|
|||
is, the session is considered held by a node as long as the default Serf health check
|
||||
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
|
||||
Watching for changes is done via a blocking query against the key. If they ever
|
||||
notice that the `Session` field in the response is blank, there is no leader, and then 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).
|
||||
|
||||
### Release the Session
|
||||
|
||||
If the leader ever wishes to step down voluntarily, this should be done by simply
|
||||
releasing the lock:
|
||||
|
||||
```text
|
||||
curl -X PUT http://localhost:8500/v1/kv/<key>?release=<session>
|
||||
```sh
|
||||
$ curl -X PUT http://localhost:8500/v1/kv/service/mysql/leader?release=4ca8e74b-6350-7587-addf-a18084928f3c
|
||||
```
|
||||
|
||||
## Discovering a Leader
|
||||
## Discover the Leader
|
||||
|
||||
Another common practice regarding leader election is for nodes to wish to identify the
|
||||
leader for a given service.
|
||||
It is possible to identify the leader of a set of service instances participating in the election process.
|
||||
|
||||
As with 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`.
|
||||
As with leader election, all instances that are participating should agree on the key being used to coordinate.
|
||||
|
||||
Clients have a very simple role, they simply read `<key>` to discover who the current
|
||||
leader is:
|
||||
### Retrieve the Key
|
||||
|
||||
```text
|
||||
curl http://localhost:8500/v1/kv/<key>
|
||||
Instances have a very simple role, they simply read the Consul KV key to discover the current leader. If the key has an associated `Session`, then there is a leader.
|
||||
|
||||
```sh
|
||||
$ curl -X GET http://localhost:8500/v1/kv/service/mysql/leader
|
||||
[
|
||||
{
|
||||
"Session": "4ca8e74b-6350-7587-addf-a18084928f3c",
|
||||
"Value": "Ym9keQ==",
|
||||
"Flags": 0,
|
||||
"Key": "<key>",
|
||||
"Key": "service/mysql/leader",
|
||||
"LockIndex": 1,
|
||||
"ModifyIndex": 29,
|
||||
"CreateIndex": 29
|
||||
|
@ -114,17 +124,18 @@ curl http://localhost:8500/v1/kv/<key>
|
|||
]
|
||||
```
|
||||
|
||||
If the key has no associated `Session`, then there is no leader.
|
||||
Otherwise, the value of the key will provide all the
|
||||
If there is a leader then the value of the key will provide all the
|
||||
application-dependent information required as a Base64 encoded blob in
|
||||
the `Value` field.
|
||||
|
||||
### Retrieve Session Information
|
||||
|
||||
You can query the
|
||||
[`/v1/session/info`](/api/session.html#session_info)
|
||||
endpoint to get details about the session:
|
||||
endpoint to get details about the session
|
||||
|
||||
```text
|
||||
curl http://localhost:8500/v1/session/info/4ca8e74b-6350-7587-addf-a18084928f3c
|
||||
```sh
|
||||
$ curl -X GET http://localhost:8500/v1/session/info/4ca8e74b-6350-7587-addf-a18084928f3c
|
||||
[
|
||||
{
|
||||
"LockDelay": 1.5e+10,
|
||||
|
@ -132,18 +143,21 @@ curl http://localhost:8500/v1/session/info/4ca8e74b-6350-7587-addf-a18084928f3c
|
|||
"serfHealth"
|
||||
],
|
||||
"Node": "consul-primary-bjsiobmvdij6-node-lhe5ihreel7y",
|
||||
"Name": "dbservice",
|
||||
"Name": "mysql-session",
|
||||
"ID": "4ca8e74b-6350-7587-addf-a18084928f3c",
|
||||
"CreateIndex": 28
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Clients should also watch the key using a blocking query for any
|
||||
## Summary
|
||||
|
||||
In this guide you used a session to initiate manual leader election for a
|
||||
set of service instances. To fully benefit from this process, instances should also watch the key using a blocking query for any
|
||||
changes. If the leader 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.
|
||||
|
||||
Using the `acquire` param is optional. This means
|
||||
Using the `acquire` parameter is optional. This means
|
||||
that if you use leader election to update a key, you must not update the key
|
||||
without the acquire parameter.
|
||||
|
|
Loading…
Reference in New Issue