Sync docs from master to gh-pages

This commit is contained in:
Marcin Grzejszczak
2017-08-29 12:22:21 +02:00
parent eb9406ba8f
commit 22f1f6dca1
53 changed files with 1683 additions and 669 deletions

18
antrun/build-main.xml Normal file
View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?>
<project name="maven-antrun-" default="main" >
<target name="main">
<echo file="/Users/mgrzejszczak/repo/spring-cloud-bus/docs/target/spring-cloud-bus.adoc">:nofooter:
:linkcss:
:stylesdir: css
:stylesheet: manual-singlepage.css
= {docs-main}
{spring-cloud-version}
== Pick The Documentation Option
- link:single/{docs-main}.html[Single HTML]
- link:multi/multi_{docs-main}.html[Multi HTML]</echo>
</target>
</project>

35
css/highlight.css Normal file
View File

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

9
css/manual-multipage.css Normal file
View File

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

View File

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

344
css/manual.css Normal file
View File

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

BIN
images/background.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
images/caution.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
images/important.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
images/note.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
images/sts_exception.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

BIN
images/tip.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

BIN
images/warning.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
images/web-selected.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

35
multi/css/highlight.css Normal file
View File

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

View File

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

View File

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

344
multi/css/manual.css Normal file
View File

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

BIN
multi/images/background.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
multi/images/caution.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
multi/images/important.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
multi/images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
multi/images/note.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

BIN
multi/images/tip.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

BIN
multi/images/warning.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

View File

@@ -0,0 +1,3 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>3.&nbsp;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-bus.html" title="Spring Cloud Bus"><link rel="up" href="multi_spring-cloud-bus.html" title="Spring Cloud Bus"><link rel="prev" href="multi__addressing_an_instance.html" title="2.&nbsp;Addressing an Instance"><link rel="next" href="multi__application_context_id_must_be_unique.html" title="4.&nbsp;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">3.&nbsp;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>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<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><h1 class="title"><a name="_addressing_all_instances_of_a_service" href="#_addressing_all_instances_of_a_service"></a>3.&nbsp;Addressing all instances of a service</h1></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>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__application_context_id_must_be_unique.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">2.&nbsp;Addressing an Instance&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-bus.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;4.&nbsp;Application Context ID must be unique</td></tr></table></div></body></html>

View File

@@ -0,0 +1,3 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>2.&nbsp;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-bus.html" title="Spring Cloud Bus"><link rel="up" href="multi_spring-cloud-bus.html" title="Spring Cloud Bus"><link rel="prev" href="multi__quick_start.html" title="1.&nbsp;Quick Start"><link rel="next" href="multi__addressing_all_instances_of_a_service.html" title="3.&nbsp;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">2.&nbsp;Addressing an Instance</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__quick_start.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<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><h1 class="title"><a name="_addressing_an_instance" href="#_addressing_an_instance"></a>2.&nbsp;Addressing an Instance</h1></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.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__addressing_all_instances_of_a_service.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">1.&nbsp;Quick Start&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-bus.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;3.&nbsp;Addressing all instances of a service</td></tr></table></div></body></html>

View File

@@ -0,0 +1,3 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>4.&nbsp;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-bus.html" title="Spring Cloud Bus"><link rel="up" href="multi_spring-cloud-bus.html" title="Spring Cloud Bus"><link rel="prev" href="multi__addressing_all_instances_of_a_service.html" title="3.&nbsp;Addressing all instances of a service"><link rel="next" href="multi__customizing_the_message_broker.html" title="5.&nbsp;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">4.&nbsp;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>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<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><h1 class="title"><a name="_application_context_id_must_be_unique" href="#_application_context_id_must_be_unique"></a>4.&nbsp;Application Context ID must be unique</h1></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>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__customizing_the_message_broker.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">3.&nbsp;Addressing all instances of a service&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-bus.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;5.&nbsp;Customizing the Message Broker</td></tr></table></div></body></html>

View File

@@ -0,0 +1,36 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>7.&nbsp;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-bus.html" title="Spring Cloud Bus"><link rel="up" href="multi_spring-cloud-bus.html" title="Spring Cloud Bus"><link rel="prev" href="multi__tracing_bus_events.html" title="6.&nbsp;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">7.&nbsp;Broadcasting Your Own Events</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__tracing_bus_events.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;</td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_broadcasting_your_own_events" href="#_broadcasting_your_own_events"></a>7.&nbsp;Broadcasting Your Own Events</h1></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>7.1&nbsp;Registering events in custom packages</h2></div></div></div><p>If you cannot or don&#8217;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>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;</td></tr><tr><td width="40%" align="left" valign="top">6.&nbsp;Tracing Bus Events&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-bus.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;</td></tr></table></div></body></html>

View File

@@ -0,0 +1,17 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>5.&nbsp;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-bus.html" title="Spring Cloud Bus"><link rel="up" href="multi_spring-cloud-bus.html" title="Spring Cloud Bus"><link rel="prev" href="multi__application_context_id_must_be_unique.html" title="4.&nbsp;Application Context ID must be unique"><link rel="next" href="multi__tracing_bus_events.html" title="6.&nbsp;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">5.&nbsp;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>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__tracing_bus_events.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_customizing_the_message_broker" href="#_customizing_the_message_broker"></a>5.&nbsp;Customizing the Message Broker</h1></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>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__tracing_bus_events.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">4.&nbsp;Application Context ID must be unique&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-bus.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;6.&nbsp;Tracing Bus Events</td></tr></table></div></body></html>

View File

@@ -0,0 +1,10 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>1.&nbsp;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-bus.html" title="Spring Cloud Bus"><link rel="up" href="multi_spring-cloud-bus.html" title="Spring Cloud Bus"><link rel="prev" href="multi_pr01.html" title=""><link rel="next" href="multi__addressing_an_instance.html" title="2.&nbsp;Addressing an Instance"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">1.&nbsp;Quick Start</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_pr01.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__addressing_an_instance.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_quick_start" href="#_quick_start"></a>1.&nbsp;Quick Start</h1></div></div></div><p>Spring Cloud Bus works by adding Spring Boot autconfiguration if it detects itself on the classpath. All you need to do to enable the bus is to add <code class="literal">spring-cloud-starter-bus-amqp</code> or <code class="literal">spring-cloud-starter-bus-kafka</code> to your dependency management and Spring Cloud takes care of the rest. Make sure the broker (RabbitMQ or Kafka) is available and configured: running on localhost you shouldn&#8217;t have to do anything, but if you are running remotely use Spring Cloud Connectors, or Spring Boot conventions to define the broker credentials, e.g. for Rabbit</p><p><b>application.yml.&nbsp;</b>
</p><pre class="screen">spring:
rabbitmq:
host: mybroker.com
port: 5672
username: user
password: secret</pre><p>
</p><p>The bus currently supports sending messages to all nodes listening or all nodes for a particular service (as defined by Eureka). More selector criteria may be added in the future (ie. only service X nodes in data center Y, etc&#8230;&#8203;). There are also some http endpoints under the <code class="literal">/bus/*</code> actuator namespace. There are currently two implemented. The first, <code class="literal">/bus/env</code>, sends key/value pairs to update each node&#8217;s Spring Environment. The second, <code class="literal">/bus/refresh</code>, will reload each application&#8217;s configuration, just as if they had all been pinged on their <code class="literal">/refresh</code> endpoint.</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 Bus starters cover Rabbit and Kafka, because those are the two most common implementations, but Spring Cloud Stream is quite flexible and binder will work combined with <code class="literal">spring-cloud-bus</code>.</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_pr01.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__addressing_an_instance.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-bus.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;2.&nbsp;Addressing an Instance</td></tr></table></div></body></html>

View File

@@ -0,0 +1,43 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>6.&nbsp;Tracing Bus 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-bus.html" title="Spring Cloud Bus"><link rel="up" href="multi_spring-cloud-bus.html" title="Spring Cloud Bus"><link rel="prev" href="multi__customizing_the_message_broker.html" title="5.&nbsp;Customizing the Message Broker"><link rel="next" href="multi__broadcasting_your_own_events.html" title="7.&nbsp;Broadcasting Your Own 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">6.&nbsp;Tracing Bus Events</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__customizing_the_message_broker.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__broadcasting_your_own_events.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_tracing_bus_events" href="#_tracing_bus_events"></a>6.&nbsp;Tracing Bus Events</h1></div></div></div><p>Bus events (subclasses of <code class="literal">RemoteApplicationEvent</code>) can be traced by
setting <code class="literal">spring.cloud.bus.trace.enabled=true</code>. If you do this then the
Spring Boot <code class="literal">TraceRepository</code> (if it is present) will show each event
sent and all the acks from each service instance. Example (from the
<code class="literal">/trace</code> endpoint):</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">"timestamp"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2015-11-26T10:24:44.411+0000"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"info"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"signal"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"spring.cloud.bus.ack"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"type"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"RefreshRemoteApplicationEvent"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"id"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"c4d374b7-58ea-4928-a312-31984def293b"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"origin"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"stores:8081"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"destination"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"*:**"</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-keyword">{</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">"2015-11-26T10:24:41.864+0000"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"info"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"signal"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"spring.cloud.bus.sent"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"type"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"RefreshRemoteApplicationEvent"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"id"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"c4d374b7-58ea-4928-a312-31984def293b"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"origin"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"customers: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">"destination"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"*:**"</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-keyword">{</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">"2015-11-26T10:24:41.862+0000"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"info"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"signal"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"spring.cloud.bus.ack"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"type"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"RefreshRemoteApplicationEvent"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"id"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"c4d374b7-58ea-4928-a312-31984def293b"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"origin"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"customers: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">"destination"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"*:**"</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>This trace shows that a <code class="literal">RefreshRemoteApplicationEvent</code> was sent from
<code class="literal">customers:9000</code>, broadcast to all services, and it was received
(acked) by <code class="literal">customers:9000</code> and <code class="literal">stores:8081</code>.</p><p>To handle the ack signals yourself you could add an <code class="literal">@EventListener</code>
for the <code class="literal">AckRemoteApplicationEvent</code> and <code class="literal">SentApplicationEvent</code> types
to your app (and enable tracing). Or you could tap into the
<code class="literal">TraceRepository</code> and mine the data from there.</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>Any Bus application can trace acks, but sometimes it will be
useful to do this in a central service that can do more complex
queries on the data. Or forward it to a specialized tracing service.</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__customizing_the_message_broker.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__broadcasting_your_own_events.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5.&nbsp;Customizing the Message Broker&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-bus.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;7.&nbsp;Broadcasting Your Own Events</td></tr></table></div></body></html>

3
multi/multi_pr01.html Normal file
View File

@@ -0,0 +1,3 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title></title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-bus.html" title="Spring Cloud Bus"><link rel="up" href="multi_spring-cloud-bus.html" title="Spring Cloud Bus"><link rel="prev" href="multi_spring-cloud-bus.html" title="Spring Cloud Bus"><link rel="next" href="multi__quick_start.html" title="1.&nbsp;Quick Start"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center"></th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_spring-cloud-bus.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__quick_start.html">Next</a></td></tr></table><hr></div><div class="preface"><div class="titlepage"><div><div><h1 class="title"><a name="d0e9" href="#d0e9"></a></h1></div></div></div><p>Spring Cloud Bus links nodes of a distributed system with a lightweight message broker. This can then be used to broadcast state changes (e.g. configuration changes) or other management instructions. A key idea is that the Bus is like a distributed Actuator for a Spring Boot application that is scaled out, but it can also be used as a communication channel between apps. Starters are provided for an AMQP broker as the transport or for Kafka, but the same basic feature set (and some more depending on the transport) is on the roadmap for other transports.</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 Cloud is released under the non-restrictive Apache 2.0 license. If you would like to contribute to this section of the documentation or if you find an error, please find the source code and issue trackers in the project at <a class="link" href="https://github.com/spring-cloud/spring-cloud-config/tree/master/docs/src/main/asciidoc" target="_top">github</a>.</p></td></tr></table></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_spring-cloud-bus.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__quick_start.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Spring Cloud Bus&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-bus.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;1.&nbsp;Quick Start</td></tr></table></div></body></html>

View File

@@ -0,0 +1,3 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring Cloud 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-bus.html" title="Spring Cloud Bus"><link rel="next" href="multi_pr01.html" title=""></head><body class="firstpage" bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Spring Cloud Bus</th></tr><tr><td width="20%" align="left">&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi_pr01.html">Next</a></td></tr></table><hr></div><div lang="en" class="book"><div class="titlepage"><div><div><h1 class="title"><a name="d0e3"></a>Spring Cloud Bus</h1></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="preface"><a href="multi_pr01.html"></a></span></dt><dt><span class="chapter"><a href="multi__quick_start.html">1. Quick Start</a></span></dt><dt><span class="chapter"><a href="multi__addressing_an_instance.html">2. Addressing an Instance</a></span></dt><dt><span class="chapter"><a href="multi__addressing_all_instances_of_a_service.html">3. Addressing all instances of a service</a></span></dt><dt><span class="chapter"><a href="multi__application_context_id_must_be_unique.html">4. Application Context ID must be unique</a></span></dt><dt><span class="chapter"><a href="multi__customizing_the_message_broker.html">5. Customizing the Message Broker</a></span></dt><dt><span class="chapter"><a href="multi__tracing_bus_events.html">6. Tracing Bus Events</a></span></dt><dt><span class="chapter"><a href="multi__broadcasting_your_own_events.html">7. Broadcasting Your Own Events</a></span></dt><dd><dl><dt><span class="section"><a href="multi__broadcasting_your_own_events.html#_registering_events_in_custom_packages">7.1. Registering events in custom packages</a></span></dt></dl></dd></dl></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left">&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi_pr01.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right" valign="top">&nbsp;</td></tr></table></div></body></html>

35
single/css/highlight.css Normal file
View File

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

View File

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

View File

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

344
single/css/manual.css Normal file
View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
single/images/caution.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
single/images/important.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
single/images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
single/images/note.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

BIN
single/images/tip.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

BIN
single/images/warning.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

View File

@@ -0,0 +1,97 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring Cloud Bus</title><link rel="stylesheet" type="text/css" href="css/manual-singlepage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div lang="en" class="book"><div class="titlepage"><div><div><h1 class="title"><a name="d0e3"></a>Spring Cloud Bus</h1></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="preface"><a href="#d0e9"></a></span></dt><dt><span class="chapter"><a href="#_quick_start">1. Quick Start</a></span></dt><dt><span class="chapter"><a href="#_addressing_an_instance">2. Addressing an Instance</a></span></dt><dt><span class="chapter"><a href="#_addressing_all_instances_of_a_service">3. Addressing all instances of a service</a></span></dt><dt><span class="chapter"><a href="#_application_context_id_must_be_unique">4. Application Context ID must be unique</a></span></dt><dt><span class="chapter"><a href="#_customizing_the_message_broker">5. Customizing the Message Broker</a></span></dt><dt><span class="chapter"><a href="#_tracing_bus_events">6. Tracing Bus Events</a></span></dt><dt><span class="chapter"><a href="#_broadcasting_your_own_events">7. Broadcasting Your Own Events</a></span></dt><dd><dl><dt><span class="section"><a href="#_registering_events_in_custom_packages">7.1. Registering events in custom packages</a></span></dt></dl></dd></dl></div><div class="preface"><div class="titlepage"><div><div><h1 class="title"><a name="d0e9" href="#d0e9"></a></h1></div></div></div><p>Spring Cloud Bus links nodes of a distributed system with a lightweight message broker. This can then be used to broadcast state changes (e.g. configuration changes) or other management instructions. A key idea is that the Bus is like a distributed Actuator for a Spring Boot application that is scaled out, but it can also be used as a communication channel between apps. Starters are provided for an AMQP broker as the transport or for Kafka, but the same basic feature set (and some more depending on the transport) is on the roadmap for other transports.</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 Cloud is released under the non-restrictive Apache 2.0 license. If you would like to contribute to this section of the documentation or if you find an error, please find the source code and issue trackers in the project at <a class="link" href="https://github.com/spring-cloud/spring-cloud-config/tree/master/docs/src/main/asciidoc" target="_top">github</a>.</p></td></tr></table></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_quick_start" href="#_quick_start"></a>1.&nbsp;Quick Start</h1></div></div></div><p>Spring Cloud Bus works by adding Spring Boot autconfiguration if it detects itself on the classpath. All you need to do to enable the bus is to add <code class="literal">spring-cloud-starter-bus-amqp</code> or <code class="literal">spring-cloud-starter-bus-kafka</code> to your dependency management and Spring Cloud takes care of the rest. Make sure the broker (RabbitMQ or Kafka) is available and configured: running on localhost you shouldn&#8217;t have to do anything, but if you are running remotely use Spring Cloud Connectors, or Spring Boot conventions to define the broker credentials, e.g. for Rabbit</p><p><b>application.yml.&nbsp;</b>
</p><pre class="screen">spring:
rabbitmq:
host: mybroker.com
port: 5672
username: user
password: secret</pre><p>
</p><p>The bus currently supports sending messages to all nodes listening or all nodes for a particular service (as defined by Eureka). More selector criteria may be added in the future (ie. only service X nodes in data center Y, etc&#8230;&#8203;). There are also some http endpoints under the <code class="literal">/bus/*</code> actuator namespace. There are currently two implemented. The first, <code class="literal">/bus/env</code>, sends key/value pairs to update each node&#8217;s Spring Environment. The second, <code class="literal">/bus/refresh</code>, will reload each application&#8217;s configuration, just as if they had all been pinged on their <code class="literal">/refresh</code> endpoint.</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 Bus starters cover Rabbit and Kafka, because those are the two most common implementations, but Spring Cloud Stream is quite flexible and binder will work combined with <code class="literal">spring-cloud-bus</code>.</p></td></tr></table></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_addressing_an_instance" href="#_addressing_an_instance"></a>2.&nbsp;Addressing an Instance</h1></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="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_addressing_all_instances_of_a_service" href="#_addressing_all_instances_of_a_service"></a>3.&nbsp;Addressing all instances of a service</h1></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="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_application_context_id_must_be_unique" href="#_application_context_id_must_be_unique"></a>4.&nbsp;Application Context ID must be unique</h1></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="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_customizing_the_message_broker" href="#_customizing_the_message_broker"></a>5.&nbsp;Customizing the Message Broker</h1></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="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_tracing_bus_events" href="#_tracing_bus_events"></a>6.&nbsp;Tracing Bus Events</h1></div></div></div><p>Bus events (subclasses of <code class="literal">RemoteApplicationEvent</code>) can be traced by
setting <code class="literal">spring.cloud.bus.trace.enabled=true</code>. If you do this then the
Spring Boot <code class="literal">TraceRepository</code> (if it is present) will show each event
sent and all the acks from each service instance. Example (from the
<code class="literal">/trace</code> endpoint):</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">"timestamp"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"2015-11-26T10:24:44.411+0000"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"info"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"signal"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"spring.cloud.bus.ack"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"type"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"RefreshRemoteApplicationEvent"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"id"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"c4d374b7-58ea-4928-a312-31984def293b"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"origin"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"stores:8081"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"destination"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"*:**"</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-keyword">{</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">"2015-11-26T10:24:41.864+0000"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"info"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"signal"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"spring.cloud.bus.sent"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"type"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"RefreshRemoteApplicationEvent"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"id"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"c4d374b7-58ea-4928-a312-31984def293b"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"origin"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"customers: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">"destination"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"*:**"</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-keyword">{</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">"2015-11-26T10:24:41.862+0000"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"info"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"signal"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"spring.cloud.bus.ack"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"type"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"RefreshRemoteApplicationEvent"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"id"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"c4d374b7-58ea-4928-a312-31984def293b"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"origin"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"customers: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">"destination"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"*:**"</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>This trace shows that a <code class="literal">RefreshRemoteApplicationEvent</code> was sent from
<code class="literal">customers:9000</code>, broadcast to all services, and it was received
(acked) by <code class="literal">customers:9000</code> and <code class="literal">stores:8081</code>.</p><p>To handle the ack signals yourself you could add an <code class="literal">@EventListener</code>
for the <code class="literal">AckRemoteApplicationEvent</code> and <code class="literal">SentApplicationEvent</code> types
to your app (and enable tracing). Or you could tap into the
<code class="literal">TraceRepository</code> and mine the data from there.</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>Any Bus application can trace acks, but sometimes it will be
useful to do this in a central service that can do more complex
queries on the data. Or forward it to a specialized tracing service.</p></td></tr></table></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_broadcasting_your_own_events" href="#_broadcasting_your_own_events"></a>7.&nbsp;Broadcasting Your Own Events</h1></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>7.1&nbsp;Registering events in custom packages</h2></div></div></div><p>If you cannot or don&#8217;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></body></html>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@@ -4,690 +4,108 @@
<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.3">
<title>Spring Cloud Bus</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<meta name="generator" content="Asciidoctor 1.5.5">
<title>spring-cloud-bus</title>
<link rel="stylesheet" href="css/manual-singlepage.css">
<style>
/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
/* Remove comment around @import statement below when using as a custom stylesheet */
/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
audio,canvas,video{display:inline-block}
audio:not([controls]){display:none;height:0}
[hidden],template{display:none}
script{display:none!important}
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
body{margin:0}
a{background:transparent}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
abbr[title]{border-bottom:1px dotted}
b,strong{font-weight:bold}
dfn{font-style:italic}
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}
input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
body{-webkit-font-smoothing:antialiased}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.center{margin-left:auto;margin-right:auto}
.spread{width:100%}
p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:none}
p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol,ul.no-bullet,ol.no-bullet{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
ul.square{list-style-type:square}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.no-bullet{list-style:none}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
abbr{text-transform:none}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
blockquote cite:before{content:"\2014 \0020"}
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
table thead,table tfoot{background:#f7f8f7;font-weight:bold}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
body{tab-size:4}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table}
.clearfix:after,.float-group:after{clear:both}
*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menu{color:rgba(0,0,0,.8)}
b.button:before,b.button:after{position:relative;top:-1px;font-weight:400}
b.button:before{content:"[";padding:0 3px 0 2px}
b.button:after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table}
#header:after,#content:after,#footnotes:after,#footer:after{clear:both}
#content{margin-top:1.25em}
#content:before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span:before{content:"\00a0\2013\00a0"}
#header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark:before{content:"\00a0|\00a0"}
#header #revnumber{text-transform:capitalize}
#header #revnumber:after{content:"\00a0"}
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}
#toc>ul{margin-left:.125em}
#toc ul.sectlevel0>li>a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media only screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}
@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2>ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
.sect1{padding-bottom:.625em}
@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}
.sect1+.sect1{border-top:1px solid #efefed}
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}
.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}
table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
.exampleblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child{margin-bottom:0}
.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
.sidebarblock>:first-child{margin-top:0}
.sidebarblock>:last-child{margin-bottom:0}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}
.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.listingblock>.content{position:relative}
.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
.listingblock:hover code[data-lang]:before{display:block}
.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}
.listingblock.terminal pre .command:not([data-prompt]):before{content:"$"}
table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
table.pyhltable td.code{padding-left:.75em;padding-right:0}
pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}
pre.pygments .lineno{display:inline-block;margin-right:.25em}
table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}
.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
.quoteblock .quoteblock blockquote:before{display:none}
.verseblock{margin:0 1em 1.25em 1em}
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract{margin:0 0 1.25em 0;display:block}
.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}
.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}
table.tableblock{max-width:100%;border-collapse:separate}
table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all th.tableblock,table.grid-all td.tableblock{border-width:0 1px 1px 0}
table.grid-all tfoot>tr>th.tableblock,table.grid-all tfoot>tr>td.tableblock{border-width:1px 1px 0 0}
table.grid-cols th.tableblock,table.grid-cols td.tableblock{border-width:0 1px 0 0}
table.grid-all *>tr>.tableblock:last-child,table.grid-cols *>tr>.tableblock:last-child{border-right-width:0}
table.grid-rows th.tableblock,table.grid-rows td.tableblock{border-width:0 0 1px 0}
table.grid-all tbody>tr:last-child>th.tableblock,table.grid-all tbody>tr:last-child>td.tableblock,table.grid-all thead:last-child>tr>th.tableblock,table.grid-rows tbody>tr:last-child>th.tableblock,table.grid-rows tbody>tr:last-child>td.tableblock,table.grid-rows thead:last-child>tr>th.tableblock{border-bottom-width:0}
table.grid-rows tfoot>tr>th.tableblock,table.grid-rows tfoot>tr>td.tableblock{border-width:1px 0 0 0}
table.frame-all{border-width:1px}
table.frame-sides{border-width:0 1px}
table.frame-topbot{border-width:1px 0}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock>code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
td>div.verse{white-space:pre}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.unstyled,ol.unnumbered,ul.checklist,ul.none{list-style-type:none}
ul.unstyled,ol.unnumbered,ul.checklist{margin-left:.625em}
ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1em;font-size:.85em}
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{width:1em;position:relative;top:1px}
ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}
ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}
ul.inline>li>*{display:block}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist>table tr>td:first-of-type{padding:0 .75em;line-height:1}
.colist>table tr>td:last-of-type{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
.imageblock>.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
.gist .file-data>table td.line-data{width:99%}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background-color:#00fafa}
.black{color:#000}
.black-background{background-color:#000}
.blue{color:#0000bf}
.blue-background{background-color:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background-color:#fa00fa}
.gray{color:#606060}
.gray-background{background-color:#7d7d7d}
.green{color:#006000}
.green-background{background-color:#007d00}
.lime{color:#00bf00}
.lime-background{background-color:#00fa00}
.maroon{color:#600000}
.maroon-background{background-color:#7d0000}
.navy{color:#000060}
.navy-background{background-color:#00007d}
.olive{color:#606000}
.olive-background{background-color:#7d7d00}
.purple{color:#600060}
.purple-background{background-color:#7d007d}
.red{color:#bf0000}
.red-background{background-color:#fa0000}
.silver{color:#909090}
.silver-background{background-color:#bcbcbc}
.teal{color:#006060}
.teal-background{background-color:#007d7d}
.white{color:#bfbfbf}
.white-background{background-color:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background-color:#fafa00}
span.icon>.fa{cursor:default}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]:after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@media print{@page{margin:1.25cm .75cm}
*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]:after{content:" (" attr(title) ")"}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}
.sect1{padding-bottom:0!important}
.sect1+.sect1{border:0!important}
#header>h1:first-child{margin-top:1.25rem}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span:before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
.listingblock code[data-lang]:before{display:block}
#footer{background:none!important;padding:0 .9375em}
#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
.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 Bus</h1>
<div id="toc" class="toc">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#_quick_start">Quick Start</a></li>
<li><a href="#_addressing_an_instance">Addressing an Instance</a></li>
<li><a href="#_addressing_all_instances_of_a_service">Addressing all instances of a service</a></li>
<li><a href="#_application_context_id_must_be_unique">Application Context ID must be unique</a></li>
<li><a href="#_customizing_the_message_broker">Customizing the Message Broker</a></li>
<li><a href="#_tracing_bus_events">Tracing Bus Events</a></li>
<li><a href="#_broadcasting_your_own_events">Broadcasting Your Own Events</a>
<ul class="sectlevel2">
<li><a href="#_registering_events_in_custom_packages">Registering events in custom packages</a></li>
</ul>
</li>
</ul>
</div>
<h1>spring-cloud-bus</h1>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Spring Cloud Bus links nodes of a distributed system with a lightweight message broker. This can then be used to broadcast state changes (e.g. configuration changes) or other management instructions. A key idea is that the Bus is like a distributed Actuator for a Spring Boot application that is scaled out, but it can also be used as a communication channel between apps. Starters are provided for an AMQP broker as the transport or for Kafka, but the same basic feature set (and some more depending on the transport) is on the roadmap for other transports.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
Spring Cloud is released under the non-restrictive Apache 2.0 license. If you would like to contribute to this section of the documentation or if you find an error, please find the source code and issue trackers in the project at <a href="https://github.com/spring-cloud/spring-cloud-config/tree/master/docs/src/main/asciidoc">github</a>.
</td>
</tr>
</table>
<p>1.3.2.BUILD-SNAPSHOT</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_quick_start">Quick Start</h2>
<h2 id="_pick_the_documentation_option">Pick The Documentation Option</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Spring Cloud Bus works by adding Spring Boot autconfiguration if it detects itself on the classpath. All you need to do to enable the bus is to add <code>spring-cloud-starter-bus-amqp</code> or <code>spring-cloud-starter-bus-kafka</code> to your dependency management and Spring Cloud takes care of the rest. Make sure the broker (RabbitMQ or Kafka) is available and configured: running on localhost you shouldn&#8217;t have to do anything, but if you are running remotely use Spring Cloud Connectors, or Spring Boot conventions to define the broker credentials, e.g. for Rabbit</p>
</div>
<div class="listingblock">
<div class="title">application.yml</div>
<div class="content">
<pre>spring:
rabbitmq:
host: mybroker.com
port: 5672
username: user
password: secret</pre>
</div>
</div>
<div class="paragraph">
<p>The bus currently supports sending messages to all nodes listening or all nodes for a particular service (as defined by Eureka). More selector criteria may be added in the future (ie. only service X nodes in data center Y, etc&#8230;&#8203;). There are also some http endpoints under the <code>/bus/*</code> actuator namespace. There are currently two implemented. The first, <code>/bus/env</code>, sends key/value pairs to update each node&#8217;s Spring Environment. The second, <code>/bus/refresh</code>, will reload each application&#8217;s configuration, just as if they had all been pinged on their <code>/refresh</code> endpoint.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
The Bus starters cover Rabbit and Kafka, because those are the two most common implementations, but Spring Cloud Stream is quite flexible and binder will work combined with <code>spring-cloud-bus</code>.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_addressing_an_instance">Addressing an Instance</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The HTTP endpoints accept a "destination" parameter, e.g. "/bus/refresh?destination=customers:9000", where the destination is an <code>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>ContextIdApplicationContextInitializer</code> to a combination of the <code>spring.application.name</code>, active profiles and <code>server.port</code> by default.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_addressing_all_instances_of_a_service">Addressing all instances of a service</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The "destination" parameter is used in a Spring <code>PathMatcher</code> (with the path separator as a colon <code>:</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>ApplicationContext</code> ID.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_application_context_id_must_be_unique">Application Context ID must be unique</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The bus tries to eliminate processing an event twice, once from the original <code>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>spring.application.index</code> to something unique for each instance of a service. For example, in lattice, set <code>spring.application.index=${INSTANCE_INDEX}</code> in application.properties (or bootstrap.properties if using configserver).</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_customizing_the_message_broker">Customizing the Message Broker</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Spring Cloud Bus uses
<a href="https://cloud.spring.io/spring-cloud-stream">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>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>spring.rabbitmq.*</code>
configuration properties. Spring Cloud Bus has a handful of native
configuration properties in <code>spring.cloud.bus.*</code>
(e.g. <code>spring.cloud.bus.destination</code> is the name of the topic to use
the the externall middleware). Normally the defaults will suffice.</p>
</div>
<div class="paragraph">
<p>To lean more about how to customize the message broker settings
consult the Spring Cloud Stream documentation.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_tracing_bus_events">Tracing Bus Events</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Bus events (subclasses of <code>RemoteApplicationEvent</code>) can be traced by
setting <code>spring.cloud.bus.trace.enabled=true</code>. If you do this then the
Spring Boot <code>TraceRepository</code> (if it is present) will show each event
sent and all the acks from each service instance. Example (from the
<code>/trace</code> endpoint):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-json" data-lang="json">{
"timestamp": "2015-11-26T10:24:44.411+0000",
"info": {
"signal": "spring.cloud.bus.ack",
"type": "RefreshRemoteApplicationEvent",
"id": "c4d374b7-58ea-4928-a312-31984def293b",
"origin": "stores:8081",
"destination": "*:**"
}
},
{
"timestamp": "2015-11-26T10:24:41.864+0000",
"info": {
"signal": "spring.cloud.bus.sent",
"type": "RefreshRemoteApplicationEvent",
"id": "c4d374b7-58ea-4928-a312-31984def293b",
"origin": "customers:9000",
"destination": "*:**"
}
},
{
"timestamp": "2015-11-26T10:24:41.862+0000",
"info": {
"signal": "spring.cloud.bus.ack",
"type": "RefreshRemoteApplicationEvent",
"id": "c4d374b7-58ea-4928-a312-31984def293b",
"origin": "customers:9000",
"destination": "*:**"
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This trace shows that a <code>RefreshRemoteApplicationEvent</code> was sent from
<code>customers:9000</code>, broadcast to all services, and it was received
(acked) by <code>customers:9000</code> and <code>stores:8081</code>.</p>
</div>
<div class="paragraph">
<p>To handle the ack signals yourself you could add an <code>@EventListener</code>
for the <code>AckRemoteApplicationEvent</code> and <code>SentApplicationEvent</code> types
to your app (and enable tracing). Or you could tap into the
<code>TraceRepository</code> and mine the data from there.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
Any Bus application can trace acks, but sometimes it will be
useful to do this in a central service that can do more complex
queries on the data. Or forward it to a specialized tracing service.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_broadcasting_your_own_events">Broadcasting Your Own Events</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The Bus can carry any event of type <code>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>org.springframework.cloud.bus.event</code>.</p>
</div>
<div class="paragraph">
<p>To customise the event name you can use <code>@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>
<div class="sect2">
<h3 id="_registering_events_in_custom_packages">Registering events in custom packages</h3>
<div class="paragraph">
<p>If you cannot or don&#8217;t want to use a subpackage of <code>org.springframework.cloud.bus.event</code>
for your custom events, you must specify which packages to scan for events of
type <code>RemoteApplicationEvent</code> using <code>@RemoteApplicationEventScan</code>. Packages
specified with <code>@RemoteApplicationEventScan</code> include subpackages.</p>
</div>
<div class="paragraph">
<p>For example, if you have a custom event called <code>FooEvent</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">package com.acme;
public class FooEvent extends RemoteApplicationEvent {
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>you can register this event with the deserializer in the following way:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">package com.acme;
@Configuration
@RemoteApplicationEventScan
public class BusConfiguration {
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Without specifying a value, the package of the class where <code>@RemoteApplicationEventScan</code>
is used will be registered. In this example <code>com.acme</code> will be registered using the
package of <code>BusConfiguration</code>.</p>
</div>
<div class="paragraph">
<p>You can also explicitly specify the packages to scan using the <code>value</code>, <code>basePackages</code> or
<code>basePackageClasses</code> properties on <code>@RemoteApplicationEventScan</code>. For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">package com.acme;
@Configuration
//@RemoteApplicationEventScan({"com.acme", "foo.bar"})
//@RemoteApplicationEventScan(basePackages = {"com.acme", "foo.bar", "fizz.buzz"})
@RemoteApplicationEventScan(basePackageClasses = BusConfiguration.class)
public class BusConfiguration {
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>All examples of <code>@RemoteApplicationEventScan</code> above are equivalent,
in that the <code>com.acme</code> package will be registered by explicitly specifying the
packages on <code>@RemoteApplicationEventScan</code>. Note, you can specify multiple base
packages to scan.</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="single/spring-cloud-bus.html">Single HTML</a></p>
</li>
<li>
<p><a href="multi/multi_spring-cloud-bus.html">Multi HTML</a></p>
</li>
</ul>
</div>
</div>
</div>

166
spring-cloud-bus.xml Normal file
View File

@@ -0,0 +1,166 @@
<?xml version="1.0" encoding="UTF-8"?>
<?asciidoc-toc?>
<?asciidoc-numbered?>
<book xmlns="http://docbook.org/ns/docbook" xmlns:xl="http://www.w3.org/1999/xlink" version="5.0" xml:lang="en">
<info>
<title>Spring Cloud Bus</title>
<date>2017-08-29</date>
</info>
<preface>
<title></title>
<simpara>Spring Cloud Bus links nodes of a distributed system with a lightweight message broker. This can then be used to broadcast state changes (e.g. configuration changes) or other management instructions. A key idea is that the Bus is like a distributed Actuator for a Spring Boot application that is scaled out, but it can also be used as a communication channel between apps. Starters are provided for an AMQP broker as the transport or for Kafka, but the same basic feature set (and some more depending on the transport) is on the roadmap for other transports.</simpara>
<note>
<simpara>Spring Cloud is released under the non-restrictive Apache 2.0 license. If you would like to contribute to this section of the documentation or if you find an error, please find the source code and issue trackers in the project at <link xl:href="https://github.com/spring-cloud/spring-cloud-config/tree/master/docs/src/main/asciidoc">github</link>.</simpara>
</note>
</preface>
<chapter xml:id="_quick_start">
<title>Quick Start</title>
<simpara>Spring Cloud Bus works by adding Spring Boot autconfiguration if it detects itself on the classpath. All you need to do to enable the bus is to add <literal>spring-cloud-starter-bus-amqp</literal> or <literal>spring-cloud-starter-bus-kafka</literal> to your dependency management and Spring Cloud takes care of the rest. Make sure the broker (RabbitMQ or Kafka) is available and configured: running on localhost you shouldn&#8217;t have to do anything, but if you are running remotely use Spring Cloud Connectors, or Spring Boot conventions to define the broker credentials, e.g. for Rabbit</simpara>
<formalpara>
<title>application.yml</title>
<para>
<screen>spring:
rabbitmq:
host: mybroker.com
port: 5672
username: user
password: secret</screen>
</para>
</formalpara>
<simpara>The bus currently supports sending messages to all nodes listening or all nodes for a particular service (as defined by Eureka). More selector criteria may be added in the future (ie. only service X nodes in data center Y, etc&#8230;&#8203;). There are also some http endpoints under the <literal>/bus/*</literal> actuator namespace. There are currently two implemented. The first, <literal>/bus/env</literal>, sends key/value pairs to update each node&#8217;s Spring Environment. The second, <literal>/bus/refresh</literal>, will reload each application&#8217;s configuration, just as if they had all been pinged on their <literal>/refresh</literal> endpoint.</simpara>
<note>
<simpara>The Bus starters cover Rabbit and Kafka, because those are the two most common implementations, but Spring Cloud Stream is quite flexible and binder will work combined with <literal>spring-cloud-bus</literal>.</simpara>
</note>
</chapter>
<chapter xml:id="_addressing_an_instance">
<title>Addressing an Instance</title>
<simpara>The HTTP endpoints accept a "destination" parameter, e.g. "/bus/refresh?destination=customers:9000", where the destination is an <literal>ApplicationContext</literal> 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 <literal>ContextIdApplicationContextInitializer</literal> to a combination of the <literal>spring.application.name</literal>, active profiles and <literal>server.port</literal> by default.</simpara>
</chapter>
<chapter xml:id="_addressing_all_instances_of_a_service">
<title>Addressing all instances of a service</title>
<simpara>The "destination" parameter is used in a Spring <literal>PathMatcher</literal> (with the path separator as a colon <literal>:</literal>) 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 <literal>ApplicationContext</literal> ID.</simpara>
</chapter>
<chapter xml:id="_application_context_id_must_be_unique">
<title>Application Context ID must be unique</title>
<simpara>The bus tries to eliminate processing an event twice, once from the original <literal>ApplicationEvent</literal> 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 <literal>spring.application.index</literal> to something unique for each instance of a service. For example, in lattice, set <literal>spring.application.index=${INSTANCE_INDEX}</literal> in application.properties (or bootstrap.properties if using configserver).</simpara>
</chapter>
<chapter xml:id="_customizing_the_message_broker">
<title>Customizing the Message Broker</title>
<simpara>Spring Cloud Bus uses
<link xl:href="https://cloud.spring.io/spring-cloud-stream">Spring Cloud Stream</link> 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
(<literal>spring-cloud-starter-bus-[amqp,kafka]</literal>). 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 <literal>spring.rabbitmq.*</literal>
configuration properties. Spring Cloud Bus has a handful of native
configuration properties in <literal>spring.cloud.bus.*</literal>
(e.g. <literal>spring.cloud.bus.destination</literal> is the name of the topic to use
the the externall middleware). Normally the defaults will suffice.</simpara>
<simpara>To lean more about how to customize the message broker settings
consult the Spring Cloud Stream documentation.</simpara>
</chapter>
<chapter xml:id="_tracing_bus_events">
<title>Tracing Bus Events</title>
<simpara>Bus events (subclasses of <literal>RemoteApplicationEvent</literal>) can be traced by
setting <literal>spring.cloud.bus.trace.enabled=true</literal>. If you do this then the
Spring Boot <literal>TraceRepository</literal> (if it is present) will show each event
sent and all the acks from each service instance. Example (from the
<literal>/trace</literal> endpoint):</simpara>
<programlisting language="json" linenumbering="unnumbered">{
"timestamp": "2015-11-26T10:24:44.411+0000",
"info": {
"signal": "spring.cloud.bus.ack",
"type": "RefreshRemoteApplicationEvent",
"id": "c4d374b7-58ea-4928-a312-31984def293b",
"origin": "stores:8081",
"destination": "*:**"
}
},
{
"timestamp": "2015-11-26T10:24:41.864+0000",
"info": {
"signal": "spring.cloud.bus.sent",
"type": "RefreshRemoteApplicationEvent",
"id": "c4d374b7-58ea-4928-a312-31984def293b",
"origin": "customers:9000",
"destination": "*:**"
}
},
{
"timestamp": "2015-11-26T10:24:41.862+0000",
"info": {
"signal": "spring.cloud.bus.ack",
"type": "RefreshRemoteApplicationEvent",
"id": "c4d374b7-58ea-4928-a312-31984def293b",
"origin": "customers:9000",
"destination": "*:**"
}
}</programlisting>
<simpara>This trace shows that a <literal>RefreshRemoteApplicationEvent</literal> was sent from
<literal>customers:9000</literal>, broadcast to all services, and it was received
(acked) by <literal>customers:9000</literal> and <literal>stores:8081</literal>.</simpara>
<simpara>To handle the ack signals yourself you could add an <literal>@EventListener</literal>
for the <literal>AckRemoteApplicationEvent</literal> and <literal>SentApplicationEvent</literal> types
to your app (and enable tracing). Or you could tap into the
<literal>TraceRepository</literal> and mine the data from there.</simpara>
<note>
<simpara>Any Bus application can trace acks, but sometimes it will be
useful to do this in a central service that can do more complex
queries on the data. Or forward it to a specialized tracing service.</simpara>
</note>
</chapter>
<chapter xml:id="_broadcasting_your_own_events">
<title>Broadcasting Your Own Events</title>
<simpara>The Bus can carry any event of type <literal>RemoteApplicationEvent</literal>, 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 <literal>org.springframework.cloud.bus.event</literal>.</simpara>
<simpara>To customise the event name you can use <literal>@JsonTypeName</literal> 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.</simpara>
<section xml:id="_registering_events_in_custom_packages">
<title>Registering events in custom packages</title>
<simpara>If you cannot or don&#8217;t want to use a subpackage of <literal>org.springframework.cloud.bus.event</literal>
for your custom events, you must specify which packages to scan for events of
type <literal>RemoteApplicationEvent</literal> using <literal>@RemoteApplicationEventScan</literal>. Packages
specified with <literal>@RemoteApplicationEventScan</literal> include subpackages.</simpara>
<simpara>For example, if you have a custom event called <literal>FooEvent</literal>:</simpara>
<programlisting language="java" linenumbering="unnumbered">package com.acme;
public class FooEvent extends RemoteApplicationEvent {
...
}</programlisting>
<simpara>you can register this event with the deserializer in the following way:</simpara>
<programlisting language="java" linenumbering="unnumbered">package com.acme;
@Configuration
@RemoteApplicationEventScan
public class BusConfiguration {
...
}</programlisting>
<simpara>Without specifying a value, the package of the class where <literal>@RemoteApplicationEventScan</literal>
is used will be registered. In this example <literal>com.acme</literal> will be registered using the
package of <literal>BusConfiguration</literal>.</simpara>
<simpara>You can also explicitly specify the packages to scan using the <literal>value</literal>, <literal>basePackages</literal> or
<literal>basePackageClasses</literal> properties on <literal>@RemoteApplicationEventScan</literal>. For example:</simpara>
<programlisting language="java" linenumbering="unnumbered">package com.acme;
@Configuration
//@RemoteApplicationEventScan({"com.acme", "foo.bar"})
//@RemoteApplicationEventScan(basePackages = {"com.acme", "foo.bar", "fizz.buzz"})
@RemoteApplicationEventScan(basePackageClasses = BusConfiguration.class)
public class BusConfiguration {
...
}</programlisting>
<simpara>All examples of <literal>@RemoteApplicationEventScan</literal> above are equivalent,
in that the <literal>com.acme</literal> package will be registered by explicitly specifying the
packages on <literal>@RemoteApplicationEventScan</literal>. Note, you can specify multiple base
packages to scan.</simpara>
</section>
</chapter>
</book>