Website: GH-730 and cleanup for docs/guides/leader-election.html.

This commit is contained in:
Ryan Breen 2015-02-28 00:08:41 -05:00
parent bca0e55770
commit 42a7251f27
1 changed files with 43 additions and 39 deletions

View File

@ -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.