From 64a2e486f57b081d779b055a50033365fb174a23 Mon Sep 17 00:00:00 2001 From: kaitlincarter-hc <43049322+kaitlincarter-hc@users.noreply.github.com> Date: Wed, 17 Apr 2019 16:16:15 -0500 Subject: [PATCH] [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> --- .../docs/guides/leader-election.html.md | 122 ++++++++++-------- 1 file changed, 68 insertions(+), 54 deletions(-) diff --git a/website/source/docs/guides/leader-election.html.md b/website/source/docs/guides/leader-election.html.md index 5a5bd86dd..74d65391b 100644 --- a/website/source/docs/guides/leader-election.html.md +++ b/website/source/docs/guides/leader-election.html.md @@ -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//leader ``` -We'll abbreviate this pattern as simply `` 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=` query parameter. The `` of the PUT should be a -JSON object representing the local node. This value is opaque to +`?acquire=` query parameter. + +The `` 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 ``. This will look something like (note that -`` is the ID returned by the call to -[`/v1/session/create`](/api/session.html#session_create)): - -```text -curl -X PUT -d http://localhost:8500/v1/kv/?acquire= +```sh +$ curl -X PUT -d 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 ``. 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 ``. If we ever -notice that the `Session` of the `` 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/?release= +```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 `` to discover who the current -leader is: +### Retrieve the Key -```text -curl http://localhost:8500/v1/kv/ +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": "service/mysql/leader", "LockIndex": 1, "ModifyIndex": 29, "CreateIndex": 29 @@ -114,17 +124,18 @@ curl http://localhost:8500/v1/kv/ ] ``` -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.