Sync docs from vDalston.SR5 to gh-pages
71
Dalston.SR5/configprops.groovy
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Run this file with groovy and collect the result as an asciidoctor source file:
|
||||
* <pre>
|
||||
* $ groovy configprops.groovy | egrep -v PathMatchingResourcePatternResolver | tee configprops.adoc
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
@GrabResolver(name='milestone', root='http://repo.spring.io/milestone/')
|
||||
@Grab('org.codehaus.groovy:groovy-json:2.4.3')
|
||||
@Grab('org.springframework.cloud:spring-cloud-stream:1.2.2.RELEASE')
|
||||
@Grab('org.springframework.cloud:spring-cloud-starter-bus-amqp:1.3.1.RELEASE')
|
||||
@Grab('org.springframework.cloud:spring-cloud-starter-config:1.3.2.RELEASE')
|
||||
@Grab('org.springframework.cloud:spring-cloud-config-server:1.3.2.RELEASE')
|
||||
@Grab('org.springframework.cloud:spring-cloud-netflix-eureka-server:1.3.4.RELEASE')
|
||||
@Grab('org.springframework.cloud:spring-cloud-starter-eureka:1.3.4.RELEASE')
|
||||
@Grab('org.springframework.cloud:spring-cloud-starter-aws:1.2.1.RELEASE')
|
||||
@Grab('org.springframework.cloud:spring-cloud-starter-security:1.2.1.RELEASE')
|
||||
@Grab('org.springframework.cloud:spring-cloud-starter-consul-all:1.2.1.RELEASE')
|
||||
@Grab('org.springframework.cloud:spring-cloud-starter-zookeeper-all:1.1.2.RELEASE')
|
||||
@Grab('org.springframework.cloud:spring-cloud-starter-sleuth:1.2.4.RELEASE')
|
||||
@Grab('org.springframework.cloud:spring-cloud-starter-cloudfoundry:1.1.0.RELEASE')
|
||||
@Grab('org.springframework.cloud:spring-cloud-cloudfoundry-discovery:1.1.0.RELEASE')
|
||||
@Grab('org.springframework.cloud:spring-cloud-contract-stub-runner:1.1.3.RELEASE')
|
||||
@Grab('org.springframework.cloud:spring-cloud-vault-config:1.0.2.RELEASE')
|
||||
@Grab('org.springframework.cloud:spring-cloud-vault-config-aws:1.0.2.RELEASE')
|
||||
@Grab('org.springframework.cloud:spring-cloud-vault-config-databases:1.0.2.RELEASE')
|
||||
@Grab('org.springframework.cloud:spring-cloud-vault-config-consul:1.0.2.RELEASE')
|
||||
@Grab('org.springframework.cloud:spring-cloud-vault-config-rabbitmq:1.0.2.RELEASE')
|
||||
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver
|
||||
import org.springframework.core.io.Resource
|
||||
import groovy.json.JsonSlurper
|
||||
|
||||
def resources = new PathMatchingResourcePatternResolver().getResources("classpath*:/META-INF/spring-configuration-metadata.json")
|
||||
|
||||
TreeSet names = new TreeSet()
|
||||
def descriptions = [:]
|
||||
resources.each { it ->
|
||||
if (it.url.toString().contains("cloud")) {
|
||||
def slurper = new JsonSlurper()
|
||||
slurper.parseText(it.inputStream.text).properties.each { val ->
|
||||
names.add val.name
|
||||
descriptions[val.name] = new ConfigValue(val.name, val.description, val.defaultValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
println "|==="
|
||||
println "|Name | Default | Description"
|
||||
println ""
|
||||
names.each { it ->
|
||||
println descriptions[it]
|
||||
println ""
|
||||
}
|
||||
println "|==="
|
||||
|
||||
|
||||
class ConfigValue {
|
||||
String name
|
||||
String description
|
||||
Object defaultValue
|
||||
ConfigValue(){}
|
||||
ConfigValue(String name, String description, Object defaultValue) {
|
||||
this.name = name
|
||||
this.description = description
|
||||
this.defaultValue = defaultValue
|
||||
}
|
||||
String toString() {
|
||||
def value = defaultValue==null?'':"${defaultValue}"
|
||||
"|${name} | ${value} | ${description?:''}"
|
||||
}
|
||||
}
|
||||
35
Dalston.SR5/css/highlight.css
Normal 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;
|
||||
}
|
||||
9
Dalston.SR5/css/manual-multipage.css
Normal 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;
|
||||
}
|
||||
6
Dalston.SR5/css/manual-singlepage.css
Normal file
@@ -0,0 +1,6 @@
|
||||
@IMPORT url("manual.css");
|
||||
|
||||
body {
|
||||
background: url("../images/background.png") no-repeat center top;
|
||||
}
|
||||
|
||||
344
Dalston.SR5/css/manual.css
Normal 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;
|
||||
}
|
||||
348
Dalston.SR5/ghpages.sh
Normal file
@@ -0,0 +1,348 @@
|
||||
#!/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) && [[ "${RELEASE_TRAIN}" != "yes" ]] ; 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() {
|
||||
if [[ "${RELEASE_TRAIN}" != "yes" ]] ; then
|
||||
git checkout v${VERSION}
|
||||
fi
|
||||
}
|
||||
|
||||
# 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}' \
|
||||
org.codehaus.mojo:exec-maven-plugin:1.3.1:exec \
|
||||
-P docs \
|
||||
-pl docs)
|
||||
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} && cd ${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
|
||||
if [[ -z "${RELEASE_TRAIN}" ]] ; then
|
||||
DESTINATION_REPO_FOLDER=${clonedStatic}/${REPO_NAME}
|
||||
else
|
||||
DESTINATION_REPO_FOLDER=${clonedStatic}
|
||||
fi
|
||||
mkdir -p ${DESTINATION_REPO_FOLDER}
|
||||
else
|
||||
if [[ ! -e "${DESTINATION}/.git" ]]; then
|
||||
echo "[${DESTINATION}] is not a git repository"
|
||||
exit 1
|
||||
fi
|
||||
if [[ -z "${RELEASE_TRAIN}" ]] ; then
|
||||
DESTINATION_REPO_FOLDER=${DESTINATION}/${REPO_NAME}
|
||||
else
|
||||
DESTINATION_REPO_FOLDER=${DESTINATION}
|
||||
fi
|
||||
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}" && -z "${RELEASE_TRAIN}" ]] ; 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}], RELEASE_TRAIN [${RELEASE_TRAIN}], 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
|
||||
if [[ "${RELEASE_TRAIN}" != "" && -z "${VERSION}" ]] ; then echo "Release train was set but no version was passed!"; 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>`
|
||||
- if the release train switch is passed (-r) 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/<version>`
|
||||
|
||||
USAGE:
|
||||
|
||||
You can use the following options:
|
||||
|
||||
-v|--version - the script will apply the whole procedure for a particular library version
|
||||
-r|--releasetrain - instead of nesting the docs under the project_name/version folder the docs will end up in 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
|
||||
;;
|
||||
-r|--releasetrain)
|
||||
RELEASE_TRAIN="yes"
|
||||
;;
|
||||
-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
|
||||
0
Dalston.SR5/images/.gitkeep
Normal file
BIN
Dalston.SR5/images/Deps.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
Dalston.SR5/images/Hystrix.png
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
Dalston.SR5/images/HystrixFallback.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
Dalston.SR5/images/HystrixGraph.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
Dalston.SR5/images/RequestLatency.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
Dalston.SR5/images/SCSt-groups.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
Dalston.SR5/images/SCSt-partitioning.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
Dalston.SR5/images/SCSt-sensors.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
Dalston.SR5/images/SCSt-with-binder.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
Dalston.SR5/images/Stubs1.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
Dalston.SR5/images/Stubs2.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
Dalston.SR5/images/background.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
Dalston.SR5/images/caution.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
Dalston.SR5/images/dependencies.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
Dalston.SR5/images/important.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
Dalston.SR5/images/kibana.png
Normal file
|
After Width: | Height: | Size: 183 KiB |
BIN
Dalston.SR5/images/logo.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
Dalston.SR5/images/note.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
Dalston.SR5/images/parents.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
Dalston.SR5/images/producers-consumers.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
Dalston.SR5/images/pws.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
Dalston.SR5/images/rabbit-binder.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
Dalston.SR5/images/redis-binder.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
Dalston.SR5/images/registration.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
Dalston.SR5/images/schema_reading.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
Dalston.SR5/images/schema_resolution.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
Dalston.SR5/images/sts_exception.png
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
Dalston.SR5/images/tip.png
Normal file
|
After Width: | Height: | Size: 931 B |
BIN
Dalston.SR5/images/trace-id.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
Dalston.SR5/images/warning.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
Dalston.SR5/images/web-selected.png
Normal file
|
After Width: | Height: | Size: 178 KiB |
BIN
Dalston.SR5/images/zipkin-error-trace-screenshot.png
Normal file
|
After Width: | Height: | Size: 206 KiB |
BIN
Dalston.SR5/images/zipkin-error-traces.png
Normal file
|
After Width: | Height: | Size: 116 KiB |
BIN
Dalston.SR5/images/zipkin-trace-screenshot.png
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
Dalston.SR5/images/zipkin-traces.png
Normal file
|
After Width: | Height: | Size: 149 KiB |
BIN
Dalston.SR5/images/zipkin-ui.png
Normal file
|
After Width: | Height: | Size: 108 KiB |
117
Dalston.SR5/index.html
Normal 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.5">
|
||||
<title>spring-cloud</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</h1>
|
||||
</div>
|
||||
<div id="content">
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>1.3.5.BUILD-SNAPSHOT</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.html">Single HTML</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="multi/multi_spring-cloud.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>
|
||||
35
Dalston.SR5/multi/css/highlight.css
Normal 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;
|
||||
}
|
||||
9
Dalston.SR5/multi/css/manual-multipage.css
Normal 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;
|
||||
}
|
||||
6
Dalston.SR5/multi/css/manual-singlepage.css
Normal file
@@ -0,0 +1,6 @@
|
||||
@IMPORT url("manual.css");
|
||||
|
||||
body {
|
||||
background: url("../images/background.png") no-repeat center top;
|
||||
}
|
||||
|
||||
344
Dalston.SR5/multi/css/manual.css
Normal 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;
|
||||
}
|
||||
BIN
Dalston.SR5/multi/images/background.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
Dalston.SR5/multi/images/caution.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
Dalston.SR5/multi/images/important.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
Dalston.SR5/multi/images/logo.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
Dalston.SR5/multi/images/note.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
Dalston.SR5/multi/images/sts_exception.png
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
Dalston.SR5/multi/images/tip.png
Normal file
|
After Width: | Height: | Size: 931 B |
BIN
Dalston.SR5/multi/images/warning.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
Dalston.SR5/multi/images/web-selected.png
Normal file
|
After Width: | Height: | Size: 178 KiB |
3
Dalston.SR5/multi/multi__additional_resources.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>46. Additional resources</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_sleuth.html" title="Part VII. Spring Cloud Sleuth"><link rel="prev" href="multi__introduction.html" title="45. Introduction"><link rel="next" href="multi__features_2.html" title="47. Features"></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">46. Additional resources</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__introduction.html">Prev</a> </td><th width="60%" align="center">Part VII. Spring Cloud Sleuth</th><td width="20%" align="right"> <a accesskey="n" href="multi__features_2.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_additional_resources" href="#_additional_resources"></a>46. Additional resources</h2></div></div></div><p><span class="strong"><strong>Marcin Grzejszczak talking about Spring Cloud Sleuth and Zipkin</strong></span></p><p><a class="link" href="https://www.youtube.com/watch?v=eQV71Mw1u1c" target="_top">click here to see the video</a></p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__introduction.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_sleuth.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__features_2.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">45. Introduction </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 47. Features</td></tr></table></div></body></html>
|
||||
@@ -0,0 +1,3 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>40. Addressing all instances of a service</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_bus.html" title="Part VI. Spring Cloud Bus"><link rel="prev" href="multi__addressing_an_instance.html" title="39. Addressing an Instance"><link rel="next" href="multi__application_context_id_must_be_unique.html" title="41. Application Context ID must be unique"></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">40. Addressing all instances of a service</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__addressing_an_instance.html">Prev</a> </td><th width="60%" align="center">Part VI. Spring Cloud Bus</th><td width="20%" align="right"> <a accesskey="n" href="multi__application_context_id_must_be_unique.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_addressing_all_instances_of_a_service" href="#_addressing_all_instances_of_a_service"></a>40. Addressing all instances of a service</h2></div></div></div><p>The "destination" parameter is used in a Spring <code class="literal">PathMatcher</code> (with the path separator as a colon <code class="literal">:</code>) to determine if an instance will process the message. Using the example from above, "/bus/refresh?destination=customers:**" will target all instances of the "customers" service regardless of the profiles and ports set as the <code class="literal">ApplicationContext</code> ID.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__addressing_an_instance.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_bus.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__application_context_id_must_be_unique.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">39. Addressing an Instance </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 41. Application Context ID must be unique</td></tr></table></div></body></html>
|
||||
3
Dalston.SR5/multi/multi__addressing_an_instance.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>39. Addressing an Instance</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_bus.html" title="Part VI. Spring Cloud Bus"><link rel="prev" href="multi__quick_start_2.html" title="38. Quick Start"><link rel="next" href="multi__addressing_all_instances_of_a_service.html" title="40. Addressing all instances of a service"></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">39. Addressing an Instance</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__quick_start_2.html">Prev</a> </td><th width="60%" align="center">Part VI. Spring Cloud Bus</th><td width="20%" align="right"> <a accesskey="n" href="multi__addressing_all_instances_of_a_service.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_addressing_an_instance" href="#_addressing_an_instance"></a>39. Addressing an Instance</h2></div></div></div><p>The HTTP endpoints accept a "destination" parameter, e.g. "/bus/refresh?destination=customers:9000", where the destination is an <code class="literal">ApplicationContext</code> ID. If the ID is owned by an instance on the Bus then it will process the message and all other instances will ignore it. Spring Boot sets the ID for you in the <code class="literal">ContextIdApplicationContextInitializer</code> to a combination of the <code class="literal">spring.application.name</code>, active profiles and <code class="literal">server.port</code> by default.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__quick_start_2.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_bus.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__addressing_all_instances_of_a_service.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">38. Quick Start </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 40. Addressing all instances of a service</td></tr></table></div></body></html>
|
||||
231
Dalston.SR5/multi/multi__apache_kafka_binder.html
Normal file
@@ -0,0 +1,231 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>36. Apache Kafka Binder</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__binder_implementations.html" title="Part V. Binder Implementations"><link rel="prev" href="multi__binder_implementations.html" title="Part V. Binder Implementations"><link rel="next" href="multi__rabbitmq_binder.html" title="37. RabbitMQ Binder"></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">36. Apache Kafka Binder</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__binder_implementations.html">Prev</a> </td><th width="60%" align="center">Part V. Binder Implementations</th><td width="20%" align="right"> <a accesskey="n" href="multi__rabbitmq_binder.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_apache_kafka_binder" href="#_apache_kafka_binder"></a>36. Apache Kafka Binder</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_usage" href="#_usage"></a>36.1 Usage</h2></div></div></div><p>For using the Apache Kafka binder, you just need to add it to your Spring Cloud Stream application, using the following Maven coordinates:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-stream-binder-kafka<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre><p>Alternatively, you can also use the Spring Cloud Stream Kafka Starter.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-starter-stream-kafka<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_apache_kafka_binder_overview" href="#_apache_kafka_binder_overview"></a>36.2 Apache Kafka Binder Overview</h2></div></div></div><p>A simplified diagram of how the Apache Kafka binder operates can be seen below.</p><div class="figure"><a name="d0e8691" href="#d0e8691"></a><p class="title"><b>Figure 36.1. Kafka Binder</b></p><div class="figure-contents"><div class="mediaobject"><img src="images/kafka-binder.png" alt="kafka binder"></div></div></div><br class="figure-break"><p>The Apache Kafka Binder implementation maps each destination to an Apache Kafka topic.
|
||||
The consumer group maps directly to the same Apache Kafka concept.
|
||||
Partitioning also maps directly to Apache Kafka partitions as well.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_configuration_options_2" href="#_configuration_options_2"></a>36.3 Configuration Options</h2></div></div></div><p>This section contains the configuration options used by the Apache Kafka binder.</p><p>For common configuration options and properties pertaining to binder, refer to the <a class="link" href="multi__configuration_options.html#binding-properties" title="27.2 Binding Properties">core documentation</a>.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_kafka_binder_properties" href="#_kafka_binder_properties"></a>36.3.1 Kafka Binder Properties</h3></div></div></div><div class="variablelist"><dl class="variablelist"><dt><span class="term">spring.cloud.stream.kafka.binder.brokers</span></dt><dd><p class="simpara">A list of brokers to which the Kafka binder will connect.</p><p class="simpara">Default: <code class="literal">localhost</code>.</p></dd><dt><span class="term">spring.cloud.stream.kafka.binder.defaultBrokerPort</span></dt><dd><p class="simpara"> <code class="literal">brokers</code> allows hosts specified with or without port information (e.g., <code class="literal">host1,host2:port2</code>).
|
||||
This sets the default port when no port is configured in the broker list.</p><p class="simpara">Default: <code class="literal">9092</code>.</p></dd><dt><span class="term">spring.cloud.stream.kafka.binder.zkNodes</span></dt><dd><p class="simpara">A list of ZooKeeper nodes to which the Kafka binder can connect.</p><p class="simpara">Default: <code class="literal">localhost</code>.</p></dd><dt><span class="term">spring.cloud.stream.kafka.binder.defaultZkPort</span></dt><dd><p class="simpara"> <code class="literal">zkNodes</code> allows hosts specified with or without port information (e.g., <code class="literal">host1,host2:port2</code>).
|
||||
This sets the default port when no port is configured in the node list.</p><p class="simpara">Default: <code class="literal">2181</code>.</p></dd><dt><span class="term">spring.cloud.stream.kafka.binder.configuration</span></dt><dd><p class="simpara"> Key/Value map of client properties (both producers and consumer) passed to all clients created by the binder.
|
||||
Due to the fact that these properties will be used by both producers and consumers, usage should be restricted to common properties, especially security settings.</p><p class="simpara">Default: Empty map.</p></dd><dt><span class="term">spring.cloud.stream.kafka.binder.headers</span></dt><dd><p class="simpara">The list of custom headers that will be transported by the binder.</p><p class="simpara">Default: empty.</p></dd><dt><span class="term">spring.cloud.stream.kafka.binder.offsetUpdateTimeWindow</span></dt><dd><p class="simpara"> The frequency, in milliseconds, with which offsets are saved.
|
||||
Ignored if <code class="literal">0</code>.</p><p class="simpara">Default: <code class="literal">10000</code>.</p></dd><dt><span class="term">spring.cloud.stream.kafka.binder.offsetUpdateCount</span></dt><dd><p class="simpara"> The frequency, in number of updates, which which consumed offsets are persisted.
|
||||
Ignored if <code class="literal">0</code>.
|
||||
Mutually exclusive with <code class="literal">offsetUpdateTimeWindow</code>.</p><p class="simpara">Default: <code class="literal">0</code>.</p></dd><dt><span class="term">spring.cloud.stream.kafka.binder.requiredAcks</span></dt><dd><p class="simpara">The number of required acks on the broker.</p><p class="simpara">Default: <code class="literal">1</code>.</p></dd><dt><span class="term">spring.cloud.stream.kafka.binder.minPartitionCount</span></dt><dd><p class="simpara"> Effective only if <code class="literal">autoCreateTopics</code> or <code class="literal">autoAddPartitions</code> is set.
|
||||
The global minimum number of partitions that the binder will configure on topics on which it produces/consumes data.
|
||||
It can be superseded by the <code class="literal">partitionCount</code> setting of the producer or by the value of <code class="literal">instanceCount</code> * <code class="literal">concurrency</code> settings of the producer (if either is larger).</p><p class="simpara">Default: <code class="literal">1</code>.</p></dd><dt><span class="term">spring.cloud.stream.kafka.binder.replicationFactor</span></dt><dd><p class="simpara">The replication factor of auto-created topics if <code class="literal">autoCreateTopics</code> is active.</p><p class="simpara">Default: <code class="literal">1</code>.</p></dd><dt><span class="term">spring.cloud.stream.kafka.binder.autoCreateTopics</span></dt><dd><p class="simpara"> If set to <code class="literal">true</code>, the binder will create new topics automatically.
|
||||
If set to <code class="literal">false</code>, the binder will rely on the topics being already configured.
|
||||
In the latter case, if the topics do not exist, the binder will fail to start.
|
||||
Of note, this setting is independent of the <code class="literal">auto.topic.create.enable</code> setting of the broker and it does not influence it: if the server is set to auto-create topics, they may be created as part of the metadata retrieval request, with default broker settings.</p><p class="simpara">Default: <code class="literal">true</code>.</p></dd><dt><span class="term">spring.cloud.stream.kafka.binder.autoAddPartitions</span></dt><dd><p class="simpara"> If set to <code class="literal">true</code>, the binder will create add new partitions if required.
|
||||
If set to <code class="literal">false</code>, the binder will rely on the partition size of the topic being already configured.
|
||||
If the partition count of the target topic is smaller than the expected value, the binder will fail to start.</p><p class="simpara">Default: <code class="literal">false</code>.</p></dd><dt><span class="term">spring.cloud.stream.kafka.binder.socketBufferSize</span></dt><dd><p class="simpara">Size (in bytes) of the socket buffer to be used by the Kafka consumers.</p><p class="simpara">Default: <code class="literal">2097152</code>.</p></dd></dl></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_kafka_consumer_properties" href="#_kafka_consumer_properties"></a>36.3.2 Kafka Consumer Properties</h3></div></div></div><p>The following properties are available for Kafka consumers only and
|
||||
must be prefixed with <code class="literal">spring.cloud.stream.kafka.bindings.<channelName>.consumer.</code>.</p><div class="variablelist"><dl class="variablelist"><dt><span class="term">autoRebalanceEnabled</span></dt><dd><p class="simpara">When <code class="literal">true</code>, topic partitions will be automatically rebalanced between the members of a consumer group.
|
||||
When <code class="literal">false</code>, each consumer will be assigned a fixed set of partitions based on <code class="literal">spring.cloud.stream.instanceCount</code> and <code class="literal">spring.cloud.stream.instanceIndex</code>.
|
||||
This requires both <code class="literal">spring.cloud.stream.instanceCount</code> and <code class="literal">spring.cloud.stream.instanceIndex</code> properties to be set appropriately on each launched instance.
|
||||
The property <code class="literal">spring.cloud.stream.instanceCount</code> must typically be greater than 1 in this case.</p><p class="simpara">Default: <code class="literal">true</code>.</p></dd><dt><span class="term">autoCommitOffset</span></dt><dd><p class="simpara"> Whether to autocommit offsets when a message has been processed.
|
||||
If set to <code class="literal">false</code>, a header with the key <code class="literal">kafka_acknowledgment</code> of the type <code class="literal">org.springframework.kafka.support.Acknowledgment</code> header will be present in the inbound message.
|
||||
Applications may use this header for acknowledging messages.
|
||||
See the examples section for details.
|
||||
When this property is set to <code class="literal">false</code>, Kafka binder will set the ack mode to <code class="literal">org.springframework.kafka.listener.AbstractMessageListenerContainer.AckMode.MANUAL</code>.</p><p class="simpara">Default: <code class="literal">true</code>.</p></dd><dt><span class="term">autoCommitOnError</span></dt><dd><p class="simpara"> Effective only if <code class="literal">autoCommitOffset</code> is set to <code class="literal">true</code>.
|
||||
If set to <code class="literal">false</code> it suppresses auto-commits for messages that result in errors, and will commit only for successful messages, allows a stream to automatically replay from the last successfully processed message, in case of persistent failures.
|
||||
If set to <code class="literal">true</code>, it will always auto-commit (if auto-commit is enabled).
|
||||
If not set (default), it effectively has the same value as <code class="literal">enableDlq</code>, auto-committing erroneous messages if they are sent to a DLQ, and not committing them otherwise.</p><p class="simpara">Default: not set.</p></dd><dt><span class="term">recoveryInterval</span></dt><dd><p class="simpara">The interval between connection recovery attempts, in milliseconds.</p><p class="simpara">Default: <code class="literal">5000</code>.</p></dd><dt><span class="term">resetOffsets</span></dt><dd><p class="simpara">Whether to reset offsets on the consumer to the value provided by <code class="literal">startOffset</code>.</p><p class="simpara">Default: <code class="literal">false</code>.</p></dd><dt><span class="term">startOffset</span></dt><dd><p class="simpara"> The starting offset for new groups, or when <code class="literal">resetOffsets</code> is <code class="literal">true</code>.
|
||||
Allowed values: <code class="literal">earliest</code>, <code class="literal">latest</code>.
|
||||
If the consumer group is set explicitly for the consumer 'binding' (via <code class="literal">spring.cloud.stream.bindings.<channelName>.group</code>), then 'startOffset' is set to <code class="literal">earliest</code>; otherwise it is set to <code class="literal">latest</code> for the <code class="literal">anonymous</code> consumer group.</p><p class="simpara">Default: null (equivalent to <code class="literal">earliest</code>).</p></dd><dt><span class="term">enableDlq</span></dt><dd><p class="simpara">When set to true, it will send enable DLQ behavior for the consumer.
|
||||
By default, messages that result in errors will be forwarded to a topic named <code class="literal">error.<destination>.<group></code>.
|
||||
The DLQ topic name can be configurable via the property <code class="literal">dlqName</code>.
|
||||
This provides an alternative option to the more common Kafka replay scenario for the case when the number of errors is relatively small and replaying the entire original topic may be too cumbersome.</p><p class="simpara">Default: <code class="literal">false</code>.</p></dd><dt><span class="term">configuration</span></dt><dd><p class="simpara">Map with a key/value pair containing generic Kafka consumer properties.</p><p class="simpara">Default: Empty map.</p></dd><dt><span class="term">dlqName</span></dt><dd><p class="simpara">The name of the DLQ topic to receive the error messages.</p><p class="simpara">Default: null (If not specified, messages that result in errors will be forwarded to a topic named <code class="literal">error.<destination>.<group></code>).</p></dd></dl></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_kafka_producer_properties" href="#_kafka_producer_properties"></a>36.3.3 Kafka Producer Properties</h3></div></div></div><p>The following properties are available for Kafka producers only and
|
||||
must be prefixed with <code class="literal">spring.cloud.stream.kafka.bindings.<channelName>.producer.</code>.</p><div class="variablelist"><dl class="variablelist"><dt><span class="term">bufferSize</span></dt><dd><p class="simpara">Upper limit, in bytes, of how much data the Kafka producer will attempt to batch before sending.</p><p class="simpara">Default: <code class="literal">16384</code>.</p></dd><dt><span class="term">sync</span></dt><dd><p class="simpara">Whether the producer is synchronous.</p><p class="simpara">Default: <code class="literal">false</code>.</p></dd><dt><span class="term">batchTimeout</span></dt><dd><p class="simpara"> How long the producer will wait before sending in order to allow more messages to accumulate in the same batch.
|
||||
(Normally the producer does not wait at all, and simply sends all the messages that accumulated while the previous send was in progress.) A non-zero value may increase throughput at the expense of latency.</p><p class="simpara">Default: <code class="literal">0</code>.</p></dd><dt><span class="term">messageKeyExpression</span></dt><dd><p class="simpara"> A SpEL expression evaluated against the outgoing message used to populate the key of the produced Kafka message.
|
||||
For example <code class="literal">headers.key</code> or <code class="literal">payload.myKey</code>.</p><p class="simpara">Default: <code class="literal">none</code>.</p></dd><dt><span class="term">configuration</span></dt><dd><p class="simpara">Map with a key/value pair containing generic Kafka producer properties.</p><p class="simpara">Default: Empty map.</p></dd></dl></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The Kafka binder will use the <code class="literal">partitionCount</code> setting of the producer as a hint to create a topic with the given partition count (in conjunction with the <code class="literal">minPartitionCount</code>, the maximum of the two being the value being used).
|
||||
Exercise caution when configuring both <code class="literal">minPartitionCount</code> for a binder and <code class="literal">partitionCount</code> for an application, as the larger value will be used.
|
||||
If a topic already exists with a smaller partition count and <code class="literal">autoAddPartitions</code> is disabled (the default), then the binder will fail to start.
|
||||
If a topic already exists with a smaller partition count and <code class="literal">autoAddPartitions</code> is enabled, new partitions will be added.
|
||||
If a topic already exists with a larger number of partitions than the maximum of (<code class="literal">minPartitionCount</code> and <code class="literal">partitionCount</code>), the existing partition count will be used.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_usage_examples" href="#_usage_examples"></a>36.3.4 Usage examples</h3></div></div></div><p>In this section, we illustrate the use of the above properties for specific scenarios.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_example_setting_literal_autocommitoffset_literal_false_and_relying_on_manual_acking" href="#_example_setting_literal_autocommitoffset_literal_false_and_relying_on_manual_acking"></a>Example: Setting <code class="literal">autoCommitOffset</code> false and relying on manual acking.</h4></div></div></div><p>This example illustrates how one may manually acknowledge offsets in a consumer application.</p><p>This example requires that <code class="literal">spring.cloud.stream.kafka.bindings.input.consumer.autoCommitOffset</code> is set to false.
|
||||
Use the corresponding input channel name for your example.</p><pre class="screen">@SpringBootApplication
|
||||
@EnableBinding(Sink.class)
|
||||
public class ManuallyAcknowdledgingConsumer {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ManuallyAcknowdledgingConsumer.class, args);
|
||||
}
|
||||
|
||||
@StreamListener(Sink.INPUT)
|
||||
public void process(Message<?> message) {
|
||||
Acknowledgment acknowledgment = message.getHeaders().get(KafkaHeaders.ACKNOWLEDGMENT, Acknowledgment.class);
|
||||
if (acknowledgment != null) {
|
||||
System.out.println("Acknowledgment provided");
|
||||
acknowledgment.acknowledge();
|
||||
}
|
||||
}
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_example_security_configuration" href="#_example_security_configuration"></a>Example: security configuration</h4></div></div></div><p>Apache Kafka 0.9 supports secure connections between client and brokers.
|
||||
To take advantage of this feature, follow the guidelines in the <a class="link" href="http://kafka.apache.org/090/documentation.html#security_configclients" target="_top">Apache Kafka Documentation</a> as well as the Kafka 0.9 <a class="link" href="http://docs.confluent.io/2.0.0/kafka/security.html" target="_top">security guidelines from the Confluent documentation</a>.
|
||||
Use the <code class="literal">spring.cloud.stream.kafka.binder.configuration</code> option to set security properties for all clients created by the binder.</p><p>For example, for setting <code class="literal">security.protocol</code> to <code class="literal">SASL_SSL</code>, set:</p><pre class="screen">spring.cloud.stream.kafka.binder.configuration.security.protocol=SASL_SSL</pre><p>All the other security properties can be set in a similar manner.</p><p>When using Kerberos, follow the instructions in the <a class="link" href="http://kafka.apache.org/090/documentation.html#security_sasl_clientconfig" target="_top">reference documentation</a> for creating and referencing the JAAS configuration.</p><p>Spring Cloud Stream supports passing JAAS configuration information to the application using a JAAS configuration file and using Spring Boot properties.</p><div class="section"><div class="titlepage"><div><div><h5 class="title"><a name="_using_jaas_configuration_files" href="#_using_jaas_configuration_files"></a>Using JAAS configuration files</h5></div></div></div><p>The JAAS, and (optionally) krb5 file locations can be set for Spring Cloud Stream applications by using system properties.
|
||||
Here is an example of launching a Spring Cloud Stream application with SASL and Kerberos using a JAAS configuration file:</p><pre class="screen"> java -Djava.security.auth.login.config=/path.to/kafka_client_jaas.conf -jar log.jar \
|
||||
--spring.cloud.stream.kafka.binder.brokers=secure.server:9092 \
|
||||
--spring.cloud.stream.kafka.binder.zkNodes=secure.zookeeper:2181 \
|
||||
--spring.cloud.stream.bindings.input.destination=stream.ticktock \
|
||||
--spring.cloud.stream.kafka.binder.configuration.security.protocol=SASL_PLAINTEXT</pre></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a name="_using_spring_boot_properties" href="#_using_spring_boot_properties"></a>Using Spring Boot properties</h5></div></div></div><p>As an alternative to having a JAAS configuration file, Spring Cloud Stream provides a mechanism for setting up the JAAS configuration for Spring Cloud Stream applications using Spring Boot properties.</p><p>The following properties can be used for configuring the login context of the Kafka client.</p><div class="variablelist"><dl class="variablelist"><dt><span class="term">spring.cloud.stream.kafka.binder.jaas.loginModule</span></dt><dd><p class="simpara">The login module name. Not necessary to be set in normal cases.</p><p class="simpara">Default: <code class="literal">com.sun.security.auth.module.Krb5LoginModule</code>.</p></dd><dt><span class="term">spring.cloud.stream.kafka.binder.jaas.controlFlag</span></dt><dd><p class="simpara">The control flag of the login module.</p><p class="simpara">Default: <code class="literal">required</code>.</p></dd><dt><span class="term">spring.cloud.stream.kafka.binder.jaas.options</span></dt><dd><p class="simpara">Map with a key/value pair containing the login module options.</p><p class="simpara">Default: Empty map.</p></dd></dl></div><p>Here is an example of launching a Spring Cloud Stream application with SASL and Kerberos using Spring Boot configuration properties:</p><pre class="screen"> java --spring.cloud.stream.kafka.binder.brokers=secure.server:9092 \
|
||||
--spring.cloud.stream.kafka.binder.zkNodes=secure.zookeeper:2181 \
|
||||
--spring.cloud.stream.bindings.input.destination=stream.ticktock \
|
||||
--spring.cloud.stream.kafka.binder.autoCreateTopics=false \
|
||||
--spring.cloud.stream.kafka.binder.configuration.security.protocol=SASL_PLAINTEXT \
|
||||
--spring.cloud.stream.kafka.binder.jaas.options.useKeyTab=true \
|
||||
--spring.cloud.stream.kafka.binder.jaas.options.storeKey=true \
|
||||
--spring.cloud.stream.kafka.binder.jaas.options.keyTab=/etc/security/keytabs/kafka_client.keytab \
|
||||
--spring.cloud.stream.kafka.binder.jaas.options.principal=kafka-client-1@EXAMPLE.COM</pre><p>This represents the equivalent of the following JAAS file:</p><pre class="screen">KafkaClient {
|
||||
com.sun.security.auth.module.Krb5LoginModule required
|
||||
useKeyTab=true
|
||||
storeKey=true
|
||||
keyTab="/etc/security/keytabs/kafka_client.keytab"
|
||||
principal="kafka-client-1@EXAMPLE.COM";
|
||||
};</pre><p>If the topics required already exist on the broker, or will be created by an administrator, autocreation can be turned off and only client JAAS properties need to be sent. As an alternative to setting <code class="literal">spring.cloud.stream.kafka.binder.autoCreateTopics</code> you can simply remove the broker dependency from the application. See <a class="xref" href="multi__apache_kafka_binder.html#exclude-admin-utils" title="Excluding Kafka broker jar from the classpath of the binder based application">the section called “Excluding Kafka broker jar from the classpath of the binder based application”</a> for details.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Do not mix JAAS configuration files and Spring Boot properties in the same application.
|
||||
If the <code class="literal">-Djava.security.auth.login.config</code> system property is already present, Spring Cloud Stream will ignore the Spring Boot properties.</p></td></tr></table></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Exercise caution when using the <code class="literal">autoCreateTopics</code> and <code class="literal">autoAddPartitions</code> if using Kerberos.
|
||||
Usually applications may use principals that do not have administrative rights in Kafka and Zookeeper, and relying on Spring Cloud Stream to create/modify topics may fail.
|
||||
In secure environments, we strongly recommend creating topics and managing ACLs administratively using Kafka tooling.</p></td></tr></table></div></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_using_the_binder_with_apache_kafka_0_10" href="#_using_the_binder_with_apache_kafka_0_10"></a>Using the binder with Apache Kafka 0.10</h4></div></div></div><p>The default Kafka support in Spring Cloud Stream Kafka binder is for Kafka version 0.10.1.1. The binder also supports connecting to other 0.10 based versions and 0.9 clients.
|
||||
In order to do this, when you create the project that contains your application, include <code class="literal">spring-cloud-starter-stream-kafka</code> as you normally would do for the default binder.
|
||||
Then add these dependencies at the top of the <code class="literal"><dependencies></code> section in the pom.xml file to override the dependencies.</p><p>Here is an example for downgrading your application to 0.10.0.1. Since it is still on the 0.10 line, the default <code class="literal">spring-kafka</code> and <code class="literal">spring-integration-kafka</code> versions can be retained.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.apache.kafka<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>kafka_2.11<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>0.10.0.1<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><exclusions></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><exclusion></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.slf4j<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>slf4j-log4j12<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></exclusion></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></exclusions></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.apache.kafka<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>kafka-clients<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>0.10.0.1<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre><p>Here is another example of using 0.9.0.1 version.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.kafka<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-kafka<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>1.0.5.RELEASE<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.integration<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-integration-kafka<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>2.0.1.RELEASE<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.apache.kafka<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>kafka_2.11<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>0.9.0.1<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><exclusions></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><exclusion></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.slf4j<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>slf4j-log4j12<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></exclusion></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></exclusions></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.apache.kafka<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>kafka-clients<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>0.9.0.1<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The versions above are provided only for the sake of the example.
|
||||
For best results, we recommend using the most recent 0.10-compatible versions of the projects.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="exclude-admin-utils" href="#exclude-admin-utils"></a>Excluding Kafka broker jar from the classpath of the binder based application</h4></div></div></div><p>The Apache Kafka Binder uses the administrative utilities which are part of the Apache Kafka server library to create and reconfigure topics.
|
||||
If the inclusion of the Apache Kafka server library and its dependencies is not necessary at runtime because the application will rely on the topics being configured administratively, the Kafka binder allows for Apache Kafka server dependency to be excluded from the application.</p><p>If you use non default versions for Kafka dependencies as advised above, all you have to do is not to include the kafka broker dependency.
|
||||
If you use the default Kafka version, then ensure that you exclude the kafka broker jar from the <code class="literal">spring-cloud-starter-stream-kafka</code> dependency as following.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-starter-stream-kafka<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><exclusions></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><exclusion></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.apache.kafka<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>kafka_2.11<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></exclusion></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></exclusions></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre><p>If you exclude the Apache Kafka server dependency and the topic is not present on the server, then the Apache Kafka broker will create the topic if auto topic creation is enabled on the server.
|
||||
Please keep in mind that if you are relying on this, then the Kafka server will use the default number of partitions and replication factors.
|
||||
On the other hand, if auto topic creation is disabled on the server, then care must be taken before running the application to create the topic with the desired number of partitions.</p><p>If you want to have full control over how partitions are allocated, then leave the default settings as they are, i.e. do not exclude the kafka broker jar and ensure that <code class="literal">spring.cloud.stream.kafka.binder.autoCreateTopics</code> is set to <code class="literal">true</code>, which is the default.</p></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="kafka-dlq-processing" href="#kafka-dlq-processing"></a>36.4 Dead-Letter Topic Processing</h2></div></div></div><p>Because it can’t be anticipated how users would want to dispose of dead-lettered messages, the framework does not provide any standard mechanism to handle them.
|
||||
If the reason for the dead-lettering is transient, you may wish to route the messages back to the original topic.
|
||||
However, if the problem is a permanent issue, that could cause an infinite loop.
|
||||
The following <code class="literal">spring-boot</code> application is an example of how to route those messages back to the original topic, but moves them to a third "parking lot" topic after three attempts.
|
||||
The application is simply another spring-cloud-stream application that reads from the dead-letter topic.
|
||||
It terminates when no messages are received for 5 seconds.</p><p>The examples assume the original destination is <code class="literal">so8400out</code> and the consumer group is <code class="literal">so8400</code>.</p><p>There are several considerations.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Consider only running the rerouting when the main application is not running.
|
||||
Otherwise, the retries for transient errors will be used up very quickly.</li><li class="listitem">Alternatively, use a two-stage approach - use this application to route to a third topic, and another to route from there back to the main topic.</li><li class="listitem">Since this technique uses a message header to keep track of retries, it won’t work with <code class="literal">headerMode=raw</code>.
|
||||
In that case, consider adding some data to the payload (that can be ignored by the main application).</li><li class="listitem"><code class="literal">x-retries</code> has to be added to the <code class="literal">headers</code> property <code class="literal">spring.cloud.stream.kafka.binder.headers=x-retries</code> on both this, and the main application so that the header is transported between the applications.</li><li class="listitem">Since kafka is publish/subscribe, replayed messages will be sent to each consumer group, even those that successfully processed a message the first time around.</li></ul></div><p><b>application.properties. </b>
|
||||
</p><pre class="screen">spring.cloud.stream.bindings.input.group=so8400replay
|
||||
spring.cloud.stream.bindings.input.destination=error.so8400out.so8400
|
||||
|
||||
spring.cloud.stream.bindings.output.destination=so8400out
|
||||
spring.cloud.stream.bindings.output.producer.partitioned=true
|
||||
|
||||
spring.cloud.stream.bindings.parkingLot.destination=so8400in.parkingLot
|
||||
spring.cloud.stream.bindings.parkingLot.producer.partitioned=true
|
||||
|
||||
spring.cloud.stream.kafka.binder.configuration.auto.offset.reset=earliest
|
||||
|
||||
spring.cloud.stream.kafka.binder.headers=x-retries</pre><p>
|
||||
</p><p><b>Application. </b>
|
||||
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@SpringBootApplication</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableBinding(TwoOutputProcessor.class)</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> ReRouteDlqKApplication <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">implements</span> CommandLineRunner {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</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">final</span> String X_RETRIES_HEADER = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"x-retries"</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) {
|
||||
SpringApplication.run(ReRouteDlqKApplication.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>, args).close();
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> AtomicInteger processed = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> AtomicInteger();
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> MessageChannel parkingLot;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@StreamListener(Processor.INPUT)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SendTo(Processor.OUTPUT)</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Message<?> reRoute(Message<?> failed) {
|
||||
processed.incrementAndGet();
|
||||
Integer retries = failed.getHeaders().get(X_RETRIES_HEADER, Integer.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (retries == null) {
|
||||
System.out.println(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"First retry for "</span> + failed);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> MessageBuilder.fromMessage(failed)
|
||||
.setHeader(X_RETRIES_HEADER, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Integer(<span class="hl-number">1</span>))
|
||||
.setHeader(BinderHeaders.PARTITION_OVERRIDE,
|
||||
failed.getHeaders().get(KafkaHeaders.RECEIVED_PARTITION_ID))
|
||||
.build();
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">else</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (retries.intValue() < <span class="hl-number">3</span>) {
|
||||
System.out.println(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Another retry for "</span> + failed);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> MessageBuilder.fromMessage(failed)
|
||||
.setHeader(X_RETRIES_HEADER, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Integer(retries.intValue() + <span class="hl-number">1</span>))
|
||||
.setHeader(BinderHeaders.PARTITION_OVERRIDE,
|
||||
failed.getHeaders().get(KafkaHeaders.RECEIVED_PARTITION_ID))
|
||||
.build();
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">else</span> {
|
||||
System.out.println(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Retries exhausted for "</span> + failed);
|
||||
parkingLot.send(MessageBuilder.fromMessage(failed)
|
||||
.setHeader(BinderHeaders.PARTITION_OVERRIDE,
|
||||
failed.getHeaders().get(KafkaHeaders.RECEIVED_PARTITION_ID))
|
||||
.build());
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> null;
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</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">void</span> run(String... args) <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">while</span> (true) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">int</span> count = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.processed.get();
|
||||
Thread.sleep(<span class="hl-number">5000</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (count == <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.processed.get()) {
|
||||
System.out.println(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Idle, terminating"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</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">interface</span> TwoOutputProcessor <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> Processor {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Output("parkingLot")</span></em>
|
||||
MessageChannel parkingLot();
|
||||
|
||||
}
|
||||
|
||||
}</pre><p>
|
||||
</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__binder_implementations.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__binder_implementations.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__rabbitmq_binder.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Part V. Binder Implementations </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 37. RabbitMQ Binder</td></tr></table></div></body></html>
|
||||
@@ -0,0 +1,3 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>41. Application Context ID must be unique</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_bus.html" title="Part VI. Spring Cloud Bus"><link rel="prev" href="multi__addressing_all_instances_of_a_service.html" title="40. Addressing all instances of a service"><link rel="next" href="multi__customizing_the_message_broker.html" title="42. Customizing the Message Broker"></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">41. Application Context ID must be unique</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__addressing_all_instances_of_a_service.html">Prev</a> </td><th width="60%" align="center">Part VI. Spring Cloud Bus</th><td width="20%" align="right"> <a accesskey="n" href="multi__customizing_the_message_broker.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_application_context_id_must_be_unique" href="#_application_context_id_must_be_unique"></a>41. Application Context ID must be unique</h2></div></div></div><p>The bus tries to eliminate processing an event twice, once from the original <code class="literal">ApplicationEvent</code> and once from the queue. To do this, it checks the sending application context id againts the current application context id. If multiple instances of a service have the same application context id, events will not be processed. Running on a local machine, each service will be on a different port and that will be part of the application context id. Cloud Foundry supplies an index to differentiate. To ensure that the application context id is the unique, set <code class="literal">spring.application.index</code> to something unique for each instance of a service. For example, in lattice, set <code class="literal">spring.application.index=${INSTANCE_INDEX}</code> in application.properties (or bootstrap.properties if using configserver).</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__addressing_all_instances_of_a_service.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_bus.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__customizing_the_message_broker.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">40. Addressing all instances of a service </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 42. Customizing the Message Broker</td></tr></table></div></body></html>
|
||||
3
Dalston.SR5/multi/multi__binder_implementations.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Part V. Binder Implementations</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="prev" href="multi__getting_started.html" title="35. Getting Started"><link rel="next" href="multi__apache_kafka_binder.html" title="36. Apache Kafka Binder"></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">Part V. Binder Implementations</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__getting_started.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__apache_kafka_binder.html">Next</a></td></tr></table><hr></div><div class="part"><div class="titlepage"><div><div><h1 class="title"><a name="_binder_implementations" href="#_binder_implementations"></a>Part V. Binder Implementations</h1></div></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__getting_started.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__apache_kafka_binder.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">35. Getting Started </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 36. Apache Kafka Binder</td></tr></table></div></body></html>
|
||||
58
Dalston.SR5/multi/multi__binders.html
Normal file
@@ -0,0 +1,58 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>26. Binders</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_stream.html" title="Part IV. Spring Cloud Stream"><link rel="prev" href="multi__programming_model.html" title="25. Programming Model"><link rel="next" href="multi__configuration_options.html" title="27. Configuration Options"></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">26. Binders</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__programming_model.html">Prev</a> </td><th width="60%" align="center">Part IV. Spring Cloud Stream</th><td width="20%" align="right"> <a accesskey="n" href="multi__configuration_options.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_binders" href="#_binders"></a>26. Binders</h2></div></div></div><p>Spring Cloud Stream provides a Binder abstraction for use in connecting to physical destinations at the external middleware.
|
||||
This section provides information about the main concepts behind the Binder SPI, its main components, and implementation-specific details.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_producers_and_consumers" href="#_producers_and_consumers"></a>26.1 Producers and Consumers</h2></div></div></div><div class="figure"><a name="d0e6630" href="#d0e6630"></a><p class="title"><b>Figure 26.1. Producers and Consumers</b></p><div class="figure-contents"><div class="mediaobject"><img src="images/producers-consumers.png" alt="producers consumers"></div></div></div><br class="figure-break"><p>A <span class="emphasis"><em>producer</em></span> is any component that sends messages to a channel.
|
||||
The channel can be bound to an external message broker via a Binder implementation for that broker.
|
||||
When invoking the <code class="literal">bindProducer()</code> method, the first parameter is the name of the destination within the broker, the second parameter is the local channel instance to which the producer will send messages, and the third parameter contains properties (such as a partition key expression) to be used within the adapter that is created for that channel.</p><p>A <span class="emphasis"><em>consumer</em></span> is any component that receives messages from a channel.
|
||||
As with a producer, the consumer’s channel can be bound to an external message broker.
|
||||
When invoking the <code class="literal">bindConsumer()</code> method, the first parameter is the destination name, and a second parameter provides the name of a logical group of consumers.
|
||||
Each group that is represented by consumer bindings for a given destination receives a copy of each message that a producer sends to that destination (i.e., publish-subscribe semantics).
|
||||
If there are multiple consumer instances bound using the same group name, then messages will be load-balanced across those consumer instances so that each message sent by a producer is consumed by only a single consumer instance within each group (i.e., queueing semantics).</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_binder_spi" href="#_binder_spi"></a>26.2 Binder SPI</h2></div></div></div><p>The Binder SPI consists of a number of interfaces, out-of-the box utility classes and discovery strategies that provide a pluggable mechanism for connecting to external middleware.</p><p>The key point of the SPI is the <code class="literal">Binder</code> interface which is a strategy for connecting inputs and outputs to external middleware.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> Binder<T, C <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> ConsumerProperties, P <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> ProducerProperties> {
|
||||
Binding<T> bindConsumer(String name, String group, T inboundBindTarget, C consumerProperties);
|
||||
|
||||
Binding<T> bindProducer(String name, T outboundBindTarget, P producerProperties);
|
||||
}</pre><p>The interface is parameterized, offering a number of extension points:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">input and output bind targets - as of version 1.0, only <code class="literal">MessageChannel</code> is supported, but this is intended to be used as an extension point in the future;</li><li class="listitem">extended consumer and producer properties - allowing specific Binder implementations to add supplemental properties which can be supported in a type-safe manner.</li></ul></div><p>A typical binder implementation consists of the following</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">a class that implements the <code class="literal">Binder</code> interface;</li><li class="listitem">a Spring <code class="literal">@Configuration</code> class that creates a bean of the type above along with the middleware connection infrastructure;</li><li class="listitem">a <code class="literal">META-INF/spring.binders</code> file found on the classpath containing one or more binder definitions, e.g.</li></ul></div><pre class="screen">kafka:\
|
||||
org.springframework.cloud.stream.binder.kafka.config.KafkaBinderConfiguration</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_binder_detection" href="#_binder_detection"></a>26.3 Binder Detection</h2></div></div></div><p>Spring Cloud Stream relies on implementations of the Binder SPI to perform the task of connecting channels to message brokers.
|
||||
Each Binder implementation typically connects to one type of messaging system.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_classpath_detection" href="#_classpath_detection"></a>26.3.1 Classpath Detection</h3></div></div></div><p>By default, Spring Cloud Stream relies on Spring Boot’s auto-configuration to configure the binding process.
|
||||
If a single Binder implementation is found on the classpath, Spring Cloud Stream will use it automatically.
|
||||
For example, a Spring Cloud Stream project that aims to bind only to RabbitMQ can simply add the following dependency:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-stream-binder-rabbit<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre><p>For the specific maven coordinates of other binder dependencies, please refer to the documentation of that binder implementation.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="multiple-binders" href="#multiple-binders"></a>26.4 Multiple Binders on the Classpath</h2></div></div></div><p>When multiple binders are present on the classpath, the application must indicate which binder is to be used for each channel binding.
|
||||
Each binder configuration contains a <code class="literal">META-INF/spring.binders</code>, which is a simple properties file:</p><pre class="screen">rabbit:\
|
||||
org.springframework.cloud.stream.binder.rabbit.config.RabbitServiceAutoConfiguration</pre><p>Similar files exist for the other provided binder implementations (e.g., Kafka), and custom binder implementations are expected to provide them, as well.
|
||||
The key represents an identifying name for the binder implementation, whereas the value is a comma-separated list of configuration classes that each contain one and only one bean definition of type <code class="literal">org.springframework.cloud.stream.binder.Binder</code>.</p><p>Binder selection can either be performed globally, using the <code class="literal">spring.cloud.stream.defaultBinder</code> property (e.g., <code class="literal">spring.cloud.stream.defaultBinder=rabbit</code>) or individually, by configuring the binder on each channel binding.
|
||||
For instance, a processor application (that has channels with the names <code class="literal">input</code> and <code class="literal">output</code> for read/write respectively) which reads from Kafka and writes to RabbitMQ can specify the following configuration:</p><pre class="screen">spring.cloud.stream.bindings.input.binder=kafka
|
||||
spring.cloud.stream.bindings.output.binder=rabbit</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="multiple-systems" href="#multiple-systems"></a>26.5 Connecting to Multiple Systems</h2></div></div></div><p>By default, binders share the application’s Spring Boot auto-configuration, so that one instance of each binder found on the classpath will be created.
|
||||
If your application should connect to more than one broker of the same type, you can specify multiple binder configurations, each with different environment settings.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Turning on explicit binder configuration will disable the default binder configuration process altogether.
|
||||
If you do this, all binders in use must be included in the configuration.
|
||||
Frameworks that intend to use Spring Cloud Stream transparently may create binder configurations that can be referenced by name, but will not affect the default binder configuration.
|
||||
In order to do so, a binder configuration may have its <code class="literal">defaultCandidate</code> flag set to false, e.g. <code class="literal">spring.cloud.stream.binders.<configurationName>.defaultCandidate=false</code>.
|
||||
This denotes a configuration that will exist independently of the default binder configuration process.</p></td></tr></table></div><p>For example, this is the typical configuration for a processor application which connects to two RabbitMQ broker instances:</p><pre class="programlisting">spring:
|
||||
cloud:
|
||||
stream:
|
||||
bindings:
|
||||
input:
|
||||
destination: foo
|
||||
binder: rabbit1
|
||||
output:
|
||||
destination: bar
|
||||
binder: rabbit2
|
||||
binders:
|
||||
rabbit1:
|
||||
type: rabbit
|
||||
environment:
|
||||
spring:
|
||||
rabbitmq:
|
||||
host: <host1>
|
||||
rabbit2:
|
||||
type: rabbit
|
||||
environment:
|
||||
spring:
|
||||
rabbitmq:
|
||||
host: <host2></pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_binder_configuration_properties" href="#_binder_configuration_properties"></a>26.6 Binder configuration properties</h2></div></div></div><p>The following properties are available when creating custom binder configurations.
|
||||
They must be prefixed with <code class="literal">spring.cloud.stream.binders.<configurationName></code>.</p><div class="variablelist"><dl class="variablelist"><dt><span class="term">type</span></dt><dd><p class="simpara"> The binder type.
|
||||
It typically references one of the binders found on the classpath, in particular a key in a <code class="literal">META-INF/spring.binders</code> file.</p><p class="simpara">By default, it has the same value as the configuration name.</p></dd><dt><span class="term">inheritEnvironment</span></dt><dd><p class="simpara">Whether the configuration will inherit the environment of the application itself.</p><p class="simpara">Default <code class="literal">true</code>.</p></dd><dt><span class="term">environment</span></dt><dd><p class="simpara"> Root for a set of properties that can be used to customize the environment of the binder.
|
||||
When this is configured, the context in which the binder is being created is not a child of the application context.
|
||||
This allows for complete separation between the binder components and the application components.</p><p class="simpara">Default <code class="literal">empty</code>.</p></dd><dt><span class="term">defaultCandidate</span></dt><dd><p class="simpara"> Whether the binder configuration is a candidate for being considered a default binder, or can be used only when explicitly referenced.
|
||||
This allows adding binder configurations without interfering with the default processing.</p><p class="simpara">Default <code class="literal">true</code>.</p></dd></dl></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__programming_model.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_stream.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__configuration_options.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">25. Programming Model </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 27. Configuration Options</td></tr></table></div></body></html>
|
||||
36
Dalston.SR5/multi/multi__broadcasting_your_own_events.html
Normal file
@@ -0,0 +1,36 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>44. Broadcasting Your Own Events</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_bus.html" title="Part VI. Spring Cloud Bus"><link rel="prev" href="multi__tracing_bus_events.html" title="43. Tracing Bus Events"><link rel="next" href="multi__spring_cloud_sleuth.html" title="Part VII. Spring Cloud Sleuth"></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">44. Broadcasting Your Own Events</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__tracing_bus_events.html">Prev</a> </td><th width="60%" align="center">Part VI. Spring Cloud Bus</th><td width="20%" align="right"> <a accesskey="n" href="multi__spring_cloud_sleuth.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_broadcasting_your_own_events" href="#_broadcasting_your_own_events"></a>44. Broadcasting Your Own Events</h2></div></div></div><p>The Bus can carry any event of type <code class="literal">RemoteApplicationEvent</code>, but the
|
||||
default transport is JSON and the deserializer needs to know which
|
||||
types are going to be used ahead of time. To register a new type it
|
||||
needs to be in a subpackage of <code class="literal">org.springframework.cloud.bus.event</code>.</p><p>To customise the event name you can use <code class="literal">@JsonTypeName</code> on your custom class
|
||||
or rely on the default strategy which is to use the simple name of the class.
|
||||
Note that both the producer and the consumer will need access to the class
|
||||
definition.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_registering_events_in_custom_packages" href="#_registering_events_in_custom_packages"></a>44.1 Registering events in custom packages</h2></div></div></div><p>If you cannot or don’t want to use a subpackage of <code class="literal">org.springframework.cloud.bus.event</code>
|
||||
for your custom events, you must specify which packages to scan for events of
|
||||
type <code class="literal">RemoteApplicationEvent</code> using <code class="literal">@RemoteApplicationEventScan</code>. Packages
|
||||
specified with <code class="literal">@RemoteApplicationEventScan</code> include subpackages.</p><p>For example, if you have a custom event called <code class="literal">FooEvent</code>:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> com.acme;
|
||||
|
||||
<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> FooEvent <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> RemoteApplicationEvent {
|
||||
...
|
||||
}</pre><p>you can register this event with the deserializer in the following way:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> com.acme;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@RemoteApplicationEventScan</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> BusConfiguration {
|
||||
...
|
||||
}</pre><p>Without specifying a value, the package of the class where <code class="literal">@RemoteApplicationEventScan</code>
|
||||
is used will be registered. In this example <code class="literal">com.acme</code> will be registered using the
|
||||
package of <code class="literal">BusConfiguration</code>.</p><p>You can also explicitly specify the packages to scan using the <code class="literal">value</code>, <code class="literal">basePackages</code> or
|
||||
<code class="literal">basePackageClasses</code> properties on <code class="literal">@RemoteApplicationEventScan</code>. For example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> com.acme;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//@RemoteApplicationEventScan({"com.acme", "foo.bar"})</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//@RemoteApplicationEventScan(basePackages = {"com.acme", "foo.bar", "fizz.buzz"})</span>
|
||||
<em><span class="hl-annotation" style="color: gray">@RemoteApplicationEventScan(basePackageClasses = BusConfiguration.class)</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> BusConfiguration {
|
||||
...
|
||||
}</pre><p>All examples of <code class="literal">@RemoteApplicationEventScan</code> above are equivalent,
|
||||
in that the <code class="literal">com.acme</code> package will be registered by explicitly specifying the
|
||||
packages on <code class="literal">@RemoteApplicationEventScan</code>. Note, you can specify multiple base
|
||||
packages to scan.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__tracing_bus_events.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_bus.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__spring_cloud_sleuth.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">43. Tracing Bus Events </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> Part VII. Spring Cloud Sleuth</td></tr></table></div></body></html>
|
||||
@@ -0,0 +1,52 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>13. Circuit Breaker: Hystrix Clients</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_netflix.html" title="Part III. Spring Cloud Netflix"><link rel="prev" href="multi_spring-cloud-eureka-server.html" title="12. Service Discovery: Eureka Server"><link rel="next" href="multi__circuit_breaker_hystrix_dashboard.html" title="14. Circuit Breaker: Hystrix Dashboard"></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">13. Circuit Breaker: Hystrix Clients</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_spring-cloud-eureka-server.html">Prev</a> </td><th width="60%" align="center">Part III. Spring Cloud Netflix</th><td width="20%" align="right"> <a accesskey="n" href="multi__circuit_breaker_hystrix_dashboard.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_circuit_breaker_hystrix_clients" href="#_circuit_breaker_hystrix_clients"></a>13. Circuit Breaker: Hystrix Clients</h2></div></div></div><p>Netflix has created a library called <a class="link" href="https://github.com/Netflix/Hystrix" target="_top">Hystrix</a> that implements the <a class="link" href="http://martinfowler.com/bliki/CircuitBreaker.html" target="_top">circuit breaker pattern</a>. In a microservice architecture it is common to have multiple layers of service calls.</p><div class="figure"><a name="d0e3031" href="#d0e3031"></a><p class="title"><b>Figure 13.1. Microservice Graph</b></p><div class="figure-contents"><div class="mediaobject"><img src="images/HystrixGraph.png" alt="HystrixGraph"></div></div></div><br class="figure-break"><p>A service failure in the lower level of services can cause cascading failure all the way up to the user. When calls to a particular service is greater than <code class="literal">circuitBreaker.requestVolumeThreshold</code> (default: 20 requests) and failue percentage is greater than <code class="literal">circuitBreaker.errorThresholdPercentage</code> (default: >50%) in a rolling window defined by <code class="literal">metrics.rollingStats.timeInMilliseconds</code> (default: 10 seconds), the circuit opens and the call is not made. In cases of error and an open circuit a fallback can be provided by the developer.</p><div class="figure"><a name="d0e3051" href="#d0e3051"></a><p class="title"><b>Figure 13.2. Hystrix fallback prevents cascading failures</b></p><div class="figure-contents"><div class="mediaobject"><img src="images/HystrixFallback.png" alt="HystrixFallback"></div></div></div><br class="figure-break"><p>Having an open circuit stops cascading failures and allows overwhelmed or failing services time to heal. The fallback can be another Hystrix protected call, static data or a sane empty value. Fallbacks may be chained so the first fallback makes some other business call which in turn falls back to static data.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="netflix-hystrix-starter" href="#netflix-hystrix-starter"></a>13.1 How to Include Hystrix</h2></div></div></div><p>To include Hystrix in your project use the starter with group <code class="literal">org.springframework.cloud</code>
|
||||
and artifact id <code class="literal">spring-cloud-starter-hystrix</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>Example boot app:</p><pre class="screen">@SpringBootApplication
|
||||
@EnableCircuitBreaker
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(Application.class).web(true).run(args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Component
|
||||
public class StoreIntegration {
|
||||
|
||||
@HystrixCommand(fallbackMethod = "defaultStores")
|
||||
public Object getStores(Map<String, Object> parameters) {
|
||||
//do stuff that might fail
|
||||
}
|
||||
|
||||
public Object defaultStores(Map<String, Object> parameters) {
|
||||
return /* something useful */;
|
||||
}
|
||||
}</pre><p>The <code class="literal">@HystrixCommand</code> is provided by a Netflix contrib library called
|
||||
<a class="link" href="https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica" target="_top">"javanica"</a>.
|
||||
Spring Cloud automatically wraps Spring beans with that
|
||||
annotation in a proxy that is connected to the Hystrix circuit
|
||||
breaker. The circuit breaker calculates when to open and close the
|
||||
circuit, and what to do in case of a failure.</p><p>To configure the <code class="literal">@HystrixCommand</code> you can use the <code class="literal">commandProperties</code>
|
||||
attribute with a list of <code class="literal">@HystrixProperty</code> annotations. See
|
||||
<a class="link" href="https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica#configuration" target="_top">here</a>
|
||||
for more details. See the <a class="link" href="https://github.com/Netflix/Hystrix/wiki/Configuration" target="_top">Hystrix wiki</a>
|
||||
for details on the properties available.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_propagating_the_security_context_or_using_spring_scopes" href="#_propagating_the_security_context_or_using_spring_scopes"></a>13.2 Propagating the Security Context or using Spring Scopes</h2></div></div></div><p>If you want some thread local context to propagate into a <code class="literal">@HystrixCommand</code> the default declaration will not work because it executes the command in a thread pool (in case of timeouts). You can switch Hystrix to use the same thread as the caller using some configuration, or directly in the annotation, by asking it to use a different "Isolation Strategy". For example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@HystrixCommand(fallbackMethod = "stubMyService",
|
||||
commandProperties = {
|
||||
@HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE")
|
||||
}
|
||||
)</span></em>
|
||||
...</pre><p>The same thing applies if you are using <code class="literal">@SessionScope</code> or <code class="literal">@RequestScope</code>. You will know when you need to do this because of a runtime exception that says it can’t find the scoped context.</p><p>You also have the option to set the <code class="literal">hystrix.shareSecurityContext</code> property to <code class="literal">true</code>. Doing so will auto configure an Hystrix concurrency strategy plugin hook who will transfer the <code class="literal">SecurityContext</code> from your main thread to the one used by the Hystrix command. Hystrix does not allow multiple hystrix concurrency strategy to be registered so an extension mechanism is available by declaring your own <code class="literal">HystrixConcurrencyStrategy</code> as a Spring bean. Spring Cloud will lookup for your implementation within the Spring context and wrap it inside its own plugin.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_health_indicator_3" href="#_health_indicator_3"></a>13.3 Health Indicator</h2></div></div></div><p>The state of the connected circuit breakers are also exposed in the
|
||||
<code class="literal">/health</code> endpoint of the calling application.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"hystrix"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"openCircuitBreakers"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">[</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"StoreIntegration::getStoresByLocationLink"</span>
|
||||
]<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"CIRCUIT_OPEN"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"UP"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_hystrix_metrics_stream" href="#_hystrix_metrics_stream"></a>13.4 Hystrix Metrics Stream</h2></div></div></div><p>To enable the Hystrix metrics stream include a dependency on <code class="literal">spring-boot-starter-actuator</code>. This will expose the <code class="literal">/hystrix.stream</code> as a management endpoint.</p><pre class="programlisting"> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.boot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-boot-starter-actuator<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre></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-eureka-server.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_netflix.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__circuit_breaker_hystrix_dashboard.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">12. Service Discovery: Eureka Server </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 14. Circuit Breaker: Hystrix Dashboard</td></tr></table></div></body></html>
|
||||
@@ -0,0 +1,3 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>14. Circuit Breaker: Hystrix Dashboard</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_netflix.html" title="Part III. Spring Cloud Netflix"><link rel="prev" href="multi__circuit_breaker_hystrix_clients.html" title="13. Circuit Breaker: Hystrix Clients"><link rel="next" href="multi__hystrix_timeouts_and_ribbon_clients.html" title="15. Hystrix Timeouts And Ribbon Clients"></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">14. Circuit Breaker: Hystrix Dashboard</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__circuit_breaker_hystrix_clients.html">Prev</a> </td><th width="60%" align="center">Part III. Spring Cloud Netflix</th><td width="20%" align="right"> <a accesskey="n" href="multi__hystrix_timeouts_and_ribbon_clients.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_circuit_breaker_hystrix_dashboard" href="#_circuit_breaker_hystrix_dashboard"></a>14. Circuit Breaker: Hystrix Dashboard</h2></div></div></div><p>One of the main benefits of Hystrix is the set of metrics it gathers about each HystrixCommand. The Hystrix Dashboard displays the health of each circuit breaker in an efficient manner.</p><div class="figure"><a name="d0e3165" href="#d0e3165"></a><p class="title"><b>Figure 14.1. Hystrix Dashboard</b></p><div class="figure-contents"><div class="mediaobject"><img src="images/Hystrix.png" alt="Hystrix"></div></div></div><br class="figure-break"></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__circuit_breaker_hystrix_clients.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_netflix.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__hystrix_timeouts_and_ribbon_clients.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">13. Circuit Breaker: Hystrix Clients </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 15. Hystrix Timeouts And Ribbon Clients</td></tr></table></div></body></html>
|
||||
66
Dalston.SR5/multi/multi__client_side_usage_2.html
Normal file
@@ -0,0 +1,66 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>90. Client Side Usage</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_vault.html" title="Part XIII. Spring Cloud Vault"><link rel="prev" href="multi__quick_start_3.html" title="89. Quick Start"><link rel="next" href="multi_vault.config.authentication.html" title="91. Authentication methods"></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">90. Client Side Usage</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__quick_start_3.html">Prev</a> </td><th width="60%" align="center">Part XIII. Spring Cloud Vault</th><td width="20%" align="right"> <a accesskey="n" href="multi_vault.config.authentication.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_client_side_usage_2" href="#_client_side_usage_2"></a>90. Client Side Usage</h2></div></div></div><p>To use these features in an application, just build it as a Spring
|
||||
Boot application that depends on <code class="literal">spring-cloud-vault-config</code> (e.g. see
|
||||
the test cases). Example Maven configuration:</p><div class="example"><a name="d0e19831" href="#d0e19831"></a><p class="title"><b>Example 90.1. pom.xml</b></p><div class="example-contents"><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><parent></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.boot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-boot-starter-parent<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>1.5.4.RELEASE<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><relativePath /></span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- lookup parent from repository --></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></parent></span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-starter-vault-config<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>1.3.5.BUILD-SNAPSHOT<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.boot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-boot-starter-test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencies></span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><build></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><plugins></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><plugin></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.boot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-boot-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugin></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugins></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></build></span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- repositories also needed for snapshots and milestones --></span></pre></div></div><br class="example-break"><p>Then you can create a standard Spring Boot application, like this simple HTTP server:</p><div class="informalexample"><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) {
|
||||
SpringApplication.run(Application.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>, args);
|
||||
}
|
||||
}</pre></div><p>When it runs it will pick up the external configuration from the
|
||||
default local Vault server on port <code class="literal">8200</code> if it is running. To modify
|
||||
the startup behavior you can change the location of the Vault server
|
||||
using <code class="literal">bootstrap.properties</code> (like <code class="literal">application.properties</code> but for
|
||||
the bootstrap phase of an application context), e.g.</p><div class="example"><a name="d0e19852" href="#d0e19852"></a><p class="title"><b>Example 90.2. bootstrap.yml</b></p><div class="example-contents"><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spring.cloud.vault</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> host</span>: localhost
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> port</span>: <span class="hl-number">8200</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> scheme</span>: https
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> connection-timeout</span>: <span class="hl-number">5000</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> read-timeout</span>: <span class="hl-number">15000</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> config</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> order</span>: -<span class="hl-number">10</span></pre></div></div><br class="example-break"><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">host</code> sets the hostname of the Vault host. The host name will be used
|
||||
for SSL certificate validation</li><li class="listitem"><code class="literal">port</code> sets the Vault port</li><li class="listitem"><code class="literal">scheme</code> setting the scheme to <code class="literal">http</code> will use plain HTTP.
|
||||
Supported schemes are <code class="literal">http</code> and <code class="literal">https</code>.</li><li class="listitem"><code class="literal">connection-timeout</code> sets the connection timeout in milliseconds</li><li class="listitem"><code class="literal">read-timeout</code> sets the read timeout in milliseconds</li><li class="listitem"><code class="literal">config.order</code> sets the order for the property source</li></ul></div><p>Enabling further integrations requires additional dependencies and
|
||||
configuration. Depending on how you have set up Vault you might need
|
||||
additional configuration like
|
||||
<a class="link" href="http://cloud.spring.io/spring-cloud-vault/spring-cloud-vault.html#vault.config.ssl" target="_top">SSL</a> and
|
||||
<a class="link" href="http://cloud.spring.io/spring-cloud-vault/spring-cloud-vault.html#vault.config.authentication" target="_top">authentication</a>.</p><p>If the application imports the <code class="literal">spring-boot-starter-actuator</code> project, the
|
||||
status of the vault server will be available via the <code class="literal">/health</code> endpoint.</p><p>The vault health indicator can be enabled or disabled through the
|
||||
property <code class="literal">health.vault.enabled</code> (default <code class="literal">true</code>).</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_authentication_2" href="#_authentication_2"></a>90.1 Authentication</h2></div></div></div><p>Vault requires an <a class="link" href="https://www.vaultproject.io/docs/concepts/auth.html" target="_top">authentication mechanism</a> to <a class="link" href="https://www.vaultproject.io/docs/concepts/tokens.html" target="_top">authorize client requests</a>.</p><p>Spring Cloud Vault supports multiple <a class="link" href="http://cloud.spring.io/spring-cloud-vault/spring-cloud-vault.html#vault.config.authentication" target="_top">authentication mechanisms</a> to authenticate applications with Vault.</p><p>For a quickstart, use the root token printed by the <a class="link" href="multi__quick_start_3.html#quickstart.vault.start">Vault initialization</a>.</p><div class="example"><a name="d0e19942" href="#d0e19942"></a><p class="title"><b>Example 90.3. bootstrap.yml</b></p><div class="example-contents"><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spring.cloud.vault</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> token</span>: <span class="hl-number">19</span>aefa97-cccc-bbbb-aaaa-<span class="hl-number">225940e63d</span>76</pre></div></div><br class="example-break"><div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Warning"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="images/warning.png"></td><th align="left">Warning</th></tr><tr><td align="left" valign="top"><p>Consider carefully your security requirements. Static token authentication is fine if you want quickly get started with Vault, but a static token is not protected any further. Any disclosure to unintended parties allows Vault use with the associated token roles.</p></td></tr></table></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__quick_start_3.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_vault.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi_vault.config.authentication.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">89. Quick Start </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 91. Authentication methods</td></tr></table></div></body></html>
|
||||
3
Dalston.SR5/multi/multi__cloud_native_applications.html
Normal file
101
Dalston.SR5/multi/multi__configuration_options.html
Normal file
@@ -0,0 +1,101 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>27. Configuration Options</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_stream.html" title="Part IV. Spring Cloud Stream"><link rel="prev" href="multi__binders.html" title="26. Binders"><link rel="next" href="multi_contenttypemanagement.html" title="28. Content Type and Transformation"></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">27. Configuration Options</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__binders.html">Prev</a> </td><th width="60%" align="center">Part IV. Spring Cloud Stream</th><td width="20%" align="right"> <a accesskey="n" href="multi_contenttypemanagement.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_configuration_options" href="#_configuration_options"></a>27. Configuration Options</h2></div></div></div><p>Spring Cloud Stream supports general configuration options as well as configuration for bindings and binders.
|
||||
Some binders allow additional binding properties to support middleware-specific features.</p><p>Configuration options can be provided to Spring Cloud Stream applications via any mechanism supported by Spring Boot.
|
||||
This includes application arguments, environment variables, and YAML or .properties files.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_spring_cloud_stream_properties" href="#_spring_cloud_stream_properties"></a>27.1 Spring Cloud Stream Properties</h2></div></div></div><div class="variablelist"><dl class="variablelist"><dt><span class="term">spring.cloud.stream.instanceCount</span></dt><dd><p class="simpara"> The number of deployed instances of an application.
|
||||
Must be set for partitioning and if using Kafka.</p><p class="simpara">Default: <code class="literal">1</code>.</p></dd><dt><span class="term">spring.cloud.stream.instanceIndex</span></dt><dd> The instance index of the application: a number from <code class="literal">0</code> to <code class="literal">instanceCount</code>-1.
|
||||
Used for partitioning and with Kafka.
|
||||
Automatically set in Cloud Foundry to match the application’s instance index.</dd><dt><span class="term">spring.cloud.stream.dynamicDestinations</span></dt><dd><p class="simpara"> A list of destinations that can be bound dynamically (for example, in a dynamic routing scenario).
|
||||
If set, only listed destinations can be bound.</p><p class="simpara">Default: empty (allowing any destination to be bound).</p></dd><dt><span class="term">spring.cloud.stream.defaultBinder</span></dt><dd><p class="simpara"> The default binder to use, if multiple binders are configured.
|
||||
See <a class="link" href="multi__binders.html#multiple-binders" title="26.4 Multiple Binders on the Classpath">Multiple Binders on the Classpath</a>.</p><p class="simpara">Default: empty.</p></dd><dt><span class="term">spring.cloud.stream.overrideCloudConnectors</span></dt><dd><p class="simpara"> This property is only applicable when the <code class="literal">cloud</code> profile is active and Spring Cloud Connectors are provided with the application.
|
||||
If the property is false (the default), the binder will detect a suitable bound service (e.g. a RabbitMQ service bound in Cloud Foundry for the RabbitMQ binder) and will use it for creating connections (usually via Spring Cloud Connectors).
|
||||
When set to true, this property instructs binders to completely ignore the bound services and rely on Spring Boot properties (e.g. relying on the <code class="literal">spring.rabbitmq.*</code> properties provided in the environment for the RabbitMQ binder).
|
||||
The typical usage of this property is to be nested in a customized environment <a class="link" href="multi__binders.html#multiple-systems" title="26.5 Connecting to Multiple Systems">when connecting to multiple systems</a>.</p><p class="simpara">Default: false.</p></dd></dl></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="binding-properties" href="#binding-properties"></a>27.2 Binding Properties</h2></div></div></div><p>Binding properties are supplied using the format <code class="literal">spring.cloud.stream.bindings.<channelName>.<property>=<value></code>.
|
||||
The <code class="literal"><channelName></code> represents the name of the channel being configured (e.g., <code class="literal">output</code> for a <code class="literal">Source</code>).</p><p>To avoid repetition, Spring Cloud Stream supports setting values for all channels, in the format <code class="literal">spring.cloud.stream.default.<property>=<value></code>.</p><p>In what follows, we indicate where we have omitted the <code class="literal">spring.cloud.stream.bindings.<channelName>.</code> prefix and focus just on the property name, with the understanding that the prefix will be included at runtime.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_properties_for_use_of_spring_cloud_stream" href="#_properties_for_use_of_spring_cloud_stream"></a>27.2.1 Properties for Use of Spring Cloud Stream</h3></div></div></div><p>The following binding properties are available for both input and output bindings and must be prefixed with <code class="literal">spring.cloud.stream.bindings.<channelName>.</code>, e.g. <code class="literal">spring.cloud.stream.bindings.input.destination=ticktock</code>.</p><p>Default values can be set by using the prefix <code class="literal">spring.cloud.stream.default</code>, e.g. <code class="literal">spring.cloud.stream.default.contentType=application/json</code>.</p><div class="variablelist"><dl class="variablelist"><dt><span class="term">destination</span></dt><dd>The target destination of a channel on the bound middleware (e.g., the RabbitMQ exchange or Kafka topic).
|
||||
If the channel is bound as a consumer, it could be bound to multiple destinations and the destination names can be specified as comma separated String values.
|
||||
If not set, the channel name is used instead.
|
||||
The default value of this property cannot be overridden.</dd><dt><span class="term">group</span></dt><dd><p class="simpara"> The consumer group of the channel.
|
||||
Applies only to inbound bindings.
|
||||
See <a class="link" href="multi__main_concepts.html#consumer-groups" title="24.4 Consumer Groups">Consumer Groups</a>.</p><p class="simpara">Default: null (indicating an anonymous consumer).</p></dd><dt><span class="term">contentType</span></dt><dd><p class="simpara">The content type of the channel.</p><p class="simpara">Default: null (so that no type coercion is performed).</p></dd><dt><span class="term">binder</span></dt><dd><p class="simpara"> The binder used by this binding.
|
||||
See <a class="xref" href="multi__binders.html#multiple-binders" title="26.4 Multiple Binders on the Classpath">Section 26.4, “Multiple Binders on the Classpath”</a> for details.</p><p class="simpara">Default: null (the default binder will be used, if one exists).</p></dd></dl></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_consumer_properties" href="#_consumer_properties"></a>27.2.2 Consumer properties</h3></div></div></div><p>The following binding properties are available for input bindings only and must be prefixed with <code class="literal">spring.cloud.stream.bindings.<channelName>.consumer.</code>, e.g. <code class="literal">spring.cloud.stream.bindings.input.consumer.concurrency=3</code>.</p><p>Default values can be set by using the prefix <code class="literal">spring.cloud.stream.default.consumer</code>, e.g. <code class="literal">spring.cloud.stream.default.consumer.headerMode=raw</code>.</p><div class="variablelist"><dl class="variablelist"><dt><span class="term">concurrency</span></dt><dd><p class="simpara">The concurrency of the inbound consumer.</p><p class="simpara">Default: <code class="literal">1</code>.</p></dd><dt><span class="term">partitioned</span></dt><dd><p class="simpara">Whether the consumer receives data from a partitioned producer.</p><p class="simpara">Default: <code class="literal">false</code>.</p></dd><dt><span class="term">headerMode</span></dt><dd><p class="simpara"> When set to <code class="literal">raw</code>, disables header parsing on input.
|
||||
Effective only for messaging middleware that does not support message headers natively and requires header embedding.
|
||||
Useful when inbound data is coming from outside Spring Cloud Stream applications.</p><p class="simpara">Default: <code class="literal">embeddedHeaders</code>.</p></dd><dt><span class="term">maxAttempts</span></dt><dd><p class="simpara">If processing fails, the number of attempts to process the message (including the first).
|
||||
Set to 1 to disable retry.</p><p class="simpara">Default: <code class="literal">3</code>.</p></dd><dt><span class="term">backOffInitialInterval</span></dt><dd><p class="simpara">The backoff initial interval on retry.</p><p class="simpara">Default: <code class="literal">1000</code>.</p></dd><dt><span class="term">backOffMaxInterval</span></dt><dd><p class="simpara">The maximum backoff interval.</p><p class="simpara">Default: <code class="literal">10000</code>.</p></dd><dt><span class="term">backOffMultiplier</span></dt><dd><p class="simpara">The backoff multiplier.</p><p class="simpara">Default: <code class="literal">2.0</code>.</p></dd><dt><span class="term">instanceIndex</span></dt><dd><p class="simpara"> When set to a value greater than equal to zero, allows customizing the instance index of this consumer (if different from <code class="literal">spring.cloud.stream.instanceIndex</code>).
|
||||
When set to a negative value, it will default to <code class="literal">spring.cloud.stream.instanceIndex</code>.</p><p class="simpara">Default: <code class="literal">-1</code>.</p></dd><dt><span class="term">instanceCount</span></dt><dd><p class="simpara"> When set to a value greater than equal to zero, allows customizing the instance count of this consumer (if different from <code class="literal">spring.cloud.stream.instanceCount</code>).
|
||||
When set to a negative value, it will default to <code class="literal">spring.cloud.stream.instanceCount</code>.</p><p class="simpara">Default: <code class="literal">-1</code>.</p></dd></dl></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_producer_properties" href="#_producer_properties"></a>27.2.3 Producer Properties</h3></div></div></div><p>The following binding properties are available for output bindings only and must be prefixed with <code class="literal">spring.cloud.stream.bindings.<channelName>.producer.</code>, e.g. <code class="literal">spring.cloud.stream.bindings.input.producer.partitionKeyExpression=payload.id</code>.</p><p>Default values can be set by using the prefix <code class="literal">spring.cloud.stream.default.producer</code>, e.g. <code class="literal">spring.cloud.stream.default.producer.partitionKeyExpression=payload.id</code>.</p><div class="variablelist"><dl class="variablelist"><dt><span class="term">partitionKeyExpression</span></dt><dd><p class="simpara"> A SpEL expression that determines how to partition outbound data.
|
||||
If set, or if <code class="literal">partitionKeyExtractorClass</code> is set, outbound data on this channel will be partitioned, and <code class="literal">partitionCount</code> must be set to a value greater than 1 to be effective.
|
||||
The two options are mutually exclusive.
|
||||
See <a class="xref" href="multi__main_concepts.html#partitioning" title="24.5 Partitioning Support">Section 24.5, “Partitioning Support”</a>.</p><p class="simpara">Default: null.</p></dd><dt><span class="term">partitionKeyExtractorClass</span></dt><dd><p class="simpara"> A <code class="literal">PartitionKeyExtractorStrategy</code> implementation.
|
||||
If set, or if <code class="literal">partitionKeyExpression</code> is set, outbound data on this channel will be partitioned, and <code class="literal">partitionCount</code> must be set to a value greater than 1 to be effective.
|
||||
The two options are mutually exclusive.
|
||||
See <a class="xref" href="multi__main_concepts.html#partitioning" title="24.5 Partitioning Support">Section 24.5, “Partitioning Support”</a>.</p><p class="simpara">Default: null.</p></dd><dt><span class="term">partitionSelectorClass</span></dt><dd><p class="simpara"> A <code class="literal">PartitionSelectorStrategy</code> implementation.
|
||||
Mutually exclusive with <code class="literal">partitionSelectorExpression</code>.
|
||||
If neither is set, the partition will be selected as the <code class="literal">hashCode(key) % partitionCount</code>, where <code class="literal">key</code> is computed via either <code class="literal">partitionKeyExpression</code> or <code class="literal">partitionKeyExtractorClass</code>.</p><p class="simpara">Default: null.</p></dd><dt><span class="term">partitionSelectorExpression</span></dt><dd><p class="simpara"> A SpEL expression for customizing partition selection.
|
||||
Mutually exclusive with <code class="literal">partitionSelectorClass</code>.
|
||||
If neither is set, the partition will be selected as the <code class="literal">hashCode(key) % partitionCount</code>, where <code class="literal">key</code> is computed via either <code class="literal">partitionKeyExpression</code> or <code class="literal">partitionKeyExtractorClass</code>.</p><p class="simpara">Default: null.</p></dd><dt><span class="term">partitionCount</span></dt><dd><p class="simpara"> The number of target partitions for the data, if partitioning is enabled.
|
||||
Must be
|
||||
set to a value greater than 1 if the producer is partitioned.
|
||||
On Kafka, interpreted as a
|
||||
hint; the larger of this and the partition count of the target topic is used instead.</p><p class="simpara">Default: <code class="literal">1</code>.</p></dd><dt><span class="term">requiredGroups</span></dt><dd>A comma-separated list of groups to which the producer must ensure message delivery even if they start after it has been created (e.g., by pre-creating durable queues in RabbitMQ).</dd><dt><span class="term">headerMode</span></dt><dd><p class="simpara"> When set to <code class="literal">raw</code>, disables header embedding on output.
|
||||
Effective only for messaging middleware that does not support message headers natively and requires header embedding.
|
||||
Useful when producing data for non-Spring Cloud Stream applications.</p><p class="simpara">Default: <code class="literal">embeddedHeaders</code>.</p></dd><dt><span class="term">useNativeEncoding</span></dt><dd><p class="simpara"> When set to <code class="literal">true</code>, the outbound message is serialized directly by client library, which must be configured correspondingly (e.g. setting an appropriate Kafka producer value serializer).
|
||||
When this configuration is being used, the outbound message marshalling is not based on the <code class="literal">contentType</code> of the binding.
|
||||
When native encoding is used, it is the responsibility of the consumer to use appropriate decoder (ex: Kafka consumer value de-serializer) to deserialize the inbound message.
|
||||
Also, when native encoding/decoding is used the <code class="literal">headerMode</code> property is ignored and headers will not be embedded into the message.</p><p class="simpara">Default: <code class="literal">false</code>.</p></dd></dl></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="dynamicdestination" href="#dynamicdestination"></a>27.3 Using dynamically bound destinations</h2></div></div></div><p>Besides the channels defined via <code class="literal">@EnableBinding</code>, Spring Cloud Stream allows applications to send messages to dynamically bound destinations.
|
||||
This is useful, for example, when the target destination needs to be determined at runtime.
|
||||
Applications can do so by using the <code class="literal">BinderAwareChannelResolver</code> bean, registered automatically by the <code class="literal">@EnableBinding</code> annotation.</p><p>The property 'spring.cloud.stream.dynamicDestinations' can be used for restricting the dynamic destination names to a set known beforehand (whitelisting).
|
||||
If the property is not set, any destination can be bound dynamicaly.</p><p>The <code class="literal">BinderAwareChannelResolver</code> can be used directly as in the following example, in which a REST controller uses a path variable to decide the target channel.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@EnableBinding</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@Controller</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> SourceWithDynamicDestination {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> BinderAwareChannelResolver resolver;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@RequestMapping(path = "/{target}", method = POST, consumes = "*/*")</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@ResponseStatus(HttpStatus.ACCEPTED)</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">void</span> handleRequest(<em><span class="hl-annotation" style="color: gray">@RequestBody</span></em> String body, <em><span class="hl-annotation" style="color: gray">@PathVariable("target")</span></em> target,
|
||||
<em><span class="hl-annotation" style="color: gray">@RequestHeader(HttpHeaders.CONTENT_TYPE)</span></em> Object contentType) {
|
||||
sendMessage(body, target, contentType);
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> sendMessage(String body, String target, Object contentType) {
|
||||
resolver.resolveDestination(target).send(MessageBuilder.createMessage(body,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> MessageHeaders(Collections.singletonMap(MessageHeaders.CONTENT_TYPE, contentType))));
|
||||
}
|
||||
}</pre><p>After starting the application on the default port 8080, when sending the following data:</p><pre class="screen">curl -H "Content-Type: application/json" -X POST -d "customer-1" http://localhost:8080/customers
|
||||
|
||||
curl -H "Content-Type: application/json" -X POST -d "order-1" http://localhost:8080/orders</pre><p>The destinations 'customers' and 'orders' are created in the broker (for example: exchange in case of Rabbit or topic in case of Kafka) with the names 'customers' and 'orders', and the data is published to the appropriate destinations.</p><p>The <code class="literal">BinderAwareChannelResolver</code> is a general purpose Spring Integration <code class="literal">DestinationResolver</code> and can be injected in other components.
|
||||
For example, in a router using a SpEL expression based on the <code class="literal">target</code> field of an incoming JSON message.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@EnableBinding</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@Controller</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> SourceWithDynamicDestination {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> BinderAwareChannelResolver resolver;
|
||||
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@RequestMapping(path = "/", method = POST, consumes = "application/json")</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@ResponseStatus(HttpStatus.ACCEPTED)</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">void</span> handleRequest(<em><span class="hl-annotation" style="color: gray">@RequestBody</span></em> String body, <em><span class="hl-annotation" style="color: gray">@RequestHeader(HttpHeaders.CONTENT_TYPE)</span></em> Object contentType) {
|
||||
sendMessage(body, contentType);
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> sendMessage(Object body, Object contentType) {
|
||||
routerChannel().send(MessageBuilder.createMessage(body,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> MessageHeaders(Collections.singletonMap(MessageHeaders.CONTENT_TYPE, contentType))));
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean(name = "routerChannel")</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> MessageChannel routerChannel() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> DirectChannel();
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@ServiceActivator(inputChannel = "routerChannel")</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> ExpressionEvaluatingRouter router() {
|
||||
ExpressionEvaluatingRouter router =
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ExpressionEvaluatingRouter(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> SpelExpressionParser().parseExpression(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"payload.target"</span>));
|
||||
router.setDefaultOutputChannelName(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"default-output"</span>);
|
||||
router.setChannelResolver(resolver);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> router;
|
||||
}
|
||||
}</pre></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__binders.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_stream.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi_contenttypemanagement.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">26. Binders </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 28. Content Type and Transformation</td></tr></table></div></body></html>
|
||||
@@ -0,0 +1,17 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>75. Configuring Authentication Downstream of a Zuul Proxy</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_security.html" title="Part X. Spring Cloud Security"><link rel="prev" href="multi__more_detail.html" title="74. More Detail"><link rel="next" href="multi__spring_cloud_for_cloud_foundry.html" title="Part XI. Spring Cloud for Cloud Foundry"></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">75. Configuring Authentication Downstream of a Zuul Proxy</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__more_detail.html">Prev</a> </td><th width="60%" align="center">Part X. Spring Cloud Security</th><td width="20%" align="right"> <a accesskey="n" href="multi__spring_cloud_for_cloud_foundry.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_configuring_authentication_downstream_of_a_zuul_proxy" href="#_configuring_authentication_downstream_of_a_zuul_proxy"></a>75. Configuring Authentication Downstream of a Zuul Proxy</h2></div></div></div><p>You can control the authorization behaviour downstream of an
|
||||
<code class="literal">@EnableZuulProxy</code> through the <code class="literal">proxy.auth.*</code> settings. Example:</p><p><b>application.yml. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">proxy</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> auth</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> routes</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> customers</span>: oauth2
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> stores</span>: passthru
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> recommendations</span>: none</pre><p>
|
||||
</p><p>In this example the "customers" service gets an OAuth2 token relay,
|
||||
the "stores" service gets a passthrough (the authorization header is
|
||||
just passed downstream), and the "recommendations" service has its
|
||||
authorization header removed. The default behaviour is to do a token
|
||||
relay if there is a token available, and passthru otherwise.</p><p>See
|
||||
<a class="link" href="https://github.com/spring-cloud/spring-cloud-security/tree/master/src/main/java/org/springframework/cloud/security/oauth2/proxy/ProxyAuthenticationProperties" target="_top">
|
||||
ProxyAuthenticationProperties</a> for full details.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__more_detail.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_security.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__spring_cloud_for_cloud_foundry.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">74. More Detail </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> Part XI. Spring Cloud for Cloud Foundry</td></tr></table></div></body></html>
|
||||
1174
Dalston.SR5/multi/multi__contract_dsl.html
Normal file
217
Dalston.SR5/multi/multi__customization.html
Normal file
@@ -0,0 +1,217 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>85. Customization</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_contract.html" title="Part XII. Spring Cloud Contract"><link rel="prev" href="multi__contract_dsl.html" title="84. Contract DSL"><link rel="next" href="multi__using_the_pluggable_architecture.html" title="86. Using the Pluggable Architecture"></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">85. Customization</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__contract_dsl.html">Prev</a> </td><th width="60%" align="center">Part XII. Spring Cloud Contract</th><td width="20%" align="right"> <a accesskey="n" href="multi__using_the_pluggable_architecture.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_customization" href="#_customization"></a>85. Customization</h2></div></div></div><p>You can customize the Spring Cloud Contract Verifier by extending the DSL, as shown in
|
||||
the remainder of this section.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_extending_the_dsl" href="#_extending_the_dsl"></a>85.1 Extending the DSL</h2></div></div></div><p>You can provide your own functions to the DSL. The key requirement for this feature is to
|
||||
maintain the static compatibility. Later in this document, you can see examples of:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Creating a JAR with reusable classes.</li><li class="listitem">Referencing of these classes in the DSLs.</li></ul></div><p>You can find the full example
|
||||
<a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples" target="_top">here</a>.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_common_jar" href="#_common_jar"></a>85.1.1 Common JAR</h3></div></div></div><p>The following examples show three classes that can be reused in the DSLs.</p><p><span class="strong"><strong>PatternUtils</strong></span> contains functions used by both the <span class="strong"><strong>consumer</strong></span> and the <span class="strong"><strong>producer</strong></span>.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> com.example;
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> java.util.regex.Pattern;
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
* If you want to use {@link Pattern} directly in your tests
|
||||
* then you can create a class resembling this one. It can
|
||||
* contain all the {@link Pattern} you want to use in the DSL.
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* request {
|
||||
* body(
|
||||
* [ age: $(c(PatternUtils.oldEnough()))]
|
||||
* )
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* Notice that we're using both {@code $()} for dynamic values
|
||||
* and {@code c()} for the consumer side.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/</strong>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//tag::impl[]</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">class</span> PatternUtils {
|
||||
|
||||
<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> String tooYoung() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::start[]</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[0-1][0-9]"</span>;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::end[return]</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> Pattern oldEnough() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::start[]</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> Pattern.compile(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"[2-9][0-9]"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::end[return]</span>
|
||||
}
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
* Makes little sense but it's just an example ;)
|
||||
*/</strong>
|
||||
<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> Pattern ok() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::start[]</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> Pattern.compile(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"OK"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::end[return]</span>
|
||||
}
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//end::impl[]</span></pre><p><span class="strong"><strong>ConsumerUtils</strong></span> contains functions used by the <span class="strong"><strong>consumer</strong></span>.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> com.example;
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.internal.ClientDslProperty;
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
* DSL Properties passed to the DSL from the consumer's perspective.
|
||||
* That means that on the input side {@code Request} for HTTP
|
||||
* or {@code Input} for messaging you can have a regular expression.
|
||||
* On the {@code Response} for HTTP or {@code Output} for messaging
|
||||
* you have to have a concrete value.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/</strong>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//tag::impl[]</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">class</span> ConsumerUtils {
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
* Consumer side property. By using the {@link ClientDslProperty}
|
||||
* you can omit most of boilerplate code from the perspective
|
||||
* of dynamic values. Example
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* request {
|
||||
* body(
|
||||
* [ age: $(ConsumerUtils.oldEnough())]
|
||||
* )
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* That way it's in the implementation that we decide what value we will pass to the consumer
|
||||
* and which one to the producer.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/</strong>
|
||||
<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> ClientDslProperty oldEnough() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::start[]</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// this example is not the best one and</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// theoretically you could just pass the regex instead of `ServerDslProperty` but</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// it's just to show some new tricks :)</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ClientDslProperty(PatternUtils.oldEnough(), <span class="hl-number">40</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//remove::end[return]</span>
|
||||
}
|
||||
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//end::impl[]</span></pre><p><span class="strong"><strong>ProducerUtils</strong></span> contains functions used by the <span class="strong"><strong>producer</strong></span>.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> com.example;
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.internal.ServerDslProperty;
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
* DSL Properties passed to the DSL from the producer's perspective.
|
||||
* That means that on the input side {@code Request} for HTTP
|
||||
* or {@code Input} for messaging you have to have a concrete value.
|
||||
* On the {@code Response} for HTTP or {@code Output} for messaging
|
||||
* you can have a regular expression.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/</strong>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//tag::impl[]</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">class</span> ProducerUtils {
|
||||
|
||||
<strong class="hl-tag" style="color: blue">/**
|
||||
* Producer side property. By using the {@link ProducerUtils}
|
||||
* you can omit most of boilerplate code from the perspective
|
||||
* of dynamic values. Example
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* response {
|
||||
* body(
|
||||
* [ status: $(ProducerUtils.ok())]
|
||||
* )
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* That way it's in the implementation that we decide what value we will pass to the consumer
|
||||
* and which one to the producer.
|
||||
*/</strong>
|
||||
<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> ServerDslProperty ok() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// this example is not the best one and</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// theoretically you could just pass the regex instead of `ServerDslProperty` but</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// it's just to show some new tricks :)</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ServerDslProperty( PatternUtils.ok(), <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"OK"</span>);
|
||||
}
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//end::impl[]</span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_adding_the_dependency_to_the_project" href="#_adding_the_dependency_to_the_project"></a>85.1.2 Adding the Dependency to the Project</h3></div></div></div><p>In order for the plugins and IDE to be able to reference the common JAR classes, you need
|
||||
to pass the dependency to your project.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_test_the_dependency_in_the_project_s_dependencies" href="#_test_the_dependency_in_the_project_s_dependencies"></a>85.1.3 Test the Dependency in the Project’s Dependencies</h3></div></div></div><p>First, add the common jar dependency as a test dependency. Because your contracts files
|
||||
are available on the test resources path, the common jar classes automatically become
|
||||
visible in your Groovy files. The following examples show how to test the dependency:</p><p class="primary"><b>Maven. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>com.example<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>beer-common<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${project.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre><p class="primary">
|
||||
</p><p class="secondary"><b>Gradle. </b>
|
||||
</p><pre class="programlisting">testCompile(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:beer-common:0.0.1-SNAPSHOT"</span>)</pre><p class="secondary">
|
||||
</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_test_a_dependency_in_the_plugin_s_dependencies" href="#_test_a_dependency_in_the_plugin_s_dependencies"></a>85.1.4 Test a Dependency in the Plugin’s Dependencies</h3></div></div></div><p>Now, you must add the dependency for the plugin to reuse at runtime, as shown in the
|
||||
following example:</p><p class="primary"><b>Maven. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><plugin></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-contract-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${spring-cloud-contract.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><extensions></span>true<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></extensions></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><configuration></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><packageWithBaseClasses></span>com.example<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></packageWithBaseClasses></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><baseClassMappings></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><baseClassMapping></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><contractPackageRegex></span>.*intoxication.*<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></contractPackageRegex></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><baseClassFQN></span>com.example.intoxication.BeerIntoxicationBase<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></baseClassFQN></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></baseClassMapping></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></baseClassMappings></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></configuration></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>com.example<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>beer-common<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${project.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>compile<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugin></span></pre><p class="primary">
|
||||
</p><p class="secondary"><b>Gradle. </b>
|
||||
</p><pre class="programlisting">classpath <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"com.example:beer-common:0.0.1-SNAPSHOT"</span></pre><p class="secondary">
|
||||
</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_referencing_classes_in_dsls" href="#_referencing_classes_in_dsls"></a>85.1.5 Referencing classes in DSLs</h3></div></div></div><p>You can now reference your classes in your DSL, as shown in the following example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> contracts.beer.rest
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> com.example.ConsumerUtils
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> com.example.ProducerUtils
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.contract.spec.Contract
|
||||
|
||||
Contract.make {
|
||||
description(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">""</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"
|
||||
</span>Represents a successful scenario of getting a beer
|
||||
|
||||
```
|
||||
given:
|
||||
client is old enough
|
||||
when:
|
||||
he applies <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">for</span> a beer
|
||||
then:
|
||||
we<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'ll grant him the beer
|
||||
</span>```
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">""</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">")
|
||||
</span> request {
|
||||
method <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'POST'</span>
|
||||
url <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'/check'</span>
|
||||
body(
|
||||
age: $(ConsumerUtils.oldEnough())
|
||||
)
|
||||
headers {
|
||||
contentType(applicationJson())
|
||||
}
|
||||
}
|
||||
response {
|
||||
status <span class="hl-number">200</span>
|
||||
body(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">""</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"
|
||||
</span> {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"${value(ProducerUtils.ok())}"</span>
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">""</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">")
|
||||
</span> headers {
|
||||
contentType(applicationJson())
|
||||
}
|
||||
}
|
||||
}</pre></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__contract_dsl.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_contract.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__using_the_pluggable_architecture.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">84. Contract DSL </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 86. Using the Pluggable Architecture</td></tr></table></div></body></html>
|
||||
149
Dalston.SR5/multi/multi__customizations.html
Normal file
@@ -0,0 +1,149 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>53. Customizations</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_sleuth.html" title="Part VII. Spring Cloud Sleuth"><link rel="prev" href="multi__managing_spans_with_annotations.html" title="52. Managing spans with annotations"><link rel="next" href="multi__span_data_as_messages.html" title="54. Span Data as Messages"></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">53. Customizations</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__managing_spans_with_annotations.html">Prev</a> </td><th width="60%" align="center">Part VII. Spring Cloud Sleuth</th><td width="20%" align="right"> <a accesskey="n" href="multi__span_data_as_messages.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_customizations" href="#_customizations"></a>53. Customizations</h2></div></div></div><p>Thanks to the <code class="literal">SpanInjector</code> and <code class="literal">SpanExtractor</code> you can customize the way spans
|
||||
are created and propagated.</p><p>There are currently two built-in ways to pass tracing information between processes:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">via Spring Integration</li><li class="listitem">via HTTP</li></ul></div><p>Span ids are extracted from Zipkin-compatible (B3) headers (either <code class="literal">Message</code>
|
||||
or HTTP headers), to start or join an existing trace. Trace information is
|
||||
injected into any outbound requests so the next hop can extract them.</p><p>The key change in comparison to the previous versions of Sleuth is that Sleuth is implementing
|
||||
the Open Tracing’s <code class="literal">TextMap</code> notion. In Sleuth it’s called <code class="literal">SpanTextMap</code>. Basically the idea
|
||||
is that any means of communication (e.g. message, http request, etc.) can be abstracted via
|
||||
a <code class="literal">SpanTextMap</code>. This abstraction defines how one can insert data into the carrier and
|
||||
how to retrieve it from there. Thanks to this if you want to instrument a new HTTP library
|
||||
that uses a <code class="literal">FooRequest</code> as a mean of sending HTTP requests then you have to create an
|
||||
implementation of a <code class="literal">SpanTextMap</code> that delegates calls to <code class="literal">FooRequest</code> in terms of retrieval
|
||||
and insertion of HTTP headers.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_spring_integration" href="#_spring_integration"></a>53.1 Spring Integration</h2></div></div></div><p>For Spring Integration there are 2 interfaces responsible for creation of a Span from a <code class="literal">Message</code>.
|
||||
These are:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">MessagingSpanTextMapExtractor</code></li><li class="listitem"><code class="literal">MessagingSpanTextMapInjector</code></li></ul></div><p>You can override them by providing your own implementation.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_http" href="#_http"></a>53.2 HTTP</h2></div></div></div><p>For HTTP there are 2 interfaces responsible for creation of a Span from a <code class="literal">Message</code>.
|
||||
These are:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">HttpSpanExtractor</code></li><li class="listitem"><code class="literal">HttpSpanInjector</code></li></ul></div><p>You can override them by providing your own implementation.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_example" href="#_example"></a>53.3 Example</h2></div></div></div><p>Let’s assume that instead of the standard Zipkin compatible tracing HTTP header names
|
||||
you have</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">for trace id - <code class="literal">correlationId</code></li><li class="listitem">for span id - <code class="literal">mySpanId</code></li></ul></div><p>This is a an example of a <code class="literal">SpanExtractor</code></p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> CustomHttpSpanExtractor <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">implements</span> HttpSpanExtractor {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Span joinTrace(SpanTextMap carrier) {
|
||||
Map<String, String> map = TextMapUtil.asMap(carrier);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">long</span> traceId = Span.hexToId(map.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"correlationid"</span>));
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">long</span> spanId = Span.hexToId(map.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"myspanid"</span>));
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// extract all necessary headers</span>
|
||||
Span.SpanBuilder builder = Span.builder().traceId(traceId).spanId(spanId);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// build rest of the Span</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> builder.build();
|
||||
}
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> CustomHttpSpanInjector <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">implements</span> HttpSpanInjector {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</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">void</span> inject(Span span, SpanTextMap carrier) {
|
||||
carrier.put(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"correlationId"</span>, span.traceIdString());
|
||||
carrier.put(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"mySpanId"</span>, Span.idToHex(span.getSpanId()));
|
||||
}
|
||||
}</pre><p>And you could register it like this:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
HttpSpanInjector customHttpSpanInjector() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> CustomHttpSpanInjector();
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
HttpSpanExtractor customHttpSpanExtractor() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> CustomHttpSpanExtractor();
|
||||
}</pre><p>Spring Cloud Sleuth does not add trace/span related headers to the Http Response for security reasons. If you need the headers then a custom <code class="literal">SpanInjector</code>
|
||||
that injects the headers into the Http Response and a Servlet filter which makes use of this can be added the following way:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> CustomHttpServletResponseSpanInjector <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> ZipkinHttpSpanInjector {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</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">void</span> inject(Span span, SpanTextMap carrier) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">super</span>.inject(span, carrier);
|
||||
carrier.put(Span.TRACE_ID_NAME, span.traceIdString());
|
||||
carrier.put(Span.SPAN_ID_NAME, Span.idToHex(span.getSpanId()));
|
||||
}
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> HttpResponseInjectingTraceFilter <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> GenericFilterBean {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Tracer tracer;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> HttpSpanInjector spanInjector;
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> HttpResponseInjectingTraceFilter(Tracer tracer, HttpSpanInjector spanInjector) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer = tracer;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.spanInjector = spanInjector;
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</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">void</span> doFilter(ServletRequest request, ServletResponse servletResponse, FilterChain filterChain) <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> IOException, ServletException {
|
||||
HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
Span currentSpan = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.getCurrentSpan();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.spanInjector.inject(currentSpan, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> HttpServletResponseTextMap(response));
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> HttpServletResponseTextMap <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">implements</span> SpanTextMap {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> HttpServletResponse delegate;
|
||||
|
||||
HttpServletResponseTextMap(HttpServletResponse delegate) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.delegate = delegate;
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Iterator<Map.Entry<String, String>> iterator() {
|
||||
Map<String, String> map = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> HashMap<>();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">for</span> (String header : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.delegate.getHeaderNames()) {
|
||||
map.put(header, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.delegate.getHeader(header));
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> map.entrySet().iterator();
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</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">void</span> put(String key, String value) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.delegate.addHeader(key, value);
|
||||
}
|
||||
}
|
||||
}</pre><p>And you could register them like this:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em> HttpSpanInjector customHttpServletResponseSpanInjector() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> CustomHttpServletResponseSpanInjector();
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
HttpResponseInjectingTraceFilter responseInjectingTraceFilter(Tracer tracer) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> HttpResponseInjectingTraceFilter(tracer, customHttpServletResponseSpanInjector());
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_tracefilter" href="#_tracefilter"></a>53.4 TraceFilter</h2></div></div></div><p>You can also modify the behaviour of the <code class="literal">TraceFilter</code> - the component that is responsible
|
||||
for processing the input HTTP request and adding tags basing on the HTTP response. You can customize
|
||||
the tags, or modify the response headers by registering your own instance of the <code class="literal">TraceFilter</code> bean.</p><p>In the following example we will register the <code class="literal">TraceFilter</code> bean and we will add the
|
||||
<code class="literal">ZIPKIN-TRACE-ID</code> response header containing the current Span’s trace id. Also we will
|
||||
add to the Span a tag with key <code class="literal">custom</code> and a value <code class="literal">tag</code>.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
TraceFilter myTraceFilter(BeanFactory beanFactory, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Tracer tracer) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceFilter(beanFactory) {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">protected</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> addResponseTags(HttpServletResponse response,
|
||||
Throwable e) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// execute the default behaviour</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">super</span>.addResponseTags(response, e);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// for readability we're returning trace id in a hex form</span>
|
||||
response.addHeader(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"ZIPKIN-TRACE-ID"</span>,
|
||||
Span.idToHex(tracer.getCurrentSpan().getTraceId()));
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// we can also add some custom tags</span>
|
||||
tracer.addTag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"custom"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"tag"</span>);
|
||||
}
|
||||
};
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_custom_sa_tag_in_zipkin" href="#_custom_sa_tag_in_zipkin"></a>53.5 Custom SA tag in Zipkin</h2></div></div></div><p>Sometimes you want to create a manual Span that will wrap a call to an external service which is not instrumented.
|
||||
What you can do is to create a span with the <code class="literal">peer.service</code> tag that will contain a value of the service that you want to call.
|
||||
Below you can see an example of a call to Redis that is wrapped in such a span.</p><pre class="programlisting">org.springframework.cloud.sleuth.Span newSpan = tracer.createSpan(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"redis"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> {
|
||||
newSpan.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"redis.op"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"get"</span>);
|
||||
newSpan.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"lc"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"redis"</span>);
|
||||
newSpan.logEvent(org.springframework.cloud.sleuth.Span.CLIENT_SEND);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// call redis service e.g</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// return (SomeObj) redisTemplate.opsForHash().get("MYHASH", someObjKey);</span>
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">finally</span> {
|
||||
newSpan.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"peer.service"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"redisService"</span>);
|
||||
newSpan.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"peer.ipv4"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"1.2.3.4"</span>);
|
||||
newSpan.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"peer.port"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"1234"</span>);
|
||||
newSpan.logEvent(org.springframework.cloud.sleuth.Span.CLIENT_RECV);
|
||||
tracer.close(newSpan);
|
||||
}</pre><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>Remember not to add both <code class="literal">peer.service</code> tag and the <code class="literal">SA</code> tag! You have to add only <code class="literal">peer.service</code>.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_custom_service_name" href="#_custom_service_name"></a>53.6 Custom service name</h2></div></div></div><p>By default Sleuth assumes that when you send a span to Zipkin, you want the span’s service name
|
||||
to be equal to <code class="literal">spring.application.name</code> value. That’s not always the case though. There
|
||||
are situations in which you want to explicitly provide a different service name for all spans coming
|
||||
from your application. To achieve that it’s enough to just pass the following property
|
||||
to your application to override that value (example for <code class="literal">foo</code> service name):</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spring.zipkin.service.name</span>: foo</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_customization_of_reported_spans" href="#_customization_of_reported_spans"></a>53.7 Customization of reported spans</h2></div></div></div><p>Before reporting spans to e.g. Zipkin you can be interested in modifying that span in some way.
|
||||
You can achieve that by using the <code class="literal">SpanAdjuster</code> interface.</p><p>Example of usage:</p><p>In Sleuth we’re generating spans with a fixed name. Some users want to modify the name depending on values
|
||||
of tags. Implementation of the <code class="literal">SpanAdjuster</code> interface can be used to alter that name. Example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
SpanAdjuster customSpanAdjuster() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
return span -> span.toBuilder().name(scrub(span.getName())).build();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre><p>This will lead in changing the name of the reported span just before it gets sent to Zipkin.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>Your <code class="literal">SpanReporter</code> should inject the <code class="literal">SpanAdjuster</code> and
|
||||
allow span manipulation before the actual reporting is done.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_host_locator" href="#_host_locator"></a>53.8 Host locator</h2></div></div></div><p>In order to define the host that is corresponding to a particular span we need to resolve the host name
|
||||
and port. The default approach is to take it from server properties. If those for some reason are not set
|
||||
then we’re trying to retrieve the host name from the network interfaces.</p><p>If you have the discovery client enabled and prefer to retrieve the host address from the registered
|
||||
instance in a service registry then you have to set the property (it’s applicable for both HTTP and
|
||||
Stream based span reporting).</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spring.zipkin.locator.discovery.enabled</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">true</span></pre></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__managing_spans_with_annotations.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_sleuth.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__span_data_as_messages.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">52. Managing spans with annotations </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 54. Span Data as Messages</td></tr></table></div></body></html>
|
||||
17
Dalston.SR5/multi/multi__customizing_the_message_broker.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>42. Customizing the Message Broker</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_bus.html" title="Part VI. Spring Cloud Bus"><link rel="prev" href="multi__application_context_id_must_be_unique.html" title="41. Application Context ID must be unique"><link rel="next" href="multi__tracing_bus_events.html" title="43. Tracing Bus Events"></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">42. Customizing the Message Broker</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__application_context_id_must_be_unique.html">Prev</a> </td><th width="60%" align="center">Part VI. Spring Cloud Bus</th><td width="20%" align="right"> <a accesskey="n" href="multi__tracing_bus_events.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_customizing_the_message_broker" href="#_customizing_the_message_broker"></a>42. Customizing the Message Broker</h2></div></div></div><p>Spring Cloud Bus uses
|
||||
<a class="link" href="https://cloud.spring.io/spring-cloud-stream" target="_top">Spring Cloud Stream</a> to
|
||||
broadcast the messages so to get messages to flow you only need to
|
||||
include the binder implementation of your choice in the
|
||||
classpath. There are convenient starters specifically for the bus with
|
||||
AMQP (RabbitMQ) and Kafka
|
||||
(<code class="literal">spring-cloud-starter-bus-[amqp,kafka]</code>). Generally speaking
|
||||
Spring Cloud Stream relies on Spring Boot autoconfiguration
|
||||
conventions for configuring middleware, so for instance the AMQP
|
||||
broker address can be changed with <code class="literal">spring.rabbitmq.*</code>
|
||||
configuration properties. Spring Cloud Bus has a handful of native
|
||||
configuration properties in <code class="literal">spring.cloud.bus.*</code>
|
||||
(e.g. <code class="literal">spring.cloud.bus.destination</code> is the name of the topic to use
|
||||
the the externall middleware). Normally the defaults will suffice.</p><p>To lean more about how to customize the message broker settings
|
||||
consult the Spring Cloud Stream documentation.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__application_context_id_must_be_unique.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_bus.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__tracing_bus_events.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">41. Application Context ID must be unique </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 43. Tracing Bus Events</td></tr></table></div></body></html>
|
||||
22
Dalston.SR5/multi/multi__discovery.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>76. Discovery</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_for_cloud_foundry.html" title="Part XI. Spring Cloud for Cloud Foundry"><link rel="prev" href="multi__spring_cloud_for_cloud_foundry.html" title="Part XI. Spring Cloud for Cloud Foundry"><link rel="next" href="multi__single_sign_on_2.html" title="77. Single Sign On"></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">76. Discovery</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__spring_cloud_for_cloud_foundry.html">Prev</a> </td><th width="60%" align="center">Part XI. Spring Cloud for Cloud Foundry</th><td width="20%" align="right"> <a accesskey="n" href="multi__single_sign_on_2.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_discovery" href="#_discovery"></a>76. Discovery</h2></div></div></div><p>Here’s a Spring Cloud app with Cloud Foundry discovery:</p><p><b>app.groovy. </b>
|
||||
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Grab('org.springframework.cloud:spring-cloud-cloudfoundry')</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@RestController</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableDiscoveryClient</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
DiscoveryClient client
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@RequestMapping('/')</span></em>
|
||||
String home() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Hello from '</span> + client.getLocalServiceInstance()
|
||||
}
|
||||
|
||||
}</pre><p>
|
||||
</p><p>If you run it without any service bindings:</p><pre class="screen">$ spring jar app.jar app.groovy
|
||||
$ cf push -p app.jar</pre><p>It will show its app name in the home page.</p><p>The <code class="literal">DiscoveryClient</code> can lists all the apps in a space, according to
|
||||
the credentials it is authenticated with, where the space defaults to
|
||||
the one the client is running in (if any). If neither org nor space
|
||||
are configured, they default per the user’s profile in Cloud Foundry.</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_for_cloud_foundry.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_for_cloud_foundry.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__single_sign_on_2.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Part XI. Spring Cloud for Cloud Foundry </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 77. Single Sign On</td></tr></table></div></body></html>
|
||||
21
Dalston.SR5/multi/multi__embedding_the_config_server.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>8. Embedding the Config Server</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_config.html" title="Part II. Spring Cloud Config"><link rel="prev" href="multi__serving_plain_text.html" title="7. Serving Plain Text"><link rel="next" href="multi__push_notifications_and_spring_cloud_bus.html" title="9. Push Notifications and Spring Cloud Bus"></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. Embedding the Config Server</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__serving_plain_text.html">Prev</a> </td><th width="60%" align="center">Part II. Spring Cloud Config</th><td width="20%" align="right"> <a accesskey="n" href="multi__push_notifications_and_spring_cloud_bus.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_embedding_the_config_server" href="#_embedding_the_config_server"></a>8. Embedding the Config Server</h2></div></div></div><p>The Config Server runs best as a standalone application, but if you
|
||||
need to you can embed it in another application. Just use the
|
||||
<code class="literal">@EnableConfigServer</code> annotation. An optional property that can be
|
||||
useful in this case is <code class="literal">spring.cloud.config.server.bootstrap</code> which is
|
||||
a flag to indicate that the server should configure itself from its
|
||||
own remote repository. The flag is off by default because it can delay
|
||||
startup, but when embedded in another application it makes sense to
|
||||
initialize the same way as any other application.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>It should be obvious, but remember that if you use the bootstrap
|
||||
flag the config server will need to have its name and repository URI
|
||||
configured in <code class="literal">bootstrap.yml</code>.</p></td></tr></table></div><p>To change the location of the server endpoints you can (optionally)
|
||||
set <code class="literal">spring.cloud.config.server.prefix</code>, e.g. "/config", to serve the
|
||||
resources under a prefix. The prefix should start but not end with a
|
||||
"/". It is applied to the <code class="literal">@RequestMappings</code> in the Config Server
|
||||
(i.e. underneath the Spring Boot prefixes <code class="literal">server.servletPath</code> and
|
||||
<code class="literal">server.contextPath</code>).</p><p>If you want to read the configuration for an application directly from
|
||||
the backend repository (instead of from the config server) that’s
|
||||
basically an embedded config server with no endpoints. You can switch
|
||||
off the endpoints entirely if you don’t use the <code class="literal">@EnableConfigServer</code>
|
||||
annotation (just set <code class="literal">spring.cloud.config.server.bootstrap=true</code>).</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__serving_plain_text.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_config.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__push_notifications_and_spring_cloud_bus.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">7. Serving Plain Text </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 9. Push Notifications and Spring Cloud Bus</td></tr></table></div></body></html>
|
||||
@@ -0,0 +1,13 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>18. External Configuration: Archaius</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_netflix.html" title="Part III. Spring Cloud Netflix"><link rel="prev" href="multi_spring-cloud-feign.html" title="17. Declarative REST Client: Feign"><link rel="next" href="multi__router_and_filter_zuul.html" title="19. Router and Filter: Zuul"></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">18. External Configuration: Archaius</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_spring-cloud-feign.html">Prev</a> </td><th width="60%" align="center">Part III. Spring Cloud Netflix</th><td width="20%" align="right"> <a accesskey="n" href="multi__router_and_filter_zuul.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_external_configuration_archaius" href="#_external_configuration_archaius"></a>18. External Configuration: Archaius</h2></div></div></div><p><a class="link" href="https://github.com/Netflix/archaius" target="_top">Archaius</a> is the Netflix client side configuration library. It is the library used by all of the Netflix OSS components for configuration. Archaius is an extension of the <a class="link" href="http://commons.apache.org/proper/commons-configuration" target="_top">Apache Commons Configuration</a> project. It allows updates to configuration by either polling a source for changes or for a source to push changes to the client. Archaius uses Dynamic<Type>Property classes as handles to properties.</p><p><b>Archaius Example. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> ArchaiusTest {
|
||||
DynamicStringProperty myprop = DynamicPropertyFactory
|
||||
.getInstance()
|
||||
.getStringProperty(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"my.prop"</span>);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> doSomething() {
|
||||
OtherClass.someMethod(myprop.get());
|
||||
}
|
||||
}</pre><p>
|
||||
</p><p>Archaius has its own set of configuration files and loading priorities. Spring applications should generally not use Archaius directly, but the need to configure the Netflix tools natively remains. Spring Cloud has a Spring Environment Bridge so Archaius can read properties from the Spring Environment. This allows Spring Boot projects to use the normal configuration toolchain, while allowing them to configure the Netflix tools, for the most part, as documented.</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-feign.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_netflix.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__router_and_filter_zuul.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">17. Declarative REST Client: Feign </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 19. Router and Filter: Zuul</td></tr></table></div></body></html>
|
||||
4
Dalston.SR5/multi/multi__features.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>1. Features</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="prev" href="multi_pr01.html" title=""><link rel="next" href="multi__cloud_native_applications.html" title="Part I. Cloud Native Applications"></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. Features</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_pr01.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__cloud_native_applications.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_features" href="#_features"></a>1. Features</h1></div></div></div><p>Spring Cloud focuses on providing good out of box experience for typical use cases
|
||||
and extensibility mechanism to cover others.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Distributed/versioned configuration</li><li class="listitem">Service registration and discovery</li><li class="listitem">Routing</li><li class="listitem">Service-to-service calls</li><li class="listitem">Load balancing</li><li class="listitem">Circuit Breakers</li><li class="listitem">Distributed messaging</li></ul></div></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> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__cloud_native_applications.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top"> </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> Part I. Cloud Native Applications</td></tr></table></div></body></html>
|
||||
22
Dalston.SR5/multi/multi__features_2.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>47. Features</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_sleuth.html" title="Part VII. Spring Cloud Sleuth"><link rel="prev" href="multi__additional_resources.html" title="46. Additional resources"><link rel="next" href="multi__sampling.html" title="48. Sampling"></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">47. Features</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__additional_resources.html">Prev</a> </td><th width="60%" align="center">Part VII. Spring Cloud Sleuth</th><td width="20%" align="right"> <a accesskey="n" href="multi__sampling.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_features_2" href="#_features_2"></a>47. Features</h2></div></div></div><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p class="simpara">Adds trace and span ids to the Slf4J MDC, so you can extract all the logs from a given trace or span in a log aggregator. Example logs:</p><pre class="screen">2016-02-02 15:30:57.902 INFO [bar,6bfd228dc00d216b,6bfd228dc00d216b,false] 23030 --- [nio-8081-exec-3] ...
|
||||
2016-02-02 15:30:58.372 ERROR [bar,6bfd228dc00d216b,6bfd228dc00d216b,false] 23030 --- [nio-8081-exec-3] ...
|
||||
2016-02-02 15:31:01.936 INFO [bar,46ab0d418373cbc9,46ab0d418373cbc9,false] 23030 --- [nio-8081-exec-4] ...</pre><p class="simpara">notice the <code class="literal">[appname,traceId,spanId,exportable]</code> entries from the MDC:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><span class="strong"><strong>spanId</strong></span> - the id of a specific operation that took place</li><li class="listitem"><span class="strong"><strong>appname</strong></span> - the name of the application that logged the span</li><li class="listitem"><span class="strong"><strong>traceId</strong></span> - the id of the latency graph that contains the span</li><li class="listitem"><span class="strong"><strong>exportable</strong></span> - whether the log should be exported to Zipkin or not. When would you like the span not to be
|
||||
exportable? In the case in which you want to wrap some operation in a Span and have it written to the logs
|
||||
only.</li></ul></div></li><li class="listitem">Provides an abstraction over common distributed tracing data models: traces, spans (forming a DAG), annotations,
|
||||
key-value annotations. Loosely based on HTrace, but Zipkin (Dapper) compatible.</li><li class="listitem"><p class="simpara">Sleuth records timing information to aid in latency analysis. Using sleuth, you can pinpoint causes of
|
||||
latency in your applications. Sleuth is written to not log too much, and to not cause your production application to crash.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">propagates structural data about your call-graph in-band, and the rest out-of-band.</li><li class="listitem">includes opinionated instrumentation of layers such as HTTP</li><li class="listitem">includes sampling policy to manage volume</li><li class="listitem">can report to a Zipkin system for query and visualization</li></ul></div></li><li class="listitem">Instruments common ingress and egress points from Spring applications (servlet filter, async endpoints,
|
||||
rest template, scheduled actions, message channels, zuul filters, feign client).</li><li class="listitem">Sleuth includes default logic to join a trace across http or messaging boundaries. For example, http propagation
|
||||
works via Zipkin-compatible request headers. This propagation logic is defined and customized via
|
||||
<code class="literal">SpanInjector</code> and <code class="literal">SpanExtractor</code> implementations.</li><li class="listitem">Sleuth gives you the possibility to propagate context (also known as baggage) between processes. That means that if you set on a Span
|
||||
a baggage element then it will be sent downstream either via HTTP or messaging to other processes.</li><li class="listitem">Provides a way to create / continue spans and add tags and logs via annotations.</li><li class="listitem">Provides simple metrics of accepted / dropped spans.</li><li class="listitem">If <code class="literal">spring-cloud-sleuth-zipkin</code> then the app will generate and collect Zipkin-compatible traces.
|
||||
By default it sends them via HTTP to a Zipkin server on localhost (port 9411).
|
||||
Configure the location of the service using <code class="literal">spring.zipkin.baseUrl</code>.</li><li class="listitem">If <code class="literal">spring-cloud-sleuth-stream</code> then the app will generate and collect traces via <a class="link" href="https://github.com/spring-cloud/spring-cloud-stream" target="_top">Spring Cloud Stream</a>.
|
||||
Your app automatically becomes a producer of tracer messages that are sent over your broker of choice
|
||||
(e.g. RabbitMQ, Apache Kafka, Redis).</li></ul></div><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>If using Zipkin or Stream, configure the percentage of spans exported using <code class="literal">spring.sleuth.sampler.percentage</code>
|
||||
(default 0.1, i.e. 10%). <span class="strong"><strong>Otherwise you might think that Sleuth is not working cause it’s omitting some spans.</strong></span></p></td></tr></table></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>the SLF4J MDC is always set and logback users will immediately see the trace and span ids in logs per the example
|
||||
above. Other logging systems have to configure their own formatter to get the same result. The default is
|
||||
<code class="literal">logging.pattern.level</code> set to <code class="literal">%5p [${spring.zipkin.service.name:${spring.application.name:-}},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}]</code>
|
||||
(this is a Spring Boot feature for logback users).
|
||||
<span class="strong"><strong>This means that if you’re not using SLF4J this pattern WILL NOT be automatically applied</strong></span>.</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__additional_resources.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_sleuth.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__sampling.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">46. Additional resources </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 48. Sampling</td></tr></table></div></body></html>
|
||||
55
Dalston.SR5/multi/multi__getting_started.html
Normal file
@@ -0,0 +1,55 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>35. Getting Started</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_stream.html" title="Part IV. Spring Cloud Stream"><link rel="prev" href="multi__samples.html" title="34. Samples"><link rel="next" href="multi__binder_implementations.html" title="Part V. Binder Implementations"></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">35. Getting Started</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__samples.html">Prev</a> </td><th width="60%" align="center">Part IV. Spring Cloud Stream</th><td width="20%" align="right"> <a accesskey="n" href="multi__binder_implementations.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_getting_started" href="#_getting_started"></a>35. Getting Started</h2></div></div></div><p>To get started with creating Spring Cloud Stream applications, visit the <a class="link" href="https://start.spring.io" target="_top">Spring Initializr</a> and create a new Maven project named "GreetingSource".
|
||||
Select Spring Boot {supported-spring-boot-version} in the dropdown.
|
||||
In the <span class="emphasis"><em>Search for dependencies</em></span> text box type <code class="literal">Stream Rabbit</code> or <code class="literal">Stream Kafka</code> depending on what binder you want to use.</p><p>Next, create a new class, <code class="literal">GreetingSource</code>, in the same package as the <code class="literal">GreetingSourceApplication</code> class.
|
||||
Give it the following code:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.stream.annotation.EnableBinding;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.stream.messaging.Source;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.integration.annotation.InboundChannelAdapter;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableBinding(Source.class)</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> GreetingSource {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@InboundChannelAdapter(Source.OUTPUT)</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String greet() {
|
||||
<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> + System.currentTimeMillis();
|
||||
}
|
||||
}</pre><p>The <code class="literal">@EnableBinding</code> annotation is what triggers the creation of Spring Integration infrastructure components.
|
||||
Specifically, it will create a Kafka connection factory, a Kafka outbound channel adapter, and the message channel defined inside the Source interface:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> Source {
|
||||
|
||||
String OUTPUT = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"output"</span>;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Output(Source.OUTPUT)</span></em>
|
||||
MessageChannel output();
|
||||
|
||||
}</pre><p>The auto-configuration also creates a default poller, so that the <code class="literal">greet()</code> method will be invoked once per second.
|
||||
The standard Spring Integration <code class="literal">@InboundChannelAdapter</code> annotation sends a message to the source’s output channel, using the return value as the payload of the message.</p><p>To test-drive this setup, run a Kafka message broker.
|
||||
An easy way to do this is to use a Docker image:</p><pre class="screen"># On OS X
|
||||
$ docker run -p 2181:2181 -p 9092:9092 --env ADVERTISED_HOST=`docker-machine ip \`docker-machine active\`` --env ADVERTISED_PORT=9092 spotify/kafka
|
||||
|
||||
# On Linux
|
||||
$ docker run -p 2181:2181 -p 9092:9092 --env ADVERTISED_HOST=localhost --env ADVERTISED_PORT=9092 spotify/kafka</pre><p>Build the application:</p><pre class="screen">./mvnw clean package</pre><p>The consumer application is coded in a similar manner.
|
||||
Go back to Initializr and create another project, named LoggingSink.
|
||||
Then create a new class, <code class="literal">LoggingSink</code>, in the same package as the class <code class="literal">LoggingSinkApplication</code> and with the following code:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.stream.annotation.EnableBinding;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.stream.annotation.StreamListener;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.stream.messaging.Sink;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableBinding(Sink.class)</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> LoggingSink {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@StreamListener(Sink.INPUT)</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">void</span> log(String message) {
|
||||
System.out.println(message);
|
||||
}
|
||||
}</pre><p>Build the application:</p><pre class="screen">./mvnw clean package</pre><p>To connect the GreetingSource application to the LoggingSink application, each application must share the same destination name.
|
||||
Starting up both applications as shown below, you will see the consumer application printing "hello world" and a timestamp to the console:</p><pre class="screen">cd GreetingSource
|
||||
java -jar target/GreetingSource-0.0.1-SNAPSHOT.jar --spring.cloud.stream.bindings.output.destination=mydest
|
||||
|
||||
cd LoggingSink
|
||||
java -jar target/LoggingSink-0.0.1-SNAPSHOT.jar --server.port=8090 --spring.cloud.stream.bindings.input.destination=mydest</pre><p>(The different server port prevents collisions of the HTTP port used to service the Spring Boot Actuator endpoints in the two applications.)</p><p>The output of the LoggingSink application will look something like the following:</p><pre class="screen">[ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8090 (http)
|
||||
[ main] com.example.LoggingSinkApplication : Started LoggingSinkApplication in 6.828 seconds (JVM running for 7.371)
|
||||
hello world 1458595076731
|
||||
hello world 1458595077732
|
||||
hello world 1458595078733
|
||||
hello world 1458595079734
|
||||
hello world 1458595080735</pre></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__samples.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_stream.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__binder_implementations.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">34. Samples </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> Part V. Binder Implementations</td></tr></table></div></body></html>
|
||||
4
Dalston.SR5/multi/multi__health_indicator_4.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>32. Health Indicator</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_stream.html" title="Part IV. Spring Cloud Stream"><link rel="prev" href="multi__testing.html" title="31. Testing"><link rel="next" href="multi__metrics_emitter.html" title="33. Metrics Emitter"></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">32. Health Indicator</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__testing.html">Prev</a> </td><th width="60%" align="center">Part IV. Spring Cloud Stream</th><td width="20%" align="right"> <a accesskey="n" href="multi__metrics_emitter.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_health_indicator_4" href="#_health_indicator_4"></a>32. Health Indicator</h2></div></div></div><p>Spring Cloud Stream provides a health indicator for binders.
|
||||
It is registered under the name of <code class="literal">binders</code> and can be enabled or disabled by setting the <code class="literal">management.health.binders.enabled</code> property.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__testing.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_stream.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__metrics_emitter.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">31. Testing </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 33. Metrics Emitter</td></tr></table></div></body></html>
|
||||
@@ -0,0 +1,24 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>15. Hystrix Timeouts And Ribbon Clients</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_netflix.html" title="Part III. Spring Cloud Netflix"><link rel="prev" href="multi__circuit_breaker_hystrix_dashboard.html" title="14. Circuit Breaker: Hystrix Dashboard"><link rel="next" href="multi_spring-cloud-ribbon.html" title="16. Client Side Load Balancer: Ribbon"></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">15. Hystrix Timeouts And Ribbon Clients</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__circuit_breaker_hystrix_dashboard.html">Prev</a> </td><th width="60%" align="center">Part III. Spring Cloud Netflix</th><td width="20%" align="right"> <a accesskey="n" href="multi_spring-cloud-ribbon.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_hystrix_timeouts_and_ribbon_clients" href="#_hystrix_timeouts_and_ribbon_clients"></a>15. Hystrix Timeouts And Ribbon Clients</h2></div></div></div><p>When using Hystrix commands that wrap Ribbon clients you want to make sure your Hystrix timeout
|
||||
is configured to be longer than the configured Ribbon timeout, including any potential
|
||||
retries that might be made. For example, if your Ribbon connection timeout is one second and
|
||||
the Ribbon client might retry the request three times, than your Hystrix timeout should
|
||||
be slightly more than three seconds.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="netflix-hystrix-dashboard-starter" href="#netflix-hystrix-dashboard-starter"></a>15.1 How to Include Hystrix Dashboard</h2></div></div></div><p>To include the Hystrix Dashboard in your project use the starter with group <code class="literal">org.springframework.cloud</code>
|
||||
and artifact id <code class="literal">spring-cloud-starter-hystrix-dashboard</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>To run the Hystrix Dashboard annotate your Spring Boot main class with <code class="literal">@EnableHystrixDashboard</code>. You then visit <code class="literal">/hystrix</code> and point the dashboard to an individual instances <code class="literal">/hystrix.stream</code> endpoint in a Hystrix client application.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>When connecting to a <code class="literal">/hystrix.stream</code> endpoint which uses HTTPS the certificate used by the server
|
||||
must be trusted by the JVM. If the certificate is not trusted you must import the certificate into the JVM
|
||||
in order for the Hystrix Dashboard to make a successful connection to the stream endpoint.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_turbine" href="#_turbine"></a>15.2 Turbine</h2></div></div></div><p>Looking at an individual instances Hystrix data is not very useful in terms of the overall health of the system. <a class="link" href="https://github.com/Netflix/Turbine" target="_top">Turbine</a> is an application that aggregates all of the relevant <code class="literal">/hystrix.stream</code> endpoints into a combined <code class="literal">/turbine.stream</code> for use in the Hystrix Dashboard. Individual instances are located via Eureka. Running Turbine is as simple as annotating your main class with the <code class="literal">@EnableTurbine</code> annotation (e.g. using spring-cloud-starter-turbine to set up the classpath). All of the documented configuration properties from <a class="link" href="https://github.com/Netflix/Turbine/wiki/Configuration-(1.x)" target="_top">the Turbine 1 wiki</a> apply. The only difference is that the <code class="literal">turbine.instanceUrlSuffix</code> does not need the port prepended as this is handled automatically unless <code class="literal">turbine.instanceInsertPort=false</code>.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>By default, Turbine looks for the <code class="literal">/hystrix.stream</code> endpoint on a registered instance by looking up its <code class="literal">homePageUrl</code> entry in Eureka, then appending <code class="literal">/hystrix.stream</code> to it. This means that if <code class="literal">spring-boot-actuator</code> is running on its own port (which is the default), the call to <code class="literal">/hystrix.stream</code> will fail.
|
||||
To make turbine find the Hystrix stream at the correct port, you need to add <code class="literal">management.port</code> to the instances' metadata:</p></td></tr></table></div><pre class="screen">eureka:
|
||||
instance:
|
||||
metadata-map:
|
||||
management.port: ${management.port:8081}</pre><p>The configuration key <code class="literal">turbine.appConfig</code> is a list of eureka serviceIds that turbine will use to lookup instances. The turbine stream is then used in the Hystrix dashboard using a url that looks like: <code class="literal"><a class="link" href="http://my.turbine.sever:8080/turbine.stream?cluster=CLUSTERNAME" target="_top">http://my.turbine.sever:8080/turbine.stream?cluster=CLUSTERNAME</a></code> (the cluster parameter can be omitted if the name is "default"). The <code class="literal">cluster</code> parameter must match an entry in <code class="literal">turbine.aggregator.clusterConfig</code>. Values returned from eureka are uppercase, thus we expect this example to work if there is an app registered with Eureka called "customers":</p><pre class="screen">turbine:
|
||||
aggregator:
|
||||
clusterConfig: CUSTOMERS
|
||||
appConfig: customers</pre><p>The <code class="literal">clusterName</code> can be customized by a SPEL expression in <code class="literal">turbine.clusterNameExpression</code> with root an instance of <code class="literal">InstanceInfo</code>. The default value is <code class="literal">appName</code>, which means that the Eureka serviceId ends up as the cluster key (i.e. the <code class="literal">InstanceInfo</code> for customers has an <code class="literal">appName</code> of "CUSTOMERS"). A different example would be <code class="literal">turbine.clusterNameExpression=aSGName</code>, which would get the cluster name from the AWS ASG name. Another example:</p><pre class="screen">turbine:
|
||||
aggregator:
|
||||
clusterConfig: SYSTEM,USER
|
||||
appConfig: customers,stores,ui,admin
|
||||
clusterNameExpression: metadata['cluster']</pre><p>In this case, the cluster name from 4 services is pulled from their metadata map, and is expected to have values that include "SYSTEM" and "USER".</p><p>To use the "default" cluster for all apps you need a string literal expression (with single quotes, and escaped with double quotes if it is in YAML as well):</p><pre class="screen">turbine:
|
||||
appConfig: customers,stores
|
||||
clusterNameExpression: "'default'"</pre><p>Spring Cloud provides a <code class="literal">spring-cloud-starter-turbine</code> that has all the dependencies you need to get a Turbine server running. Just create a Spring Boot application and annotate it with <code class="literal">@EnableTurbine</code>.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>by default Spring Cloud allows Turbine to use the host and port to allow multiple processes per host, per cluster. If you want the native Netflix behaviour built into Turbine that does <span class="emphasis"><em>not</em></span> allow multiple processes per host, per cluster (the key to the instance id is the hostname), then set the property <code class="literal">turbine.combineHostPort=false</code>.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_turbine_stream" href="#_turbine_stream"></a>15.3 Turbine Stream</h2></div></div></div><p>In some environments (e.g. in a PaaS setting), the classic Turbine model of pulling metrics from all the distributed Hystrix commands doesn’t work. In that case you might want to have your Hystrix commands push metrics to Turbine, and Spring Cloud enables that with messaging. All you need to do on the client is add a dependency to <code class="literal">spring-cloud-netflix-hystrix-stream</code> and the <code class="literal">spring-cloud-starter-stream-*</code> of your choice (see Spring Cloud Stream documentation for details on the brokers, and how to configure the client credentials, but it should work out of the box for a local broker).</p><p>On the server side Just create a Spring Boot application and annotate it with <code class="literal">@EnableTurbineStream</code> and by default it will come up on port 8989 (point your Hystrix dashboard to that port, any path). You can customize the port using either <code class="literal">server.port</code> or <code class="literal">turbine.stream.port</code>. If you have <code class="literal">spring-boot-starter-web</code> and <code class="literal">spring-boot-starter-actuator</code> on the classpath as well, then you can open up the Actuator endpoints on a separate port (with Tomcat by default) by providing a <code class="literal">management.port</code> which is different.</p><p>You can then point the Hystrix Dashboard to the Turbine Stream Server instead of individual Hystrix streams. If Turbine Stream is running on port 8989 on myhost, then put <code class="literal"><a class="link" href="http://myhost:8989" target="_top">http://myhost:8989</a></code> in the stream input field in the Hystrix Dashboard. Circuits will be prefixed by their respective serviceId, followed by a dot, then the circuit name.</p><p>Spring Cloud provides a <code class="literal">spring-cloud-starter-turbine-stream</code> that has all the dependencies you need to get a Turbine Stream server running - just add the Stream binder of your choice, e.g. <code class="literal">spring-cloud-starter-stream-rabbit</code>. You need Java 8 to run the app because it is Netty-based.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__circuit_breaker_hystrix_dashboard.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_netflix.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi_spring-cloud-ribbon.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">14. Circuit Breaker: Hystrix Dashboard </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 16. Client Side Load Balancer: Ribbon</td></tr></table></div></body></html>
|
||||
18
Dalston.SR5/multi/multi__instrumentation.html
Normal file
@@ -0,0 +1,18 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>49. Instrumentation</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_sleuth.html" title="Part VII. Spring Cloud Sleuth"><link rel="prev" href="multi__sampling.html" title="48. Sampling"><link rel="next" href="multi__span_lifecycle.html" title="50. Span lifecycle"></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">49. Instrumentation</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__sampling.html">Prev</a> </td><th width="60%" align="center">Part VII. Spring Cloud Sleuth</th><td width="20%" align="right"> <a accesskey="n" href="multi__span_lifecycle.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_instrumentation" href="#_instrumentation"></a>49. Instrumentation</h2></div></div></div><p>Spring Cloud Sleuth instruments all your Spring application
|
||||
automatically, so you shouldn’t have to do anything to activate
|
||||
it. The instrumentation is added using a variety of technologies
|
||||
according to the stack that is available, e.g. for a servlet web
|
||||
application we use a <code class="literal">Filter</code>, and for Spring Integration we use
|
||||
<code class="literal">ChannelInterceptors</code>.</p><p>You can customize the keys used in span tags. To limit the volume of
|
||||
span data, by default an HTTP request will be tagged only with a
|
||||
handful of metadata like the status code, host and URL. You can add
|
||||
request headers by configuring <code class="literal">spring.sleuth.keys.http.headers</code> (a
|
||||
list of header names).</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Remember that tags are only collected and exported if there is a
|
||||
<code class="literal">Sampler</code> that allows it (by default there is not, so there is no
|
||||
danger of accidentally collecting too much data without configuring
|
||||
something).</p></td></tr></table></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Currently the instrumentation in Spring Cloud Sleuth is eager - it means that
|
||||
we’re actively trying to pass the tracing context between threads. Also timing events
|
||||
are captured even when sleuth isn’t exporting data to a tracing system.
|
||||
This approach may change in the future towards being lazy on this matter.</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__sampling.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_sleuth.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__span_lifecycle.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">48. Sampling </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 50. Span lifecycle</td></tr></table></div></body></html>
|
||||
162
Dalston.SR5/multi/multi__integrations.html
Normal file
@@ -0,0 +1,162 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>56. Integrations</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_sleuth.html" title="Part VII. Spring Cloud Sleuth"><link rel="prev" href="multi__metrics.html" title="55. Metrics"><link rel="next" href="multi__running_examples.html" title="57. Running examples"></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">56. Integrations</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__metrics.html">Prev</a> </td><th width="60%" align="center">Part VII. Spring Cloud Sleuth</th><td width="20%" align="right"> <a accesskey="n" href="multi__running_examples.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_integrations" href="#_integrations"></a>56. Integrations</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_runnable_and_callable" href="#_runnable_and_callable"></a>56.1 Runnable and Callable</h2></div></div></div><p>If you’re wrapping your logic in <code class="literal">Runnable</code> or <code class="literal">Callable</code> it’s enough to wrap those classes in their Sleuth representative.</p><p>Example for <code class="literal">Runnable</code>:</p><pre class="programlisting">Runnable runnable = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Runnable() {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</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">void</span> run() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// do some work</span>
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String toString() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"spanNameFromToStringMethod"</span>;
|
||||
}
|
||||
};
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Manual `TraceRunnable` creation with explicit "calculateTax" Span name</span>
|
||||
Runnable traceRunnable = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceRunnable(tracer, spanNamer, runnable, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"calculateTax"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Wrapping `Runnable` with `Tracer`. The Span name will be taken either from the</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// `@SpanName` annotation or from `toString` method</span>
|
||||
Runnable traceRunnableFromTracer = tracer.wrap(runnable);</pre><p>Example for <code class="literal">Callable</code>:</p><pre class="programlisting">Callable<String> callable = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Callable<String>() {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String call() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> someLogic();
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String toString() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"spanNameFromToStringMethod"</span>;
|
||||
}
|
||||
};
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Manual `TraceCallable` creation with explicit "calculateTax" Span name</span>
|
||||
Callable<String> traceCallable = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceCallable<>(tracer, spanNamer, callable, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"calculateTax"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Wrapping `Callable` with `Tracer`. The Span name will be taken either from the</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// `@SpanName` annotation or from `toString` method</span>
|
||||
Callable<String> traceCallableFromTracer = tracer.wrap(callable);</pre><p>That way you will ensure that a new Span is created and closed for each execution.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_hystrix" href="#_hystrix"></a>56.2 Hystrix</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_custom_concurrency_strategy" href="#_custom_concurrency_strategy"></a>56.2.1 Custom Concurrency Strategy</h3></div></div></div><p>We’re registering a custom <a class="link" href="https://github.com/Netflix/Hystrix/wiki/Plugins#concurrencystrategy" target="_top"><code class="literal">HystrixConcurrencyStrategy</code></a>
|
||||
that wraps all <code class="literal">Callable</code> instances into their Sleuth representative -
|
||||
the <code class="literal">TraceCallable</code>. The strategy either starts or continues a span depending on the fact whether tracing was already going
|
||||
on before the Hystrix command was called. To disable the custom Hystrix Concurrency Strategy set the <code class="literal">spring.sleuth.hystrix.strategy.enabled</code> to <code class="literal">false</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_manual_command_setting" href="#_manual_command_setting"></a>56.2.2 Manual Command setting</h3></div></div></div><p>Assuming that you have the following <code class="literal">HystrixCommand</code>:</p><pre class="programlisting">HystrixCommand<String> hystrixCommand = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> HystrixCommand<String>(setter) {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">protected</span> String run() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> someLogic();
|
||||
}
|
||||
};</pre><p>In order to pass the tracing information you have to wrap the same logic in the Sleuth version of the <code class="literal">HystrixCommand</code> which is the
|
||||
<code class="literal">TraceCommand</code>:</p><pre class="programlisting">TraceCommand<String> traceCommand = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceCommand<String>(tracer, traceKeys, setter) {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String doRun() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> someLogic();
|
||||
}
|
||||
};</pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_rxjava" href="#_rxjava"></a>56.3 RxJava</h2></div></div></div><p>We’re registering a custom <a class="link" href="https://github.com/ReactiveX/RxJava/wiki/Plugins#rxjavaschedulershook" target="_top"><code class="literal">RxJavaSchedulersHook</code></a>
|
||||
that wraps all <code class="literal">Action0</code> instances into their Sleuth representative -
|
||||
the <code class="literal">TraceAction</code>. The hook either starts or continues a span depending on the fact whether tracing was already going
|
||||
on before the Action was scheduled. To disable the custom RxJavaSchedulersHook set the <code class="literal">spring.sleuth.rxjava.schedulers.hook.enabled</code> to <code class="literal">false</code>.</p><p>You can define a list of regular expressions for thread names, for which you don’t want a Span to be created. Just provide a comma separated list
|
||||
of regular expressions in the <code class="literal">spring.sleuth.rxjava.schedulers.ignoredthreads</code> property.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_http_integration" href="#_http_integration"></a>56.4 HTTP integration</h2></div></div></div><p>Features from this section can be disabled by providing the <code class="literal">spring.sleuth.web.enabled</code> property with value equal to <code class="literal">false</code>.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_http_filter" href="#_http_filter"></a>56.4.1 HTTP Filter</h3></div></div></div><p>Via the <code class="literal">TraceFilter</code> all sampled incoming requests result in creation of a Span. That Span’s name is <code class="literal">http:</code> + the path to which
|
||||
the request was sent. E.g. if the request was sent to <code class="literal">/foo/bar</code> then the name will be <code class="literal">http:/foo/bar</code>. You can configure which URIs you would
|
||||
like to skip via the <code class="literal">spring.sleuth.web.skipPattern</code> property. If you have <code class="literal">ManagementServerProperties</code> on classpath then
|
||||
its value of <code class="literal">contextPath</code> gets appended to the provided skip pattern.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_handlerinterceptor" href="#_handlerinterceptor"></a>56.4.2 HandlerInterceptor</h3></div></div></div><p>Since we want the span names to be precise we’re using a <code class="literal">TraceHandlerInterceptor</code> that either wraps an
|
||||
existing <code class="literal">HandlerInterceptor</code> or is added directly to the list of existing <code class="literal">HandlerInterceptors</code>. The
|
||||
<code class="literal">TraceHandlerInterceptor</code> adds a special request attribute to the given <code class="literal">HttpServletRequest</code>. If the
|
||||
the <code class="literal">TraceFilter</code> doesn’t see this attribute set it will create a "fallback" span which is an additional
|
||||
span created on the server side so that the trace is presented properly in the UI. Seeing that most likely
|
||||
signifies that there is a missing instrumentation. In that case please file an issue in Spring Cloud Sleuth.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_async_servlet_support" href="#_async_servlet_support"></a>56.4.3 Async Servlet support</h3></div></div></div><p>If your controller returns a <code class="literal">Callable</code> or a <code class="literal">WebAsyncTask</code> Spring Cloud Sleuth will continue the existing span instead of creating a new one.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_http_client_integration" href="#_http_client_integration"></a>56.5 HTTP client integration</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_synchronous_rest_template" href="#_synchronous_rest_template"></a>56.5.1 Synchronous Rest Template</h3></div></div></div><p>We’re injecting a <code class="literal">RestTemplate</code> interceptor that ensures that all the tracing information is passed to the requests. Each time a
|
||||
call is made a new Span is created. It gets closed upon receiving the response. In order to block the synchronous <code class="literal">RestTemplate</code> features
|
||||
just set <code class="literal">spring.sleuth.web.client.enabled</code> to <code class="literal">false</code>.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>You have to register <code class="literal">RestTemplate</code> as a bean so that the interceptors will get injected.
|
||||
If you create a <code class="literal">RestTemplate</code> instance with a <code class="literal">new</code> keyword then the instrumentation WILL NOT work.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_asynchronous_rest_template" href="#_asynchronous_rest_template"></a>56.5.2 Asynchronous Rest Template</h3></div></div></div><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>A traced version of an <code class="literal">AsyncRestTemplate</code> bean is registered for you out of the box. If you
|
||||
have your own bean you have to wrap it in a <code class="literal">TraceAsyncRestTemplate</code> representation. The best solution
|
||||
is to only customize the <code class="literal">ClientHttpRequestFactory</code> and / or <code class="literal">AsyncClientHttpRequestFactory</code>.
|
||||
<span class="strong"><strong>If you have your own <code class="literal">AsyncRestTemplate</code> and you don’t wrap it your calls WILL NOT GET TRACED</strong></span>.</p></td></tr></table></div><p>Custom instrumentation is set to create and close Spans upon sending and receiving requests. You can customize the <code class="literal">ClientHttpRequestFactory</code>
|
||||
and the <code class="literal">AsyncClientHttpRequestFactory</code> by registering your beans. Remember to use tracing compatible implementations (e.g. don’t forget to
|
||||
wrap <code class="literal">ThreadPoolTaskScheduler</code> in a <code class="literal">TraceAsyncListenableTaskExecutor</code>). Example of custom request factories:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@EnableAutoConfiguration</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@Configuration</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">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> TestConfiguration {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
ClientHttpRequestFactory mySyncClientFactory() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> MySyncClientHttpRequestFactory();
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
AsyncClientHttpRequestFactory myAsyncClientFactory() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> MyAsyncClientHttpRequestFactory();
|
||||
}
|
||||
}</pre><p>To block the <code class="literal">AsyncRestTemplate</code> features set <code class="literal">spring.sleuth.web.async.client.enabled</code> to <code class="literal">false</code>.
|
||||
To disable creation of the default <code class="literal">TraceAsyncClientHttpRequestFactoryWrapper</code> set <code class="literal">spring.sleuth.web.async.client.factory.enabled</code>
|
||||
to <code class="literal">false</code>. If you don’t want to create <code class="literal">AsyncRestClient</code> at all set <code class="literal">spring.sleuth.web.async.client.template.enabled</code> to <code class="literal">false</code>.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_multiple_asynchronous_rest_templates" href="#_multiple_asynchronous_rest_templates"></a>Multiple Asynchronous Rest Templates</h4></div></div></div><p>Sometimes you need to use multiple implementations of Asynchronous Rest Template. In the following snippet you
|
||||
can see an example of how to set up such a custom <code class="literal">AsyncRestTemplate</code>.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableAutoConfiguration</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Config {
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em> HttpTraceKeysInjector httpTraceKeysInjector;
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em> HttpSpanInjector spanInjector;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean(name = "customAsyncRestTemplate")</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> AsyncRestTemplate traceAsyncRestTemplate(<em><span class="hl-annotation" style="color: gray">@Qualifier("customHttpRequestFactoryWrapper")</span></em>
|
||||
TraceAsyncClientHttpRequestFactoryWrapper wrapper) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceAsyncRestTemplate(wrapper, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer);
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean(name = "customHttpRequestFactoryWrapper")</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> TraceAsyncClientHttpRequestFactoryWrapper traceAsyncClientHttpRequestFactory() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceAsyncClientHttpRequestFactoryWrapper(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.spanInjector,
|
||||
asyncClientFactory(),
|
||||
clientHttpRequestFactory(),
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.httpTraceKeysInjector);
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> ClientHttpRequestFactory clientHttpRequestFactory() {
|
||||
ClientHttpRequestFactory clientHttpRequestFactory = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> CustomClientHttpRequestFactory();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//CUSTOMIZE HERE</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> clientHttpRequestFactory;
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> AsyncClientHttpRequestFactory asyncClientFactory() {
|
||||
AsyncClientHttpRequestFactory factory = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> CustomAsyncClientHttpRequestFactory();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//CUSTOMIZE HERE</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> factory;
|
||||
}
|
||||
}</pre></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_traverson" href="#_traverson"></a>56.5.3 Traverson</h3></div></div></div><p>If you’re using the <a class="link" href="http://docs.spring.io/spring-hateoas/docs/current/reference/html/#client.traverson" target="_top">Traverson</a> library
|
||||
it’s enough for you to inject a <code class="literal">RestTemplate</code> as a bean into your Traverson object. Since <code class="literal">RestTemplate</code>
|
||||
is already intercepted, you will get full support of tracing in your client. Below you can find a pseudo code
|
||||
of how to do that:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> RestTemplate restTemplate;
|
||||
|
||||
Traverson traverson = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Traverson(URI.create(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://some/address"</span>),
|
||||
MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON_UTF8).setRestOperations(restTemplate);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// use Traverson</span></pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_feign" href="#_feign"></a>56.6 Feign</h2></div></div></div><p>By default Spring Cloud Sleuth provides integration with feign via the <code class="literal">TraceFeignClientAutoConfiguration</code>. You can disable it entirely
|
||||
by setting <code class="literal">spring.sleuth.feign.enabled</code> to false. If you do so then no Feign related instrumentation will take place.</p><p>Part of Feign instrumentation is done via a <code class="literal">FeignBeanPostProcessor</code>. You can disable it by providing the <code class="literal">spring.sleuth.feign.processor.enabled</code> equal to <code class="literal">false</code>.
|
||||
If you set it like this then Spring Cloud Sleuth will not instrument any of your custom Feign components. All the default instrumentation
|
||||
however will be still there.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_asynchronous_communication" href="#_asynchronous_communication"></a>56.7 Asynchronous communication</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="__async_annotated_methods" href="#__async_annotated_methods"></a>56.7.1 @Async annotated methods</h3></div></div></div><p>In Spring Cloud Sleuth we’re instrumenting async related components so that the tracing information is passed between threads.
|
||||
You can disable this behaviour by setting the value of <code class="literal">spring.sleuth.async.enabled</code> to <code class="literal">false</code>.</p><p>If you annotate your method with <code class="literal">@Async</code> then we’ll automatically create a new Span with the following characteristics:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">the Span name will be the annotated method name</li><li class="listitem">the Span will be tagged with that method’s class name and the method name too</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="__scheduled_annotated_methods" href="#__scheduled_annotated_methods"></a>56.7.2 @Scheduled annotated methods</h3></div></div></div><p>In Spring Cloud Sleuth we’re instrumenting scheduled method execution so that the tracing information is passed between threads. You can disable this behaviour
|
||||
by setting the value of <code class="literal">spring.sleuth.scheduled.enabled</code> to <code class="literal">false</code>.</p><p>If you annotate your method with <code class="literal">@Scheduled</code> then we’ll automatically create a new Span with the following characteristics:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">the Span name will be the annotated method name</li><li class="listitem">the Span will be tagged with that method’s class name and the method name too</li></ul></div><p>If you want to skip Span creation for some <code class="literal">@Scheduled</code> annotated classes you can set the
|
||||
<code class="literal">spring.sleuth.scheduled.skipPattern</code> with a regular expression that will match the fully qualified name of the
|
||||
<code class="literal">@Scheduled</code> annotated class.</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>If you are using <code class="literal">spring-cloud-sleuth-stream</code> and <code class="literal">spring-cloud-netflix-hystrix-stream</code> together, Span will be created for each Hystrix metrics and sent to Zipkin. This may be annoying. You can prevent this by setting <code class="literal">spring.sleuth.scheduled.skipPattern=org.springframework.cloud.netflix.hystrix.stream.HystrixStreamTask</code></p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_executor_executorservice_and_scheduledexecutorservice" href="#_executor_executorservice_and_scheduledexecutorservice"></a>56.7.3 Executor, ExecutorService and ScheduledExecutorService</h3></div></div></div><p>We’re providing <code class="literal">LazyTraceExecutor</code>, <code class="literal">TraceableExecutorService</code> and <code class="literal">TraceableScheduledExecutorService</code>. Those implementations
|
||||
are creating Spans each time a new task is submitted, invoked or scheduled.</p><p>Here you can see an example of how to pass tracing information with <code class="literal">TraceableExecutorService</code> when working with <code class="literal">CompletableFuture</code>:</p><pre class="programlisting">CompletableFuture<Long> completableFuture = CompletableFuture.supplyAsync(() -> {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// perform some logic</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span class="hl-number">1</span>_<span class="hl-number">000</span>_<span class="hl-number">000L</span>;
|
||||
}, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceableExecutorService(executorService,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// 'calculateTax' explicitly names the span - this param is optional</span>
|
||||
tracer, traceKeys, spanNamer, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"calculateTax"</span>));</pre><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>Sleuth doesn’t work with <code class="literal">parallelStream()</code> out of the box. If you want
|
||||
to have the tracing information propagated through the stream you have to use the
|
||||
approach with <code class="literal">supplyAsync(…​)</code> as presented above.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_customization_of_executors" href="#_customization_of_executors"></a>Customization of Executors</h4></div></div></div><p>Sometimes you need to set up a custom instance of the <code class="literal">AsyncExecutor</code>. In the following snippet you
|
||||
can see an example of how to set up such a custom <code class="literal">Executor</code>.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableAutoConfiguration</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableAsync</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> CustomExecutorConfig <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> AsyncConfigurerSupport {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em> BeanFactory beanFactory;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Executor getAsyncExecutor() {
|
||||
ThreadPoolTaskExecutor executor = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ThreadPoolTaskExecutor();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// CUSTOMIZE HERE</span>
|
||||
executor.setCorePoolSize(<span class="hl-number">7</span>);
|
||||
executor.setMaxPoolSize(<span class="hl-number">42</span>);
|
||||
executor.setQueueCapacity(<span class="hl-number">11</span>);
|
||||
executor.setThreadNamePrefix(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"MyExecutor-"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// DON'T FORGET TO INITIALIZE</span>
|
||||
executor.initialize();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> LazyTraceExecutor(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.beanFactory, executor);
|
||||
}
|
||||
}</pre></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_messaging" href="#_messaging"></a>56.8 Messaging</h2></div></div></div><p>Spring Cloud Sleuth integrates with <a class="link" href="http://projects.spring.io/spring-integration/" target="_top">Spring Integration</a>. It creates spans for publish and
|
||||
subscribe events. To disable Spring Integration instrumentation, set <code class="literal">spring.sleuth.integration.enabled</code> to false.</p><p>You can provide the <code class="literal">spring.sleuth.integration.patterns</code> pattern to explicitly
|
||||
provide the names of channels that you want to include for tracing. By default all channels
|
||||
are included.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>When using the <code class="literal">Executor</code> to build a Spring Integration <code class="literal">IntegrationFlow</code> remember to use the <span class="strong"><strong>untraced</strong></span> version of the <code class="literal">Executor</code>.
|
||||
Decorating Spring Integration Executor Channel with <code class="literal">TraceableExecutorService</code> will cause the spans to be improperly closed.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_zuul_2" href="#_zuul_2"></a>56.9 Zuul</h2></div></div></div><p>We’re registering Zuul filters to propagate the tracing information (the request header is enriched with tracing data).
|
||||
To disable Zuul support set the <code class="literal">spring.sleuth.zuul.enabled</code> property to <code class="literal">false</code>.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__metrics.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_sleuth.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__running_examples.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">55. Metrics </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 57. Running examples</td></tr></table></div></body></html>
|
||||
@@ -0,0 +1,26 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>30. Inter-Application Communication</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_stream.html" title="Part IV. Spring Cloud Stream"><link rel="prev" href="multi_schema-evolution.html" title="29. Schema evolution support"><link rel="next" href="multi__testing.html" title="31. Testing"></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">30. Inter-Application Communication</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_schema-evolution.html">Prev</a> </td><th width="60%" align="center">Part IV. Spring Cloud Stream</th><td width="20%" align="right"> <a accesskey="n" href="multi__testing.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_inter_application_communication" href="#_inter_application_communication"></a>30. Inter-Application Communication</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_connecting_multiple_application_instances" href="#_connecting_multiple_application_instances"></a>30.1 Connecting Multiple Application Instances</h2></div></div></div><p>While Spring Cloud Stream makes it easy for individual Spring Boot applications to connect to messaging systems, the typical scenario for Spring Cloud Stream is the creation of multi-application pipelines, where microservice applications send data to each other.
|
||||
You can achieve this scenario by correlating the input and output destinations of adjacent applications.</p><p>Supposing that a design calls for the Time Source application to send data to the Log Sink application, you can use a common destination named <code class="literal">ticktock</code> for bindings within both applications.</p><p>Time Source (that has the channel name <code class="literal">output</code>) will set the following property:</p><pre class="screen">spring.cloud.stream.bindings.output.destination=ticktock</pre><p>Log Sink (that has the channel name <code class="literal">input</code>) will set the following property:</p><pre class="screen">spring.cloud.stream.bindings.input.destination=ticktock</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_instance_index_and_instance_count" href="#_instance_index_and_instance_count"></a>30.2 Instance Index and Instance Count</h2></div></div></div><p>When scaling up Spring Cloud Stream applications, each instance can receive information about how many other instances of the same application exist and what its own instance index is.
|
||||
Spring Cloud Stream does this through the <code class="literal">spring.cloud.stream.instanceCount</code> and <code class="literal">spring.cloud.stream.instanceIndex</code> properties.
|
||||
For example, if there are three instances of a HDFS sink application, all three instances will have <code class="literal">spring.cloud.stream.instanceCount</code> set to <code class="literal">3</code>, and the individual applications will have <code class="literal">spring.cloud.stream.instanceIndex</code> set to <code class="literal">0</code>, <code class="literal">1</code>, and <code class="literal">2</code>, respectively.</p><p>When Spring Cloud Stream applications are deployed via Spring Cloud Data Flow, these properties are configured automatically; when Spring Cloud Stream applications are launched independently, these properties must be set correctly.
|
||||
By default, <code class="literal">spring.cloud.stream.instanceCount</code> is <code class="literal">1</code>, and <code class="literal">spring.cloud.stream.instanceIndex</code> is <code class="literal">0</code>.</p><p>In a scaled-up scenario, correct configuration of these two properties is important for addressing partitioning behavior (see below) in general, and the two properties are always required by certain binders (e.g., the Kafka binder) in order to ensure that data are split correctly across multiple consumer instances.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_partitioning" href="#_partitioning"></a>30.3 Partitioning</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_configuring_output_bindings_for_partitioning" href="#_configuring_output_bindings_for_partitioning"></a>30.3.1 Configuring Output Bindings for Partitioning</h3></div></div></div><p>An output binding is configured to send partitioned data by setting one and only one of its <code class="literal">partitionKeyExpression</code> or <code class="literal">partitionKeyExtractorClass</code> properties, as well as its <code class="literal">partitionCount</code> property.
|
||||
For example, the following is a valid and typical configuration:</p><pre class="screen">spring.cloud.stream.bindings.output.producer.partitionKeyExpression=payload.id
|
||||
spring.cloud.stream.bindings.output.producer.partitionCount=5</pre><p>Based on the above example configuration, data will be sent to the target partition using the following logic.</p><p>A partition key’s value is calculated for each message sent to a partitioned output channel based on the <code class="literal">partitionKeyExpression</code>.
|
||||
The <code class="literal">partitionKeyExpression</code> is a SpEL expression which is evaluated against the outbound message for extracting the partitioning key.</p><p>If a SpEL expression is not sufficient for your needs, you can instead calculate the partition key value by setting the property <code class="literal">partitionKeyExtractorClass</code> to a class which implements the <code class="literal">org.springframework.cloud.stream.binder.PartitionKeyExtractorStrategy</code> interface.
|
||||
While the SpEL expression should usually suffice, more complex cases may use the custom implementation strategy.
|
||||
In that case, the property 'partitionKeyExtractorClass' can be set as follows:</p><pre class="screen">spring.cloud.stream.bindings.output.producer.partitionKeyExtractorClass=com.example.MyKeyExtractor
|
||||
spring.cloud.stream.bindings.output.producer.partitionCount=5</pre><p>Once the message key is calculated, the partition selection process will determine the target partition as a value between <code class="literal">0</code> and <code class="literal">partitionCount - 1</code>.
|
||||
The default calculation, applicable in most scenarios, is based on the formula <code class="literal">key.hashCode() % partitionCount</code>.
|
||||
This can be customized on the binding, either by setting a SpEL expression to be evaluated against the 'key' (via the <code class="literal">partitionSelectorExpression</code> property) or by setting a <code class="literal">org.springframework.cloud.stream.binder.PartitionSelectorStrategy</code> implementation (via the <code class="literal">partitionSelectorClass</code> property).</p><p>The binding level properties for 'partitionSelectorExpression' and 'partitionSelectorClass' can be specified similar to the way 'partitionKeyExpression' and 'partitionKeyExtractorClass' properties are specified in the above examples.
|
||||
Additional properties can be configured for more advanced scenarios, as described in the following section.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_spring_managed_custom_literal_partitionkeyextractorclass_literal_implementations" href="#_spring_managed_custom_literal_partitionkeyextractorclass_literal_implementations"></a>Spring-managed custom <code class="literal">PartitionKeyExtractorClass</code> implementations</h4></div></div></div><p>In the example above, a custom strategy such as <code class="literal">MyKeyExtractor</code> is instantiated by the Spring Cloud Stream directly.
|
||||
In some cases, it is necessary for such a custom strategy implementation to be created as a Spring bean, for being able to be managed by Spring, so that it can perform dependency injection, property binding, etc.
|
||||
This can be done by configuring it as a @Bean in the application context and using the fully qualified class name as the bean’s name, as in the following example.</p><pre class="screen">@Bean(name="com.example.MyKeyExtractor")
|
||||
public MyKeyExtractor extractor() {
|
||||
return new MyKeyExtractor();
|
||||
}</pre><p>As a Spring bean, the custom strategy benefits from the full lifecycle of a Spring bean.
|
||||
For example, if the implementation need access to the application context directly, it can make implement 'ApplicationContextAware'.</p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_configuring_input_bindings_for_partitioning" href="#_configuring_input_bindings_for_partitioning"></a>Configuring Input Bindings for Partitioning</h4></div></div></div><p>An input binding (with the channel name <code class="literal">input</code>) is configured to receive partitioned data by setting its <code class="literal">partitioned</code> property, as well as the <code class="literal">instanceIndex</code> and <code class="literal">instanceCount</code> properties on the application itself, as in the following example:</p><pre class="screen">spring.cloud.stream.bindings.input.consumer.partitioned=true
|
||||
spring.cloud.stream.instanceIndex=3
|
||||
spring.cloud.stream.instanceCount=5</pre><p>The <code class="literal">instanceCount</code> value represents the total number of application instances between which the data need to be partitioned, and the <code class="literal">instanceIndex</code> must be a unique value across the multiple instances, between <code class="literal">0</code> and <code class="literal">instanceCount - 1</code>.
|
||||
The instance index helps each application instance to identify the unique partition (or, in the case of Kafka, the partition set) from which it receives data.
|
||||
It is important to set both values correctly in order to ensure that all of the data is consumed and that the application instances receive mutually exclusive datasets.</p><p>While a scenario which using multiple instances for partitioned data processing may be complex to set up in a standalone case, Spring Cloud Dataflow can simplify the process significantly by populating both the input and output values correctly as well as relying on the runtime infrastructure to provide information about the instance index and instance count.</p></div></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_schema-evolution.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_stream.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__testing.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">29. Schema evolution support </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 31. Testing</td></tr></table></div></body></html>
|
||||
@@ -0,0 +1,40 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>23. Introducing Spring Cloud Stream</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_stream.html" title="Part IV. Spring Cloud Stream"><link rel="prev" href="multi__spring_cloud_stream.html" title="Part IV. Spring Cloud Stream"><link rel="next" href="multi__main_concepts.html" title="24. Main Concepts"></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">23. Introducing Spring Cloud Stream</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__spring_cloud_stream.html">Prev</a> </td><th width="60%" align="center">Part IV. Spring Cloud Stream</th><td width="20%" align="right"> <a accesskey="n" href="multi__main_concepts.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_introducing_spring_cloud_stream" href="#_introducing_spring_cloud_stream"></a>23. Introducing Spring Cloud Stream</h2></div></div></div><p>Spring Cloud Stream is a framework for building message-driven microservice applications.
|
||||
Spring Cloud Stream builds upon Spring Boot to create standalone, production-grade Spring applications, and uses Spring Integration to provide connectivity to message brokers.
|
||||
It provides opinionated configuration of middleware from several vendors, introducing the concepts of persistent publish-subscribe semantics, consumer groups, and partitions.</p><p>You can add the <code class="literal">@EnableBinding</code> annotation to your application to get immediate connectivity to a message broker, and you can add <code class="literal">@StreamListener</code> to a method to cause it to receive events for stream processing.
|
||||
The following is a simple sink application which receives external messages.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@SpringBootApplication</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableBinding(Sink.class)</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> VoteRecordingSinkApplication {
|
||||
|
||||
<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) {
|
||||
SpringApplication.run(VoteRecordingSinkApplication.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>, args);
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@StreamListener(Sink.INPUT)</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">void</span> processVote(Vote vote) {
|
||||
votingService.recordVote(vote);
|
||||
}
|
||||
}</pre><p>The <code class="literal">@EnableBinding</code> annotation takes one or more interfaces as parameters (in this case, the parameter is a single <code class="literal">Sink</code> interface).
|
||||
An interface declares input and/or output channels.
|
||||
Spring Cloud Stream provides the interfaces <code class="literal">Source</code>, <code class="literal">Sink</code>, and <code class="literal">Processor</code>; you can also define your own interfaces.</p><p>The following is the definition of the <code class="literal">Sink</code> interface:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> Sink {
|
||||
String INPUT = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"input"</span>;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Input(Sink.INPUT)</span></em>
|
||||
SubscribableChannel input();
|
||||
}</pre><p>The <code class="literal">@Input</code> annotation identifies an <span class="emphasis"><em>input channel</em></span>, through which received messages enter the application; the <code class="literal">@Output</code> annotation identifies an <span class="emphasis"><em>output channel</em></span>, through which published messages leave the application.
|
||||
The <code class="literal">@Input</code> and <code class="literal">@Output</code> annotations can take a channel name as a parameter; if a name is not provided, the name of the annotated method will be used.</p><p>Spring Cloud Stream will create an implementation of the interface for you.
|
||||
You can use this in the application by autowiring it, as in the following example of a test case.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RunWith(SpringJUnit4ClassRunner.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringApplicationConfiguration(classes = VoteRecordingSinkApplication.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@WebAppConfiguration</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@DirtiesContext</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> StreamApplicationTests {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> Sink sink;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Test</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">void</span> contextLoads() {
|
||||
assertNotNull(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.sink.input());
|
||||
}
|
||||
}</pre></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__spring_cloud_stream.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_stream.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__main_concepts.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Part IV. Spring Cloud Stream </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 24. Main Concepts</td></tr></table></div></body></html>
|
||||
297
Dalston.SR5/multi/multi__introduction.html
Normal file
@@ -0,0 +1,297 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>45. Introduction</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_sleuth.html" title="Part VII. Spring Cloud Sleuth"><link rel="prev" href="multi__spring_cloud_sleuth.html" title="Part VII. Spring Cloud Sleuth"><link rel="next" href="multi__additional_resources.html" title="46. Additional resources"></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">45. Introduction</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__spring_cloud_sleuth.html">Prev</a> </td><th width="60%" align="center">Part VII. Spring Cloud Sleuth</th><td width="20%" align="right"> <a accesskey="n" href="multi__additional_resources.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_introduction" href="#_introduction"></a>45. Introduction</h2></div></div></div><p>Spring Cloud Sleuth implements a distributed tracing solution for <a class="link" href="http://cloud.spring.io" target="_top">Spring Cloud</a>.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_terminology" href="#_terminology"></a>45.1 Terminology</h2></div></div></div><p>Spring Cloud Sleuth borrows <a class="link" href="http://research.google.com/pubs/pub36356.html" target="_top">Dapper’s</a> terminology.</p><p><span class="strong"><strong>Span:</strong></span> The basic unit of work. For example, sending an RPC is a new span, as is sending a response to an
|
||||
RPC. Span’s are identified by a unique 64-bit ID for the span and another 64-bit ID for the trace the span
|
||||
is a part of. Spans also have other data, such as descriptions, timestamped events, key-value
|
||||
annotations (tags), the ID of the span that caused them, and process ID’s (normally IP address).</p><p>Spans are started and stopped, and they keep track of their timing information. Once you create a
|
||||
span, you must stop it at some point in the future.</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>The initial span that starts a trace is called a <code class="literal">root span</code>. The value of span id
|
||||
of that span is equal to trace id.</p></td></tr></table></div><p><span class="strong"><strong>Trace:</strong></span> A set of spans forming a tree-like structure. For example, if you are running a distributed
|
||||
big-data store, a trace might be formed by a put request.</p><p><span class="strong"><strong>Annotation:</strong></span> is used to record existence of an event in time. Some of the core annotations used to define
|
||||
the start and stop of a request are:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><span class="strong"><strong>cs</strong></span> - Client Sent - The client has made a request. This annotation depicts the start of the span.</li><li class="listitem"><span class="strong"><strong>sr</strong></span> - Server Received - The server side got the request and will start processing it.
|
||||
If one subtracts the cs timestamp from this timestamp one will receive the network latency.</li><li class="listitem"><span class="strong"><strong>ss</strong></span> - Server Sent - Annotated upon completion of request processing (when the response
|
||||
got sent back to the client). If one subtracts the sr timestamp from this timestamp one
|
||||
will receive the time needed by the server side to process the request.</li><li class="listitem"><span class="strong"><strong>cr</strong></span> - Client Received - Signifies the end of the span. The client has successfully received the
|
||||
response from the server side. If one subtracts the cs timestamp from this timestamp one
|
||||
will receive the whole time needed by the client to receive the response from the server.</li></ul></div><p>Visualization of what <span class="strong"><strong>Span</strong></span> and <span class="strong"><strong>Trace</strong></span> will look in a system together with the Zipkin annotations:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/trace-id.png" alt="Trace Info propagation"></div></div><p>Each color of a note signifies a span (7 spans - from <span class="strong"><strong>A</strong></span> to <span class="strong"><strong>G</strong></span>). If you have such information in the note:</p><pre class="screen">Trace Id = X
|
||||
Span Id = D
|
||||
Client Sent</pre><p>That means that the current span has <span class="strong"><strong>Trace-Id</strong></span> set to <span class="strong"><strong>X</strong></span>, <span class="strong"><strong>Span-Id</strong></span> set to <span class="strong"><strong>D</strong></span>. It also has emitted
|
||||
<span class="strong"><strong>Client Sent</strong></span> event.</p><p>This is how the visualization of the parent / child relationship of spans would look like:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/parents.png" alt="Parent child relationship"></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_purpose" href="#_purpose"></a>45.2 Purpose</h2></div></div></div><p>In the following sections the example from the image above will be taken into consideration.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_distributed_tracing_with_zipkin" href="#_distributed_tracing_with_zipkin"></a>45.2.1 Distributed tracing with Zipkin</h3></div></div></div><p>Altogether there are <span class="strong"><strong>7 spans</strong></span> . If you go to traces in Zipkin you will see this number in the second trace:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/zipkin-traces.png" alt="Traces"></div></div><p>However if you pick a particular trace then you will see <span class="strong"><strong>4 spans</strong></span>:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/zipkin-ui.png" alt="Traces Info propagation"></div></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>When picking a particular trace you will see merged spans. That means that if there were 2 spans sent to
|
||||
Zipkin with Server Received and Server Sent / Client Received and Client Sent
|
||||
annotations then they will presented as a single span.</p></td></tr></table></div><p>Why is there a difference between the 7 and 4 spans in this case?</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">2 spans come from <code class="literal">http:/start</code> span. It has the Server Received (SR) and Server Sent (SS) annotations.</li><li class="listitem">2 spans come from the RPC call from <code class="literal">service1</code> to <code class="literal">service2</code> to the <code class="literal">http:/foo</code> endpoint. It has the Client Sent (CS)
|
||||
and Client Received (CR) annotations on <code class="literal">service1</code> side. It also has Server Received (SR) and Server Sent (SS) annotations
|
||||
on the <code class="literal">service2</code> side. Physically there are 2 spans but they form 1 logical span related to an RPC call.</li><li class="listitem">2 spans come from the RPC call from <code class="literal">service2</code> to <code class="literal">service3</code> to the <code class="literal">http:/bar</code> endpoint. It has the Client Sent (CS)
|
||||
and Client Received (CR) annotations on <code class="literal">service2</code> side. It also has Server Received (SR) and Server Sent (SS) annotations
|
||||
on the <code class="literal">service3</code> side. Physically there are 2 spans but they form 1 logical span related to an RPC call.</li><li class="listitem">2 spans come from the RPC call from <code class="literal">service2</code> to <code class="literal">service4</code> to the <code class="literal">http:/baz</code> endpoint. It has the Client Sent (CS)
|
||||
and Client Received (CR) annotations on <code class="literal">service2</code> side. It also has Server Received (SR) and Server Sent (SS) annotations
|
||||
on the <code class="literal">service4</code> side. Physically there are 2 spans but they form 1 logical span related to an RPC call.</li></ul></div><p>So if we count the physical spans we have <span class="strong"><strong>1</strong></span> from <code class="literal">http:/start</code>, <span class="strong"><strong>2</strong></span> from <code class="literal">service1</code> calling <code class="literal">service2</code>, <span class="strong"><strong>2</strong></span> form <code class="literal">service2</code>
|
||||
calling <code class="literal">service3</code> and <span class="strong"><strong>2</strong></span> from <code class="literal">service2</code> calling <code class="literal">service4</code>. Altogether <span class="strong"><strong>7</strong></span> spans.</p><p>Logically we see the information of <span class="strong"><strong>Total Spans: 4</strong></span> because we have <span class="strong"><strong>1</strong></span> span related to the incoming request
|
||||
to <code class="literal">service1</code> and <span class="strong"><strong>3</strong></span> spans related to RPC calls.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_visualizing_errors" href="#_visualizing_errors"></a>45.2.2 Visualizing errors</h3></div></div></div><p>Zipkin allows you to visualize errors in your trace. When an exception was thrown and wasn’t caught then we’re
|
||||
setting proper tags on the span which Zipkin can properly colorize. You could see in the list of traces one
|
||||
trace that was in red color. That’s because there was an exception thrown.</p><p>If you click that trace then you’ll see a similar picture</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/zipkin-error-traces.png" alt="Error Traces"></div></div><p>Then if you click on one of the spans you’ll see the following</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/zipkin-error-trace-screenshot.png" alt="Error Traces Info propagation"></div></div><p>As you can see you can easily see the reason for an error and the whole stacktrace related to it.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_live_examples" href="#_live_examples"></a>45.2.3 Live examples</h3></div></div></div><div class="figure"><a name="d0e11224" href="#d0e11224"></a><p class="title"><b>Figure 45.1. Click Pivotal Web Services icon to see it live!</b></p><div class="figure-contents"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/pws.png" alt="Zipkin deployed on Pivotal Web Services"></div></div></div><br class="figure-break"><p>The dependency graph in Zipkin would look like this:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/dependencies.png" alt="Dependencies"></div></div><div class="figure"><a name="d0e11242" href="#d0e11242"></a><p class="title"><b>Figure 45.2. Click Pivotal Web Services icon to see it live!</b></p><div class="figure-contents"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/pws.png" alt="Zipkin deployed on Pivotal Web Services"></div></div></div><br class="figure-break"></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_log_correlation" href="#_log_correlation"></a>45.2.4 Log correlation</h3></div></div></div><p>When grepping the logs of those four applications by trace id equal to e.g. <code class="literal">2485ec27856c56f4</code> one would get the following:</p><pre class="screen">service1.log:2016-02-26 11:15:47.561 INFO [service1,2485ec27856c56f4,2485ec27856c56f4,true] 68058 --- [nio-8081-exec-1] i.s.c.sleuth.docs.service1.Application : Hello from service1. Calling service2
|
||||
service2.log:2016-02-26 11:15:47.710 INFO [service2,2485ec27856c56f4,9aa10ee6fbde75fa,true] 68059 --- [nio-8082-exec-1] i.s.c.sleuth.docs.service2.Application : Hello from service2. Calling service3 and then service4
|
||||
service3.log:2016-02-26 11:15:47.895 INFO [service3,2485ec27856c56f4,1210be13194bfe5,true] 68060 --- [nio-8083-exec-1] i.s.c.sleuth.docs.service3.Application : Hello from service3
|
||||
service2.log:2016-02-26 11:15:47.924 INFO [service2,2485ec27856c56f4,9aa10ee6fbde75fa,true] 68059 --- [nio-8082-exec-1] i.s.c.sleuth.docs.service2.Application : Got response from service3 [Hello from service3]
|
||||
service4.log:2016-02-26 11:15:48.134 INFO [service4,2485ec27856c56f4,1b1845262ffba49d,true] 68061 --- [nio-8084-exec-1] i.s.c.sleuth.docs.service4.Application : Hello from service4
|
||||
service2.log:2016-02-26 11:15:48.156 INFO [service2,2485ec27856c56f4,9aa10ee6fbde75fa,true] 68059 --- [nio-8082-exec-1] i.s.c.sleuth.docs.service2.Application : Got response from service4 [Hello from service4]
|
||||
service1.log:2016-02-26 11:15:48.182 INFO [service1,2485ec27856c56f4,2485ec27856c56f4,true] 68058 --- [nio-8081-exec-1] i.s.c.sleuth.docs.service1.Application : Got response from service2 [Hello from service2, response from service3 [Hello from service3] and from service4 [Hello from service4]]</pre><p>If you’re using a log aggregating tool like <a class="link" href="https://www.elastic.co/products/kibana" target="_top">Kibana</a>,
|
||||
<a class="link" href="http://www.splunk.com/" target="_top">Splunk</a> etc. you can order the events that took place. An example of
|
||||
Kibana would look like this:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/kibana.png" alt="Log correlation with Kibana"></div></div><p>If you want to use <a class="link" href="https://www.elastic.co/guide/en/logstash/current/index.html" target="_top">Logstash</a> here is the Grok pattern for Logstash:</p><pre class="screen">filter {
|
||||
# pattern matching logback pattern
|
||||
grok {
|
||||
match => { "message" => "%{TIMESTAMP_ISO8601:timestamp}\s+%{LOGLEVEL:severity}\s+\[%{DATA:service},%{DATA:trace},%{DATA:span},%{DATA:exportable}\]\s+%{DATA:pid}\s+---\s+\[%{DATA:thread}\]\s+%{DATA:class}\s+:\s+%{GREEDYDATA:rest}" }
|
||||
}
|
||||
}</pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>If you want to use Grok together with the logs from Cloud Foundry you have to use this pattern:</p></td></tr></table></div><pre class="screen">filter {
|
||||
# pattern matching logback pattern
|
||||
grok {
|
||||
match => { "message" => "(?m)OUT\s+%{TIMESTAMP_ISO8601:timestamp}\s+%{LOGLEVEL:severity}\s+\[%{DATA:service},%{DATA:trace},%{DATA:span},%{DATA:exportable}\]\s+%{DATA:pid}\s+---\s+\[%{DATA:thread}\]\s+%{DATA:class}\s+:\s+%{GREEDYDATA:rest}" }
|
||||
}
|
||||
}</pre><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_json_logback_with_logstash" href="#_json_logback_with_logstash"></a>JSON Logback with Logstash</h4></div></div></div><p>Often you do not want to store your logs in a text file but in a JSON file that Logstash can immediately pick. To do that you have to do the following (for readability
|
||||
we’re passing the dependencies in the <code class="literal">groupId:artifactId:version</code> notation.</p><p><span class="strong"><strong>Dependencies setup</strong></span></p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Ensure that Logback is on the classpath (<code class="literal">ch.qos.logback:logback-core</code>)</li><li class="listitem">Add Logstash Logback encode - example for version <code class="literal">4.6</code> : <code class="literal">net.logstash.logback:logstash-logback-encoder:4.6</code></li></ul></div><p><span class="strong"><strong>Logback setup</strong></span></p><p>Below you can find an example of a Logback configuration (file named <a class="link" href="https://github.com/spring-cloud-samples/sleuth-documentation-apps/blob/master/service1/src/main/resources/logback-spring.xml" target="_top">logback-spring.xml</a>) that:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">logs information from the application in a JSON format to a <code class="literal">build/${spring.application.name}.json</code> file</li><li class="listitem">has commented out two additional appenders - console and standard log file</li><li class="listitem">has the same logging pattern as the one presented in the previous section</li></ul></div><pre class="programlisting"><span class="hl-directive" style="color: maroon"><?xml version="1.0" encoding="UTF-8"?></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><configuration></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><include</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">resource</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"org/springframework/boot/logging/logback/defaults.xml"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">/></span>
|
||||
​
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><springProperty</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">scope</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"context"</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">name</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"springAppName"</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">source</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"spring.application.name"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">/></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- Example for logging into the build folder of your project --></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><property</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">name</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"LOG_FILE"</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">value</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"${BUILD_FOLDER:-build}/${springAppName}"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">/></span>​
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- You can override this to have a custom pattern --></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><property</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">name</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"CONSOLE_LOG_PATTERN"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">value</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">/></span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- Appender to log to console --></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><appender</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">name</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"console"</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">class</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"ch.qos.logback.core.ConsoleAppender"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><filter</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">class</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"ch.qos.logback.classic.filter.ThresholdFilter"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- Minimum logging level to be presented in the console logs--></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><level></span>DEBUG<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></level></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></filter></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><encoder></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><pattern></span>${CONSOLE_LOG_PATTERN}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></pattern></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><charset></span>utf8<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></charset></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></encoder></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></appender></span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- Appender to log to file --></span>​
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><appender</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">name</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"flatfile"</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">class</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"ch.qos.logback.core.rolling.RollingFileAppender"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><file></span>${LOG_FILE}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></file></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><rollingPolicy</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">class</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"ch.qos.logback.core.rolling.TimeBasedRollingPolicy"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><fileNamePattern></span>${LOG_FILE}.%d{yyyy-MM-dd}.gz<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></fileNamePattern></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><maxHistory></span>7<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></maxHistory></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></rollingPolicy></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><encoder></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><pattern></span>${CONSOLE_LOG_PATTERN}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></pattern></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><charset></span>utf8<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></charset></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></encoder></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></appender></span>
|
||||
​
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- Appender to log to file in a JSON format --></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><appender</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">name</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"logstash"</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">class</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"ch.qos.logback.core.rolling.RollingFileAppender"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><file></span>${LOG_FILE}.json<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></file></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><rollingPolicy</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">class</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"ch.qos.logback.core.rolling.TimeBasedRollingPolicy"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><fileNamePattern></span>${LOG_FILE}.json.%d{yyyy-MM-dd}.gz<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></fileNamePattern></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><maxHistory></span>7<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></maxHistory></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></rollingPolicy></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><encoder</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">class</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><providers></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><timestamp></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><timeZone></span>UTC<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></timeZone></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></timestamp></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><pattern></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><pattern></span>
|
||||
{
|
||||
"severity": "%level",
|
||||
"service": "${springAppName:-}",
|
||||
"trace": "%X{X-B3-TraceId:-}",
|
||||
"span": "%X{X-B3-SpanId:-}",
|
||||
"parent": "%X{X-B3-ParentSpanId:-}",
|
||||
"exportable": "%X{X-Span-Export:-}",
|
||||
"pid": "${PID:-}",
|
||||
"thread": "%thread",
|
||||
"class": "%logger{40}",
|
||||
"rest": "%message"
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></pattern></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></pattern></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></providers></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></encoder></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></appender></span>
|
||||
​
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><root</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">level</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"INFO"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><appender-ref</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">ref</span>=<span xmlns:d="http://docbook.org/ns/docbook" class="hl-value">"console"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag">/></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- uncomment this to have also JSON logs --></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!--<appender-ref ref="logstash"/>--></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!--<appender-ref ref="flatfile"/>--></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></root></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></configuration></span></pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>If you’re using a custom <code class="literal">logback-spring.xml</code> then you have to pass the <code class="literal">spring.application.name</code> in
|
||||
<code class="literal">bootstrap</code> instead of <code class="literal">application</code> property file. Otherwise your custom logback file won’t read the property properly.</p></td></tr></table></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_propagating_span_context" href="#_propagating_span_context"></a>45.2.5 Propagating Span Context</h3></div></div></div><p>The span context is the state that must get propagated to any child Spans across process boundaries.
|
||||
Part of the Span Context is the Baggage. The trace and span IDs are a required part of the span context.
|
||||
Baggage is an optional part.</p><p>Baggage is a set of key:value pairs stored in the span context. Baggage travels together with the trace
|
||||
and is attached to every span. Spring Cloud Sleuth will understand that a header is baggage related if the HTTP
|
||||
header is prefixed with <code class="literal">baggage-</code> and for messaging it starts with <code class="literal">baggage_</code>.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>There’s currently no limitation of the count or size of baggage items. However, keep in mind that
|
||||
too many can decrease system throughput or increase RPC latency. In extreme cases, it could crash the app due
|
||||
to exceeding transport-level message or header capacity.</p></td></tr></table></div><p>Example of setting baggage on a span:</p><pre class="programlisting">Span initialSpan = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.createSpan(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"span"</span>);
|
||||
initialSpan.setBaggageItem(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bar"</span>);
|
||||
initialSpan.setBaggageItem(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"UPPER_CASE"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"someValue"</span>);</pre><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_baggage_vs_span_tags" href="#_baggage_vs_span_tags"></a>Baggage vs. Span Tags</h4></div></div></div><p>Baggage travels with the trace (i.e. every child span contains the baggage of its parent). Zipkin has no knowledge of
|
||||
baggage and will not even receive that information.</p><p>Tags are attached to a specific span - they are presented for that particular span only. However you
|
||||
can search by tag to find the trace, where there exists a span having the searched tag value.</p><p>If you want to be able to lookup a span based on baggage, you should add corresponding entry as a tag in the root span.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
|
||||
Span span = tracer.getCurrentSpan();
|
||||
String baggageKey = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"key"</span>;
|
||||
String baggageValue = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>;
|
||||
span.setBaggageItem(baggageKey, baggageValue);
|
||||
tracer.addTag(baggageKey, baggageValue);</pre></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_adding_to_the_project" href="#_adding_to_the_project"></a>45.3 Adding to the project</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_only_sleuth_log_correlation" href="#_only_sleuth_log_correlation"></a>45.3.1 Only Sleuth (log correlation)</h3></div></div></div><p>If you want to profit only from Spring Cloud Sleuth without the Zipkin integration just add
|
||||
the <code class="literal">spring-cloud-starter-sleuth</code> module to your project.</p><p class="primary"><b>Maven. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencyManagement></span> <a name="CO1-1" href="#CO1-1"></a><span><img src="images/callouts/1.png" alt="1" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-dependencies<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${release.train.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><type></span>pom<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></type></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>import<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencyManagement></span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span> <a name="CO1-2" href="#CO1-2"></a><span><img src="images/callouts/2.png" alt="2" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-starter-sleuth<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre><p class="primary">
|
||||
</p><div class="calloutlist"><table border="0" summary="Callout list"><tr><td width="5%" valign="top" align="left"><p><a href="#CO1-1"><span><img src="images/callouts/1.png" alt="1" border="0"></span></a> </p></td><td valign="top" align="left"><p>In order not to pick versions by yourself it’s much better if you add the dependency management via
|
||||
the Spring BOM</p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO1-2"><span><img src="images/callouts/2.png" alt="2" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add the dependency to <code class="literal">spring-cloud-starter-sleuth</code></p></td></tr></table></div><p class="secondary"><b>Gradle. </b>
|
||||
</p><pre class="programlisting">dependencyManagement { <a name="CO2-1" href="#CO2-1"></a><span><img src="images/callouts/1.png" alt="1" border="0"></span>
|
||||
imports {
|
||||
mavenBom <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-dependencies:${releaseTrainVersion}"</span>
|
||||
}
|
||||
}
|
||||
|
||||
dependencies { <a name="CO2-2" href="#CO2-2"></a><span><img src="images/callouts/2.png" alt="2" border="0"></span>
|
||||
compile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-starter-sleuth"</span>
|
||||
}</pre><p class="secondary">
|
||||
</p><div class="calloutlist"><table border="0" summary="Callout list"><tr><td width="5%" valign="top" align="left"><p><a href="#CO2-1"><span><img src="images/callouts/1.png" alt="1" border="0"></span></a> </p></td><td valign="top" align="left"><p>In order not to pick versions by yourself it’s much better if you add the dependency management via
|
||||
the Spring BOM</p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO2-2"><span><img src="images/callouts/2.png" alt="2" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add the dependency to <code class="literal">spring-cloud-starter-sleuth</code></p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_sleuth_with_zipkin_via_http" href="#_sleuth_with_zipkin_via_http"></a>45.3.2 Sleuth with Zipkin via HTTP</h3></div></div></div><p>If you want both Sleuth and Zipkin just add the <code class="literal">spring-cloud-starter-zipkin</code> dependency.</p><p class="primary"><b>Maven. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencyManagement></span> <a name="CO3-1" href="#CO3-1"></a><span><img src="images/callouts/1.png" alt="1" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-dependencies<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${release.train.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><type></span>pom<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></type></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>import<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencyManagement></span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span> <a name="CO3-2" href="#CO3-2"></a><span><img src="images/callouts/2.png" alt="2" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-starter-zipkin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre><p class="primary">
|
||||
</p><div class="calloutlist"><table border="0" summary="Callout list"><tr><td width="5%" valign="top" align="left"><p><a href="#CO3-1"><span><img src="images/callouts/1.png" alt="1" border="0"></span></a> </p></td><td valign="top" align="left"><p>In order not to pick versions by yourself it’s much better if you add the dependency management via
|
||||
the Spring BOM</p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO3-2"><span><img src="images/callouts/2.png" alt="2" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add the dependency to <code class="literal">spring-cloud-starter-zipkin</code></p></td></tr></table></div><p class="secondary"><b>Gradle. </b>
|
||||
</p><pre class="programlisting">dependencyManagement { <a name="CO4-1" href="#CO4-1"></a><span><img src="images/callouts/1.png" alt="1" border="0"></span>
|
||||
imports {
|
||||
mavenBom <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-dependencies:${releaseTrainVersion}"</span>
|
||||
}
|
||||
}
|
||||
|
||||
dependencies { <a name="CO4-2" href="#CO4-2"></a><span><img src="images/callouts/2.png" alt="2" border="0"></span>
|
||||
compile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-starter-zipkin"</span>
|
||||
}</pre><p class="secondary">
|
||||
</p><div class="calloutlist"><table border="0" summary="Callout list"><tr><td width="5%" valign="top" align="left"><p><a href="#CO4-1"><span><img src="images/callouts/1.png" alt="1" border="0"></span></a> </p></td><td valign="top" align="left"><p>In order not to pick versions by yourself it’s much better if you add the dependency management via
|
||||
the Spring BOM</p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO4-2"><span><img src="images/callouts/2.png" alt="2" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add the dependency to <code class="literal">spring-cloud-starter-zipkin</code></p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_sleuth_with_zipkin_via_spring_cloud_stream" href="#_sleuth_with_zipkin_via_spring_cloud_stream"></a>45.3.3 Sleuth with Zipkin via Spring Cloud Stream</h3></div></div></div><p>If you want both Sleuth and Zipkin just add the <code class="literal">spring-cloud-sleuth-stream</code> dependency.</p><p class="primary"><b>Maven. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencyManagement></span> <a name="CO5-1" href="#CO5-1"></a><span><img src="images/callouts/1.png" alt="1" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-dependencies<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${release.train.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><type></span>pom<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></type></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>import<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencyManagement></span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span> <a name="CO5-2" href="#CO5-2"></a><span><img src="images/callouts/2.png" alt="2" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-sleuth-stream<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span> <a name="CO5-3" href="#CO5-3"></a><span><img src="images/callouts/3.png" alt="3" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-starter-sleuth<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- EXAMPLE FOR RABBIT BINDING --></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span> <a name="CO5-4" href="#CO5-4"></a><span><img src="images/callouts/4.png" alt="4" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-stream-binder-rabbit<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre><p class="primary">
|
||||
</p><div class="calloutlist"><table border="0" summary="Callout list"><tr><td width="5%" valign="top" align="left"><p><a href="#CO5-1"><span><img src="images/callouts/1.png" alt="1" border="0"></span></a> </p></td><td valign="top" align="left"><p>In order not to pick versions by yourself it’s much better if you add the dependency management via
|
||||
the Spring BOM</p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO5-2"><span><img src="images/callouts/2.png" alt="2" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add the dependency to <code class="literal">spring-cloud-sleuth-stream</code></p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO5-3"><span><img src="images/callouts/3.png" alt="3" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add the dependency to <code class="literal">spring-cloud-starter-sleuth</code> - that way all dependant dependencies will be downloaded</p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO5-4"><span><img src="images/callouts/4.png" alt="4" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add a binder (e.g. Rabbit binder) to tell Spring Cloud Stream what it should bind to</p></td></tr></table></div><p class="secondary"><b>Gradle. </b>
|
||||
</p><pre class="programlisting">dependencyManagement { <a name="CO6-1" href="#CO6-1"></a><span><img src="images/callouts/1.png" alt="1" border="0"></span>
|
||||
imports {
|
||||
mavenBom <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-dependencies:${releaseTrainVersion}"</span>
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-sleuth-stream"</span> <a name="CO6-2" href="#CO6-2"></a><span><img src="images/callouts/2.png" alt="2" border="0"></span>
|
||||
compile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-starter-sleuth"</span> <a name="CO6-3" href="#CO6-3"></a><span><img src="images/callouts/3.png" alt="3" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Example for Rabbit binding</span>
|
||||
compile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-stream-binder-rabbit"</span> <a name="CO6-4" href="#CO6-4"></a><span><img src="images/callouts/4.png" alt="4" border="0"></span>
|
||||
}</pre><p class="secondary">
|
||||
</p><div class="calloutlist"><table border="0" summary="Callout list"><tr><td width="5%" valign="top" align="left"><p><a href="#CO6-1"><span><img src="images/callouts/1.png" alt="1" border="0"></span></a> </p></td><td valign="top" align="left"><p>In order not to pick versions by yourself it’s much better if you add the dependency management via
|
||||
the Spring BOM</p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO6-2"><span><img src="images/callouts/2.png" alt="2" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add the dependency to <code class="literal">spring-cloud-sleuth-stream</code></p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO6-3"><span><img src="images/callouts/3.png" alt="3" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add the dependency to <code class="literal">spring-cloud-starter-sleuth</code> - that way all dependant dependencies will be downloaded</p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO6-4"><span><img src="images/callouts/4.png" alt="4" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add a binder (e.g. Rabbit binder) to tell Spring Cloud Stream what it should bind to</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_spring_cloud_sleuth_stream_zipkin_collector" href="#_spring_cloud_sleuth_stream_zipkin_collector"></a>45.3.4 Spring Cloud Sleuth Stream Zipkin Collector</h3></div></div></div><p>If you want to start a Spring Cloud Sleuth Stream Zipkin collector just add the <code class="literal">spring-cloud-sleuth-zipkin-stream</code>
|
||||
dependency</p><p class="primary"><b>Maven. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencyManagement></span> <a name="CO7-1" href="#CO7-1"></a><span><img src="images/callouts/1.png" alt="1" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-dependencies<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${release.train.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><type></span>pom<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></type></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>import<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencyManagement></span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span> <a name="CO7-2" href="#CO7-2"></a><span><img src="images/callouts/2.png" alt="2" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-sleuth-zipkin-stream<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span> <a name="CO7-3" href="#CO7-3"></a><span><img src="images/callouts/3.png" alt="3" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-starter-sleuth<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- EXAMPLE FOR RABBIT BINDING --></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span> <a name="CO7-4" href="#CO7-4"></a><span><img src="images/callouts/4.png" alt="4" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-stream-binder-rabbit<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre><p class="primary">
|
||||
</p><div class="calloutlist"><table border="0" summary="Callout list"><tr><td width="5%" valign="top" align="left"><p><a href="#CO7-1"><span><img src="images/callouts/1.png" alt="1" border="0"></span></a> </p></td><td valign="top" align="left"><p>In order not to pick versions by yourself it’s much better if you add the dependency management via
|
||||
the Spring BOM</p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO7-2"><span><img src="images/callouts/2.png" alt="2" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add the dependency to <code class="literal">spring-cloud-sleuth-zipkin-stream</code></p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO7-3"><span><img src="images/callouts/3.png" alt="3" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add the dependency to <code class="literal">spring-cloud-starter-sleuth</code> - that way all dependant dependencies will be downloaded</p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO7-4"><span><img src="images/callouts/4.png" alt="4" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add a binder (e.g. Rabbit binder) to tell Spring Cloud Stream what it should bind to</p></td></tr></table></div><p class="secondary"><b>Gradle. </b>
|
||||
</p><pre class="programlisting">dependencyManagement { <a name="CO8-1" href="#CO8-1"></a><span><img src="images/callouts/1.png" alt="1" border="0"></span>
|
||||
imports {
|
||||
mavenBom <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-dependencies:${releaseTrainVersion}"</span>
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-sleuth-zipkin-stream"</span> <a name="CO8-2" href="#CO8-2"></a><span><img src="images/callouts/2.png" alt="2" border="0"></span>
|
||||
compile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-starter-sleuth"</span> <a name="CO8-3" href="#CO8-3"></a><span><img src="images/callouts/3.png" alt="3" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Example for Rabbit binding</span>
|
||||
compile <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"org.springframework.cloud:spring-cloud-stream-binder-rabbit"</span> <a name="CO8-4" href="#CO8-4"></a><span><img src="images/callouts/4.png" alt="4" border="0"></span>
|
||||
}</pre><p class="secondary">
|
||||
</p><div class="calloutlist"><table border="0" summary="Callout list"><tr><td width="5%" valign="top" align="left"><p><a href="#CO8-1"><span><img src="images/callouts/1.png" alt="1" border="0"></span></a> </p></td><td valign="top" align="left"><p>In order not to pick versions by yourself it’s much better if you add the dependency management via
|
||||
the Spring BOM</p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO8-2"><span><img src="images/callouts/2.png" alt="2" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add the dependency to <code class="literal">spring-cloud-sleuth-zipkin-stream</code></p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO8-3"><span><img src="images/callouts/3.png" alt="3" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add the dependency to <code class="literal">spring-cloud-starter-sleuth</code> - that way all dependant dependencies will be downloaded</p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO8-4"><span><img src="images/callouts/4.png" alt="4" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add a binder (e.g. Rabbit binder) to tell Spring Cloud Stream what it should bind to</p></td></tr></table></div><p>and then just annotate your main class with <code class="literal">@EnableZipkinStreamServer</code> annotation:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> example;
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.boot.SpringApplication;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">import</span> org.springframework.cloud.sleuth.zipkin.stream.EnableZipkinStreamServer;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootApplication</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableZipkinStreamServer</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> ZipkinStreamServerApplication {
|
||||
|
||||
<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">throws</span> Exception {
|
||||
SpringApplication.run(ZipkinStreamServerApplication.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>, args);
|
||||
}
|
||||
|
||||
}</pre></div></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_sleuth.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_sleuth.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__additional_resources.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Part VII. Spring Cloud Sleuth </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 46. Additional resources</td></tr></table></div></body></html>
|
||||
3
Dalston.SR5/multi/multi__links.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>88. Links</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_contract.html" title="Part XII. Spring Cloud Contract"><link rel="prev" href="multi__spring_cloud_contract_wiremock.html" title="87. Spring Cloud Contract WireMock"><link rel="next" href="multi__spring_cloud_vault.html" title="Part XIII. Spring Cloud Vault"></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">88. Links</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__spring_cloud_contract_wiremock.html">Prev</a> </td><th width="60%" align="center">Part XII. Spring Cloud Contract</th><td width="20%" align="right"> <a accesskey="n" href="multi__spring_cloud_vault.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_links" href="#_links"></a>88. Links</h2></div></div></div><p>Here you can find interesting links related to Spring Cloud Contract Verifier:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="https://github.com/spring-cloud/spring-cloud-contract/" target="_top">Spring Cloud Contract Github Repository</a></li><li class="listitem"><a class="link" href="https://github.com/spring-cloud-samples/spring-cloud-contract-samples/" target="_top">Spring Cloud Contract Samples</a></li><li class="listitem"><a class="link" href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html" target="_top">Spring Cloud Contract Documentation</a></li><li class="listitem"><a class="link" href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html/deprecated" target="_top">Accurest Legacy Documentation</a></li><li class="listitem"><a class="link" href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html/#spring-cloud-contract-stub-runner" target="_top">Spring Cloud Contract Stub Runner Documentation</a></li><li class="listitem"><a class="link" href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html/#stub-runner-for-messaging" target="_top">Spring Cloud Contract Stub Runner Messaging Documentation</a></li><li class="listitem"><a class="link" href="https://gitter.im/spring-cloud/spring-cloud-contract" target="_top">Spring Cloud Contract Gitter</a></li><li class="listitem"><a class="link" href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract-maven-plugin/" target="_top">Spring Cloud Contract Maven Plugin</a></li><li class="listitem"><a class="link" href="https://www.youtube.com/watch?v=sAAklvxmPmk" target="_top">Spring Cloud Contract WJUG Presentation by Marcin Grzejszczak</a></li></ul></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_contract_wiremock.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_contract.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__spring_cloud_vault.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">87. Spring Cloud Contract WireMock </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> Part XIII. Spring Cloud Vault</td></tr></table></div></body></html>
|
||||
34
Dalston.SR5/multi/multi__main_concepts.html
Normal file
@@ -0,0 +1,34 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>24. Main Concepts</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_stream.html" title="Part IV. Spring Cloud Stream"><link rel="prev" href="multi__introducing_spring_cloud_stream.html" title="23. Introducing Spring Cloud Stream"><link rel="next" href="multi__programming_model.html" title="25. Programming Model"></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">24. Main Concepts</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__introducing_spring_cloud_stream.html">Prev</a> </td><th width="60%" align="center">Part IV. Spring Cloud Stream</th><td width="20%" align="right"> <a accesskey="n" href="multi__programming_model.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_main_concepts" href="#_main_concepts"></a>24. Main Concepts</h2></div></div></div><p>Spring Cloud Stream provides a number of abstractions and primitives that simplify the writing of message-driven microservice applications.
|
||||
This section gives an overview of the following:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Spring Cloud Stream’s application model</li><li class="listitem">The Binder abstraction</li><li class="listitem">Persistent publish-subscribe support</li><li class="listitem">Consumer group support</li><li class="listitem">Partitioning support</li><li class="listitem">A pluggable Binder API</li></ul></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_application_model" href="#_application_model"></a>24.1 Application Model</h2></div></div></div><p>A Spring Cloud Stream application consists of a middleware-neutral core.
|
||||
The application communicates with the outside world through input and output <span class="emphasis"><em>channels</em></span> injected into it by Spring Cloud Stream.
|
||||
Channels are connected to external brokers through middleware-specific Binder implementations.</p><div class="figure"><a name="d0e5821" href="#d0e5821"></a><p class="title"><b>Figure 24.1. Spring Cloud Stream Application</b></p><div class="figure-contents"><div class="mediaobject"><img src="images/SCSt-with-binder.png" alt="SCSt with binder"></div></div></div><br class="figure-break"><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_fat_jar" href="#_fat_jar"></a>24.1.1 Fat JAR</h3></div></div></div><p>Spring Cloud Stream applications can be run in standalone mode from your IDE for testing.
|
||||
To run a Spring Cloud Stream application in production, you can create an executable (or "fat") JAR by using the standard Spring Boot tooling provided for Maven or Gradle.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_the_binder_abstraction" href="#_the_binder_abstraction"></a>24.2 The Binder Abstraction</h2></div></div></div><p>Spring Cloud Stream provides Binder implementations for <a class="link" href="https://github.com/spring-cloud/spring-cloud-stream/tree/master/spring-cloud-stream-binders/spring-cloud-stream-binder-kafka" target="_top">Kafka</a> and <a class="link" href="https://github.com/spring-cloud/spring-cloud-stream/tree/master/spring-cloud-stream-binders/spring-cloud-stream-binder-rabbit" target="_top">Rabbit MQ</a>.
|
||||
Spring Cloud Stream also includes a <a class="link" href="https://github.com/spring-cloud/spring-cloud-stream/blob/master/spring-cloud-stream-test-support/src/main/java/org/springframework/cloud/stream/test/binder/TestSupportBinder.java" target="_top">TestSupportBinder</a>, which leaves a channel unmodified so that tests can interact with channels directly and reliably assert on what is received.
|
||||
You can use the extensible API to write your own Binder.</p><p>Spring Cloud Stream uses Spring Boot for configuration, and the Binder abstraction makes it possible for a Spring Cloud Stream application to be flexible in how it connects to middleware.
|
||||
For example, deployers can dynamically choose, at runtime, the destinations (e.g., the Kafka topics or RabbitMQ exchanges) to which channels connect.
|
||||
Such configuration can be provided through external configuration properties and in any form supported by Spring Boot (including application arguments, environment variables, and <code class="literal">application.yml</code> or <code class="literal">application.properties</code> files).
|
||||
In the sink example from the <a class="xref" href="multi__introducing_spring_cloud_stream.html" title="23. Introducing Spring Cloud Stream">Chapter 23, <i>Introducing Spring Cloud Stream</i></a> section, setting the application property <code class="literal">spring.cloud.stream.bindings.input.destination</code> to <code class="literal">raw-sensor-data</code> will cause it to read from the <code class="literal">raw-sensor-data</code> Kafka topic, or from a queue bound to the <code class="literal">raw-sensor-data</code> RabbitMQ exchange.</p><p>Spring Cloud Stream automatically detects and uses a binder found on the classpath.
|
||||
You can easily use different types of middleware with the same code: just include a different binder at build time.
|
||||
For more complex use cases, you can also package multiple binders with your application and have it choose the binder, and even whether to use different binders for different channels, at runtime.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_persistent_publish_subscribe_support" href="#_persistent_publish_subscribe_support"></a>24.3 Persistent Publish-Subscribe Support</h2></div></div></div><p>Communication between applications follows a publish-subscribe model, where data is broadcast through shared topics.
|
||||
This can be seen in the following figure, which shows a typical deployment for a set of interacting Spring Cloud Stream applications.</p><div class="figure"><a name="d0e5878" href="#d0e5878"></a><p class="title"><b>Figure 24.2. Spring Cloud Stream Publish-Subscribe</b></p><div class="figure-contents"><div class="mediaobject"><img src="images/SCSt-sensors.png" alt="SCSt sensors"></div></div></div><br class="figure-break"><p>Data reported by sensors to an HTTP endpoint is sent to a common destination named <code class="literal">raw-sensor-data</code>.
|
||||
From the destination, it is independently processed by a microservice application that computes time-windowed averages and by another microservice application that ingests the raw data into HDFS.
|
||||
In order to process the data, both applications declare the topic as their input at runtime.</p><p>The publish-subscribe communication model reduces the complexity of both the producer and the consumer, and allows new applications to be added to the topology without disruption of the existing flow.
|
||||
For example, downstream from the average-calculating application, you can add an application that calculates the highest temperature values for display and monitoring.
|
||||
You can then add another application that interprets the same flow of averages for fault detection.
|
||||
Doing all communication through shared topics rather than point-to-point queues reduces coupling between microservices.</p><p>While the concept of publish-subscribe messaging is not new, Spring Cloud Stream takes the extra step of making it an opinionated choice for its application model.
|
||||
By using native middleware support, Spring Cloud Stream also simplifies use of the publish-subscribe model across different platforms.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="consumer-groups" href="#consumer-groups"></a>24.4 Consumer Groups</h2></div></div></div><p>While the publish-subscribe model makes it easy to connect applications through shared topics, the ability to scale up by creating multiple instances of a given application is equally important.
|
||||
When doing this, different instances of an application are placed in a competing consumer relationship, where only one of the instances is expected to handle a given message.</p><p>Spring Cloud Stream models this behavior through the concept of a <span class="emphasis"><em>consumer group</em></span>.
|
||||
(Spring Cloud Stream consumer groups are similar to and inspired by Kafka consumer groups.)
|
||||
Each consumer binding can use the <code class="literal">spring.cloud.stream.bindings.<channelName>.group</code> property to specify a group name.
|
||||
For the consumers shown in the following figure, this property would be set as <code class="literal">spring.cloud.stream.bindings.<channelName>.group=hdfsWrite</code> or <code class="literal">spring.cloud.stream.bindings.<channelName>.group=average</code>.</p><div class="figure"><a name="d0e5915" href="#d0e5915"></a><p class="title"><b>Figure 24.3. Spring Cloud Stream Consumer Groups</b></p><div class="figure-contents"><div class="mediaobject"><img src="images/SCSt-groups.png" alt="SCSt groups"></div></div></div><br class="figure-break"><p>All groups which subscribe to a given destination receive a copy of published data, but only one member of each group receives a given message from that destination.
|
||||
By default, when a group is not specified, Spring Cloud Stream assigns the application to an anonymous and independent single-member consumer group that is in a publish-subscribe relationship with all other consumer groups.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="durability" href="#durability"></a>24.4.1 Durability</h3></div></div></div><p>Consistent with the opinionated application model of Spring Cloud Stream, consumer group subscriptions are <span class="emphasis"><em>durable</em></span>.
|
||||
That is, a binder implementation ensures that group subscriptions are persistent, and once at least one subscription for a group has been created, the group will receive messages, even if they are sent while all applications in the group are stopped.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Anonymous subscriptions are non-durable by nature.
|
||||
For some binder implementations (e.g., RabbitMQ), it is possible to have non-durable group subscriptions.</p></td></tr></table></div><p>In general, it is preferable to always specify a consumer group when binding an application to a given destination.
|
||||
When scaling up a Spring Cloud Stream application, you must specify a consumer group for each of its input bindings.
|
||||
This prevents the application’s instances from receiving duplicate messages (unless that behavior is desired, which is unusual).</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="partitioning" href="#partitioning"></a>24.5 Partitioning Support</h2></div></div></div><p>Spring Cloud Stream provides support for <span class="emphasis"><em>partitioning</em></span> data between multiple instances of a given application.
|
||||
In a partitioned scenario, the physical communication medium (e.g., the broker topic) is viewed as being structured into multiple partitions.
|
||||
One or more producer application instances send data to multiple consumer application instances and ensure that data identified by common characteristics are processed by the same consumer instance.</p><p>Spring Cloud Stream provides a common abstraction for implementing partitioned processing use cases in a uniform fashion.
|
||||
Partitioning can thus be used whether the broker itself is naturally partitioned (e.g., Kafka) or not (e.g., RabbitMQ).</p><div class="figure"><a name="d0e5949" href="#d0e5949"></a><p class="title"><b>Figure 24.4. Spring Cloud Stream Partitioning</b></p><div class="figure-contents"><div class="mediaobject"><img src="images/SCSt-partitioning.png" alt="SCSt partitioning"></div></div></div><br class="figure-break"><p>Partitioning is a critical concept in stateful processing, where it is critiical, for either performance or consistency reasons, to ensure that all related data is processed together.
|
||||
For example, in the time-windowed average calculation example, it is important that all measurements from any given sensor are processed by the same application instance.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>To set up a partitioned processing scenario, you must configure both the data-producing and the data-consuming ends.</p></td></tr></table></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__introducing_spring_cloud_stream.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_stream.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__programming_model.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">23. Introducing Spring Cloud Stream </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 25. Programming Model</td></tr></table></div></body></html>
|
||||
@@ -0,0 +1,47 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>52. Managing spans with annotations</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_sleuth.html" title="Part VII. Spring Cloud Sleuth"><link rel="prev" href="multi__naming_spans.html" title="51. Naming spans"><link rel="next" href="multi__customizations.html" title="53. Customizations"></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">52. Managing spans with annotations</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__naming_spans.html">Prev</a> </td><th width="60%" align="center">Part VII. Spring Cloud Sleuth</th><td width="20%" align="right"> <a accesskey="n" href="multi__customizations.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_managing_spans_with_annotations" href="#_managing_spans_with_annotations"></a>52. Managing spans with annotations</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_rationale" href="#_rationale"></a>52.1 Rationale</h2></div></div></div><p>The main arguments for this features are</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p class="simpara">api-agnostic means to collaborate with a span</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">use of annotations allows users to add to a span with no library dependency on a span api.
|
||||
This allows Sleuth to change its core api less impact to user code.</li></ul></div></li><li class="listitem"><p class="simpara">reduced surface area for basic span operations.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">without this feature one has to use the span api, which has lifecycle commands that
|
||||
could be used incorrectly. By only exposing scope, tag and log functionality, users can
|
||||
collaborate without accidentally breaking span lifecycle.</li></ul></div></li><li class="listitem"><p class="simpara">collaboration with runtime generated code</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">with libraries such as Spring Data / Feign the implementations of interfaces are generated
|
||||
at runtime thus span wrapping of objects was tedious. Now you can provide annotations
|
||||
over interfaces and arguments of those interfaces</li></ul></div></li></ul></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_creating_new_spans" href="#_creating_new_spans"></a>52.2 Creating new spans</h2></div></div></div><p>If you really don’t want to take care of creating local spans manually you can profit from the
|
||||
<code class="literal">@NewSpan</code> annotation. Also we give you the <code class="literal">@SpanTag</code> annotation to add tags in an automated
|
||||
fashion.</p><p>Let’s look at some examples of usage.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@NewSpan</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> testMethod();</pre><p>Annotating the method without any parameter will lead to a creation of a new span whose name
|
||||
will be equal to annotated method name.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@NewSpan("customNameOnTestMethod4")</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> testMethod4();</pre><p>If you provide the value in the annotation (either directly or via the <code class="literal">name</code> parameter) then
|
||||
the created span will have the name as the provided value.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// method declaration</span>
|
||||
<em><span class="hl-annotation" style="color: gray">@NewSpan(name = "customNameOnTestMethod5")</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> testMethod5(<em><span class="hl-annotation" style="color: gray">@SpanTag("testTag")</span></em> String param);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// and method execution</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.testBean.testMethod5(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"test"</span>);</pre><p>You can combine both the name and a tag. Let’s focus on the latter. In this case whatever the value of
|
||||
the annotated method’s parameter runtime value will be - that will be the value of the tag. In our sample
|
||||
the tag key will be <code class="literal">testTag</code> and the tag value will be <code class="literal">test</code>.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@NewSpan(name = "customNameOnTestMethod3")</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</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">void</span> testMethod3() {
|
||||
}</pre><p>You can place the <code class="literal">@NewSpan</code> annotation on both the class and an interface. If you override the
|
||||
interface’s method and provide a different value of the <code class="literal">@NewSpan</code> annotation then the most
|
||||
concrete one wins (in this case <code class="literal">customNameOnTestMethod3</code> will be set).</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_continuing_spans" href="#_continuing_spans"></a>52.3 Continuing spans</h2></div></div></div><p>If you want to just add tags and annotations to an existing span it’s enough
|
||||
to use the <code class="literal">@ContinueSpan</code> annotation as presented below. Note that in contrast
|
||||
with the <code class="literal">@NewSpan</code> annotation you can also add logs via the <code class="literal">log</code> parameter:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// method declaration</span>
|
||||
<em><span class="hl-annotation" style="color: gray">@ContinueSpan(log = "testMethod11")</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> testMethod11(<em><span class="hl-annotation" style="color: gray">@SpanTag("testTag11")</span></em> String param);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// method execution</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.testBean.testMethod11(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"test"</span>);</pre><p>That way the span will get continued and:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">logs with name <code class="literal">testMethod11.before</code> and <code class="literal">testMethod11.after</code> will be created</li><li class="listitem">if an exception will be thrown a log <code class="literal">testMethod11.afterFailure</code> will also be created</li><li class="listitem">tag with key <code class="literal">testTag11</code> and value <code class="literal">test</code> will be created</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_more_advanced_tag_setting" href="#_more_advanced_tag_setting"></a>52.4 More advanced tag setting</h2></div></div></div><p>There are 3 different ways to add tags to a span. All of them are controlled by the <code class="literal">SpanTag</code> annotation.
|
||||
Precedence is:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">try with the bean of <code class="literal">TagValueResolver</code> type and provided name</li><li class="listitem">if one hasn’t provided the bean name, try to evaluate an expression. We’re searching for a <code class="literal">TagValueExpressionResolver</code> bean.
|
||||
The default implementation uses SPEL expression resolution.</li><li class="listitem">if one hasn’t provided any expression to evaluate just return a <code class="literal">toString()</code> value of the parameter</li></ul></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_custom_extractor" href="#_custom_extractor"></a>52.4.1 Custom extractor</h3></div></div></div><p>The value of the tag for following method will be computed by an implementation of <code class="literal">TagValueResolver</code> interface.
|
||||
Its class name has to be passed as the value of the <code class="literal">resolver</code> attribute.</p><p>Having such an annotated method:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@NewSpan</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">void</span> getAnnotationForTagValueResolver(<em><span class="hl-annotation" style="color: gray">@SpanTag(key = "test", resolver = TagValueResolver.class)</span></em> String test) {
|
||||
}</pre><p>and such a <code class="literal">TagValueResolver</code> bean implementation</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean(name = "myCustomTagValueResolver")</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> TagValueResolver tagValueResolver() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> parameter -> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Value from myCustomTagValueResolver"</span>;
|
||||
}</pre><p>Will lead to setting of a tag value equal to <code class="literal">Value from myCustomTagValueResolver</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_resolving_expressions_for_value" href="#_resolving_expressions_for_value"></a>52.4.2 Resolving expressions for value</h3></div></div></div><p>Having such an annotated method:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@NewSpan</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">void</span> getAnnotationForTagValueExpression(<em><span class="hl-annotation" style="color: gray">@SpanTag(key = "test", expression = "length() + ' characters'")</span></em> String test) {
|
||||
}</pre><p>and no custom implementation of a <code class="literal">TagValueExpressionResolver</code> will lead to evaluation of the SPEL expression and a tag with value <code class="literal">4 characters</code> will be set on the span.
|
||||
If you want to use some other expression resolution mechanism you can create your own implementation
|
||||
of the bean.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_using_tostring_method" href="#_using_tostring_method"></a>52.4.3 Using toString method</h3></div></div></div><p>Having such an annotated method:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@NewSpan</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">void</span> getAnnotationForArgumentToString(<em><span class="hl-annotation" style="color: gray">@SpanTag("test")</span></em> Long param) {
|
||||
}</pre><p>if executed with a value of <code class="literal">15</code> will lead to setting of a tag with a String value of <code class="literal">"15"</code>.</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__naming_spans.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_sleuth.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__customizations.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">51. Naming spans </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 53. Customizations</td></tr></table></div></body></html>
|
||||
7
Dalston.SR5/multi/multi__metrics.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>55. Metrics</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_sleuth.html" title="Part VII. Spring Cloud Sleuth"><link rel="prev" href="multi__span_data_as_messages.html" title="54. Span Data as Messages"><link rel="next" href="multi__integrations.html" title="56. Integrations"></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">55. Metrics</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__span_data_as_messages.html">Prev</a> </td><th width="60%" align="center">Part VII. Spring Cloud Sleuth</th><td width="20%" align="right"> <a accesskey="n" href="multi__integrations.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_metrics" href="#_metrics"></a>55. Metrics</h2></div></div></div><p>Currently Spring Cloud Sleuth registers very simple metrics related to spans.
|
||||
It’s using the <a class="link" href="http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-metrics.html#production-ready-recording-metrics" target="_top">Spring Boot’s metrics support</a>
|
||||
to calculate the number of accepted and dropped spans. Each time a span gets
|
||||
sent to Zipkin the number of accepted spans will increase. If there’s an error then
|
||||
the number of dropped spans will get increased.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__span_data_as_messages.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_sleuth.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__integrations.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">54. Span Data as Messages </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 56. Integrations</td></tr></table></div></body></html>
|
||||
77
Dalston.SR5/multi/multi__metrics_emitter.html
Normal file
@@ -0,0 +1,77 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>33. Metrics Emitter</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_stream.html" title="Part IV. Spring Cloud Stream"><link rel="prev" href="multi__health_indicator_4.html" title="32. Health Indicator"><link rel="next" href="multi__samples.html" title="34. Samples"></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">33. Metrics Emitter</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__health_indicator_4.html">Prev</a> </td><th width="60%" align="center">Part IV. Spring Cloud Stream</th><td width="20%" align="right"> <a accesskey="n" href="multi__samples.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_metrics_emitter" href="#_metrics_emitter"></a>33. Metrics Emitter</h2></div></div></div><p>Spring Cloud Stream provides a module called <code class="literal">spring-cloud-stream-metrics</code> that can be used to emit any available metric from <a class="link" href="https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-metrics.html" target="_top">Spring Boot metrics endpoint</a> to a named channel.
|
||||
This module allow operators to collect metrics from stream applications without relying on polling their endpoints.</p><p>The module is activated when you set the destination name for metrics binding, e.g. <code class="literal">spring.cloud.stream.bindings.applicationMetrics.destination=<DESTINATION_NAME></code>.
|
||||
<code class="literal">applicationMetrics</code> can be configured in a similar fashion to any other producer binding.
|
||||
The default <code class="literal">contentType</code> setting of <code class="literal">applicationMetrics</code> is <code class="literal">application/json</code>.</p><p>The following properties can be used for customizing the emission of metrics:</p><div class="variablelist"><dl class="variablelist"><dt><span class="term">spring.cloud.stream.metrics.key</span></dt><dd>The name of the metric being emitted. Should be an unique value per application.</dd><dt><span class="term">Default</span></dt><dd><code class="literal">${spring.application.name:${vcap.application.name:${spring.config.name:application}}}</code></dd><dt><span class="term">spring.cloud.stream.metrics.prefix</span></dt><dd><p class="simpara">Prefix string to be prepended to the metrics key.</p><p class="simpara">Default: ``</p></dd><dt><span class="term">spring.cloud.stream.metrics.properties</span></dt><dd><p class="simpara">Just like the <code class="literal">includes</code> option, it allows white listing application properties that will be added to the metrics payload</p><p class="simpara">Default: null.</p></dd></dl></div><p>A detailed overview of the metrics export process can be found in the <a class="link" href="https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-metrics.html#production-ready-metric-writers" target="_top">Spring Boot reference documentation</a>.
|
||||
Spring Cloud Stream provides a metric exporter named <code class="literal">application</code> that can be configured via regular <a class="link" href="https://github.com/spring-projects/spring-boot/blob/1.5.x/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/TriggerProperties.java" target="_top">Spring Boot metrics configuration properties</a>.</p><p>The exporter can be configured either by using the global Spring Boot configuration settings for exporters, or by using exporter-specific properties.
|
||||
For using the global configuration settings, the properties should be prefixed by <code class="literal">spring.metric.export</code> (e.g. <code class="literal">spring.metric.export.includes=integration**</code>).
|
||||
These configuration options will apply to all exporters (unless they have been configured differently).
|
||||
Alternatively, if it is intended to use configuration settings that are different from the other exporters (e.g. for restricting the number of metrics published), the Spring Cloud Stream provided metrics exporter can be configured using the prefix <code class="literal">spring.metrics.export.triggers.application</code> (e.g. <code class="literal">spring.metrics.export.triggers.application.includes=integration**</code>).</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Due to Spring Boot’s <a class="link" href="https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-relaxed-binding" target="_top">relaxed binding</a> the value of a property being included can be slightly different than the original value.</p><p>As a rule of thumb, the metric exporter will attempt to normalize all the properties in a consistent format using the dot notation (e.g. <code class="literal">JAVA_HOME</code> becomes <code class="literal">java.home</code>).</p><p>The goal of normalization is to make downstream consumers of those metrics capable of receiving property names consistently, regardless of how they are set on the monitored application (<code class="literal">--spring.application.name</code> or <code class="literal">SPRING_APPLICATION_NAME</code> would always yield <code class="literal">spring.application.name</code>).</p></td></tr></table></div><p>Below is a sample of the data published to the channel in JSON format by the following command:</p><pre class="screen">java -jar time-source.jar \
|
||||
--spring.cloud.stream.bindings.applicationMetrics.destination=someMetrics \
|
||||
--spring.cloud.stream.metrics.properties=spring.application** \
|
||||
--spring.metrics.export.includes=integration.channel.input**,integration.channel.output**</pre><p>The resulting JSON is:</p><pre class="programlisting">{
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"name"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"time-source"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"metrics"</span>:[
|
||||
{
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"name"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"integration.channel.output.errorRate.mean"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"value"</span>:<span class="hl-number">0.0</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"timestamp"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2017-04-11T16:56:35.790Z"</span>
|
||||
},
|
||||
{
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"name"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"integration.channel.output.errorRate.max"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"value"</span>:<span class="hl-number">0.0</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"timestamp"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2017-04-11T16:56:35.790Z"</span>
|
||||
},
|
||||
{
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"name"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"integration.channel.output.errorRate.min"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"value"</span>:<span class="hl-number">0.0</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"timestamp"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2017-04-11T16:56:35.790Z"</span>
|
||||
},
|
||||
{
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"name"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"integration.channel.output.errorRate.stdev"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"value"</span>:<span class="hl-number">0.0</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"timestamp"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2017-04-11T16:56:35.790Z"</span>
|
||||
},
|
||||
{
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"name"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"integration.channel.output.errorRate.count"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"value"</span>:<span class="hl-number">0.0</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"timestamp"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2017-04-11T16:56:35.790Z"</span>
|
||||
},
|
||||
{
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"name"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"integration.channel.output.sendCount"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"value"</span>:<span class="hl-number">6.0</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"timestamp"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2017-04-11T16:56:35.790Z"</span>
|
||||
},
|
||||
{
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"name"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"integration.channel.output.sendRate.mean"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"value"</span>:<span class="hl-number">0.994885872292989</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"timestamp"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2017-04-11T16:56:35.790Z"</span>
|
||||
},
|
||||
{
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"name"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"integration.channel.output.sendRate.max"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"value"</span>:<span class="hl-number">1.006247080013156</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"timestamp"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2017-04-11T16:56:35.790Z"</span>
|
||||
},
|
||||
{
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"name"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"integration.channel.output.sendRate.min"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"value"</span>:<span class="hl-number">1.0012035220116378</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"timestamp"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2017-04-11T16:56:35.790Z"</span>
|
||||
},
|
||||
{
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"name"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"integration.channel.output.sendRate.stdev"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"value"</span>:<span class="hl-number">6.505181111084848E-4</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"timestamp"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2017-04-11T16:56:35.790Z"</span>
|
||||
},
|
||||
{
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"name"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"integration.channel.output.sendRate.count"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"value"</span>:<span class="hl-number">6.0</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"timestamp"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2017-04-11T16:56:35.790Z"</span>
|
||||
}
|
||||
],
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"createdTime"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2017-04-11T20:56:35.790Z"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"properties"</span>:{
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"spring.application.name"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"time-source"</span>,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"spring.application.index"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"0"</span>
|
||||
}
|
||||
}</pre></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__health_indicator_4.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_stream.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__samples.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">32. Health Indicator </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 34. Samples</td></tr></table></div></body></html>
|
||||
84
Dalston.SR5/multi/multi__more_detail.html
Normal file
@@ -0,0 +1,84 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>74. More Detail</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_security.html" title="Part X. Spring Cloud Security"><link rel="prev" href="multi__quickstart.html" title="73. Quickstart"><link rel="next" href="multi__configuring_authentication_downstream_of_a_zuul_proxy.html" title="75. Configuring Authentication Downstream of a Zuul Proxy"></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">74. More Detail</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__quickstart.html">Prev</a> </td><th width="60%" align="center">Part X. Spring Cloud Security</th><td width="20%" align="right"> <a accesskey="n" href="multi__configuring_authentication_downstream_of_a_zuul_proxy.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_more_detail" href="#_more_detail"></a>74. More Detail</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_single_sign_on" href="#_single_sign_on"></a>74.1 Single Sign On</h2></div></div></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>All of the OAuth2 SSO and resource server features moved to Spring Boot
|
||||
in version 1.3. You can find documentation in the
|
||||
<a class="link" href="http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/" target="_top">Spring Boot user guide</a>.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_token_relay" href="#_token_relay"></a>74.2 Token Relay</h2></div></div></div><p>A Token Relay is where an OAuth2 consumer acts as a Client and
|
||||
forwards the incoming token to outgoing resource requests. The
|
||||
consumer can be a pure Client (like an SSO application) or a Resource
|
||||
Server.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_client_token_relay" href="#_client_token_relay"></a>74.2.1 Client Token Relay</h3></div></div></div><p>If your app is a user facing OAuth2 client (i.e. has declared
|
||||
<code class="literal">@EnableOAuth2Sso</code> or <code class="literal">@EnableOAuth2Client</code>) then it has an
|
||||
<code class="literal">OAuth2ClientContext</code> in request scope from Spring Boot. You can
|
||||
create your own <code class="literal">OAuth2RestTemplate</code> from this context and an
|
||||
autowired <code class="literal">OAuth2ProtectedResourceDetails</code>, and then the context will
|
||||
always forward the access token downstream, also refreshing the access
|
||||
token automatically if it expires. (These are features of Spring
|
||||
Security and Spring Boot.)</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Spring Boot (1.4.1) does not create an
|
||||
<code class="literal">OAuth2ProtectedResourceDetails</code> automatically if you are using
|
||||
<code class="literal">client_credentials</code> tokens. In that case you need to create your own
|
||||
<code class="literal">ClientCredentialsResourceDetails</code> and configure it with
|
||||
<code class="literal">@ConfigurationProperties("security.oauth2.client")</code>.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_client_token_relay_in_zuul_proxy" href="#_client_token_relay_in_zuul_proxy"></a>74.2.2 Client Token Relay in Zuul Proxy</h3></div></div></div><p>If your app also has a
|
||||
<a class="link" href="http://cloud.spring.io/spring-cloud.html#netflix-zuul-reverse-proxy" target="_top">Spring
|
||||
Cloud Zuul</a> embedded reverse proxy (using <code class="literal">@EnableZuulProxy</code>) then you
|
||||
can ask it to forward OAuth2 access tokens downstream to the services
|
||||
it is proxying. Thus the SSO app above can be enhanced simply like
|
||||
this:</p><p><b>app.groovy. </b>
|
||||
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Controller</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableOAuth2Sso</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableZuulProxy</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
|
||||
|
||||
}</pre><p>
|
||||
</p><p>and it will (in addition to logging the user in and grabbing a token)
|
||||
pass the authentication token downstream to the <code class="literal">/proxy/*</code>
|
||||
services. If those services are implemented with
|
||||
<code class="literal">@EnableResourceServer</code> then they will get a valid token in the
|
||||
correct header.</p><p>How does it work? The <code class="literal">@EnableOAuth2Sso</code> annotation pulls in
|
||||
<code class="literal">spring-cloud-starter-security</code> (which you could do manually in a
|
||||
traditional app), and that in turn triggers some autoconfiguration for
|
||||
a <code class="literal">ZuulFilter</code>, which itself is activated because Zuul is on the
|
||||
classpath (via <code class="literal">@EnableZuulProxy</code>). The
|
||||
<a class="link" href="https://github.com/spring-cloud/spring-cloud-security/tree/master/src/main/java/org/springframework/cloud/security/oauth2/proxy/OAuth2TokenRelayFilter.java" target="_top">filter</a>
|
||||
just extracts an access token from the currently authenticated user,
|
||||
and puts it in a request header for the downstream requests.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_resource_server_token_relay" href="#_resource_server_token_relay"></a>74.2.3 Resource Server Token Relay</h3></div></div></div><p>If your app has <code class="literal">@EnableResourceServer</code> you might want to relay the
|
||||
incoming token downstream to other services. If you use a
|
||||
<code class="literal">RestTemplate</code> to contact the downstream services then this is just a
|
||||
matter of how to create the template with the right context.</p><p>If your service uses <code class="literal">UserInfoTokenServices</code> to authenticate incoming
|
||||
tokens (i.e. it is using the <code class="literal">security.oauth2.user-info-uri</code>
|
||||
configuration), then you can simply create an <code class="literal">OAuth2RestTemplate</code>
|
||||
using an autowired <code class="literal">OAuth2ClientContext</code> (it will be populated by the
|
||||
authentication process before it hits the backend code). Equivalently
|
||||
(with Spring Boot 1.4), you could inject a
|
||||
<code class="literal">UserInfoRestTemplateFactory</code> and grab its <code class="literal">OAuth2RestTemplate</code> in
|
||||
your configuration. For example:</p><p><b>MyConfiguration.java. </b>
|
||||
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> OAuth2RestTemplate restTemplate(UserInfoRestTemplateFactory factory) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> factory.getUserInfoRestTemplate();
|
||||
}</pre><p>
|
||||
</p><p>This rest template will then have the same <code class="literal">OAuth2ClientContext</code>
|
||||
(request-scoped) that is used by the authentication filter, so you can
|
||||
use it to send requests with the same access token.</p><p>If your app is not using <code class="literal">UserInfoTokenServices</code> but is still a client
|
||||
(i.e. it declares <code class="literal">@EnableOAuth2Client</code> or <code class="literal">@EnableOAuth2Sso</code>), then
|
||||
with Spring Security Cloud any <code class="literal">OAuth2RestOperations</code> that the user
|
||||
creates from an <code class="literal">@Autowired</code> <code class="literal">@OAuth2Context</code> will also forward
|
||||
tokens. This feature is implemented by default as an MVC handler
|
||||
interceptor, so it only works in Spring MVC. If you are not using MVC
|
||||
you could use a custom filter or AOP interceptor wrapping an
|
||||
<code class="literal">AccessTokenContextRelay</code> to provide the same feature.</p><p>Here’s a basic
|
||||
example showing the use of an autowired rest template created
|
||||
elsewhere ("foo.com" is a Resource Server accepting the same tokens as
|
||||
the surrounding app):</p><p><b>MyController.java. </b>
|
||||
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> OAuth2RestOperations restTemplate;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@RequestMapping("/relay")</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String relay() {
|
||||
ResponseEntity<String> response =
|
||||
restTemplate.getForEntity(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"https://foo.com/bar"</span>, String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Success! ("</span> + response.getBody() + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">")"</span>;
|
||||
}</pre><p>
|
||||
</p><p>If you don’t want to forward tokens (and that is a valid
|
||||
choice, since you might want to act as yourself, rather than the
|
||||
client that sent you the token), then you only need to create your own
|
||||
<code class="literal">OAuth2Context</code> instead of autowiring the default one.</p><p>Feign clients will also pick up an interceptor that uses the
|
||||
<code class="literal">OAuth2ClientContext</code> if it is available, so they should also do a
|
||||
token relay anywhere where a <code class="literal">RestTemplate</code> would.</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__quickstart.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_security.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__configuring_authentication_downstream_of_a_zuul_proxy.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">73. Quickstart </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 75. Configuring Authentication Downstream of a Zuul Proxy</td></tr></table></div></body></html>
|
||||
27
Dalston.SR5/multi/multi__naming_spans.html
Normal file
@@ -0,0 +1,27 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>51. Naming spans</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_sleuth.html" title="Part VII. Spring Cloud Sleuth"><link rel="prev" href="multi__span_lifecycle.html" title="50. Span lifecycle"><link rel="next" href="multi__managing_spans_with_annotations.html" title="52. Managing spans with annotations"></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">51. Naming spans</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__span_lifecycle.html">Prev</a> </td><th width="60%" align="center">Part VII. Spring Cloud Sleuth</th><td width="20%" align="right"> <a accesskey="n" href="multi__managing_spans_with_annotations.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_naming_spans" href="#_naming_spans"></a>51. Naming spans</h2></div></div></div><p>Picking a span name is not a trivial task. Span name should depict an operation name. The name should
|
||||
be low cardinality (e.g. not include identifiers).</p><p>Since there is a lot of instrumentation going on some of the span names will be
|
||||
artificial like:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">controller-method-name</code> when received by a Controller with a method name <code class="literal">conrollerMethodName</code></li><li class="listitem"><code class="literal">async</code> for asynchronous operations done via wrapped <code class="literal">Callable</code> and <code class="literal">Runnable</code>.</li><li class="listitem"><code class="literal">@Scheduled</code> annotated methods will return the simple name of the class.</li></ul></div><p>Fortunately, for the asynchronous processing you can provide explicit naming.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="__spanname_annotation" href="#__spanname_annotation"></a>51.1 @SpanName annotation</h2></div></div></div><p>You can name the span explicitly via the <code class="literal">@SpanName</code> annotation.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@SpanName("calculateTax")</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> TaxCountingRunnable <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">implements</span> Runnable {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</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">void</span> run() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// perform logic</span>
|
||||
}
|
||||
}</pre><p>In this case, when processed in the following manner:</p><pre class="programlisting">Runnable runnable = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceRunnable(tracer, spanNamer, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TaxCountingRunnable());
|
||||
Future<?> future = executorService.submit(runnable);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// ... some additional logic ...</span>
|
||||
future.get();</pre><p>The span will be named <code class="literal">calculateTax</code>.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_tostring_method" href="#_tostring_method"></a>51.2 toString() method</h2></div></div></div><p>It’s pretty rare to create separate classes for <code class="literal">Runnable</code> or <code class="literal">Callable</code>. Typically one creates an anonymous
|
||||
instance of those classes. You can’t annotate such classes thus to override that, if there is no <code class="literal">@SpanName</code> annotation present,
|
||||
we’re checking if the class has a custom implementation of the <code class="literal">toString()</code> method.</p><p>So executing such code:</p><pre class="programlisting">Runnable runnable = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceRunnable(tracer, spanNamer, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Runnable() {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</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">void</span> run() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// perform logic</span>
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String toString() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"calculateTax"</span>;
|
||||
}
|
||||
});
|
||||
Future<?> future = executorService.submit(runnable);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// ... some additional logic ...</span>
|
||||
future.get();</pre><p>will lead in creating a span named <code class="literal">calculateTax</code>.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__span_lifecycle.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_sleuth.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__managing_spans_with_annotations.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">50. Span lifecycle </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 52. Managing spans with annotations</td></tr></table></div></body></html>
|
||||
67
Dalston.SR5/multi/multi__polyglot_support_with_sidecar.html
Normal file
@@ -0,0 +1,67 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>20. Polyglot support with Sidecar</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_netflix.html" title="Part III. Spring Cloud Netflix"><link rel="prev" href="multi__router_and_filter_zuul.html" title="19. Router and Filter: Zuul"><link rel="next" href="multi_netflix-rxjava-springmvc.html" title="21. RxJava with Spring MVC"></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">20. Polyglot support with Sidecar</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__router_and_filter_zuul.html">Prev</a> </td><th width="60%" align="center">Part III. Spring Cloud Netflix</th><td width="20%" align="right"> <a accesskey="n" href="multi_netflix-rxjava-springmvc.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_polyglot_support_with_sidecar" href="#_polyglot_support_with_sidecar"></a>20. Polyglot support with Sidecar</h2></div></div></div><p>Do you have non-jvm languages you want to take advantage of Eureka, Ribbon and
|
||||
Config Server? The Spring Cloud Netflix Sidecar was inspired by
|
||||
<a class="link" href="https://github.com/Netflix/Prana" target="_top">Netflix Prana</a>. It includes a simple http api
|
||||
to get all of the instances (ie host and port) for a given service. You can
|
||||
also proxy service calls through an embedded Zuul proxy which gets its route
|
||||
entries from Eureka. The Spring Cloud Config Server can be accessed directly
|
||||
via host lookup or through the Zuul Proxy. The non-jvm app should implement
|
||||
a health check so the Sidecar can report to eureka if the app is up or down.</p><p>To include Sidecar in your project use the dependency with group <code class="literal">org.springframework.cloud</code>
|
||||
and artifact id <code class="literal">spring-cloud-netflix-sidecar</code>.</p><p>To enable the Sidecar, create a Spring Boot application with <code class="literal">@EnableSidecar</code>.
|
||||
This annotation includes <code class="literal">@EnableCircuitBreaker</code>, <code class="literal">@EnableDiscoveryClient</code>,
|
||||
and <code class="literal">@EnableZuulProxy</code>. Run the resulting application on the same host as the
|
||||
non-jvm application.</p><p>To configure the side car add <code class="literal">sidecar.port</code> and <code class="literal">sidecar.health-uri</code> to <code class="literal">application.yml</code>.
|
||||
The <code class="literal">sidecar.port</code> property is the port the non-jvm app is listening on. This
|
||||
is so the Sidecar can properly register the app with Eureka. The <code class="literal">sidecar.health-uri</code>
|
||||
is a uri accessible on the non-jvm app that mimicks a Spring Boot health
|
||||
indicator. It should return a json document like the following:</p><p><b>health-uri-document. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"status"</span>:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"UP"</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre><p>
|
||||
</p><p>Here is an example application.yml for a Sidecar application:</p><p><b>application.yml. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">server</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> port</span>: <span class="hl-number">5678</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spring</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> application</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: sidecar
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">sidecar</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> port</span>: <span class="hl-number">8000</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> health-uri</span>: http://localhost:<span class="hl-number">8000</span>/health.json</pre><p>
|
||||
</p><p>The api for the <code class="literal">DiscoveryClient.getInstances()</code> method is <code class="literal">/hosts/{serviceId}</code>.
|
||||
Here is an example response for <code class="literal">/hosts/customers</code> that returns two instances on
|
||||
different hosts. This api is accessible to the non-jvm app (if the sidecar is
|
||||
on port 5678) at <code class="literal"><a class="link" href="http://localhost:5678/hosts/{serviceId}" target="_top">http://localhost:5678/hosts/{serviceId}</a></code>.</p><p><b>/hosts/customers. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">[</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"host"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"myhost"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"port"</span>: <span class="hl-number">9000</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"uri"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://myhost:9000"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"serviceId"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"CUSTOMERS"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"secure"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">false</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"host"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"myhost2"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"port"</span>: <span class="hl-number">9000</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"uri"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://myhost2:9000"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"serviceId"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"CUSTOMERS"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"secure"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">false</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">]</span></pre><p>
|
||||
</p><p>The Zuul proxy automatically adds routes for each service known in eureka to
|
||||
<code class="literal">/<serviceId></code>, so the customers service is available at <code class="literal">/customers</code>. The
|
||||
Non-jvm app can access the customer service via <code class="literal"><a class="link" href="http://localhost:5678/customers" target="_top">http://localhost:5678/customers</a></code>
|
||||
(assuming the sidecar is listening on port 5678).</p><p>If the Config Server is registered with Eureka, non-jvm application can access
|
||||
it via the Zuul proxy. If the serviceId of the ConfigServer is <code class="literal">configserver</code>
|
||||
and the Sidecar is on port 5678, then it can be accessed at
|
||||
<a class="link" href="http://localhost:5678/configserver" target="_top">http://localhost:5678/configserver</a></p><p>Non-jvm app can take advantage of the Config Server’s ability to return YAML
|
||||
documents. For example, a call to <a class="link" href="http://sidecar.local.spring.io:5678/configserver/default-master.yml" target="_top">http://sidecar.local.spring.io:5678/configserver/default-master.yml</a>
|
||||
might result in a YAML document like the following</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">eureka</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> client</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> serviceUrl</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> defaultZone</span>: http://localhost:<span class="hl-number">8761</span>/eureka/
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> password</span>: password
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">info</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> description</span>: Spring Cloud Samples
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> url</span>: https://github.com/spring-cloud-samples</pre></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__router_and_filter_zuul.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_netflix.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi_netflix-rxjava-springmvc.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">19. Router and Filter: Zuul </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 21. RxJava with Spring MVC</td></tr></table></div></body></html>
|
||||
272
Dalston.SR5/multi/multi__programming_model.html
Normal file
@@ -0,0 +1,272 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>25. Programming Model</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_stream.html" title="Part IV. Spring Cloud Stream"><link rel="prev" href="multi__main_concepts.html" title="24. Main Concepts"><link rel="next" href="multi__binders.html" title="26. Binders"></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">25. Programming Model</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__main_concepts.html">Prev</a> </td><th width="60%" align="center">Part IV. Spring Cloud Stream</th><td width="20%" align="right"> <a accesskey="n" href="multi__binders.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_programming_model" href="#_programming_model"></a>25. Programming Model</h2></div></div></div><p>This section describes Spring Cloud Stream’s programming model.
|
||||
Spring Cloud Stream provides a number of predefined annotations for declaring bound input and output channels as well as how to listen to channels.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_declaring_and_binding_channels" href="#_declaring_and_binding_channels"></a>25.1 Declaring and Binding Channels</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_triggering_binding_via_literal_enablebinding_literal" href="#_triggering_binding_via_literal_enablebinding_literal"></a>25.1.1 Triggering Binding Via <code class="literal">@EnableBinding</code></h3></div></div></div><p>You can turn a Spring application into a Spring Cloud Stream application by applying the <code class="literal">@EnableBinding</code> annotation to one of the application’s configuration classes.
|
||||
The <code class="literal">@EnableBinding</code> annotation itself is meta-annotated with <code class="literal">@Configuration</code> and triggers the configuration of Spring Cloud Stream infrastructure:</p><pre class="programlisting">...
|
||||
<em><span class="hl-annotation" style="color: gray">@Import(...)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableIntegration</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <em><span class="hl-annotation" style="color: gray">@interface</span></em> EnableBinding {
|
||||
...
|
||||
Class<?>[] value() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">default</span> {};
|
||||
}</pre><p>The <code class="literal">@EnableBinding</code> annotation can take as parameters one or more interface classes that contain methods which represent bindable components (typically message channels).</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>In Spring Cloud Stream 1.0, the only supported bindable components are the Spring Messaging <code class="literal">MessageChannel</code> and its extensions <code class="literal">SubscribableChannel</code> and <code class="literal">PollableChannel</code>.
|
||||
Future versions should extend this support to other types of components, using the same mechanism.
|
||||
In this documentation, we will continue to refer to channels.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="__literal_input_literal_and_literal_output_literal" href="#__literal_input_literal_and_literal_output_literal"></a>25.1.2 <code class="literal">@Input</code> and <code class="literal">@Output</code></h3></div></div></div><p>A Spring Cloud Stream application can have an arbitrary number of input and output channels defined in an interface as <code class="literal">@Input</code> and <code class="literal">@Output</code> methods:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> Barista {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Input</span></em>
|
||||
SubscribableChannel orders();
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Output</span></em>
|
||||
MessageChannel hotDrinks();
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Output</span></em>
|
||||
MessageChannel coldDrinks();
|
||||
}</pre><p>Using this interface as a parameter to <code class="literal">@EnableBinding</code> will trigger the creation of three bound channels named <code class="literal">orders</code>, <code class="literal">hotDrinks</code>, and <code class="literal">coldDrinks</code>, respectively.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@EnableBinding(Barista.class)</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> CafeConfiguration {
|
||||
|
||||
...
|
||||
}</pre><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_customizing_channel_names" href="#_customizing_channel_names"></a>Customizing Channel Names</h4></div></div></div><p>Using the <code class="literal">@Input</code> and <code class="literal">@Output</code> annotations, you can specify a customized channel name for the channel, as shown in the following example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> Barista {
|
||||
...
|
||||
<em><span class="hl-annotation" style="color: gray">@Input("inboundOrders")</span></em>
|
||||
SubscribableChannel orders();
|
||||
}</pre><p>In this example, the created bound channel will be named <code class="literal">inboundOrders</code>.</p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="__literal_source_literal_literal_sink_literal_and_literal_processor_literal" href="#__literal_source_literal_literal_sink_literal_and_literal_processor_literal"></a><code class="literal">Source</code>, <code class="literal">Sink</code>, and <code class="literal">Processor</code></h4></div></div></div><p>For easy addressing of the most common use cases, which involve either an input channel, an output channel, or both, Spring Cloud Stream provides three predefined interfaces out of the box.</p><p><code class="literal">Source</code> can be used for an application which has a single outbound channel.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> Source {
|
||||
|
||||
String OUTPUT = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"output"</span>;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Output(Source.OUTPUT)</span></em>
|
||||
MessageChannel output();
|
||||
|
||||
}</pre><p><code class="literal">Sink</code> can be used for an application which has a single inbound channel.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> Sink {
|
||||
|
||||
String INPUT = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"input"</span>;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Input(Sink.INPUT)</span></em>
|
||||
SubscribableChannel input();
|
||||
|
||||
}</pre><p><code class="literal">Processor</code> can be used for an application which has both an inbound channel and an outbound channel.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> Processor <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> Source, Sink {
|
||||
}</pre><p>Spring Cloud Stream provides no special handling for any of these interfaces; they are only provided out of the box.</p></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_accessing_bound_channels" href="#_accessing_bound_channels"></a>25.1.3 Accessing Bound Channels</h3></div></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_injecting_the_bound_interfaces" href="#_injecting_the_bound_interfaces"></a>Injecting the Bound Interfaces</h4></div></div></div><p>For each bound interface, Spring Cloud Stream will generate a bean that implements the interface.
|
||||
Invoking a <code class="literal">@Input</code>-annotated or <code class="literal">@Output</code>-annotated method of one of these beans will return the relevant bound channel.</p><p>The bean in the following example sends a message on the output channel when its <code class="literal">hello</code> method is invoked.
|
||||
It invokes <code class="literal">output()</code> on the injected <code class="literal">Source</code> bean to retrieve the target channel.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Component</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> SendingBean {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> Source source;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> SendingBean(Source source) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.source = source;
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> sayHello(String name) {
|
||||
source.output().send(MessageBuilder.withPayload(name).build());
|
||||
}
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_injecting_channels_directly" href="#_injecting_channels_directly"></a>Injecting Channels Directly</h4></div></div></div><p>Bound channels can be also injected directly:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Component</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> SendingBean {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> MessageChannel output;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> SendingBean(MessageChannel output) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.output = output;
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> sayHello(String name) {
|
||||
output.send(MessageBuilder.withPayload(name).build());
|
||||
}
|
||||
}</pre><p>If the name of the channel is customized on the declaring annotation, that name should be used instead of the method name.
|
||||
Given the following declaration:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> CustomSource {
|
||||
...
|
||||
<em><span class="hl-annotation" style="color: gray">@Output("customOutput")</span></em>
|
||||
MessageChannel output();
|
||||
}</pre><p>The channel will be injected as shown in the following example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Component</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> SendingBean {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> MessageChannel output;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> SendingBean(<em><span class="hl-annotation" style="color: gray">@Qualifier("customOutput")</span></em> MessageChannel output) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.output = output;
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> sayHello(String name) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.output.send(MessageBuilder.withPayload(name).build());
|
||||
}
|
||||
}</pre></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_producing_and_consuming_messages" href="#_producing_and_consuming_messages"></a>25.1.4 Producing and Consuming Messages</h3></div></div></div><p>You can write a Spring Cloud Stream application using either Spring Integration annotations or Spring Cloud Stream’s <code class="literal">@StreamListener</code> annotation.
|
||||
The <code class="literal">@StreamListener</code> annotation is modeled after other Spring Messaging annotations (such as <code class="literal">@MessageMapping</code>, <code class="literal">@JmsListener</code>, <code class="literal">@RabbitListener</code>, etc.) but adds content type management and type coercion features.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_native_spring_integration_support" href="#_native_spring_integration_support"></a>Native Spring Integration Support</h4></div></div></div><p>Because Spring Cloud Stream is based on Spring Integration, Stream completely inherits Integration’s foundation and infrastructure as well as the component itself.
|
||||
For example, you can attach the output channel of a <code class="literal">Source</code> to a <code class="literal">MessageSource</code>:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@EnableBinding(Source.class)</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> TimerSource {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Value("${format}")</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> String format;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@InboundChannelAdapter(value = Source.OUTPUT, poller = @Poller(fixedDelay = "${fixedDelay}", maxMessagesPerPoll = "1"))</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> MessageSource<String> timerMessageSource() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> () -> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> GenericMessage<>(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> SimpleDateFormat(format).format(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Date()));
|
||||
}
|
||||
}</pre><p>Or you can use a processor’s channels in a transformer:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@EnableBinding(Processor.class)</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> TransformProcessor {
|
||||
<em><span class="hl-annotation" style="color: gray">@Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Object transform(String message) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> message.toUpperCase();
|
||||
}
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_spring_integration_error_channel_support" href="#_spring_integration_error_channel_support"></a>Spring Integration Error Channel Support</h4></div></div></div><p>Spring Cloud Stream supports publishing error messages received by the Spring Integration global
|
||||
error channel. Error messages sent to the <code class="literal">errorChannel</code> can be published to a specific destination
|
||||
at the broker by configuring a binding for the outbound target named <code class="literal">error</code>. For example, to
|
||||
publish error messages to a broker destination named "myErrors", provide the following property:
|
||||
<code class="literal">spring.cloud.stream.bindings.error.destination=myErrors</code></p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_using_streamlistener_for_automatic_content_type_handling" href="#_using_streamlistener_for_automatic_content_type_handling"></a>Using @StreamListener for Automatic Content Type Handling</h4></div></div></div><p>Complementary to its Spring Integration support, Spring Cloud Stream provides its own <code class="literal">@StreamListener</code> annotation, modeled after other Spring Messaging annotations (e.g. <code class="literal">@MessageMapping</code>, <code class="literal">@JmsListener</code>, <code class="literal">@RabbitListener</code>, etc.).
|
||||
The <code class="literal">@StreamListener</code> annotation provides a simpler model for handling inbound messages, especially when dealing with use cases that involve content type management and type coercion.</p><p>Spring Cloud Stream provides an extensible <code class="literal">MessageConverter</code> mechanism for handling data conversion by bound channels and for, in this case, dispatching to methods annotated with <code class="literal">@StreamListener</code>.
|
||||
The following is an example of an application which processes external <code class="literal">Vote</code> events:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@EnableBinding(Sink.class)</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> VoteHandler {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
VotingService votingService;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@StreamListener(Sink.INPUT)</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">void</span> handle(Vote vote) {
|
||||
votingService.record(vote);
|
||||
}
|
||||
}</pre><p>The distinction between <code class="literal">@StreamListener</code> and a Spring Integration <code class="literal">@ServiceActivator</code> is seen when considering an inbound <code class="literal">Message</code> that has a <code class="literal">String</code> payload and a <code class="literal">contentType</code> header of <code class="literal">application/json</code>.
|
||||
In the case of <code class="literal">@StreamListener</code>, the <code class="literal">MessageConverter</code> mechanism will use the <code class="literal">contentType</code> header to parse the <code class="literal">String</code> payload into a <code class="literal">Vote</code> object.</p><p>As with other Spring Messaging methods, method arguments can be annotated with <code class="literal">@Payload</code>, <code class="literal">@Headers</code> and <code class="literal">@Header</code>.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>For methods which return data, you must use the <code class="literal">@SendTo</code> annotation to specify the output binding destination for data returned by the method:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@EnableBinding(Processor.class)</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> TransformProcessor {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
VotingService votingService;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@StreamListener(Processor.INPUT)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@SendTo(Processor.OUTPUT)</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> VoteResult handle(Vote vote) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> votingService.record(vote);
|
||||
}
|
||||
}</pre></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_using_streamlistener_for_dispatching_messages_to_multiple_methods" href="#_using_streamlistener_for_dispatching_messages_to_multiple_methods"></a>Using @StreamListener for dispatching messages to multiple methods</h4></div></div></div><p>Since version 1.2, Spring Cloud Stream supports dispatching messages to multiple <code class="literal">@StreamListener</code> methods registered on an input channel, based on a condition.</p><p>In order to be eligible to support conditional dispatching, a method must satisfy the follow conditions:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">it must not return a value</li><li class="listitem">it must be an individual message handling method (reactive API methods are not supported)</li></ul></div><p>The condition is specified via a SpEL expression in the <code class="literal">condition</code> attribute of the annotation and is evaluated for each message.
|
||||
All the handlers that match the condition will be invoked in the same thread and no assumption must be made about the order in which the invocations take place.</p><p>An example of using <code class="literal">@StreamListener</code> with dispatching conditions can be seen below.
|
||||
In this example, all the messages bearing a header <code class="literal">type</code> with the value <code class="literal">foo</code> will be dispatched to the <code class="literal">receiveFoo</code> method, and all the messages bearing a header <code class="literal">type</code> with the value <code class="literal">bar</code> will be dispatched to the <code class="literal">receiveBar</code> method.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@EnableBinding(Sink.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableAutoConfiguration</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">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> TestPojoWithAnnotatedArguments {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@StreamListener(target = Sink.INPUT, condition = "headers['type']=='foo'")</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">void</span> receiveFoo(<em><span class="hl-annotation" style="color: gray">@Payload</span></em> FooPojo fooPojo) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// handle the message</span>
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@StreamListener(target = Sink.INPUT, condition = "headers['type']=='bar'")</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">void</span> receiveBar(<em><span class="hl-annotation" style="color: gray">@Payload</span></em> BarPojo barPojo) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// handle the message</span>
|
||||
}
|
||||
}</pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Dispatching via <code class="literal">@StreamListener</code> conditions is only supported for handlers of individual messages, and not for reactive programming support (described below).</p></td></tr></table></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_reactive_programming_support" href="#_reactive_programming_support"></a>25.1.5 Reactive Programming Support</h3></div></div></div><p>Spring Cloud Stream also supports the use of reactive APIs where incoming and outgoing data is handled as continuous data flows.
|
||||
Support for reactive APIs is available via the <code class="literal">spring-cloud-stream-reactive</code>, which needs to be added explicitly to your project.</p><p>The programming model with reactive APIs is declarative, where instead of specifying how each individual message should be handled, you can use operators that describe functional transformations from inbound to outbound data flows.</p><p>Spring Cloud Stream supports the following reactive APIs:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Reactor</li><li class="listitem">RxJava 1.x</li></ul></div><p>In the future, it is intended to support a more generic model based on Reactive Streams.</p><p>The reactive programming model is also using the <code class="literal">@StreamListener</code> annotation for setting up reactive handlers. The differences are that:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">the <code class="literal">@StreamListener</code> annotation must not specify an input or output, as they are provided as arguments and return values from the method;</li><li class="listitem">the arguments of the method must be annotated with <code class="literal">@Input</code> and <code class="literal">@Output</code> indicating which input or output will the incoming and respectively outgoing data flows connect to;</li><li class="listitem">the return value of the method, if any, will be annotated with <code class="literal">@Output</code>, indicating the input where data shall be sent.</li></ul></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Reactive programming support requires Java 1.8.</p></td></tr></table></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>As of Spring Cloud Stream 1.1.1 and later (starting with release train Brooklyn.SR2), reactive programming support requires the use of Reactor 3.0.4.RELEASE and higher.
|
||||
Earlier Reactor versions (including 3.0.1.RELEASE, 3.0.2.RELEASE and 3.0.3.RELEASE) are not supported.
|
||||
<code class="literal">spring-cloud-stream-reactive</code> will transitively retrieve the proper version, but it is possible for the project structure to manage the version of the <code class="literal">io.projectreactor:reactor-core</code> to an earlier release, especially when using Maven.
|
||||
This is the case for projects generated via Spring Initializr with Spring Boot 1.x, which will override the Reactor version to <code class="literal">2.0.8.RELEASE</code>.
|
||||
In such cases you must ensure that the proper version of the artifact is released.
|
||||
This can be simply achieved by adding a direct dependency on <code class="literal">io.projectreactor:reactor-core</code> with a version of <code class="literal">3.0.4.RELEASE</code> or later to your project.</p></td></tr></table></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The use of term <code class="literal">reactive</code> is currently referring to the reactive APIs being used and not to the execution model being reactive (i.e. the bound endpoints are still using a 'push' rather than 'pull' model). While some backpressure support is provided by the use of Reactor, we do intend on the long run to support entirely reactive pipelines by the use of native reactive clients for the connected middleware.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_reactor_based_handlers" href="#_reactor_based_handlers"></a>Reactor-based handlers</h4></div></div></div><p>A Reactor based handler can have the following argument types:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">For arguments annotated with <code class="literal">@Input</code>, it supports the Reactor type <code class="literal">Flux</code>.
|
||||
The parameterization of the inbound Flux follows the same rules as in the case of individual message handling: it can be the entire <code class="literal">Message</code>, a POJO which can be the <code class="literal">Message</code> payload, or a POJO which is the result of a transformation based on the <code class="literal">Message</code> content-type header. Multiple inputs are provided;</li><li class="listitem">For arguments annotated with <code class="literal">Output</code>, it supports the type <code class="literal">FluxSender</code> which connects a <code class="literal">Flux</code> produced by the method with an output. Generally speaking, specifying outputs as arguments is only recommended when the method can have multiple outputs;</li></ul></div><p>A Reactor based handler supports a return type of <code class="literal">Flux</code>, case in which it must be annotated with <code class="literal">@Output</code>. We recommend using the return value of the method when a single output flux is available.</p><p>Here is an example of a simple Reactor-based Processor.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@EnableBinding(Processor.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableAutoConfiguration</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">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> UppercaseTransformer {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@StreamListener</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@Output(Processor.OUTPUT)</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Flux<String> receive(<em><span class="hl-annotation" style="color: gray">@Input(Processor.INPUT)</span></em> Flux<String> input) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> input.map(s -> s.toUpperCase());
|
||||
}
|
||||
}</pre><p>The same processor using output arguments looks like this:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@EnableBinding(Processor.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableAutoConfiguration</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">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> UppercaseTransformer {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@StreamListener</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">void</span> receive(<em><span class="hl-annotation" style="color: gray">@Input(Processor.INPUT)</span></em> Flux<String> input,
|
||||
<em><span class="hl-annotation" style="color: gray">@Output(Processor.OUTPUT)</span></em> FluxSender output) {
|
||||
output.send(input.map(s -> s.toUpperCase()));
|
||||
}
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_rxjava_1_x_support" href="#_rxjava_1_x_support"></a>RxJava 1.x support</h4></div></div></div><p>RxJava 1.x handlers follow the same rules as Reactor-based one, but will use <code class="literal">Observable</code> and <code class="literal">ObservableSender</code> arguments and return types.</p><p>So the first example above will become:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@EnableBinding(Processor.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableAutoConfiguration</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">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> UppercaseTransformer {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@StreamListener</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@Output(Processor.OUTPUT)</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Observable<String> receive(<em><span class="hl-annotation" style="color: gray">@Input(Processor.INPUT)</span></em> Observable<String> input) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> input.map(s -> s.toUpperCase());
|
||||
}
|
||||
}</pre><p>The second example above will become:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@EnableBinding(Processor.class)</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableAutoConfiguration</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">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> UppercaseTransformer {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@StreamListener</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">void</span> receive(<em><span class="hl-annotation" style="color: gray">@Input(Processor.INPUT)</span></em> Observable<String> input,
|
||||
<em><span class="hl-annotation" style="color: gray">@Output(Processor.OUTPUT)</span></em> ObservableSender output) {
|
||||
output.send(input.map(s -> s.toUpperCase()));
|
||||
}
|
||||
}</pre></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_aggregation" href="#_aggregation"></a>25.1.6 Aggregation</h3></div></div></div><p>Spring Cloud Stream provides support for aggregating multiple applications together, connecting their input and output channels directly and avoiding the additional cost of exchanging messages via a broker.
|
||||
As of version 1.0 of Spring Cloud Stream, aggregation is supported only for the following types of applications:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><span class="emphasis"><em>sources</em></span> - applications with a single output channel named <code class="literal">output</code>, typically having a single binding of the type <code class="literal">org.springframework.cloud.stream.messaging.Source</code></li><li class="listitem"><span class="emphasis"><em>sinks</em></span> - applications with a single input channel named <code class="literal">input</code>, typically having a single binding of the type <code class="literal">org.springframework.cloud.stream.messaging.Sink</code></li><li class="listitem"><span class="emphasis"><em>processors</em></span> - applications with a single input channel named <code class="literal">input</code> and a single output channel named <code class="literal">output</code>, typically having a single binding of the type <code class="literal">org.springframework.cloud.stream.messaging.Processor</code>.</li></ul></div><p>They can be aggregated together by creating a sequence of interconnected applications, in which the output channel of an element in the sequence is connected to the input channel of the next element, if it exists.
|
||||
A sequence can start with either a <span class="emphasis"><em>source</em></span> or a <span class="emphasis"><em>processor</em></span>, it can contain an arbitrary number of <span class="emphasis"><em>processors</em></span> and must end with either a <span class="emphasis"><em>processor</em></span> or a <span class="emphasis"><em>sink</em></span>.</p><p>Depending on the nature of the starting and ending element, the sequence may have one or more bindable channels, as follows:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">if the sequence starts with a source and ends with a sink, all communication between the applications is direct and no channels will be bound</li><li class="listitem">if the sequence starts with a processor, then its input channel will become the <code class="literal">input</code> channel of the aggregate and will be bound accordingly</li><li class="listitem">if the sequence ends with a processor, then its output channel will become the <code class="literal">output</code> channel of the aggregate and will be bound accordingly</li></ul></div><p>Aggregation is performed using the <code class="literal">AggregateApplicationBuilder</code> utility class, as in the following example.
|
||||
Let’s consider a project in which we have source, processor and a sink, which may be defined in the project, or may be contained in one of the project’s dependencies.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Each component (source, sink or processor) in an aggregate application must be provided in a separate package if the configuration classes use <code class="literal">@SpringBootApplication</code>.
|
||||
This is required to avoid cross-talk between applications, due to the classpath scanning performed by <code class="literal">@SpringBootApplication</code> on the configuration classes inside the same package.
|
||||
In the example below, it can be seen that the Source, Processor and Sink application classes are grouped in separate packages.
|
||||
A possible alternative is to provide the source, sink or processor configuration in a separate <code class="literal">@Configuration</code> class, avoid the use of <code class="literal">@SpringBootApplication</code>/<code class="literal">@ComponentScan</code> and use those for aggregation.</p></td></tr></table></div><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> com.app.mysink;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootApplication</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableBinding(Sink.class)</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> SinkApplication {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> Logger logger = LoggerFactory.getLogger(SinkApplication.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@ServiceActivator(inputChannel=Sink.INPUT)</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">void</span> loggerSink(Object payload) {
|
||||
logger.info(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Received: "</span> + payload);
|
||||
}
|
||||
}</pre><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> com.app.myprocessor;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootApplication</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableBinding(Processor.class)</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> ProcessorApplication {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Transformer</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String loggerSink(String payload) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> payload.toUpperCase();
|
||||
}
|
||||
}</pre><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> com.app.mysource;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootApplication</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableBinding(Source.class)</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> SourceApplication {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@InboundChannelAdapter(value = Source.OUTPUT)</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String timerMessageSource() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> SimpleDateFormat().format(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Date());
|
||||
}
|
||||
}</pre><p>Each configuration can be used for running a separate component, but in this case they can be aggregated together as follows:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> com.app;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@SpringBootApplication</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> SampleAggregateApplication {
|
||||
|
||||
<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> AggregateApplicationBuilder()
|
||||
.from(SourceApplication.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>).args(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"--fixedDelay=5000"</span>)
|
||||
.via(ProcessorApplication.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)
|
||||
.to(SinkApplication.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>).args(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"--debug=true"</span>).run(args);
|
||||
}
|
||||
}</pre><p>The starting component of the sequence is provided as argument to the <code class="literal">from()</code> method.
|
||||
The ending component of the sequence is provided as argument to the <code class="literal">to()</code> method.
|
||||
Intermediate processors are provided as argument to the <code class="literal">via()</code> method.
|
||||
Multiple processors of the same type can be chained together (e.g. for pipelining transformations with different configurations).
|
||||
For each component, the builder can provide runtime arguments for Spring Boot configuration.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_configuring_aggregate_application" href="#_configuring_aggregate_application"></a>Configuring aggregate application</h4></div></div></div><p>Spring Cloud Stream supports passing properties for the individual applications inside the aggregate application using 'namespace' as prefix.</p><p>The namespace can be set for applications as follows:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@SpringBootApplication</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> SampleAggregateApplication {
|
||||
|
||||
<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> AggregateApplicationBuilder()
|
||||
.from(SourceApplication.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>).namespace(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"source"</span>).args(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"--fixedDelay=5000"</span>)
|
||||
.via(ProcessorApplication.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>).namespace(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"processor1"</span>)
|
||||
.to(SinkApplication.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>).namespace(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"sink"</span>).args(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"--debug=true"</span>).run(args);
|
||||
}
|
||||
}</pre><p>Once the 'namespace' is set for the individual applications, the application properties with the <code class="literal">namespace</code> as prefix can be passed to the aggregate application using any supported property source (commandline, environment properties etc.,)</p><p>For instance, to override the default <code class="literal">fixedDelay</code> and <code class="literal">debug</code> properties of 'source' and 'sink' applications:</p><pre class="screen">java -jar target/MyAggregateApplication-0.0.1-SNAPSHOT.jar --source.fixedDelay=10000 --sink.debug=false</pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_configuring_binding_service_properties_for_non_self_contained_aggregate_application" href="#_configuring_binding_service_properties_for_non_self_contained_aggregate_application"></a>Configuring binding service properties for non self contained aggregate application</h4></div></div></div><p>The non self-contained aggregate application is bound to external broker via either or both the inbound/outbound components (typically, message channels) of the aggregate application while the applications inside the aggregate application are directly bound.
|
||||
For example: a source application’s output and a processor application’s input are directly bound while the processor’s output channel is bound to an external destination at the broker.
|
||||
When passing the binding service properties for non-self contained aggregate application, it is required to pass the binding service properties to the aggregate application instead of setting them as 'args' to individual child application.
|
||||
For instance,</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@SpringBootApplication</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> SampleAggregateApplication {
|
||||
|
||||
<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> AggregateApplicationBuilder()
|
||||
.from(SourceApplication.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>).namespace(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"source"</span>).args(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"--fixedDelay=5000"</span>)
|
||||
.via(ProcessorApplication.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>).namespace(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"processor1"</span>).args(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"--debug=true"</span>).run(args);
|
||||
}
|
||||
}</pre><p>The binding properties like <code class="literal">--spring.cloud.stream.bindings.output.destination=processor-output</code> need to be specified as one of the external configuration properties (cmdline arg etc.,).</p></div></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__main_concepts.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_stream.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__binders.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">24. Main Concepts </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 26. Binders</td></tr></table></div></body></html>
|
||||
@@ -0,0 +1,30 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>9. Push Notifications and Spring Cloud Bus</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_config.html" title="Part II. Spring Cloud Config"><link rel="prev" href="multi__embedding_the_config_server.html" title="8. Embedding the Config Server"><link rel="next" href="multi__spring_cloud_config_client.html" title="10. Spring Cloud Config Client"></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">9. Push Notifications and Spring Cloud Bus</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__embedding_the_config_server.html">Prev</a> </td><th width="60%" align="center">Part II. Spring Cloud Config</th><td width="20%" align="right"> <a accesskey="n" href="multi__spring_cloud_config_client.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_push_notifications_and_spring_cloud_bus" href="#_push_notifications_and_spring_cloud_bus"></a>9. Push Notifications and Spring Cloud Bus</h2></div></div></div><p>Many source code repository providers (like Github, Gitlab or Bitbucket
|
||||
for instance) will notify you of changes in a repository through a
|
||||
webhook. You can configure the webhook via the provider’s user
|
||||
interface as a URL and a set of events in which you are
|
||||
interested. For instance
|
||||
<a class="link" href="https://developer.github.com/v3/activity/events/types/#pushevent" target="_top">Github</a>
|
||||
will POST to the webhook with a JSON body containing a list of
|
||||
commits, and a header "X-Github-Event" equal to "push". If you add a
|
||||
dependency on the <code class="literal">spring-cloud-config-monitor</code> library and activate
|
||||
the Spring Cloud Bus in your Config Server, then a "/monitor" endpoint
|
||||
is enabled.</p><p>When the webhook is activated the Config Server will send a
|
||||
<code class="literal">RefreshRemoteApplicationEvent</code> targeted at the applications it thinks
|
||||
might have changed. The change detection can be strategized, but by
|
||||
default it just looks for changes in files that match the application
|
||||
name (e.g. "foo.properties" is targeted at the "foo" application, and
|
||||
"application.properties" is targeted at all applications). The strategy
|
||||
if you want to override the behaviour is <code class="literal">PropertyPathNotificationExtractor</code>
|
||||
which accepts the request headers and body as parameters and returns a list
|
||||
of file paths that changed.</p><p>The default configuration works out of the box with Github, Gitlab or
|
||||
Bitbucket. In addition to the JSON notifications from Github, Gitlab
|
||||
or Bitbucket you can trigger a change notification by POSTing to
|
||||
"/monitor" with a form-encoded body parameters <code class="literal">path={name}</code>. This will
|
||||
broadcast to applications matching the "{name}" pattern (can contain
|
||||
wildcards).</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>the <code class="literal">RefreshRemoteApplicationEvent</code> will only be transmitted if
|
||||
the <code class="literal">spring-cloud-bus</code> is activated in the Config Server and in the
|
||||
client application.</p></td></tr></table></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>the default configuration also detects filesystem changes in
|
||||
local git repositories (the webhook is not used in that case but as
|
||||
soon as you edit a config file a refresh will be broadcast).</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__embedding_the_config_server.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_config.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__spring_cloud_config_client.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">8. Embedding the Config Server </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 10. Spring Cloud Config Client</td></tr></table></div></body></html>
|
||||
105
Dalston.SR5/multi/multi__quick_start.html
Normal file
@@ -0,0 +1,105 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>4. Quick Start</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_config.html" title="Part II. Spring Cloud Config"><link rel="prev" href="multi__spring_cloud_config.html" title="Part II. Spring Cloud Config"><link rel="next" href="multi__spring_cloud_config_server.html" title="5. Spring Cloud Config Server"></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. Quick Start</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__spring_cloud_config.html">Prev</a> </td><th width="60%" align="center">Part II. Spring Cloud Config</th><td width="20%" align="right"> <a accesskey="n" href="multi__spring_cloud_config_server.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_quick_start" href="#_quick_start"></a>4. Quick Start</h2></div></div></div><p>Start the server:</p><pre class="screen">$ cd spring-cloud-config-server
|
||||
$ ../mvnw spring-boot:run</pre><p>The server is a Spring Boot application so you can run it from your
|
||||
IDE instead if you prefer (the main class is
|
||||
<code class="literal">ConfigServerApplication</code>). Then try out a client:</p><pre class="screen">$ curl localhost:8888/foo/development
|
||||
{"name":"development","label":"master","propertySources":[
|
||||
{"name":"https://github.com/scratches/config-repo/foo-development.properties","source":{"bar":"spam"}},
|
||||
{"name":"https://github.com/scratches/config-repo/foo.properties","source":{"foo":"bar"}}
|
||||
]}</pre><p>The default strategy for locating property sources is to clone a git
|
||||
repository (at <code class="literal">spring.cloud.config.server.git.uri</code>) and use it to
|
||||
initialize a mini <code class="literal">SpringApplication</code>. The mini-application’s
|
||||
<code class="literal">Environment</code> is used to enumerate property sources and publish them
|
||||
via a JSON endpoint.</p><p>The HTTP service has resources in the form:</p><pre class="screen">/{application}/{profile}[/{label}]
|
||||
/{application}-{profile}.yml
|
||||
/{label}/{application}-{profile}.yml
|
||||
/{application}-{profile}.properties
|
||||
/{label}/{application}-{profile}.properties</pre><p>where the "application" is injected as the <code class="literal">spring.config.name</code> in the
|
||||
<code class="literal">SpringApplication</code> (i.e. what is normally "application" in a regular
|
||||
Spring Boot app), "profile" is an active profile (or comma-separated
|
||||
list of properties), and "label" is an optional git label (defaults to
|
||||
"master".)</p><p>Spring Cloud Config Server pulls configuration for remote clients
|
||||
from a git repository (which must be provided):</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spring</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> cloud</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> config</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> server</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> git</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> uri</span>: https://github.com/spring-cloud-samples/config-repo</pre><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_client_side_usage" href="#_client_side_usage"></a>4.1 Client Side Usage</h2></div></div></div><p>To use these features in an application, just build it as a Spring
|
||||
Boot application that depends on spring-cloud-config-client (e.g. see
|
||||
the test cases for the config-client, or the sample app). The most
|
||||
convenient way to add the dependency is via a Spring Boot starter
|
||||
<code class="literal">org.springframework.cloud:spring-cloud-starter-config</code>. There is also a
|
||||
parent pom and BOM (<code class="literal">spring-cloud-starter-parent</code>) for Maven users and a
|
||||
Spring IO version management properties file for Gradle and Spring CLI
|
||||
users. Example Maven configuration:</p><p><b>pom.xml. </b>
|
||||
</p><pre class="programlisting"> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><parent></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.boot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-boot-starter-parent<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>1.3.5.RELEASE<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><relativePath /></span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- lookup parent from repository --></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></parent></span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencyManagement></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-dependencies<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>Brixton.RELEASE<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><type></span>pom<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></type></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>import<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencyManagement></span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-cloud-starter-config<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.boot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-boot-starter-test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>test<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencies></span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><build></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><plugins></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><plugin></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.boot<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>spring-boot-maven-plugin<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugin></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></plugins></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></build></span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!-- repositories also needed for snapshots and milestones --></span></pre><p>
|
||||
</p><p>Then you can create a standard Spring Boot application, like this simple HTTP server:</p><pre class="screen">@SpringBootApplication
|
||||
@RestController
|
||||
public class Application {
|
||||
|
||||
@RequestMapping("/")
|
||||
public String home() {
|
||||
return "Hello World!";
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}</pre><p>When it runs it will pick up the external configuration from the
|
||||
default local config server on port 8888 if it is running. To modify
|
||||
the startup behaviour you can change the location of the config server
|
||||
using <code class="literal">bootstrap.properties</code> (like <code class="literal">application.properties</code> but for
|
||||
the bootstrap phase of an application context), e.g.</p><pre class="screen">spring.cloud.config.uri: http://myconfigserver.com</pre><p>The bootstrap properties will show up in the <code class="literal">/env</code> endpoint as a
|
||||
high-priority property source, e.g.</p><pre class="screen">$ curl localhost:8080/env
|
||||
{
|
||||
"profiles":[],
|
||||
"configService:https://github.com/spring-cloud-samples/config-repo/bar.properties":{"foo":"bar"},
|
||||
"servletContextInitParams":{},
|
||||
"systemProperties":{...},
|
||||
...
|
||||
}</pre><p>(a property source called "configService:<URL of remote
|
||||
repository>/<file name>" contains the property "foo" with value
|
||||
"bar" and is highest priority).</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>the URL in the property source name is the git repository not
|
||||
the config server URL.</p></td></tr></table></div></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_config.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_config.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__spring_cloud_config_server.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Part II. Spring Cloud Config </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 5. Spring Cloud Config Server</td></tr></table></div></body></html>
|
||||