Sync docs from v2.1.0.RC1 to gh-pages

This commit is contained in:
buildmaster
2018-12-11 18:37:21 +00:00
parent e2e598bec9
commit ed93d0b58b
57 changed files with 2326 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
/*
code highlight CSS resemblign the Eclipse IDE default color schema
@author Costin Leau
*/
.hl-keyword {
color: #7F0055;
font-weight: bold;
}
.hl-comment {
color: #3F5F5F;
font-style: italic;
}
.hl-multiline-comment {
color: #3F5FBF;
font-style: italic;
}
.hl-tag {
color: #3F7F7F;
}
.hl-attribute {
color: #7F007F;
}
.hl-value {
color: #2A00FF;
}
.hl-string {
color: #2A00FF;
}

View File

@@ -0,0 +1,9 @@
@IMPORT url("manual.css");
body.firstpage {
background: url("../images/background.png") no-repeat center top;
}
div.part h1 {
border-top: none;
}

View File

@@ -0,0 +1,6 @@
@IMPORT url("manual.css");
body {
background: url("../images/background.png") no-repeat center top;
}

View File

@@ -0,0 +1,344 @@
@IMPORT url("highlight.css");
html {
padding: 0pt;
margin: 0pt;
}
body {
color: #333333;
margin: 15px 30px;
font-family: Helvetica, Arial, Freesans, Clean, Sans-serif;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
code {
font-size: 16px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
:not(a)>code {
color: #6D180B;
}
:not(pre)>code {
background-color: #F2F2F2;
border: 1px solid #CCCCCC;
border-radius: 4px;
padding: 1px 3px 0;
text-shadow: none;
white-space: nowrap;
}
body>*:first-child {
margin-top: 0 !important;
}
div {
margin: 0pt;
}
hr {
border: 1px solid #CCCCCC;
background: #CCCCCC;
}
h1,h2,h3,h4,h5,h6 {
color: #000000;
cursor: text;
font-weight: bold;
margin: 30px 0 10px;
padding: 0;
}
h1,h2,h3 {
margin: 40px 0 10px;
}
h1 {
margin: 70px 0 30px;
padding-top: 20px;
}
div.part h1 {
border-top: 1px dotted #CCCCCC;
}
h1,h1 code {
font-size: 32px;
}
h2,h2 code {
font-size: 24px;
}
h3,h3 code {
font-size: 20px;
}
h4,h1 code,h5,h5 code,h6,h6 code {
font-size: 18px;
}
div.book,div.chapter,div.appendix,div.part,div.preface {
min-width: 300px;
max-width: 1200px;
margin: 0 auto;
}
p.releaseinfo {
font-weight: bold;
margin-bottom: 40px;
margin-top: 40px;
}
div.authorgroup {
line-height: 1;
}
p.copyright {
line-height: 1;
margin-bottom: -5px;
}
.legalnotice p {
font-style: italic;
font-size: 14px;
line-height: 1;
}
div.titlepage+p,div.titlepage+p {
margin-top: 0;
}
pre {
line-height: 1.0;
color: black;
}
a {
color: #4183C4;
text-decoration: none;
}
p {
margin: 15px 0;
text-align: left;
}
ul,ol {
padding-left: 30px;
}
li p {
margin: 0;
}
div.table {
margin: 1em;
padding: 0.5em;
text-align: center;
}
div.table table,div.informaltable table {
display: table;
width: 100%;
}
div.table td {
padding-left: 7px;
padding-right: 7px;
}
.sidebar {
line-height: 1.4;
padding: 0 20px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
}
.sidebar p.title {
color: #6D180B;
}
pre.programlisting,pre.screen {
font-size: 15px;
padding: 6px 10px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
clear: both;
overflow: auto;
line-height: 1.4;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #DDDDDD !important;
border-radius: 4px !important;
border-collapse: separate !important;
line-height: 1.6;
}
table thead {
background: #F5F5F5;
}
table tr {
border: none;
border-bottom: none;
}
table th {
font-weight: bold;
}
table th,table td {
border: none !important;
padding: 6px 13px;
}
table tr:nth-child(2n) {
background-color: #F8F8F8;
}
td p {
margin: 0 0 15px 0;
}
div.table-contents td p {
margin: 0;
}
div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist *
{
border: none !important;
background: none !important;
margin: 0;
}
div.important p,div.note p,div.tip p,div.warning p {
color: #6F6F6F;
line-height: 1.6;
}
div.important code,div.note code,div.tip code,div.warning code {
background-color: #F2F2F2 !important;
border: 1px solid #CCCCCC !important;
border-radius: 4px !important;
padding: 1px 3px 0 !important;
text-shadow: none !important;
white-space: nowrap !important;
}
.note th,.tip th,.warning th {
display: none;
}
.note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td
{
border-right: 1px solid #CCCCCC !important;
padding-top: 10px;
}
div.calloutlist p,div.calloutlist td {
padding: 0;
margin: 0;
}
div.calloutlist>table>tbody>tr>td:first-child {
padding-left: 10px;
width: 30px !important;
}
div.important,div.note,div.tip,div.warning {
margin-left: 0px !important;
margin-right: 20px !important;
margin-top: 20px;
margin-bottom: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
div.toc {
line-height: 1.2;
}
dl,dt {
margin-top: 1px;
margin-bottom: 0;
}
div.toc>dl>dt {
font-size: 32px;
font-weight: bold;
margin: 30px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dt {
font-size: 24px;
font-weight: bold;
margin: 20px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dd>dl>dt {
font-weight: bold;
font-size: 20px;
margin: 10px 0 0 0;
}
tbody.footnotes * {
border: none !important;
}
div.footnote p {
margin: 0;
line-height: 1;
}
div.footnote p sup {
margin-right: 6px;
vertical-align: middle;
}
div.navheader {
border-bottom: 1px solid #CCCCCC;
}
div.navfooter {
border-top: 1px solid #CCCCCC;
}
.title {
margin-left: -1em;
padding-left: 1em;
}
.title>a {
position: absolute;
visibility: hidden;
display: block;
font-size: 0.85em;
margin-top: 0.05em;
margin-left: -1em;
vertical-align: text-top;
color: black;
}
.title>a:before {
content: "\00A7";
}
.title:hover>a,.title>a:hover,.title:hover>a:hover {
visibility: visible;
}
.title:focus>a,.title>a:focus,.title:focus>a:focus {
outline: 0;
}

View File

@@ -0,0 +1,330 @@
#!/bin/bash -x
set -e
# Set default props like MAVEN_PATH, ROOT_FOLDER etc.
function set_default_props() {
# The script should be executed from the root folder
ROOT_FOLDER=`pwd`
echo "Current folder is ${ROOT_FOLDER}"
if [[ ! -e "${ROOT_FOLDER}/.git" ]]; then
echo "You're not in the root folder of the project!"
exit 1
fi
# Prop that will let commit the changes
COMMIT_CHANGES="no"
MAVEN_PATH=${MAVEN_PATH:-}
echo "Path to Maven is [${MAVEN_PATH}]"
REPO_NAME=${PWD##*/}
echo "Repo name is [${REPO_NAME}]"
SPRING_CLOUD_STATIC_REPO=${SPRING_CLOUD_STATIC_REPO:-git@github.com:spring-cloud/spring-cloud-static.git}
echo "Spring Cloud Static repo is [${SPRING_CLOUD_STATIC_REPO}"
}
# Check if gh-pages exists and docs have been built
function check_if_anything_to_sync() {
git remote set-url --push origin `git config remote.origin.url | sed -e 's/^git:/https:/'`
if ! (git remote set-branches --add origin gh-pages && git fetch -q); then
echo "No gh-pages, so not syncing"
exit 0
fi
if ! [ -d docs/target/generated-docs ] && ! [ "${BUILD}" == "yes" ]; then
echo "No gh-pages sources in docs/target/generated-docs, so not syncing"
exit 0
fi
}
function retrieve_current_branch() {
# Code getting the name of the current branch. For master we want to publish as we did until now
# http://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch
# If there is a branch already passed will reuse it - otherwise will try to find it
CURRENT_BRANCH=${BRANCH}
if [[ -z "${CURRENT_BRANCH}" ]] ; then
CURRENT_BRANCH=$(git symbolic-ref -q HEAD)
CURRENT_BRANCH=${CURRENT_BRANCH##refs/heads/}
CURRENT_BRANCH=${CURRENT_BRANCH:-HEAD}
fi
echo "Current branch is [${CURRENT_BRANCH}]"
git checkout ${CURRENT_BRANCH} || echo "Failed to check the branch... continuing with the script"
}
# Switches to the provided value of the release version. We always prefix it with `v`
function switch_to_tag() {
git checkout v${VERSION}
}
# Build the docs if switch is on
function build_docs_if_applicable() {
if [[ "${BUILD}" == "yes" ]] ; then
./mvnw clean install -P docs -pl docs -DskipTests
fi
}
# Get the name of the `docs.main` property
# Get whitelisted branches - assumes that a `docs` module is available under `docs` profile
function retrieve_doc_properties() {
MAIN_ADOC_VALUE=$("${MAVEN_PATH}"mvn -q \
-Dexec.executable="echo" \
-Dexec.args='${docs.main}' \
--non-recursive \
org.codehaus.mojo:exec-maven-plugin:1.3.1:exec)
echo "Extracted 'main.adoc' from Maven build [${MAIN_ADOC_VALUE}]"
WHITELIST_PROPERTY=${WHITELIST_PROPERTY:-"docs.whitelisted.branches"}
WHITELISTED_BRANCHES_VALUE=$("${MAVEN_PATH}"mvn -q \
-Dexec.executable="echo" \
-Dexec.args="\${${WHITELIST_PROPERTY}}" \
org.codehaus.mojo:exec-maven-plugin:1.3.1:exec \
-P docs \
-pl docs)
echo "Extracted '${WHITELIST_PROPERTY}' from Maven build [${WHITELISTED_BRANCHES_VALUE}]"
}
# Stash any outstanding changes
function stash_changes() {
git diff-index --quiet HEAD && dirty=$? || (echo "Failed to check if the current repo is dirty. Assuming that it is." && dirty="1")
if [ "$dirty" != "0" ]; then git stash; fi
}
# Switch to gh-pages branch to sync it with current branch
function add_docs_from_target() {
local DESTINATION_REPO_FOLDER
if [[ -z "${DESTINATION}" && -z "${CLONE}" ]] ; then
DESTINATION_REPO_FOLDER=${ROOT_FOLDER}
elif [[ "${CLONE}" == "yes" ]]; then
mkdir -p ${ROOT_FOLDER}/target
local clonedStatic=${ROOT_FOLDER}/target/spring-cloud-static
if [[ ! -e "${clonedStatic}/.git" ]]; then
echo "Cloning Spring Cloud Static to target"
git clone ${SPRING_CLOUD_STATIC_REPO} ${clonedStatic} && git checkout gh-pages
else
echo "Spring Cloud Static already cloned - will pull changes"
cd ${clonedStatic} && git checkout gh-pages && git pull origin gh-pages
fi
DESTINATION_REPO_FOLDER=${clonedStatic}/${REPO_NAME}
mkdir -p ${DESTINATION_REPO_FOLDER}
else
if [[ ! -e "${DESTINATION}/.git" ]]; then
echo "[${DESTINATION}] is not a git repository"
exit 1
fi
DESTINATION_REPO_FOLDER=${DESTINATION}/${REPO_NAME}
mkdir -p ${DESTINATION_REPO_FOLDER}
echo "Destination was provided [${DESTINATION}]"
fi
cd ${DESTINATION_REPO_FOLDER}
git checkout gh-pages
git pull origin gh-pages
# Add git branches
###################################################################
if [[ -z "${VERSION}" ]] ; then
copy_docs_for_current_version
else
copy_docs_for_provided_version
fi
commit_changes_if_applicable
}
# Copies the docs by using the retrieved properties from Maven build
function copy_docs_for_current_version() {
if [[ "${CURRENT_BRANCH}" == "master" ]] ; then
echo -e "Current branch is master - will copy the current docs only to the root folder"
for f in docs/target/generated-docs/*; do
file=${f#docs/target/generated-docs/*}
if ! git ls-files -i -o --exclude-standard --directory | grep -q ^$file$; then
# Not ignored...
cp -rf $f ${ROOT_FOLDER}/
git add -A ${ROOT_FOLDER}/$file
fi
done
COMMIT_CHANGES="yes"
else
echo -e "Current branch is [${CURRENT_BRANCH}]"
# http://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin
if [[ ",${WHITELISTED_BRANCHES_VALUE}," = *",${CURRENT_BRANCH},"* ]] ; then
mkdir -p ${ROOT_FOLDER}/${CURRENT_BRANCH}
echo -e "Branch [${CURRENT_BRANCH}] is whitelisted! Will copy the current docs to the [${CURRENT_BRANCH}] folder"
for f in docs/target/generated-docs/*; do
file=${f#docs/target/generated-docs/*}
if ! git ls-files -i -o --exclude-standard --directory | grep -q ^$file$; then
# Not ignored...
# We want users to access 1.0.0.RELEASE/ instead of 1.0.0.RELEASE/spring-cloud.sleuth.html
if [[ "${file}" == "${MAIN_ADOC_VALUE}.html" ]] ; then
# We don't want to copy the spring-cloud-sleuth.html
# we want it to be converted to index.html
cp -rf $f ${ROOT_FOLDER}/${CURRENT_BRANCH}/index.html
git add -A ${ROOT_FOLDER}/${CURRENT_BRANCH}/index.html
else
cp -rf $f ${ROOT_FOLDER}/${CURRENT_BRANCH}
git add -A ${ROOT_FOLDER}/${CURRENT_BRANCH}/$file
fi
fi
done
COMMIT_CHANGES="yes"
else
echo -e "Branch [${CURRENT_BRANCH}] is not on the white list! Check out the Maven [${WHITELIST_PROPERTY}] property in
[docs] module available under [docs] profile. Won't commit any changes to gh-pages for this branch."
fi
fi
}
# Copies the docs by using the explicitly provided version
function copy_docs_for_provided_version() {
local FOLDER=${DESTINATION_REPO_FOLDER}/${VERSION}
mkdir -p ${FOLDER}
echo -e "Current tag is [v${VERSION}] Will copy the current docs to the [${FOLDER}] folder"
for f in ${ROOT_FOLDER}/docs/target/generated-docs/*; do
file=${f#${ROOT_FOLDER}/docs/target/generated-docs/*}
copy_docs_for_branch ${file} ${FOLDER}
done
COMMIT_CHANGES="yes"
CURRENT_BRANCH="v${VERSION}"
}
# Copies the docs from target to the provided destination
# Params:
# $1 - file from target
# $2 - destination to which copy the files
function copy_docs_for_branch() {
local file=$1
local destination=$2
if ! git ls-files -i -o --exclude-standard --directory | grep -q ^${file}$; then
# Not ignored...
# We want users to access 1.0.0.RELEASE/ instead of 1.0.0.RELEASE/spring-cloud.sleuth.html
if [[ ("${file}" == "${MAIN_ADOC_VALUE}.html") || ("${file}" == "${REPO_NAME}.html") ]] ; then
# We don't want to copy the spring-cloud-sleuth.html
# we want it to be converted to index.html
cp -rf $f ${destination}/index.html
git add -A ${destination}/index.html
else
cp -rf $f ${destination}
git add -A ${destination}/$file
fi
fi
}
function commit_changes_if_applicable() {
if [[ "${COMMIT_CHANGES}" == "yes" ]] ; then
COMMIT_SUCCESSFUL="no"
git commit -a -m "Sync docs from ${CURRENT_BRANCH} to gh-pages" && COMMIT_SUCCESSFUL="yes" || echo "Failed to commit changes"
# Uncomment the following push if you want to auto push to
# the gh-pages branch whenever you commit to master locally.
# This is a little extreme. Use with care!
###################################################################
if [[ "${COMMIT_SUCCESSFUL}" == "yes" ]] ; then
git push origin gh-pages
fi
fi
}
# Switch back to the previous branch and exit block
function checkout_previous_branch() {
# If -version was provided we need to come back to root project
cd ${ROOT_FOLDER}
git checkout ${CURRENT_BRANCH} || echo "Failed to check the branch... continuing with the script"
if [ "$dirty" != "0" ]; then git stash pop; fi
exit 0
}
# Assert if properties have been properly passed
function assert_properties() {
echo "VERSION [${VERSION}], DESTINATION [${DESTINATION}], CLONE [${CLONE}]"
if [[ "${VERSION}" != "" && (-z "${DESTINATION}" && -z "${CLONE}") ]] ; then echo "Version was set but destination / clone was not!"; exit 1;fi
if [[ ("${DESTINATION}" != "" && "${CLONE}" != "") && -z "${VERSION}" ]] ; then echo "Destination / clone was set but version was not!"; exit 1;fi
if [[ "${DESTINATION}" != "" && "${CLONE}" == "yes" ]] ; then echo "Destination and clone was set. Pick one!"; exit 1;fi
}
# Prints the usage
function print_usage() {
cat <<EOF
The idea of this script is to update gh-pages branch with the generated docs. Without any options
the script will work in the following manner:
- if there's no gh-pages / target for docs module then the script ends
- for master branch the generated docs are copied to the root of gh-pages branch
- for any other branch (if that branch is whitelisted) a subfolder with branch name is created
and docs are copied there
- if the version switch is passed (-v) then a tag with (v) prefix will be retrieved and a folder
with that version number will be created in the gh-pages branch. WARNING! No whitelist verification will take place
- if the destination switch is passed (-d) then the script will check if the provided dir is a git repo and then will
switch to gh-pages of that repo and copy the generated docs to `docs/<project-name>/<version>`
- if the destination switch is passed (-d) then the script will check if the provided dir is a git repo and then will
switch to gh-pages of that repo and copy the generated docs to `docs/<project-name>/<version>`
USAGE:
You can use the following options:
-v|--version - the script will apply the whole procedure for a particular library version
-d|--destination - the root of destination folder where the docs should be copied. You have to use the full path.
E.g. point to spring-cloud-static folder. Can't be used with (-c)
-b|--build - will run the standard build process after checking out the branch
-c|--clone - will automatically clone the spring-cloud-static repo instead of providing the destination.
Obviously can't be used with (-d)
EOF
}
# ==========================================
# ____ ____ _____ _____ _____ _______
# / ____|/ ____| __ \|_ _| __ \__ __|
# | (___ | | | |__) | | | | |__) | | |
# \___ \| | | _ / | | | ___/ | |
# ____) | |____| | \ \ _| |_| | | |
# |_____/ \_____|_| \_\_____|_| |_|
#
# ==========================================
while [[ $# > 0 ]]
do
key="$1"
case ${key} in
-v|--version)
VERSION="$2"
shift # past argument
;;
-d|--destination)
DESTINATION="$2"
shift # past argument
;;
-b|--build)
BUILD="yes"
;;
-c|--clone)
CLONE="yes"
;;
-h|--help)
print_usage
exit 0
;;
*)
echo "Invalid option: [$1]"
print_usage
exit 1
;;
esac
shift # past argument or value
done
assert_properties
set_default_props
check_if_anything_to_sync
if [[ -z "${VERSION}" ]] ; then
retrieve_current_branch
else
switch_to_tag
fi
build_docs_if_applicable
retrieve_doc_properties
stash_changes
add_docs_from_target
checkout_previous_branch

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,117 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 1.5.7.1">
<title>spring-cloud-consul</title>
<link rel="stylesheet" href="css/manual-singlepage.css">
<style>
.hidden {
display: none;
}
.switch {
border-width: 1px 1px 0 1px;
border-style: solid;
border-color: #7a2518;
display: inline-block;
}
.switch--item {
padding: 10px;
background-color: #ffffff;
color: #7a2518;
display: inline-block;
cursor: pointer;
}
.switch--item.selected {
background-color: #7a2519;
color: #ffffff;
}
</style>
<script src="http://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script>
<script type="text/javascript">
function addBlockSwitches() {
$('.primary').each(function() {
primary = $(this);
createSwitchItem(primary, createBlockSwitch(primary)).item.addClass("selected");
primary.children('.title').remove();
});
$('.secondary').each(function(idx, node) {
secondary = $(node);
primary = findPrimary(secondary);
switchItem = createSwitchItem(secondary, primary.children('.switch'));
switchItem.content.addClass('hidden');
findPrimary(secondary).append(switchItem.content);
secondary.remove();
});
}
function createBlockSwitch(primary) {
blockSwitch = $('<div class="switch"></div>');
primary.prepend(blockSwitch);
return blockSwitch;
}
function findPrimary(secondary) {
candidate = secondary.prev();
while (!candidate.is('.primary')) {
candidate = candidate.prev();
}
return candidate;
}
function createSwitchItem(block, blockSwitch) {
blockName = block.children('.title').text();
content = block.children('.content').first().append(block.next('.colist'));
item = $('<div class="switch--item">' + blockName + '</div>');
item.on('click', '', content, function(e) {
$(this).addClass('selected');
$(this).siblings().removeClass('selected');
e.data.siblings('.content').addClass('hidden');
e.data.removeClass('hidden');
});
blockSwitch.append(item);
return {'item': item, 'content': content};
}
$(addBlockSwitches);
</script>
</head>
<body class="article">
<div id="header">
<h1>spring-cloud-consul</h1>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>2.1.0.RC1</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_pick_the_documentation_option">Pick The Documentation Option</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p><a href="single/spring-cloud-consul.html">Single HTML</a></p>
</li>
<li>
<p><a href="multi/multi_spring-cloud-consul.html">Multi HTML</a></p>
</li>
</ul>
</div>
</div>
</div>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js"></script>
<script>prettyPrint()</script>
</body>
</html>

View File

@@ -0,0 +1,35 @@
/*
code highlight CSS resemblign the Eclipse IDE default color schema
@author Costin Leau
*/
.hl-keyword {
color: #7F0055;
font-weight: bold;
}
.hl-comment {
color: #3F5F5F;
font-style: italic;
}
.hl-multiline-comment {
color: #3F5FBF;
font-style: italic;
}
.hl-tag {
color: #3F7F7F;
}
.hl-attribute {
color: #7F007F;
}
.hl-value {
color: #2A00FF;
}
.hl-string {
color: #2A00FF;
}

View File

@@ -0,0 +1,9 @@
@IMPORT url("manual.css");
body.firstpage {
background: url("../images/background.png") no-repeat center top;
}
div.part h1 {
border-top: none;
}

View File

@@ -0,0 +1,6 @@
@IMPORT url("manual.css");
body {
background: url("../images/background.png") no-repeat center top;
}

View File

@@ -0,0 +1,344 @@
@IMPORT url("highlight.css");
html {
padding: 0pt;
margin: 0pt;
}
body {
color: #333333;
margin: 15px 30px;
font-family: Helvetica, Arial, Freesans, Clean, Sans-serif;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
code {
font-size: 16px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
:not(a)>code {
color: #6D180B;
}
:not(pre)>code {
background-color: #F2F2F2;
border: 1px solid #CCCCCC;
border-radius: 4px;
padding: 1px 3px 0;
text-shadow: none;
white-space: nowrap;
}
body>*:first-child {
margin-top: 0 !important;
}
div {
margin: 0pt;
}
hr {
border: 1px solid #CCCCCC;
background: #CCCCCC;
}
h1,h2,h3,h4,h5,h6 {
color: #000000;
cursor: text;
font-weight: bold;
margin: 30px 0 10px;
padding: 0;
}
h1,h2,h3 {
margin: 40px 0 10px;
}
h1 {
margin: 70px 0 30px;
padding-top: 20px;
}
div.part h1 {
border-top: 1px dotted #CCCCCC;
}
h1,h1 code {
font-size: 32px;
}
h2,h2 code {
font-size: 24px;
}
h3,h3 code {
font-size: 20px;
}
h4,h1 code,h5,h5 code,h6,h6 code {
font-size: 18px;
}
div.book,div.chapter,div.appendix,div.part,div.preface {
min-width: 300px;
max-width: 1200px;
margin: 0 auto;
}
p.releaseinfo {
font-weight: bold;
margin-bottom: 40px;
margin-top: 40px;
}
div.authorgroup {
line-height: 1;
}
p.copyright {
line-height: 1;
margin-bottom: -5px;
}
.legalnotice p {
font-style: italic;
font-size: 14px;
line-height: 1;
}
div.titlepage+p,div.titlepage+p {
margin-top: 0;
}
pre {
line-height: 1.0;
color: black;
}
a {
color: #4183C4;
text-decoration: none;
}
p {
margin: 15px 0;
text-align: left;
}
ul,ol {
padding-left: 30px;
}
li p {
margin: 0;
}
div.table {
margin: 1em;
padding: 0.5em;
text-align: center;
}
div.table table,div.informaltable table {
display: table;
width: 100%;
}
div.table td {
padding-left: 7px;
padding-right: 7px;
}
.sidebar {
line-height: 1.4;
padding: 0 20px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
}
.sidebar p.title {
color: #6D180B;
}
pre.programlisting,pre.screen {
font-size: 15px;
padding: 6px 10px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
clear: both;
overflow: auto;
line-height: 1.4;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #DDDDDD !important;
border-radius: 4px !important;
border-collapse: separate !important;
line-height: 1.6;
}
table thead {
background: #F5F5F5;
}
table tr {
border: none;
border-bottom: none;
}
table th {
font-weight: bold;
}
table th,table td {
border: none !important;
padding: 6px 13px;
}
table tr:nth-child(2n) {
background-color: #F8F8F8;
}
td p {
margin: 0 0 15px 0;
}
div.table-contents td p {
margin: 0;
}
div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist *
{
border: none !important;
background: none !important;
margin: 0;
}
div.important p,div.note p,div.tip p,div.warning p {
color: #6F6F6F;
line-height: 1.6;
}
div.important code,div.note code,div.tip code,div.warning code {
background-color: #F2F2F2 !important;
border: 1px solid #CCCCCC !important;
border-radius: 4px !important;
padding: 1px 3px 0 !important;
text-shadow: none !important;
white-space: nowrap !important;
}
.note th,.tip th,.warning th {
display: none;
}
.note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td
{
border-right: 1px solid #CCCCCC !important;
padding-top: 10px;
}
div.calloutlist p,div.calloutlist td {
padding: 0;
margin: 0;
}
div.calloutlist>table>tbody>tr>td:first-child {
padding-left: 10px;
width: 30px !important;
}
div.important,div.note,div.tip,div.warning {
margin-left: 0px !important;
margin-right: 20px !important;
margin-top: 20px;
margin-bottom: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
div.toc {
line-height: 1.2;
}
dl,dt {
margin-top: 1px;
margin-bottom: 0;
}
div.toc>dl>dt {
font-size: 32px;
font-weight: bold;
margin: 30px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dt {
font-size: 24px;
font-weight: bold;
margin: 20px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dd>dl>dt {
font-weight: bold;
font-size: 20px;
margin: 10px 0 0 0;
}
tbody.footnotes * {
border: none !important;
}
div.footnote p {
margin: 0;
line-height: 1;
}
div.footnote p sup {
margin-right: 6px;
vertical-align: middle;
}
div.navheader {
border-bottom: 1px solid #CCCCCC;
}
div.navfooter {
border-top: 1px solid #CCCCCC;
}
.title {
margin-left: -1em;
padding-left: 1em;
}
.title>a {
position: absolute;
visibility: hidden;
display: block;
font-size: 0.85em;
margin-top: 0.05em;
margin-left: -1em;
vertical-align: text-top;
color: black;
}
.title>a:before {
content: "\00A7";
}
.title:hover>a,.title>a:hover,.title:hover>a:hover {
visibility: visible;
}
.title:focus>a,.title>a:focus,.title:focus>a:focus {
outline: 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,9 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title></title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="up" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="prev" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="next" href="multi_spring-cloud-consul-install.html" title="1.&nbsp;Install Consul"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center"></th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_spring-cloud-consul.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi_spring-cloud-consul-install.html">Next</a></td></tr></table><hr></div><div class="preface"><div class="titlepage"><div><div><h1 class="title"><a name="d0e9" href="#d0e9"></a></h1></div></div></div><p><span class="strong"><strong>2.1.0.RC1</strong></span></p><p>This project provides Consul integrations for Spring Boot apps through autoconfiguration
and binding to the Spring Environment and other Spring programming model idioms. With a few
simple annotations you can quickly enable and configure the common patterns inside your
application and build large distributed systems with Consul based components. The
patterns provided include Service Discovery, Control Bus and Configuration.
Intelligent Routing (Zuul) and Client Side Load Balancing (Ribbon), Circuit Breaker
(Hystrix) are provided by integration with Spring Cloud Netflix.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_spring-cloud-consul.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi_spring-cloud-consul-install.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Spring Cloud Consul&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-consul.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;1.&nbsp;Install Consul</td></tr></table></div></body></html>

View File

@@ -0,0 +1,3 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>2.&nbsp;Consul Agent</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="up" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="prev" href="multi_spring-cloud-consul-install.html" title="1.&nbsp;Install Consul"><link rel="next" href="multi_spring-cloud-consul-discovery.html" title="3.&nbsp;Service Discovery with Consul"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">2.&nbsp;Consul Agent</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_spring-cloud-consul-install.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi_spring-cloud-consul-discovery.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="spring-cloud-consul-agent" href="#spring-cloud-consul-agent"></a>2.&nbsp;Consul Agent</h1></div></div></div><p>A Consul Agent client must be available to all Spring Cloud Consul applications. By default, the Agent client is expected to be at <code class="literal">localhost:8500</code>. See the <a class="link" href="https://consul.io/docs/agent/basics.html" target="_top">Agent documentation</a> for specifics on how to start an Agent client and how to connect to a cluster of Consul Agent Servers. For development, after you have installed consul, you may start a Consul Agent using the following command:</p><pre class="screen">./src/main/bash/local_run_consul.sh</pre><p>This will start an agent in server mode on port 8500, with the ui available at <a class="link" href="http://localhost:8500" target="_top">http://localhost:8500</a></p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_spring-cloud-consul-install.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi_spring-cloud-consul-discovery.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">1.&nbsp;Install Consul&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-consul.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;3.&nbsp;Service Discovery with Consul</td></tr></table></div></body></html>

View File

@@ -0,0 +1,3 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>6.&nbsp;Spring Cloud Bus with Consul</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="up" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="prev" href="multi_spring-cloud-consul-retry.html" title="5.&nbsp;Consul Retry"><link rel="next" href="multi_spring-cloud-consul-hystrix.html" title="7.&nbsp;Circuit Breaker with Hystrix"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">6.&nbsp;Spring Cloud Bus with Consul</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_spring-cloud-consul-retry.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi_spring-cloud-consul-hystrix.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="spring-cloud-consul-bus" href="#spring-cloud-consul-bus"></a>6.&nbsp;Spring Cloud Bus with Consul</h1></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_how_to_activate_3" href="#_how_to_activate_3"></a>6.1&nbsp;How to activate</h2></div></div></div><p>To get started with the Consul Bus use the starter with group <code class="literal">org.springframework.cloud</code> and artifact id <code class="literal">spring-cloud-starter-consul-bus</code>. See the <a class="link" href="http://projects.spring.io/spring-cloud/" target="_top">Spring Cloud Project page</a> for details on setting up your build system with the current Spring Cloud Release Train.</p><p>See the <a class="link" href="https://cloud.spring.io/spring-cloud-bus/" target="_top">Spring Cloud Bus</a> documentation for the available actuator endpoints and howto send custom messages.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_spring-cloud-consul-retry.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi_spring-cloud-consul-hystrix.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5.&nbsp;Consul Retry&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-consul.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;7.&nbsp;Circuit Breaker with Hystrix</td></tr></table></div></body></html>

View File

@@ -0,0 +1,38 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>4.&nbsp;Distributed Configuration with Consul</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="up" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="prev" href="multi_spring-cloud-consul-discovery.html" title="3.&nbsp;Service Discovery with Consul"><link rel="next" href="multi_spring-cloud-consul-retry.html" title="5.&nbsp;Consul Retry"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">4.&nbsp;Distributed Configuration with Consul</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_spring-cloud-consul-discovery.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi_spring-cloud-consul-retry.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="spring-cloud-consul-config" href="#spring-cloud-consul-config"></a>4.&nbsp;Distributed Configuration with Consul</h1></div></div></div><p>Consul provides a <a class="link" href="https://consul.io/docs/agent/http/kv.html" target="_top">Key/Value Store</a> for storing configuration and other metadata. Spring Cloud Consul Config is an alternative to the <a class="link" href="https://github.com/spring-cloud/spring-cloud-config" target="_top">Config Server and Client</a>. Configuration is loaded into the Spring Environment during the special "bootstrap" phase. Configuration is stored in the <code class="literal">/config</code> folder by default. Multiple <code class="literal">PropertySource</code> instances are created based on the application&#8217;s name and the active profiles that mimicks the Spring Cloud Config order of resolving properties. For example, an application with the name "testApp" and with the "dev" profile will have the following property sources created:</p><pre class="screen">config/testApp,dev/
config/testApp/
config/application,dev/
config/application/</pre><p>The most specific property source is at the top, with the least specific at the bottom. Properties in the <code class="literal">config/application</code> folder are applicable to all applications using consul for configuration. Properties in the <code class="literal">config/testApp</code> folder are only available to the instances of the service named "testApp".</p><p>Configuration is currently read on startup of the application. Sending a HTTP POST to <code class="literal">/refresh</code> will cause the configuration to be reloaded. <a class="xref" href="multi_spring-cloud-consul-config.html#spring-cloud-consul-config-watch" title="4.3&nbsp;Config Watch">Section&nbsp;4.3, &#8220;Config Watch&#8221;</a> will also automatically detect changes and reload the application context.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_how_to_activate_2" href="#_how_to_activate_2"></a>4.1&nbsp;How to activate</h2></div></div></div><p>To get started with Consul Configuration use the starter with group <code class="literal">org.springframework.cloud</code> and artifact id <code class="literal">spring-cloud-starter-consul-config</code>. See the <a class="link" href="http://projects.spring.io/spring-cloud/" target="_top">Spring Cloud Project page</a> for details on setting up your build system with the current Spring Cloud Release Train.</p><p>This will enable auto-configuration that will setup Spring Cloud Consul Config.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_customizing" href="#_customizing"></a>4.2&nbsp;Customizing</h2></div></div></div><p>Consul Config may be customized using the following properties:</p><p><b>bootstrap.yml.&nbsp;</b>
</p><pre class="screen">spring:
cloud:
consul:
config:
enabled: true
prefix: configuration
defaultContext: apps
profileSeparator: '::'</pre><p>
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">enabled</code> setting this value to "false" disables Consul Config</li><li class="listitem"><code class="literal">prefix</code> sets the base folder for configuration values</li><li class="listitem"><code class="literal">defaultContext</code> sets the folder name used by all applications</li><li class="listitem"><code class="literal">profileSeparator</code> sets the value of the separator used to separate the profile name in property sources with profiles</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-cloud-consul-config-watch" href="#spring-cloud-consul-config-watch"></a>4.3&nbsp;Config Watch</h2></div></div></div><p>The Consul Config Watch takes advantage of the ability of consul to <a class="link" href="https://www.consul.io/docs/agent/watches.html#keyprefix" target="_top">watch a key prefix</a>. The Config Watch makes a blocking Consul HTTP API call to determine if any relevant configuration data has changed for the current application. If there is new configuration data a Refresh Event is published. This is equivalent to calling the <code class="literal">/refresh</code> actuator endpoint.</p><p>To change the frequency of when the Config Watch is called change <code class="literal">spring.cloud.consul.config.watch.delay</code>. The default value is 1000, which is in milliseconds. The delay is the amount of time after the end of the previous invocation and the start of the next.</p><p>To disable the Config Watch set <code class="literal">spring.cloud.consul.config.watch.enabled=false</code>.</p><p>The watch uses a Spring <code class="literal">TaskScheduler</code> to schedule the call to consul. By default it is a <code class="literal">ThreadPoolTaskScheduler</code> with a <code class="literal">poolSize</code> of 1. To change the <code class="literal">TaskScheduler</code>, create a bean of type <code class="literal">TaskScheduler</code> named with the <code class="literal">ConsulConfigAutoConfiguration.CONFIG_WATCH_TASK_SCHEDULER_NAME</code> constant.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-cloud-consul-config-format" href="#spring-cloud-consul-config-format"></a>4.4&nbsp;YAML or Properties with Config</h2></div></div></div><p>It may be more convenient to store a blob of properties in YAML or Properties format as opposed to individual key/value pairs. Set the <code class="literal">spring.cloud.consul.config.format</code> property to <code class="literal">YAML</code> or <code class="literal">PROPERTIES</code>. For example to use YAML:</p><p><b>bootstrap.yml.&nbsp;</b>
</p><pre class="screen">spring:
cloud:
consul:
config:
format: YAML</pre><p>
</p><p>YAML must be set in the appropriate <code class="literal">data</code> key in consul. Using the defaults above the keys would look like:</p><pre class="screen">config/testApp,dev/data
config/testApp/data
config/application,dev/data
config/application/data</pre><p>You could store a YAML document in any of the keys listed above.</p><p>You can change the data key using <code class="literal">spring.cloud.consul.config.data-key</code>.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-cloud-consul-config-git2consul" href="#spring-cloud-consul-config-git2consul"></a>4.5&nbsp;git2consul with Config</h2></div></div></div><p>git2consul is a Consul community project that loads files from a git repository to individual keys into Consul. By default the names of the keys are names of the files. YAML and Properties files are supported with file extensions of <code class="literal">.yml</code> and <code class="literal">.properties</code> respectively. Set the <code class="literal">spring.cloud.consul.config.format</code> property to <code class="literal">FILES</code>. For example:</p><p><b>bootstrap.yml.&nbsp;</b>
</p><pre class="screen">spring:
cloud:
consul:
config:
format: FILES</pre><p>
</p><p>Given the following keys in <code class="literal">/config</code>, the <code class="literal">development</code> profile and an application name of <code class="literal">foo</code>:</p><pre class="screen">.gitignore
application.yml
bar.properties
foo-development.properties
foo-production.yml
foo.properties
master.ref</pre><p>the following property sources would be created:</p><pre class="screen">config/foo-development.properties
config/foo.properties
config/application.yml</pre><p>The value of each key needs to be a properly formatted YAML or Properties file.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-cloud-consul-failfast" href="#spring-cloud-consul-failfast"></a>4.6&nbsp;Fail Fast</h2></div></div></div><p>It may be convenient in certain circumstances (like local development or certain test scenarios) to not fail if consul isn&#8217;t available for configuration. Setting <code class="literal">spring.cloud.consul.config.failFast=false</code> in <code class="literal">bootstrap.yml</code> will cause the configuration module to log a warning rather than throw an exception. This will allow the application to continue startup normally.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_spring-cloud-consul-discovery.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi_spring-cloud-consul-retry.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">3.&nbsp;Service Discovery with Consul&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-consul.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;5.&nbsp;Consul Retry</td></tr></table></div></body></html>

View File

@@ -0,0 +1,78 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>3.&nbsp;Service Discovery with Consul</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="up" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="prev" href="multi_spring-cloud-consul-agent.html" title="2.&nbsp;Consul Agent"><link rel="next" href="multi_spring-cloud-consul-config.html" title="4.&nbsp;Distributed Configuration with Consul"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">3.&nbsp;Service Discovery with Consul</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_spring-cloud-consul-agent.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi_spring-cloud-consul-config.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="spring-cloud-consul-discovery" href="#spring-cloud-consul-discovery"></a>3.&nbsp;Service Discovery with Consul</h1></div></div></div><p>Service Discovery is one of the key tenets of a microservice based architecture. Trying to hand configure each client or some form of convention can be very difficult to do and can be very brittle. Consul provides Service Discovery services via an <a class="link" href="https://www.consul.io/docs/agent/http.html" target="_top">HTTP API</a> and <a class="link" href="https://www.consul.io/docs/agent/dns.html" target="_top">DNS</a>. Spring Cloud Consul leverages the HTTP API for service registration and discovery. This does not prevent non-Spring Cloud applications from leveraging the DNS interface. Consul Agents servers are run in a <a class="link" href="https://www.consul.io/docs/internals/architecture.html" target="_top">cluster</a> that communicates via a <a class="link" href="https://www.consul.io/docs/internals/gossip.html" target="_top">gossip protocol</a> and uses the <a class="link" href="https://www.consul.io/docs/internals/consensus.html" target="_top">Raft consensus protocol</a>.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_how_to_activate" href="#_how_to_activate"></a>3.1&nbsp;How to activate</h2></div></div></div><p>To activate Consul Service Discovery use the starter with group <code class="literal">org.springframework.cloud</code> and artifact id <code class="literal">spring-cloud-starter-consul-discovery</code>. See the <a class="link" href="http://projects.spring.io/spring-cloud/" target="_top">Spring Cloud Project page</a> for details on setting up your build system with the current Spring Cloud Release Train.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_registering_with_consul" href="#_registering_with_consul"></a>3.2&nbsp;Registering with Consul</h2></div></div></div><p>When a client registers with Consul, it provides meta-data about itself such as host and port, id, name and tags. An HTTP <a class="link" href="https://www.consul.io/docs/agent/checks.html" target="_top">Check</a> is created by default that Consul hits the <code class="literal">/health</code> endpoint every 10 seconds. If the health check fails, the service instance is marked as critical.</p><p>Example Consul client:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@SpringBootApplication</span></em>
<em><span class="hl-annotation" style="color: gray">@RestController</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
<em><span class="hl-annotation" style="color: gray">@RequestMapping("/")</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String home() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Hello world"</span>;
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> main(String[] args) {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> SpringApplicationBuilder(Application.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>).web(true).run(args);
}
}</pre><p>(i.e. utterly normal Spring Boot app). If the Consul client is located somewhere other than <code class="literal">localhost:8500</code>, the configuration is required to locate the client. Example:</p><p><b>application.yml.&nbsp;</b>
</p><pre class="screen">spring:
cloud:
consul:
host: localhost
port: 8500</pre><p>
</p><div class="caution" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Caution"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Caution]" src="images/caution.png"></td><th align="left">Caution</th></tr><tr><td align="left" valign="top"><p>If you use <a class="link" href="multi_spring-cloud-consul-config.html" title="4.&nbsp;Distributed Configuration with Consul">Spring Cloud Consul Config</a>, the above values will need to be placed in <code class="literal">bootstrap.yml</code> instead of <code class="literal">application.yml</code>.</p></td></tr></table></div><p>The default service name, instance id and port, taken from the <code class="literal">Environment</code>, are <code class="literal">${spring.application.name}</code>, the Spring Context ID and <code class="literal">${server.port}</code> respectively.</p><p>To disable the Consul Discovery Client you can set <code class="literal">spring.cloud.consul.discovery.enabled</code> to <code class="literal">false</code>.</p><p>To disable the service registration you can set <code class="literal">spring.cloud.consul.discovery.register</code> to <code class="literal">false</code>.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_http_health_check" href="#_http_health_check"></a>3.3&nbsp;HTTP Health Check</h2></div></div></div><p>The health check for a Consul instance defaults to "/health", which is the default locations of a useful endpoint in a Spring Boot Actuator application. You need to change these, even for an Actuator application if you use a non-default context path or servlet path (e.g. <code class="literal">server.servletPath=/foo</code>) or management endpoint path (e.g. <code class="literal">management.server.servlet.context-path=/admin</code>). The interval that Consul uses to check the health endpoint may also be configured. "10s" and "1m" represent 10 seconds and 1 minute respectively. Example:</p><p><b>application.yml.&nbsp;</b>
</p><pre class="screen">spring:
cloud:
consul:
discovery:
healthCheckPath: ${management.server.servlet.context-path}/health
healthCheckInterval: 15s</pre><p>
</p><p>You can disable the health check by setting <code class="literal">management.health.consul.enabled=false</code>.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_metadata_and_consul_tags" href="#_metadata_and_consul_tags"></a>3.3.1&nbsp;Metadata and Consul tags</h3></div></div></div><p>Consul does not yet support metadata on services. Spring Cloud&#8217;s <code class="literal">ServiceInstance</code> has a <code class="literal">Map&lt;String, String&gt; metadata</code> field. Spring Cloud Consul uses Consul tags to approximate metadata until Consul officially supports metadata. Tags with the form <code class="literal">key=value</code> will be split and used as a <code class="literal">Map</code> key and value respectively. Tags without the equal <code class="literal">=</code> sign, will be used as both the key and value.</p><p><b>application.yml.&nbsp;</b>
</p><pre class="screen">spring:
cloud:
consul:
discovery:
tags: foo=bar, baz</pre><p>
</p><p>The above configuration will result in a map with <code class="literal">foo&#8594;bar</code> and <code class="literal">baz&#8594;baz</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_making_the_consul_instance_id_unique" href="#_making_the_consul_instance_id_unique"></a>3.3.2&nbsp;Making the Consul Instance ID Unique</h3></div></div></div><p>By default a consul instance is registered with an ID that is equal to its Spring Application Context ID. By default, the Spring Application Context ID is <code class="literal">${spring.application.name}:comma,separated,profiles:${server.port}</code>. For most cases, this will allow multiple instances of one service to run on one machine. If further uniqueness is required, Using Spring Cloud you can override this by providing a unique identifier in <code class="literal">spring.cloud.consul.discovery.instanceId</code>. For example:</p><p><b>application.yml.&nbsp;</b>
</p><pre class="screen">spring:
cloud:
consul:
discovery:
instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}</pre><p>
</p><p>With this metadata, and multiple service instances deployed on localhost, the random value will kick in there to make the instance unique. In Cloudfoundry the <code class="literal">vcap.application.instance_id</code> will be populated automatically in a Spring Boot application, so the random value will not be needed.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_applying_headers_to_health_check_requests" href="#_applying_headers_to_health_check_requests"></a>3.3.3&nbsp;Applying Headers to Health Check Requests</h3></div></div></div><p>Headers can be applied to health check requests. For example, if you&#8217;re trying to register a <a class="link" href="https://cloud.spring.io/spring-cloud-config/" target="_top">Spring Cloud Config</a> server that uses <a class="link" href="https://github.com/spring-cloud/spring-cloud-config/blob/master/docs/src/main/asciidoc/spring-cloud-config.adoc#vault-backend" target="_top">Vault Backend</a>:</p><p><b>application.yml.&nbsp;</b>
</p><pre class="screen">spring:
cloud:
consul:
discovery:
health-check-headers:
X-Config-Token: 6442e58b-d1ea-182e-cfa5-cf9cddef0722</pre><p>
</p><p>According to the HTTP standard, each header can have more than one values, in which case, an array can be supplied:</p><p><b>application.yml.&nbsp;</b>
</p><pre class="screen">spring:
cloud:
consul:
discovery:
health-check-headers:
X-Config-Token:
- "6442e58b-d1ea-182e-cfa5-cf9cddef0722"
- "Some other value"</pre><p>
</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_looking_up_services" href="#_looking_up_services"></a>3.4&nbsp;Looking up services</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_using_ribbon" href="#_using_ribbon"></a>3.4.1&nbsp;Using Ribbon</h3></div></div></div><p>Spring Cloud has support for <a class="link" href="https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-feign" target="_top">Feign</a> (a REST client builder) and also <a class="link" href="https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-ribbon" target="_top">Spring <code class="literal">RestTemplate</code></a>
for looking up services using the logical service names/ids instead of physical URLs. Both Feign and the discovery-aware RestTemplate utilize <a class="link" href="http://cloud.spring.io/spring-cloud-netflix/single/spring-cloud-netflix.html#spring-cloud-ribbon" target="_top">Ribbon</a> for client-side load balancing.</p><p>If you want to access service STORES using the RestTemplate simply declare:</p><pre class="screen">@LoadBalanced
@Bean
public RestTemplate loadbalancedRestTemplate() {
new RestTemplate();
}</pre><p>and use it like this (notice how we use the STORES service name/id from Consul instead of a fully qualified domainname):</p><pre class="screen">@Autowired
RestTemplate restTemplate;
public String getFirstProduct() {
return this.restTemplate.getForObject("https://STORES/products/1", String.class);
}</pre><p>If you have Consul clusters in multiple datacenters and you want to access a service in another datacenter a service name/id alone is not enough. In that case
you use property <code class="literal">spring.cloud.consul.discovery.datacenters.STORES=dc-west</code> where <code class="literal">STORES</code> is the service name/id and <code class="literal">dc-west</code> is the datacenter
where the STORES service lives.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_using_the_discoveryclient" href="#_using_the_discoveryclient"></a>3.4.2&nbsp;Using the DiscoveryClient</h3></div></div></div><p>You can also use the <code class="literal">org.springframework.cloud.client.discovery.DiscoveryClient</code> which provides a simple API for discovery clients that is not specific to Netflix, e.g.</p><pre class="screen">@Autowired
private DiscoveryClient discoveryClient;
public String serviceUrl() {
List&lt;ServiceInstance&gt; list = discoveryClient.getInstances("STORES");
if (list != null &amp;&amp; list.size() &gt; 0 ) {
return list.get(0).getUri();
}
return null;
}</pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_consul_catalog_watch" href="#_consul_catalog_watch"></a>3.5&nbsp;Consul Catalog Watch</h2></div></div></div><p>The Consul Catalog Watch takes advantage of the ability of consul to <a class="link" href="https://www.consul.io/docs/agent/watches.html#services" target="_top">watch services</a>. The Catalog Watch makes a blocking Consul HTTP API call to determine if any services have changed. If there is new service data a Heartbeat Event is published.</p><p>To change the frequency of when the Config Watch is called change <code class="literal">spring.cloud.consul.config.discovery.catalog-services-watch-delay</code>. The default value is 1000, which is in milliseconds. The delay is the amount of time after the end of the previous invocation and the start of the next.</p><p>To disable the Catalog Watch set <code class="literal">spring.cloud.consul.discovery.catalogServicesWatch.enabled=false</code>.</p><p>The watch uses a Spring <code class="literal">TaskScheduler</code> to schedule the call to consul. By default it is a <code class="literal">ThreadPoolTaskScheduler</code> with a <code class="literal">poolSize</code> of 1. To change the <code class="literal">TaskScheduler</code>, create a bean of type <code class="literal">TaskScheduler</code> named with the <code class="literal">ConsulDiscoveryClientConfiguration.CATALOG_WATCH_TASK_SCHEDULER_NAME</code> constant.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_spring-cloud-consul-agent.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi_spring-cloud-consul-config.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">2.&nbsp;Consul Agent&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-consul.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;4.&nbsp;Distributed Configuration with Consul</td></tr></table></div></body></html>

View File

@@ -0,0 +1,3 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>7.&nbsp;Circuit Breaker with Hystrix</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="up" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="prev" href="multi_spring-cloud-consul-bus.html" title="6.&nbsp;Spring Cloud Bus with Consul"><link rel="next" href="multi_spring-cloud-consul-turbine.html" title="8.&nbsp;Hystrix metrics aggregation with Turbine and Consul"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">7.&nbsp;Circuit Breaker with Hystrix</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_spring-cloud-consul-bus.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi_spring-cloud-consul-turbine.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="spring-cloud-consul-hystrix" href="#spring-cloud-consul-hystrix"></a>7.&nbsp;Circuit Breaker with Hystrix</h1></div></div></div><p>Applications can use the Hystrix Circuit Breaker provided by the Spring Cloud Netflix project by including this starter in the projects pom.xml: <code class="literal">spring-cloud-starter-hystrix</code>. Hystrix doesn&#8217;t depend on the Netflix Discovery Client. The <code class="literal">@EnableHystrix</code> annotation should be placed on a configuration class (usually the main class). Then methods can be annotated with <code class="literal">@HystrixCommand</code> to be protected by a circuit breaker. See <a class="link" href="http://projects.spring.io/spring-cloud/spring-cloud.html#_circuit_breaker_hystrix_clients" target="_top">the documentation</a> for more details.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_spring-cloud-consul-bus.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi_spring-cloud-consul-turbine.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">6.&nbsp;Spring Cloud Bus with Consul&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-consul.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;8.&nbsp;Hystrix metrics aggregation with Turbine and Consul</td></tr></table></div></body></html>

View File

@@ -0,0 +1,3 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>1.&nbsp;Install Consul</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="up" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="prev" href="multi_pr01.html" title=""><link rel="next" href="multi_spring-cloud-consul-agent.html" title="2.&nbsp;Consul Agent"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">1.&nbsp;Install Consul</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_pr01.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi_spring-cloud-consul-agent.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="spring-cloud-consul-install" href="#spring-cloud-consul-install"></a>1.&nbsp;Install Consul</h1></div></div></div><p>Please see the <a class="link" href="https://www.consul.io/intro/getting-started/install.html" target="_top">installation documentation</a> for instructions on how to install Consul.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_pr01.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi_spring-cloud-consul-agent.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-consul.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;2.&nbsp;Consul Agent</td></tr></table></div></body></html>

View File

@@ -0,0 +1,11 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>5.&nbsp;Consul Retry</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="up" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="prev" href="multi_spring-cloud-consul-config.html" title="4.&nbsp;Distributed Configuration with Consul"><link rel="next" href="multi_spring-cloud-consul-bus.html" title="6.&nbsp;Spring Cloud Bus with Consul"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">5.&nbsp;Consul Retry</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_spring-cloud-consul-config.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi_spring-cloud-consul-bus.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="spring-cloud-consul-retry" href="#spring-cloud-consul-retry"></a>5.&nbsp;Consul Retry</h1></div></div></div><p>If you expect that the consul agent may occasionally be unavailable when
your app starts, you can ask it to keep trying after a failure. You need to add
<code class="literal">spring-retry</code> and <code class="literal">spring-boot-starter-aop</code> to your classpath. The default
behaviour is to retry 6 times with an initial backoff interval of 1000ms and an
exponential multiplier of 1.1 for subsequent backoffs. You can configure these
properties (and others) using <code class="literal">spring.cloud.consul.retry.*</code> configuration properties.
This works with both Spring Cloud Consul Config and Discovery registration.</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>To take full control of the retry add a <code class="literal">@Bean</code> of type
<code class="literal">RetryOperationsInterceptor</code> with id "consulRetryInterceptor". Spring
Retry has a <code class="literal">RetryInterceptorBuilder</code> that makes it easy to create one.</p></td></tr></table></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_spring-cloud-consul-config.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi_spring-cloud-consul-bus.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">4.&nbsp;Distributed Configuration with Consul&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-consul.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;6.&nbsp;Spring Cloud Bus with Consul</td></tr></table></div></body></html>

View File

@@ -0,0 +1,27 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>8.&nbsp;Hystrix metrics aggregation with Turbine and Consul</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="up" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="prev" href="multi_spring-cloud-consul-hystrix.html" title="7.&nbsp;Circuit Breaker with Hystrix"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">8.&nbsp;Hystrix metrics aggregation with Turbine and Consul</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_spring-cloud-consul-hystrix.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;</td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="spring-cloud-consul-turbine" href="#spring-cloud-consul-turbine"></a>8.&nbsp;Hystrix metrics aggregation with Turbine and Consul</h1></div></div></div><p>Turbine (provided by the Spring Cloud Netflix project), aggregates multiple instances Hystrix metrics streams, so the dashboard can display an aggregate view. Turbine uses the <code class="literal">DiscoveryClient</code> interface to lookup relevant instances. To use Turbine with Spring Cloud Consul, configure the Turbine application in a manner similar to the following examples:</p><p><b>pom.xml.&nbsp;</b>
</p><pre class="screen">&lt;dependency&gt;
&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
&lt;artifactId&gt;spring-cloud-netflix-turbine&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
&lt;artifactId&gt;spring-cloud-starter-consul-discovery&lt;/artifactId&gt;
&lt;/dependency&gt;</pre><p>
</p><p>Notice that the Turbine dependency is not a starter. The turbine starter includes support for Netflix Eureka.</p><p><b>application.yml.&nbsp;</b>
</p><pre class="screen">spring.application.name: turbine
applications: consulhystrixclient
turbine:
aggregator:
clusterConfig: ${applications}
appConfig: ${applications}</pre><p>
</p><p>The <code class="literal">clusterConfig</code> and <code class="literal">appConfig</code> sections must match, so it&#8217;s useful to put the comma-separated list of service ID&#8217;s into a separate configuration property.</p><p><b>Turbine.java.&nbsp;</b>
</p><pre class="screen">@EnableTurbine
@SpringBootApplication
public class Turbine {
public static void main(String[] args) {
SpringApplication.run(DemoturbinecommonsApplication.class, args);
}
}</pre><p>
</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_spring-cloud-consul-hystrix.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;</td></tr><tr><td width="40%" align="left" valign="top">7.&nbsp;Circuit Breaker with Hystrix&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-consul.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;</td></tr></table></div></body></html>

View File

@@ -0,0 +1,3 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring Cloud Consul</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-consul.html" title="Spring Cloud Consul"><link rel="next" href="multi_pr01.html" title=""></head><body class="firstpage" bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Spring Cloud Consul</th></tr><tr><td width="20%" align="left">&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi_pr01.html">Next</a></td></tr></table><hr></div><div lang="en" class="book"><div class="titlepage"><div><div><h1 class="title"><a name="d0e3"></a>Spring Cloud Consul</h1></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="preface"><a href="multi_pr01.html"></a></span></dt><dt><span class="chapter"><a href="multi_spring-cloud-consul-install.html">1. Install Consul</a></span></dt><dt><span class="chapter"><a href="multi_spring-cloud-consul-agent.html">2. Consul Agent</a></span></dt><dt><span class="chapter"><a href="multi_spring-cloud-consul-discovery.html">3. Service Discovery with Consul</a></span></dt><dd><dl><dt><span class="section"><a href="multi_spring-cloud-consul-discovery.html#_how_to_activate">3.1. How to activate</a></span></dt><dt><span class="section"><a href="multi_spring-cloud-consul-discovery.html#_registering_with_consul">3.2. Registering with Consul</a></span></dt><dt><span class="section"><a href="multi_spring-cloud-consul-discovery.html#_http_health_check">3.3. HTTP Health Check</a></span></dt><dd><dl><dt><span class="section"><a href="multi_spring-cloud-consul-discovery.html#_metadata_and_consul_tags">3.3.1. Metadata and Consul tags</a></span></dt><dt><span class="section"><a href="multi_spring-cloud-consul-discovery.html#_making_the_consul_instance_id_unique">3.3.2. Making the Consul Instance ID Unique</a></span></dt><dt><span class="section"><a href="multi_spring-cloud-consul-discovery.html#_applying_headers_to_health_check_requests">3.3.3. Applying Headers to Health Check Requests</a></span></dt></dl></dd><dt><span class="section"><a href="multi_spring-cloud-consul-discovery.html#_looking_up_services">3.4. Looking up services</a></span></dt><dd><dl><dt><span class="section"><a href="multi_spring-cloud-consul-discovery.html#_using_ribbon">3.4.1. Using Ribbon</a></span></dt><dt><span class="section"><a href="multi_spring-cloud-consul-discovery.html#_using_the_discoveryclient">3.4.2. Using the DiscoveryClient</a></span></dt></dl></dd><dt><span class="section"><a href="multi_spring-cloud-consul-discovery.html#_consul_catalog_watch">3.5. Consul Catalog Watch</a></span></dt></dl></dd><dt><span class="chapter"><a href="multi_spring-cloud-consul-config.html">4. Distributed Configuration with Consul</a></span></dt><dd><dl><dt><span class="section"><a href="multi_spring-cloud-consul-config.html#_how_to_activate_2">4.1. How to activate</a></span></dt><dt><span class="section"><a href="multi_spring-cloud-consul-config.html#_customizing">4.2. Customizing</a></span></dt><dt><span class="section"><a href="multi_spring-cloud-consul-config.html#spring-cloud-consul-config-watch">4.3. Config Watch</a></span></dt><dt><span class="section"><a href="multi_spring-cloud-consul-config.html#spring-cloud-consul-config-format">4.4. YAML or Properties with Config</a></span></dt><dt><span class="section"><a href="multi_spring-cloud-consul-config.html#spring-cloud-consul-config-git2consul">4.5. git2consul with Config</a></span></dt><dt><span class="section"><a href="multi_spring-cloud-consul-config.html#spring-cloud-consul-failfast">4.6. Fail Fast</a></span></dt></dl></dd><dt><span class="chapter"><a href="multi_spring-cloud-consul-retry.html">5. Consul Retry</a></span></dt><dt><span class="chapter"><a href="multi_spring-cloud-consul-bus.html">6. Spring Cloud Bus with Consul</a></span></dt><dd><dl><dt><span class="section"><a href="multi_spring-cloud-consul-bus.html#_how_to_activate_3">6.1. How to activate</a></span></dt></dl></dd><dt><span class="chapter"><a href="multi_spring-cloud-consul-hystrix.html">7. Circuit Breaker with Hystrix</a></span></dt><dt><span class="chapter"><a href="multi_spring-cloud-consul-turbine.html">8. Hystrix metrics aggregation with Turbine and Consul</a></span></dt></dl></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left">&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi_pr01.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right" valign="top">&nbsp;</td></tr></table></div></body></html>

View File

@@ -0,0 +1,35 @@
/*
code highlight CSS resemblign the Eclipse IDE default color schema
@author Costin Leau
*/
.hl-keyword {
color: #7F0055;
font-weight: bold;
}
.hl-comment {
color: #3F5F5F;
font-style: italic;
}
.hl-multiline-comment {
color: #3F5FBF;
font-style: italic;
}
.hl-tag {
color: #3F7F7F;
}
.hl-attribute {
color: #7F007F;
}
.hl-value {
color: #2A00FF;
}
.hl-string {
color: #2A00FF;
}

View File

@@ -0,0 +1,9 @@
@IMPORT url("manual.css");
body.firstpage {
background: url("../images/background.png") no-repeat center top;
}
div.part h1 {
border-top: none;
}

View File

@@ -0,0 +1,6 @@
@IMPORT url("manual.css");
body {
background: url("../images/background.png") no-repeat center top;
}

View File

@@ -0,0 +1,344 @@
@IMPORT url("highlight.css");
html {
padding: 0pt;
margin: 0pt;
}
body {
color: #333333;
margin: 15px 30px;
font-family: Helvetica, Arial, Freesans, Clean, Sans-serif;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
code {
font-size: 16px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
:not(a)>code {
color: #6D180B;
}
:not(pre)>code {
background-color: #F2F2F2;
border: 1px solid #CCCCCC;
border-radius: 4px;
padding: 1px 3px 0;
text-shadow: none;
white-space: nowrap;
}
body>*:first-child {
margin-top: 0 !important;
}
div {
margin: 0pt;
}
hr {
border: 1px solid #CCCCCC;
background: #CCCCCC;
}
h1,h2,h3,h4,h5,h6 {
color: #000000;
cursor: text;
font-weight: bold;
margin: 30px 0 10px;
padding: 0;
}
h1,h2,h3 {
margin: 40px 0 10px;
}
h1 {
margin: 70px 0 30px;
padding-top: 20px;
}
div.part h1 {
border-top: 1px dotted #CCCCCC;
}
h1,h1 code {
font-size: 32px;
}
h2,h2 code {
font-size: 24px;
}
h3,h3 code {
font-size: 20px;
}
h4,h1 code,h5,h5 code,h6,h6 code {
font-size: 18px;
}
div.book,div.chapter,div.appendix,div.part,div.preface {
min-width: 300px;
max-width: 1200px;
margin: 0 auto;
}
p.releaseinfo {
font-weight: bold;
margin-bottom: 40px;
margin-top: 40px;
}
div.authorgroup {
line-height: 1;
}
p.copyright {
line-height: 1;
margin-bottom: -5px;
}
.legalnotice p {
font-style: italic;
font-size: 14px;
line-height: 1;
}
div.titlepage+p,div.titlepage+p {
margin-top: 0;
}
pre {
line-height: 1.0;
color: black;
}
a {
color: #4183C4;
text-decoration: none;
}
p {
margin: 15px 0;
text-align: left;
}
ul,ol {
padding-left: 30px;
}
li p {
margin: 0;
}
div.table {
margin: 1em;
padding: 0.5em;
text-align: center;
}
div.table table,div.informaltable table {
display: table;
width: 100%;
}
div.table td {
padding-left: 7px;
padding-right: 7px;
}
.sidebar {
line-height: 1.4;
padding: 0 20px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
}
.sidebar p.title {
color: #6D180B;
}
pre.programlisting,pre.screen {
font-size: 15px;
padding: 6px 10px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
clear: both;
overflow: auto;
line-height: 1.4;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #DDDDDD !important;
border-radius: 4px !important;
border-collapse: separate !important;
line-height: 1.6;
}
table thead {
background: #F5F5F5;
}
table tr {
border: none;
border-bottom: none;
}
table th {
font-weight: bold;
}
table th,table td {
border: none !important;
padding: 6px 13px;
}
table tr:nth-child(2n) {
background-color: #F8F8F8;
}
td p {
margin: 0 0 15px 0;
}
div.table-contents td p {
margin: 0;
}
div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist *
{
border: none !important;
background: none !important;
margin: 0;
}
div.important p,div.note p,div.tip p,div.warning p {
color: #6F6F6F;
line-height: 1.6;
}
div.important code,div.note code,div.tip code,div.warning code {
background-color: #F2F2F2 !important;
border: 1px solid #CCCCCC !important;
border-radius: 4px !important;
padding: 1px 3px 0 !important;
text-shadow: none !important;
white-space: nowrap !important;
}
.note th,.tip th,.warning th {
display: none;
}
.note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td
{
border-right: 1px solid #CCCCCC !important;
padding-top: 10px;
}
div.calloutlist p,div.calloutlist td {
padding: 0;
margin: 0;
}
div.calloutlist>table>tbody>tr>td:first-child {
padding-left: 10px;
width: 30px !important;
}
div.important,div.note,div.tip,div.warning {
margin-left: 0px !important;
margin-right: 20px !important;
margin-top: 20px;
margin-bottom: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
div.toc {
line-height: 1.2;
}
dl,dt {
margin-top: 1px;
margin-bottom: 0;
}
div.toc>dl>dt {
font-size: 32px;
font-weight: bold;
margin: 30px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dt {
font-size: 24px;
font-weight: bold;
margin: 20px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dd>dl>dt {
font-weight: bold;
font-size: 20px;
margin: 10px 0 0 0;
}
tbody.footnotes * {
border: none !important;
}
div.footnote p {
margin: 0;
line-height: 1;
}
div.footnote p sup {
margin-right: 6px;
vertical-align: middle;
}
div.navheader {
border-bottom: 1px solid #CCCCCC;
}
div.navfooter {
border-top: 1px solid #CCCCCC;
}
.title {
margin-left: -1em;
padding-left: 1em;
}
.title>a {
position: absolute;
visibility: hidden;
display: block;
font-size: 0.85em;
margin-top: 0.05em;
margin-left: -1em;
vertical-align: text-top;
color: black;
}
.title>a:before {
content: "\00A7";
}
.title:hover>a,.title>a:hover,.title:hover>a:hover {
visibility: visible;
}
.title:focus>a,.title>a:focus,.title:focus>a:focus {
outline: 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,151 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring Cloud Consul</title><link rel="stylesheet" type="text/css" href="css/manual-singlepage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div lang="en" class="book"><div class="titlepage"><div><div><h1 class="title"><a name="d0e3"></a>Spring Cloud Consul</h1></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="preface"><a href="#d0e9"></a></span></dt><dt><span class="chapter"><a href="#spring-cloud-consul-install">1. Install Consul</a></span></dt><dt><span class="chapter"><a href="#spring-cloud-consul-agent">2. Consul Agent</a></span></dt><dt><span class="chapter"><a href="#spring-cloud-consul-discovery">3. Service Discovery with Consul</a></span></dt><dd><dl><dt><span class="section"><a href="#_how_to_activate">3.1. How to activate</a></span></dt><dt><span class="section"><a href="#_registering_with_consul">3.2. Registering with Consul</a></span></dt><dt><span class="section"><a href="#_http_health_check">3.3. HTTP Health Check</a></span></dt><dd><dl><dt><span class="section"><a href="#_metadata_and_consul_tags">3.3.1. Metadata and Consul tags</a></span></dt><dt><span class="section"><a href="#_making_the_consul_instance_id_unique">3.3.2. Making the Consul Instance ID Unique</a></span></dt><dt><span class="section"><a href="#_applying_headers_to_health_check_requests">3.3.3. Applying Headers to Health Check Requests</a></span></dt></dl></dd><dt><span class="section"><a href="#_looking_up_services">3.4. Looking up services</a></span></dt><dd><dl><dt><span class="section"><a href="#_using_ribbon">3.4.1. Using Ribbon</a></span></dt><dt><span class="section"><a href="#_using_the_discoveryclient">3.4.2. Using the DiscoveryClient</a></span></dt></dl></dd><dt><span class="section"><a href="#_consul_catalog_watch">3.5. Consul Catalog Watch</a></span></dt></dl></dd><dt><span class="chapter"><a href="#spring-cloud-consul-config">4. Distributed Configuration with Consul</a></span></dt><dd><dl><dt><span class="section"><a href="#_how_to_activate_2">4.1. How to activate</a></span></dt><dt><span class="section"><a href="#_customizing">4.2. Customizing</a></span></dt><dt><span class="section"><a href="#spring-cloud-consul-config-watch">4.3. Config Watch</a></span></dt><dt><span class="section"><a href="#spring-cloud-consul-config-format">4.4. YAML or Properties with Config</a></span></dt><dt><span class="section"><a href="#spring-cloud-consul-config-git2consul">4.5. git2consul with Config</a></span></dt><dt><span class="section"><a href="#spring-cloud-consul-failfast">4.6. Fail Fast</a></span></dt></dl></dd><dt><span class="chapter"><a href="#spring-cloud-consul-retry">5. Consul Retry</a></span></dt><dt><span class="chapter"><a href="#spring-cloud-consul-bus">6. Spring Cloud Bus with Consul</a></span></dt><dd><dl><dt><span class="section"><a href="#_how_to_activate_3">6.1. How to activate</a></span></dt></dl></dd><dt><span class="chapter"><a href="#spring-cloud-consul-hystrix">7. Circuit Breaker with Hystrix</a></span></dt><dt><span class="chapter"><a href="#spring-cloud-consul-turbine">8. Hystrix metrics aggregation with Turbine and Consul</a></span></dt></dl></div><div class="preface"><div class="titlepage"><div><div><h1 class="title"><a name="d0e9" href="#d0e9"></a></h1></div></div></div><p><span class="strong"><strong>2.1.0.RC1</strong></span></p><p>This project provides Consul integrations for Spring Boot apps through autoconfiguration
and binding to the Spring Environment and other Spring programming model idioms. With a few
simple annotations you can quickly enable and configure the common patterns inside your
application and build large distributed systems with Consul based components. The
patterns provided include Service Discovery, Control Bus and Configuration.
Intelligent Routing (Zuul) and Client Side Load Balancing (Ribbon), Circuit Breaker
(Hystrix) are provided by integration with Spring Cloud Netflix.</p></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="spring-cloud-consul-install" href="#spring-cloud-consul-install"></a>1.&nbsp;Install Consul</h1></div></div></div><p>Please see the <a class="link" href="https://www.consul.io/intro/getting-started/install.html" target="_top">installation documentation</a> for instructions on how to install Consul.</p></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="spring-cloud-consul-agent" href="#spring-cloud-consul-agent"></a>2.&nbsp;Consul Agent</h1></div></div></div><p>A Consul Agent client must be available to all Spring Cloud Consul applications. By default, the Agent client is expected to be at <code class="literal">localhost:8500</code>. See the <a class="link" href="https://consul.io/docs/agent/basics.html" target="_top">Agent documentation</a> for specifics on how to start an Agent client and how to connect to a cluster of Consul Agent Servers. For development, after you have installed consul, you may start a Consul Agent using the following command:</p><pre class="screen">./src/main/bash/local_run_consul.sh</pre><p>This will start an agent in server mode on port 8500, with the ui available at <a class="link" href="http://localhost:8500" target="_top">http://localhost:8500</a></p></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="spring-cloud-consul-discovery" href="#spring-cloud-consul-discovery"></a>3.&nbsp;Service Discovery with Consul</h1></div></div></div><p>Service Discovery is one of the key tenets of a microservice based architecture. Trying to hand configure each client or some form of convention can be very difficult to do and can be very brittle. Consul provides Service Discovery services via an <a class="link" href="https://www.consul.io/docs/agent/http.html" target="_top">HTTP API</a> and <a class="link" href="https://www.consul.io/docs/agent/dns.html" target="_top">DNS</a>. Spring Cloud Consul leverages the HTTP API for service registration and discovery. This does not prevent non-Spring Cloud applications from leveraging the DNS interface. Consul Agents servers are run in a <a class="link" href="https://www.consul.io/docs/internals/architecture.html" target="_top">cluster</a> that communicates via a <a class="link" href="https://www.consul.io/docs/internals/gossip.html" target="_top">gossip protocol</a> and uses the <a class="link" href="https://www.consul.io/docs/internals/consensus.html" target="_top">Raft consensus protocol</a>.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_how_to_activate" href="#_how_to_activate"></a>3.1&nbsp;How to activate</h2></div></div></div><p>To activate Consul Service Discovery use the starter with group <code class="literal">org.springframework.cloud</code> and artifact id <code class="literal">spring-cloud-starter-consul-discovery</code>. See the <a class="link" href="http://projects.spring.io/spring-cloud/" target="_top">Spring Cloud Project page</a> for details on setting up your build system with the current Spring Cloud Release Train.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_registering_with_consul" href="#_registering_with_consul"></a>3.2&nbsp;Registering with Consul</h2></div></div></div><p>When a client registers with Consul, it provides meta-data about itself such as host and port, id, name and tags. An HTTP <a class="link" href="https://www.consul.io/docs/agent/checks.html" target="_top">Check</a> is created by default that Consul hits the <code class="literal">/health</code> endpoint every 10 seconds. If the health check fails, the service instance is marked as critical.</p><p>Example Consul client:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@SpringBootApplication</span></em>
<em><span class="hl-annotation" style="color: gray">@RestController</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
<em><span class="hl-annotation" style="color: gray">@RequestMapping("/")</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String home() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Hello world"</span>;
}
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> main(String[] args) {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> SpringApplicationBuilder(Application.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>).web(true).run(args);
}
}</pre><p>(i.e. utterly normal Spring Boot app). If the Consul client is located somewhere other than <code class="literal">localhost:8500</code>, the configuration is required to locate the client. Example:</p><p><b>application.yml.&nbsp;</b>
</p><pre class="screen">spring:
cloud:
consul:
host: localhost
port: 8500</pre><p>
</p><div class="caution" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Caution"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Caution]" src="images/caution.png"></td><th align="left">Caution</th></tr><tr><td align="left" valign="top"><p>If you use <a class="link" href="#spring-cloud-consul-config" title="4.&nbsp;Distributed Configuration with Consul">Spring Cloud Consul Config</a>, the above values will need to be placed in <code class="literal">bootstrap.yml</code> instead of <code class="literal">application.yml</code>.</p></td></tr></table></div><p>The default service name, instance id and port, taken from the <code class="literal">Environment</code>, are <code class="literal">${spring.application.name}</code>, the Spring Context ID and <code class="literal">${server.port}</code> respectively.</p><p>To disable the Consul Discovery Client you can set <code class="literal">spring.cloud.consul.discovery.enabled</code> to <code class="literal">false</code>.</p><p>To disable the service registration you can set <code class="literal">spring.cloud.consul.discovery.register</code> to <code class="literal">false</code>.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_http_health_check" href="#_http_health_check"></a>3.3&nbsp;HTTP Health Check</h2></div></div></div><p>The health check for a Consul instance defaults to "/health", which is the default locations of a useful endpoint in a Spring Boot Actuator application. You need to change these, even for an Actuator application if you use a non-default context path or servlet path (e.g. <code class="literal">server.servletPath=/foo</code>) or management endpoint path (e.g. <code class="literal">management.server.servlet.context-path=/admin</code>). The interval that Consul uses to check the health endpoint may also be configured. "10s" and "1m" represent 10 seconds and 1 minute respectively. Example:</p><p><b>application.yml.&nbsp;</b>
</p><pre class="screen">spring:
cloud:
consul:
discovery:
healthCheckPath: ${management.server.servlet.context-path}/health
healthCheckInterval: 15s</pre><p>
</p><p>You can disable the health check by setting <code class="literal">management.health.consul.enabled=false</code>.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_metadata_and_consul_tags" href="#_metadata_and_consul_tags"></a>3.3.1&nbsp;Metadata and Consul tags</h3></div></div></div><p>Consul does not yet support metadata on services. Spring Cloud&#8217;s <code class="literal">ServiceInstance</code> has a <code class="literal">Map&lt;String, String&gt; metadata</code> field. Spring Cloud Consul uses Consul tags to approximate metadata until Consul officially supports metadata. Tags with the form <code class="literal">key=value</code> will be split and used as a <code class="literal">Map</code> key and value respectively. Tags without the equal <code class="literal">=</code> sign, will be used as both the key and value.</p><p><b>application.yml.&nbsp;</b>
</p><pre class="screen">spring:
cloud:
consul:
discovery:
tags: foo=bar, baz</pre><p>
</p><p>The above configuration will result in a map with <code class="literal">foo&#8594;bar</code> and <code class="literal">baz&#8594;baz</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_making_the_consul_instance_id_unique" href="#_making_the_consul_instance_id_unique"></a>3.3.2&nbsp;Making the Consul Instance ID Unique</h3></div></div></div><p>By default a consul instance is registered with an ID that is equal to its Spring Application Context ID. By default, the Spring Application Context ID is <code class="literal">${spring.application.name}:comma,separated,profiles:${server.port}</code>. For most cases, this will allow multiple instances of one service to run on one machine. If further uniqueness is required, Using Spring Cloud you can override this by providing a unique identifier in <code class="literal">spring.cloud.consul.discovery.instanceId</code>. For example:</p><p><b>application.yml.&nbsp;</b>
</p><pre class="screen">spring:
cloud:
consul:
discovery:
instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}</pre><p>
</p><p>With this metadata, and multiple service instances deployed on localhost, the random value will kick in there to make the instance unique. In Cloudfoundry the <code class="literal">vcap.application.instance_id</code> will be populated automatically in a Spring Boot application, so the random value will not be needed.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_applying_headers_to_health_check_requests" href="#_applying_headers_to_health_check_requests"></a>3.3.3&nbsp;Applying Headers to Health Check Requests</h3></div></div></div><p>Headers can be applied to health check requests. For example, if you&#8217;re trying to register a <a class="link" href="https://cloud.spring.io/spring-cloud-config/" target="_top">Spring Cloud Config</a> server that uses <a class="link" href="https://github.com/spring-cloud/spring-cloud-config/blob/master/docs/src/main/asciidoc/spring-cloud-config.adoc#vault-backend" target="_top">Vault Backend</a>:</p><p><b>application.yml.&nbsp;</b>
</p><pre class="screen">spring:
cloud:
consul:
discovery:
health-check-headers:
X-Config-Token: 6442e58b-d1ea-182e-cfa5-cf9cddef0722</pre><p>
</p><p>According to the HTTP standard, each header can have more than one values, in which case, an array can be supplied:</p><p><b>application.yml.&nbsp;</b>
</p><pre class="screen">spring:
cloud:
consul:
discovery:
health-check-headers:
X-Config-Token:
- "6442e58b-d1ea-182e-cfa5-cf9cddef0722"
- "Some other value"</pre><p>
</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_looking_up_services" href="#_looking_up_services"></a>3.4&nbsp;Looking up services</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_using_ribbon" href="#_using_ribbon"></a>3.4.1&nbsp;Using Ribbon</h3></div></div></div><p>Spring Cloud has support for <a class="link" href="https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-feign" target="_top">Feign</a> (a REST client builder) and also <a class="link" href="https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-ribbon" target="_top">Spring <code class="literal">RestTemplate</code></a>
for looking up services using the logical service names/ids instead of physical URLs. Both Feign and the discovery-aware RestTemplate utilize <a class="link" href="http://cloud.spring.io/spring-cloud-netflix/single/spring-cloud-netflix.html#spring-cloud-ribbon" target="_top">Ribbon</a> for client-side load balancing.</p><p>If you want to access service STORES using the RestTemplate simply declare:</p><pre class="screen">@LoadBalanced
@Bean
public RestTemplate loadbalancedRestTemplate() {
new RestTemplate();
}</pre><p>and use it like this (notice how we use the STORES service name/id from Consul instead of a fully qualified domainname):</p><pre class="screen">@Autowired
RestTemplate restTemplate;
public String getFirstProduct() {
return this.restTemplate.getForObject("https://STORES/products/1", String.class);
}</pre><p>If you have Consul clusters in multiple datacenters and you want to access a service in another datacenter a service name/id alone is not enough. In that case
you use property <code class="literal">spring.cloud.consul.discovery.datacenters.STORES=dc-west</code> where <code class="literal">STORES</code> is the service name/id and <code class="literal">dc-west</code> is the datacenter
where the STORES service lives.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_using_the_discoveryclient" href="#_using_the_discoveryclient"></a>3.4.2&nbsp;Using the DiscoveryClient</h3></div></div></div><p>You can also use the <code class="literal">org.springframework.cloud.client.discovery.DiscoveryClient</code> which provides a simple API for discovery clients that is not specific to Netflix, e.g.</p><pre class="screen">@Autowired
private DiscoveryClient discoveryClient;
public String serviceUrl() {
List&lt;ServiceInstance&gt; list = discoveryClient.getInstances("STORES");
if (list != null &amp;&amp; list.size() &gt; 0 ) {
return list.get(0).getUri();
}
return null;
}</pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_consul_catalog_watch" href="#_consul_catalog_watch"></a>3.5&nbsp;Consul Catalog Watch</h2></div></div></div><p>The Consul Catalog Watch takes advantage of the ability of consul to <a class="link" href="https://www.consul.io/docs/agent/watches.html#services" target="_top">watch services</a>. The Catalog Watch makes a blocking Consul HTTP API call to determine if any services have changed. If there is new service data a Heartbeat Event is published.</p><p>To change the frequency of when the Config Watch is called change <code class="literal">spring.cloud.consul.config.discovery.catalog-services-watch-delay</code>. The default value is 1000, which is in milliseconds. The delay is the amount of time after the end of the previous invocation and the start of the next.</p><p>To disable the Catalog Watch set <code class="literal">spring.cloud.consul.discovery.catalogServicesWatch.enabled=false</code>.</p><p>The watch uses a Spring <code class="literal">TaskScheduler</code> to schedule the call to consul. By default it is a <code class="literal">ThreadPoolTaskScheduler</code> with a <code class="literal">poolSize</code> of 1. To change the <code class="literal">TaskScheduler</code>, create a bean of type <code class="literal">TaskScheduler</code> named with the <code class="literal">ConsulDiscoveryClientConfiguration.CATALOG_WATCH_TASK_SCHEDULER_NAME</code> constant.</p></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="spring-cloud-consul-config" href="#spring-cloud-consul-config"></a>4.&nbsp;Distributed Configuration with Consul</h1></div></div></div><p>Consul provides a <a class="link" href="https://consul.io/docs/agent/http/kv.html" target="_top">Key/Value Store</a> for storing configuration and other metadata. Spring Cloud Consul Config is an alternative to the <a class="link" href="https://github.com/spring-cloud/spring-cloud-config" target="_top">Config Server and Client</a>. Configuration is loaded into the Spring Environment during the special "bootstrap" phase. Configuration is stored in the <code class="literal">/config</code> folder by default. Multiple <code class="literal">PropertySource</code> instances are created based on the application&#8217;s name and the active profiles that mimicks the Spring Cloud Config order of resolving properties. For example, an application with the name "testApp" and with the "dev" profile will have the following property sources created:</p><pre class="screen">config/testApp,dev/
config/testApp/
config/application,dev/
config/application/</pre><p>The most specific property source is at the top, with the least specific at the bottom. Properties in the <code class="literal">config/application</code> folder are applicable to all applications using consul for configuration. Properties in the <code class="literal">config/testApp</code> folder are only available to the instances of the service named "testApp".</p><p>Configuration is currently read on startup of the application. Sending a HTTP POST to <code class="literal">/refresh</code> will cause the configuration to be reloaded. <a class="xref" href="#spring-cloud-consul-config-watch" title="4.3&nbsp;Config Watch">Section&nbsp;4.3, &#8220;Config Watch&#8221;</a> will also automatically detect changes and reload the application context.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_how_to_activate_2" href="#_how_to_activate_2"></a>4.1&nbsp;How to activate</h2></div></div></div><p>To get started with Consul Configuration use the starter with group <code class="literal">org.springframework.cloud</code> and artifact id <code class="literal">spring-cloud-starter-consul-config</code>. See the <a class="link" href="http://projects.spring.io/spring-cloud/" target="_top">Spring Cloud Project page</a> for details on setting up your build system with the current Spring Cloud Release Train.</p><p>This will enable auto-configuration that will setup Spring Cloud Consul Config.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_customizing" href="#_customizing"></a>4.2&nbsp;Customizing</h2></div></div></div><p>Consul Config may be customized using the following properties:</p><p><b>bootstrap.yml.&nbsp;</b>
</p><pre class="screen">spring:
cloud:
consul:
config:
enabled: true
prefix: configuration
defaultContext: apps
profileSeparator: '::'</pre><p>
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">enabled</code> setting this value to "false" disables Consul Config</li><li class="listitem"><code class="literal">prefix</code> sets the base folder for configuration values</li><li class="listitem"><code class="literal">defaultContext</code> sets the folder name used by all applications</li><li class="listitem"><code class="literal">profileSeparator</code> sets the value of the separator used to separate the profile name in property sources with profiles</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-cloud-consul-config-watch" href="#spring-cloud-consul-config-watch"></a>4.3&nbsp;Config Watch</h2></div></div></div><p>The Consul Config Watch takes advantage of the ability of consul to <a class="link" href="https://www.consul.io/docs/agent/watches.html#keyprefix" target="_top">watch a key prefix</a>. The Config Watch makes a blocking Consul HTTP API call to determine if any relevant configuration data has changed for the current application. If there is new configuration data a Refresh Event is published. This is equivalent to calling the <code class="literal">/refresh</code> actuator endpoint.</p><p>To change the frequency of when the Config Watch is called change <code class="literal">spring.cloud.consul.config.watch.delay</code>. The default value is 1000, which is in milliseconds. The delay is the amount of time after the end of the previous invocation and the start of the next.</p><p>To disable the Config Watch set <code class="literal">spring.cloud.consul.config.watch.enabled=false</code>.</p><p>The watch uses a Spring <code class="literal">TaskScheduler</code> to schedule the call to consul. By default it is a <code class="literal">ThreadPoolTaskScheduler</code> with a <code class="literal">poolSize</code> of 1. To change the <code class="literal">TaskScheduler</code>, create a bean of type <code class="literal">TaskScheduler</code> named with the <code class="literal">ConsulConfigAutoConfiguration.CONFIG_WATCH_TASK_SCHEDULER_NAME</code> constant.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-cloud-consul-config-format" href="#spring-cloud-consul-config-format"></a>4.4&nbsp;YAML or Properties with Config</h2></div></div></div><p>It may be more convenient to store a blob of properties in YAML or Properties format as opposed to individual key/value pairs. Set the <code class="literal">spring.cloud.consul.config.format</code> property to <code class="literal">YAML</code> or <code class="literal">PROPERTIES</code>. For example to use YAML:</p><p><b>bootstrap.yml.&nbsp;</b>
</p><pre class="screen">spring:
cloud:
consul:
config:
format: YAML</pre><p>
</p><p>YAML must be set in the appropriate <code class="literal">data</code> key in consul. Using the defaults above the keys would look like:</p><pre class="screen">config/testApp,dev/data
config/testApp/data
config/application,dev/data
config/application/data</pre><p>You could store a YAML document in any of the keys listed above.</p><p>You can change the data key using <code class="literal">spring.cloud.consul.config.data-key</code>.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-cloud-consul-config-git2consul" href="#spring-cloud-consul-config-git2consul"></a>4.5&nbsp;git2consul with Config</h2></div></div></div><p>git2consul is a Consul community project that loads files from a git repository to individual keys into Consul. By default the names of the keys are names of the files. YAML and Properties files are supported with file extensions of <code class="literal">.yml</code> and <code class="literal">.properties</code> respectively. Set the <code class="literal">spring.cloud.consul.config.format</code> property to <code class="literal">FILES</code>. For example:</p><p><b>bootstrap.yml.&nbsp;</b>
</p><pre class="screen">spring:
cloud:
consul:
config:
format: FILES</pre><p>
</p><p>Given the following keys in <code class="literal">/config</code>, the <code class="literal">development</code> profile and an application name of <code class="literal">foo</code>:</p><pre class="screen">.gitignore
application.yml
bar.properties
foo-development.properties
foo-production.yml
foo.properties
master.ref</pre><p>the following property sources would be created:</p><pre class="screen">config/foo-development.properties
config/foo.properties
config/application.yml</pre><p>The value of each key needs to be a properly formatted YAML or Properties file.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-cloud-consul-failfast" href="#spring-cloud-consul-failfast"></a>4.6&nbsp;Fail Fast</h2></div></div></div><p>It may be convenient in certain circumstances (like local development or certain test scenarios) to not fail if consul isn&#8217;t available for configuration. Setting <code class="literal">spring.cloud.consul.config.failFast=false</code> in <code class="literal">bootstrap.yml</code> will cause the configuration module to log a warning rather than throw an exception. This will allow the application to continue startup normally.</p></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="spring-cloud-consul-retry" href="#spring-cloud-consul-retry"></a>5.&nbsp;Consul Retry</h1></div></div></div><p>If you expect that the consul agent may occasionally be unavailable when
your app starts, you can ask it to keep trying after a failure. You need to add
<code class="literal">spring-retry</code> and <code class="literal">spring-boot-starter-aop</code> to your classpath. The default
behaviour is to retry 6 times with an initial backoff interval of 1000ms and an
exponential multiplier of 1.1 for subsequent backoffs. You can configure these
properties (and others) using <code class="literal">spring.cloud.consul.retry.*</code> configuration properties.
This works with both Spring Cloud Consul Config and Discovery registration.</p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>To take full control of the retry add a <code class="literal">@Bean</code> of type
<code class="literal">RetryOperationsInterceptor</code> with id "consulRetryInterceptor". Spring
Retry has a <code class="literal">RetryInterceptorBuilder</code> that makes it easy to create one.</p></td></tr></table></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="spring-cloud-consul-bus" href="#spring-cloud-consul-bus"></a>6.&nbsp;Spring Cloud Bus with Consul</h1></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_how_to_activate_3" href="#_how_to_activate_3"></a>6.1&nbsp;How to activate</h2></div></div></div><p>To get started with the Consul Bus use the starter with group <code class="literal">org.springframework.cloud</code> and artifact id <code class="literal">spring-cloud-starter-consul-bus</code>. See the <a class="link" href="http://projects.spring.io/spring-cloud/" target="_top">Spring Cloud Project page</a> for details on setting up your build system with the current Spring Cloud Release Train.</p><p>See the <a class="link" href="https://cloud.spring.io/spring-cloud-bus/" target="_top">Spring Cloud Bus</a> documentation for the available actuator endpoints and howto send custom messages.</p></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="spring-cloud-consul-hystrix" href="#spring-cloud-consul-hystrix"></a>7.&nbsp;Circuit Breaker with Hystrix</h1></div></div></div><p>Applications can use the Hystrix Circuit Breaker provided by the Spring Cloud Netflix project by including this starter in the projects pom.xml: <code class="literal">spring-cloud-starter-hystrix</code>. Hystrix doesn&#8217;t depend on the Netflix Discovery Client. The <code class="literal">@EnableHystrix</code> annotation should be placed on a configuration class (usually the main class). Then methods can be annotated with <code class="literal">@HystrixCommand</code> to be protected by a circuit breaker. See <a class="link" href="http://projects.spring.io/spring-cloud/spring-cloud.html#_circuit_breaker_hystrix_clients" target="_top">the documentation</a> for more details.</p></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="spring-cloud-consul-turbine" href="#spring-cloud-consul-turbine"></a>8.&nbsp;Hystrix metrics aggregation with Turbine and Consul</h1></div></div></div><p>Turbine (provided by the Spring Cloud Netflix project), aggregates multiple instances Hystrix metrics streams, so the dashboard can display an aggregate view. Turbine uses the <code class="literal">DiscoveryClient</code> interface to lookup relevant instances. To use Turbine with Spring Cloud Consul, configure the Turbine application in a manner similar to the following examples:</p><p><b>pom.xml.&nbsp;</b>
</p><pre class="screen">&lt;dependency&gt;
&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
&lt;artifactId&gt;spring-cloud-netflix-turbine&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
&lt;artifactId&gt;spring-cloud-starter-consul-discovery&lt;/artifactId&gt;
&lt;/dependency&gt;</pre><p>
</p><p>Notice that the Turbine dependency is not a starter. The turbine starter includes support for Netflix Eureka.</p><p><b>application.yml.&nbsp;</b>
</p><pre class="screen">spring.application.name: turbine
applications: consulhystrixclient
turbine:
aggregator:
clusterConfig: ${applications}
appConfig: ${applications}</pre><p>
</p><p>The <code class="literal">clusterConfig</code> and <code class="literal">appConfig</code> sections must match, so it&#8217;s useful to put the comma-separated list of service ID&#8217;s into a separate configuration property.</p><p><b>Turbine.java.&nbsp;</b>
</p><pre class="screen">@EnableTurbine
@SpringBootApplication
public class Turbine {
public static void main(String[] args) {
SpringApplication.run(DemoturbinecommonsApplication.class, args);
}
}</pre><p>
</p></div></div></body></html>

View File

@@ -0,0 +1,368 @@
<?xml version="1.0" encoding="UTF-8"?>
<?asciidoc-toc?>
<?asciidoc-numbered?>
<book xmlns="http://docbook.org/ns/docbook" xmlns:xl="http://www.w3.org/1999/xlink" version="5.0" xml:lang="en">
<info>
<title>Spring Cloud Consul</title>
<date>2018-12-11</date>
</info>
<preface>
<title></title>
<simpara><emphasis role="strong">2.1.0.RC1</emphasis></simpara>
<simpara>This project provides Consul integrations for Spring Boot apps through autoconfiguration
and binding to the Spring Environment and other Spring programming model idioms. With a few
simple annotations you can quickly enable and configure the common patterns inside your
application and build large distributed systems with Consul based components. The
patterns provided include Service Discovery, Control Bus and Configuration.
Intelligent Routing (Zuul) and Client Side Load Balancing (Ribbon), Circuit Breaker
(Hystrix) are provided by integration with Spring Cloud Netflix.</simpara>
</preface>
<chapter xml:id="spring-cloud-consul-install">
<title>Install Consul</title>
<simpara>Please see the <link xl:href="https://www.consul.io/intro/getting-started/install.html">installation documentation</link> for instructions on how to install Consul.</simpara>
</chapter>
<chapter xml:id="spring-cloud-consul-agent">
<title>Consul Agent</title>
<simpara>A Consul Agent client must be available to all Spring Cloud Consul applications. By default, the Agent client is expected to be at <literal>localhost:8500</literal>. See the <link xl:href="https://consul.io/docs/agent/basics.html">Agent documentation</link> for specifics on how to start an Agent client and how to connect to a cluster of Consul Agent Servers. For development, after you have installed consul, you may start a Consul Agent using the following command:</simpara>
<screen>./src/main/bash/local_run_consul.sh</screen>
<simpara>This will start an agent in server mode on port 8500, with the ui available at <link xl:href="http://localhost:8500">http://localhost:8500</link></simpara>
</chapter>
<chapter xml:id="spring-cloud-consul-discovery">
<title>Service Discovery with Consul</title>
<simpara>Service Discovery is one of the key tenets of a microservice based architecture. Trying to hand configure each client or some form of convention can be very difficult to do and can be very brittle. Consul provides Service Discovery services via an <link xl:href="https://www.consul.io/docs/agent/http.html">HTTP API</link> and <link xl:href="https://www.consul.io/docs/agent/dns.html">DNS</link>. Spring Cloud Consul leverages the HTTP API for service registration and discovery. This does not prevent non-Spring Cloud applications from leveraging the DNS interface. Consul Agents servers are run in a <link xl:href="https://www.consul.io/docs/internals/architecture.html">cluster</link> that communicates via a <link xl:href="https://www.consul.io/docs/internals/gossip.html">gossip protocol</link> and uses the <link xl:href="https://www.consul.io/docs/internals/consensus.html">Raft consensus protocol</link>.</simpara>
<section xml:id="_how_to_activate">
<title>How to activate</title>
<simpara>To activate Consul Service Discovery use the starter with group <literal>org.springframework.cloud</literal> and artifact id <literal>spring-cloud-starter-consul-discovery</literal>. See the <link xl:href="http://projects.spring.io/spring-cloud/">Spring Cloud Project page</link> for details on setting up your build system with the current Spring Cloud Release Train.</simpara>
</section>
<section xml:id="_registering_with_consul">
<title>Registering with Consul</title>
<simpara>When a client registers with Consul, it provides meta-data about itself such as host and port, id, name and tags. An HTTP <link xl:href="https://www.consul.io/docs/agent/checks.html">Check</link> is created by default that Consul hits the <literal>/health</literal> endpoint every 10 seconds. If the health check fails, the service instance is marked as critical.</simpara>
<simpara>Example Consul client:</simpara>
<programlisting language="java" linenumbering="unnumbered">@SpringBootApplication
@RestController
public class Application {
@RequestMapping("/")
public String home() {
return "Hello world";
}
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}</programlisting>
<simpara>(i.e. utterly normal Spring Boot app). If the Consul client is located somewhere other than <literal>localhost:8500</literal>, the configuration is required to locate the client. Example:</simpara>
<formalpara>
<title>application.yml</title>
<para>
<screen>spring:
cloud:
consul:
host: localhost
port: 8500</screen>
</para>
</formalpara>
<caution>
<simpara>If you use <link linkend="spring-cloud-consul-config">Spring Cloud Consul Config</link>, the above values will need to be placed in <literal>bootstrap.yml</literal> instead of <literal>application.yml</literal>.</simpara>
</caution>
<simpara>The default service name, instance id and port, taken from the <literal>Environment</literal>, are <literal>${spring.application.name}</literal>, the Spring Context ID and <literal>${server.port}</literal> respectively.</simpara>
<simpara>To disable the Consul Discovery Client you can set <literal>spring.cloud.consul.discovery.enabled</literal> to <literal>false</literal>.</simpara>
<simpara>To disable the service registration you can set <literal>spring.cloud.consul.discovery.register</literal> to <literal>false</literal>.</simpara>
</section>
<section xml:id="_http_health_check">
<title>HTTP Health Check</title>
<simpara>The health check for a Consul instance defaults to "/health", which is the default locations of a useful endpoint in a Spring Boot Actuator application. You need to change these, even for an Actuator application if you use a non-default context path or servlet path (e.g. <literal>server.servletPath=/foo</literal>) or management endpoint path (e.g. <literal>management.server.servlet.context-path=/admin</literal>). The interval that Consul uses to check the health endpoint may also be configured. "10s" and "1m" represent 10 seconds and 1 minute respectively. Example:</simpara>
<formalpara>
<title>application.yml</title>
<para>
<screen>spring:
cloud:
consul:
discovery:
healthCheckPath: ${management.server.servlet.context-path}/health
healthCheckInterval: 15s</screen>
</para>
</formalpara>
<simpara>You can disable the health check by setting <literal>management.health.consul.enabled=false</literal>.</simpara>
<section xml:id="_metadata_and_consul_tags">
<title>Metadata and Consul tags</title>
<simpara>Consul does not yet support metadata on services. Spring Cloud&#8217;s <literal>ServiceInstance</literal> has a <literal>Map&lt;String, String&gt; metadata</literal> field. Spring Cloud Consul uses Consul tags to approximate metadata until Consul officially supports metadata. Tags with the form <literal>key=value</literal> will be split and used as a <literal>Map</literal> key and value respectively. Tags without the equal <literal>=</literal> sign, will be used as both the key and value.</simpara>
<formalpara>
<title>application.yml</title>
<para>
<screen>spring:
cloud:
consul:
discovery:
tags: foo=bar, baz</screen>
</para>
</formalpara>
<simpara>The above configuration will result in a map with <literal>foo&#8594;bar</literal> and <literal>baz&#8594;baz</literal>.</simpara>
</section>
<section xml:id="_making_the_consul_instance_id_unique">
<title>Making the Consul Instance ID Unique</title>
<simpara>By default a consul instance is registered with an ID that is equal to its Spring Application Context ID. By default, the Spring Application Context ID is <literal>${spring.application.name}:comma,separated,profiles:${server.port}</literal>. For most cases, this will allow multiple instances of one service to run on one machine. If further uniqueness is required, Using Spring Cloud you can override this by providing a unique identifier in <literal>spring.cloud.consul.discovery.instanceId</literal>. For example:</simpara>
<formalpara>
<title>application.yml</title>
<para>
<screen>spring:
cloud:
consul:
discovery:
instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}</screen>
</para>
</formalpara>
<simpara>With this metadata, and multiple service instances deployed on localhost, the random value will kick in there to make the instance unique. In Cloudfoundry the <literal>vcap.application.instance_id</literal> will be populated automatically in a Spring Boot application, so the random value will not be needed.</simpara>
</section>
<section xml:id="_applying_headers_to_health_check_requests">
<title>Applying Headers to Health Check Requests</title>
<simpara>Headers can be applied to health check requests. For example, if you&#8217;re trying to register a <link xl:href="https://cloud.spring.io/spring-cloud-config/">Spring Cloud Config</link> server that uses <link xl:href="https://github.com/spring-cloud/spring-cloud-config/blob/master/docs/src/main/asciidoc/spring-cloud-config.adoc#vault-backend">Vault Backend</link>:</simpara>
<formalpara>
<title>application.yml</title>
<para>
<screen>spring:
cloud:
consul:
discovery:
health-check-headers:
X-Config-Token: 6442e58b-d1ea-182e-cfa5-cf9cddef0722</screen>
</para>
</formalpara>
<simpara>According to the HTTP standard, each header can have more than one values, in which case, an array can be supplied:</simpara>
<formalpara>
<title>application.yml</title>
<para>
<screen>spring:
cloud:
consul:
discovery:
health-check-headers:
X-Config-Token:
- "6442e58b-d1ea-182e-cfa5-cf9cddef0722"
- "Some other value"</screen>
</para>
</formalpara>
</section>
</section>
<section xml:id="_looking_up_services">
<title>Looking up services</title>
<section xml:id="_using_ribbon">
<title>Using Ribbon</title>
<simpara>Spring Cloud has support for <link xl:href="https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-feign">Feign</link> (a REST client builder) and also <link xl:href="https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-ribbon">Spring <literal>RestTemplate</literal></link>
for looking up services using the logical service names/ids instead of physical URLs. Both Feign and the discovery-aware RestTemplate utilize <link xl:href="http://cloud.spring.io/spring-cloud-netflix/single/spring-cloud-netflix.html#spring-cloud-ribbon">Ribbon</link> for client-side load balancing.</simpara>
<simpara>If you want to access service STORES using the RestTemplate simply declare:</simpara>
<screen>@LoadBalanced
@Bean
public RestTemplate loadbalancedRestTemplate() {
new RestTemplate();
}</screen>
<simpara>and use it like this (notice how we use the STORES service name/id from Consul instead of a fully qualified domainname):</simpara>
<screen>@Autowired
RestTemplate restTemplate;
public String getFirstProduct() {
return this.restTemplate.getForObject("https://STORES/products/1", String.class);
}</screen>
<simpara>If you have Consul clusters in multiple datacenters and you want to access a service in another datacenter a service name/id alone is not enough. In that case
you use property <literal>spring.cloud.consul.discovery.datacenters.STORES=dc-west</literal> where <literal>STORES</literal> is the service name/id and <literal>dc-west</literal> is the datacenter
where the STORES service lives.</simpara>
</section>
<section xml:id="_using_the_discoveryclient">
<title>Using the DiscoveryClient</title>
<simpara>You can also use the <literal>org.springframework.cloud.client.discovery.DiscoveryClient</literal> which provides a simple API for discovery clients that is not specific to Netflix, e.g.</simpara>
<screen>@Autowired
private DiscoveryClient discoveryClient;
public String serviceUrl() {
List&lt;ServiceInstance&gt; list = discoveryClient.getInstances("STORES");
if (list != null &amp;&amp; list.size() &gt; 0 ) {
return list.get(0).getUri();
}
return null;
}</screen>
</section>
</section>
<section xml:id="_consul_catalog_watch">
<title>Consul Catalog Watch</title>
<simpara>The Consul Catalog Watch takes advantage of the ability of consul to <link xl:href="https://www.consul.io/docs/agent/watches.html#services">watch services</link>. The Catalog Watch makes a blocking Consul HTTP API call to determine if any services have changed. If there is new service data a Heartbeat Event is published.</simpara>
<simpara>To change the frequency of when the Config Watch is called change <literal>spring.cloud.consul.config.discovery.catalog-services-watch-delay</literal>. The default value is 1000, which is in milliseconds. The delay is the amount of time after the end of the previous invocation and the start of the next.</simpara>
<simpara>To disable the Catalog Watch set <literal>spring.cloud.consul.discovery.catalogServicesWatch.enabled=false</literal>.</simpara>
<simpara>The watch uses a Spring <literal>TaskScheduler</literal> to schedule the call to consul. By default it is a <literal>ThreadPoolTaskScheduler</literal> with a <literal>poolSize</literal> of 1. To change the <literal>TaskScheduler</literal>, create a bean of type <literal>TaskScheduler</literal> named with the <literal>ConsulDiscoveryClientConfiguration.CATALOG_WATCH_TASK_SCHEDULER_NAME</literal> constant.</simpara>
</section>
</chapter>
<chapter xml:id="spring-cloud-consul-config">
<title>Distributed Configuration with Consul</title>
<simpara>Consul provides a <link xl:href="https://consul.io/docs/agent/http/kv.html">Key/Value Store</link> for storing configuration and other metadata. Spring Cloud Consul Config is an alternative to the <link xl:href="https://github.com/spring-cloud/spring-cloud-config">Config Server and Client</link>. Configuration is loaded into the Spring Environment during the special "bootstrap" phase. Configuration is stored in the <literal>/config</literal> folder by default. Multiple <literal>PropertySource</literal> instances are created based on the application&#8217;s name and the active profiles that mimicks the Spring Cloud Config order of resolving properties. For example, an application with the name "testApp" and with the "dev" profile will have the following property sources created:</simpara>
<screen>config/testApp,dev/
config/testApp/
config/application,dev/
config/application/</screen>
<simpara>The most specific property source is at the top, with the least specific at the bottom. Properties in the <literal>config/application</literal> folder are applicable to all applications using consul for configuration. Properties in the <literal>config/testApp</literal> folder are only available to the instances of the service named "testApp".</simpara>
<simpara>Configuration is currently read on startup of the application. Sending a HTTP POST to <literal>/refresh</literal> will cause the configuration to be reloaded. <xref linkend="spring-cloud-consul-config-watch"/> will also automatically detect changes and reload the application context.</simpara>
<section xml:id="_how_to_activate_2">
<title>How to activate</title>
<simpara>To get started with Consul Configuration use the starter with group <literal>org.springframework.cloud</literal> and artifact id <literal>spring-cloud-starter-consul-config</literal>. See the <link xl:href="http://projects.spring.io/spring-cloud/">Spring Cloud Project page</link> for details on setting up your build system with the current Spring Cloud Release Train.</simpara>
<simpara>This will enable auto-configuration that will setup Spring Cloud Consul Config.</simpara>
</section>
<section xml:id="_customizing">
<title>Customizing</title>
<simpara>Consul Config may be customized using the following properties:</simpara>
<formalpara>
<title>bootstrap.yml</title>
<para>
<screen>spring:
cloud:
consul:
config:
enabled: true
prefix: configuration
defaultContext: apps
profileSeparator: '::'</screen>
</para>
</formalpara>
<itemizedlist>
<listitem>
<simpara><literal>enabled</literal> setting this value to "false" disables Consul Config</simpara>
</listitem>
<listitem>
<simpara><literal>prefix</literal> sets the base folder for configuration values</simpara>
</listitem>
<listitem>
<simpara><literal>defaultContext</literal> sets the folder name used by all applications</simpara>
</listitem>
<listitem>
<simpara><literal>profileSeparator</literal> sets the value of the separator used to separate the profile name in property sources with profiles</simpara>
</listitem>
</itemizedlist>
</section>
<section xml:id="spring-cloud-consul-config-watch">
<title>Config Watch</title>
<simpara>The Consul Config Watch takes advantage of the ability of consul to <link xl:href="https://www.consul.io/docs/agent/watches.html#keyprefix">watch a key prefix</link>. The Config Watch makes a blocking Consul HTTP API call to determine if any relevant configuration data has changed for the current application. If there is new configuration data a Refresh Event is published. This is equivalent to calling the <literal>/refresh</literal> actuator endpoint.</simpara>
<simpara>To change the frequency of when the Config Watch is called change <literal>spring.cloud.consul.config.watch.delay</literal>. The default value is 1000, which is in milliseconds. The delay is the amount of time after the end of the previous invocation and the start of the next.</simpara>
<simpara>To disable the Config Watch set <literal>spring.cloud.consul.config.watch.enabled=false</literal>.</simpara>
<simpara>The watch uses a Spring <literal>TaskScheduler</literal> to schedule the call to consul. By default it is a <literal>ThreadPoolTaskScheduler</literal> with a <literal>poolSize</literal> of 1. To change the <literal>TaskScheduler</literal>, create a bean of type <literal>TaskScheduler</literal> named with the <literal>ConsulConfigAutoConfiguration.CONFIG_WATCH_TASK_SCHEDULER_NAME</literal> constant.</simpara>
</section>
<section xml:id="spring-cloud-consul-config-format">
<title>YAML or Properties with Config</title>
<simpara>It may be more convenient to store a blob of properties in YAML or Properties format as opposed to individual key/value pairs. Set the <literal>spring.cloud.consul.config.format</literal> property to <literal>YAML</literal> or <literal>PROPERTIES</literal>. For example to use YAML:</simpara>
<formalpara>
<title>bootstrap.yml</title>
<para>
<screen>spring:
cloud:
consul:
config:
format: YAML</screen>
</para>
</formalpara>
<simpara>YAML must be set in the appropriate <literal>data</literal> key in consul. Using the defaults above the keys would look like:</simpara>
<screen>config/testApp,dev/data
config/testApp/data
config/application,dev/data
config/application/data</screen>
<simpara>You could store a YAML document in any of the keys listed above.</simpara>
<simpara>You can change the data key using <literal>spring.cloud.consul.config.data-key</literal>.</simpara>
</section>
<section xml:id="spring-cloud-consul-config-git2consul">
<title>git2consul with Config</title>
<simpara>git2consul is a Consul community project that loads files from a git repository to individual keys into Consul. By default the names of the keys are names of the files. YAML and Properties files are supported with file extensions of <literal>.yml</literal> and <literal>.properties</literal> respectively. Set the <literal>spring.cloud.consul.config.format</literal> property to <literal>FILES</literal>. For example:</simpara>
<formalpara>
<title>bootstrap.yml</title>
<para>
<screen>spring:
cloud:
consul:
config:
format: FILES</screen>
</para>
</formalpara>
<simpara>Given the following keys in <literal>/config</literal>, the <literal>development</literal> profile and an application name of <literal>foo</literal>:</simpara>
<screen>.gitignore
application.yml
bar.properties
foo-development.properties
foo-production.yml
foo.properties
master.ref</screen>
<simpara>the following property sources would be created:</simpara>
<screen>config/foo-development.properties
config/foo.properties
config/application.yml</screen>
<simpara>The value of each key needs to be a properly formatted YAML or Properties file.</simpara>
</section>
<section xml:id="spring-cloud-consul-failfast">
<title>Fail Fast</title>
<simpara>It may be convenient in certain circumstances (like local development or certain test scenarios) to not fail if consul isn&#8217;t available for configuration. Setting <literal>spring.cloud.consul.config.failFast=false</literal> in <literal>bootstrap.yml</literal> will cause the configuration module to log a warning rather than throw an exception. This will allow the application to continue startup normally.</simpara>
</section>
</chapter>
<chapter xml:id="spring-cloud-consul-retry">
<title>Consul Retry</title>
<simpara>If you expect that the consul agent may occasionally be unavailable when
your app starts, you can ask it to keep trying after a failure. You need to add
<literal>spring-retry</literal> and <literal>spring-boot-starter-aop</literal> to your classpath. The default
behaviour is to retry 6 times with an initial backoff interval of 1000ms and an
exponential multiplier of 1.1 for subsequent backoffs. You can configure these
properties (and others) using <literal>spring.cloud.consul.retry.*</literal> configuration properties.
This works with both Spring Cloud Consul Config and Discovery registration.</simpara>
<tip>
<simpara>To take full control of the retry add a <literal>@Bean</literal> of type
<literal>RetryOperationsInterceptor</literal> with id "consulRetryInterceptor". Spring
Retry has a <literal>RetryInterceptorBuilder</literal> that makes it easy to create one.</simpara>
</tip>
</chapter>
<chapter xml:id="spring-cloud-consul-bus">
<title>Spring Cloud Bus with Consul</title>
<section xml:id="_how_to_activate_3">
<title>How to activate</title>
<simpara>To get started with the Consul Bus use the starter with group <literal>org.springframework.cloud</literal> and artifact id <literal>spring-cloud-starter-consul-bus</literal>. See the <link xl:href="http://projects.spring.io/spring-cloud/">Spring Cloud Project page</link> for details on setting up your build system with the current Spring Cloud Release Train.</simpara>
<simpara>See the <link xl:href="https://cloud.spring.io/spring-cloud-bus/">Spring Cloud Bus</link> documentation for the available actuator endpoints and howto send custom messages.</simpara>
</section>
</chapter>
<chapter xml:id="spring-cloud-consul-hystrix">
<title>Circuit Breaker with Hystrix</title>
<simpara>Applications can use the Hystrix Circuit Breaker provided by the Spring Cloud Netflix project by including this starter in the projects pom.xml: <literal>spring-cloud-starter-hystrix</literal>. Hystrix doesn&#8217;t depend on the Netflix Discovery Client. The <literal>@EnableHystrix</literal> annotation should be placed on a configuration class (usually the main class). Then methods can be annotated with <literal>@HystrixCommand</literal> to be protected by a circuit breaker. See <link xl:href="http://projects.spring.io/spring-cloud/spring-cloud.html#_circuit_breaker_hystrix_clients">the documentation</link> for more details.</simpara>
</chapter>
<chapter xml:id="spring-cloud-consul-turbine">
<title>Hystrix metrics aggregation with Turbine and Consul</title>
<simpara>Turbine (provided by the Spring Cloud Netflix project), aggregates multiple instances Hystrix metrics streams, so the dashboard can display an aggregate view. Turbine uses the <literal>DiscoveryClient</literal> interface to lookup relevant instances. To use Turbine with Spring Cloud Consul, configure the Turbine application in a manner similar to the following examples:</simpara>
<formalpara>
<title>pom.xml</title>
<para>
<screen>&lt;dependency&gt;
&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
&lt;artifactId&gt;spring-cloud-netflix-turbine&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
&lt;artifactId&gt;spring-cloud-starter-consul-discovery&lt;/artifactId&gt;
&lt;/dependency&gt;</screen>
</para>
</formalpara>
<simpara>Notice that the Turbine dependency is not a starter. The turbine starter includes support for Netflix Eureka.</simpara>
<formalpara>
<title>application.yml</title>
<para>
<screen>spring.application.name: turbine
applications: consulhystrixclient
turbine:
aggregator:
clusterConfig: ${applications}
appConfig: ${applications}</screen>
</para>
</formalpara>
<simpara>The <literal>clusterConfig</literal> and <literal>appConfig</literal> sections must match, so it&#8217;s useful to put the comma-separated list of service ID&#8217;s into a separate configuration property.</simpara>
<formalpara>
<title>Turbine.java</title>
<para>
<screen>@EnableTurbine
@SpringBootApplication
public class Turbine {
public static void main(String[] args) {
SpringApplication.run(DemoturbinecommonsApplication.class, args);
}
}</screen>
</para>
</formalpara>
</chapter>
</book>