diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 2942d11..1702d2a 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -1,3 +1,8 @@ * xref:index.adoc[] +* xref:quickstart.adoc[] * xref:spring-cloud-bus.adoc[] +** xref:spring-cloud-bus/bus-endpoints.adoc[] +** xref:spring-cloud-bus/addressing.adoc[] +** xref:spring-cloud-bus/configuration.adoc[] +** xref:spring-cloud-bus/custom-events.adoc[] * xref:appendix.adoc[] diff --git a/docs/modules/ROOT/pages/appendix.adoc b/docs/modules/ROOT/pages/appendix.adoc index fe0143e..6a78360 100644 --- a/docs/modules/ROOT/pages/appendix.adoc +++ b/docs/modules/ROOT/pages/appendix.adoc @@ -11,3 +11,4 @@ This appendix provides a list of common Spring Cloud Bus properties and referenc NOTE: Property contributions can come from additional jar files on your classpath, so you should not consider this an exhaustive list. Also, you can define your own properties. +include::partial$_configprops.adoc[] \ No newline at end of file diff --git a/docs/modules/ROOT/pages/quickstart.adoc b/docs/modules/ROOT/pages/quickstart.adoc index 25dedda..98a17bf 100644 --- a/docs/modules/ROOT/pages/quickstart.adoc +++ b/docs/modules/ROOT/pages/quickstart.adoc @@ -1,5 +1,5 @@ [[spring-cloud-gateway-quickstart]] -== Quickstart += Quickstart Spring Cloud Bus works by adding Spring Boot autconfiguration if it detects itself on the classpath. To enable the bus, add `spring-cloud-starter-bus-amqp` or diff --git a/docs/modules/ROOT/pages/spring-cloud-bus.adoc b/docs/modules/ROOT/pages/spring-cloud-bus.adoc index 9adb7fe..883c77b 100644 --- a/docs/modules/ROOT/pages/spring-cloud-bus.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-bus.adoc @@ -1,236 +1,5 @@ [[spring-cloud-bus]] = Spring Cloud Bus +:page-section-summary-toc: 1 -include::quickstart.adoc[] - -[[bus-endpoints]] -== Bus Endpoints - -Spring Cloud Bus provides two endpoints, `/actuator/busrefresh` and `/actuator/busenv` -that correspond to individual actuator endpoints in Spring Cloud Commons, -`/actuator/refresh` and `/actuator/env` respectively. - -[[bus-refresh-endpoint]] -=== Bus Refresh Endpoint -The `/actuator/busrefresh` endpoint clears the `RefreshScope` cache and rebinds -`@ConfigurationProperties`. See the <> documentation for -more information. - -To expose the `/actuator/busrefresh` endpoint, you need to add following configuration to your -application: - -[source,properties] ----- -management.endpoints.web.exposure.include=busrefresh ----- - -[[bus-env-endpoint]] -=== Bus Env Endpoint -The `/actuator/busenv` endpoint updates each instances environment with the specified -key/value pair across multiple instances. - -To expose the `/actuator/busenv` endpoint, you need to add following configuration to your -application: - -[source,properties] ----- -management.endpoints.web.exposure.include=busenv ----- - -The `/actuator/busenv` endpoint accepts `POST` requests with the following shape: - -[source,json] ----- -{ - "name": "key1", - "value": "value1" -} ----- - -[[addressing-an-instance]] -== Addressing an Instance - -Each instance of the application has a service ID, whose value can be set with -`spring.cloud.bus.id` and whose value is expected to be a colon-separated list of -identifiers, in order from least specific to most specific. The default value is -constructed from the environment as a combination of the `spring.application.name` and -`server.port` (or `spring.application.index`, if set). The default value of the ID is -constructed in the form of `app:index:id`, where: - -* `app` is the `vcap.application.name`, if it exists, or `spring.application.name` -* `index` is the `vcap.application.instance_index`, if it exists, -`spring.application.index`, `local.server.port`, `server.port`, or `0` (in that order). -* `id` is the `vcap.application.instance_id`, if it exists, or a random value. - -The HTTP endpoints accept a "`destination`" path parameter, such as -`/busrefresh/customers:9000`, where `destination` is a service ID. If the ID -is owned by an instance on the bus, it processes the message, and all other instances -ignore it. - -[[addressing-all-instances-of-a-service]] -== Addressing All Instances of a Service - -The "`destination`" parameter is used in a Spring `PathMatcher` (with the path separator -as a colon -- `:`) to determine if an instance processes the message. Using the example -from earlier, `/busenv/customers:**` targets all instances of the -"`customers`" service regardless of the rest of the service ID. - -[[service-id-must-be-unique]] -== Service ID Must Be Unique - -The bus tries twice to eliminate processing an event -- once from the original -`ApplicationEvent` and once from the queue. To do so, it checks the sending service ID -against the current service ID. If multiple instances of a service have the same ID, -events are not processed. When running on a local machine, each service is on a different -port, and that port is part of the ID. Cloud Foundry supplies an index to differentiate. -To ensure that the ID is unique outside Cloud Foundry, set `spring.application.index` to -something unique for each instance of a service. - -[[customizing-the-message-broker]] -== Customizing the Message Broker - -Spring Cloud Bus uses https://cloud.spring.io/spring-cloud-stream[Spring Cloud Stream] to -broadcast the messages. So, to get messages to flow, you need only include the binder -implementation of your choice in the classpath. There are convenient starters for the bus -with AMQP (RabbitMQ) and Kafka (`spring-cloud-starter-bus-[amqp|kafka]`). Generally -speaking, Spring Cloud Stream relies on Spring Boot autoconfiguration conventions for -configuring middleware. For instance, the AMQP broker address can be changed with -`spring.rabbitmq.{asterisk}` configuration properties. Spring Cloud Bus has a handful of -native configuration properties in `spring.cloud.bus.{asterisk}` (for example, -`spring.cloud.bus.destination` is the name of the topic to use as the external -middleware). Normally, the defaults suffice. - -To learn more about how to customize the message broker settings, consult the Spring Cloud -Stream documentation. - -[[tracing-bus-events]] -== Tracing Bus Events - -Bus events (subclasses of `RemoteApplicationEvent`) can be traced by setting -`spring.cloud.bus.trace.enabled=true`. If you do so, the Spring Boot `TraceRepository` -(if it is present) shows each event sent and all the acks from each service instance. The -following example comes from the `/trace` endpoint: - -[source,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": "*:**" - } -} ----- - -The preceding trace shows that a `RefreshRemoteApplicationEvent` was sent from -`customers:9000`, broadcast to all services, and received (acked) by `customers:9000` and -`stores:8081`. - -To handle the ack signals yourself, you could add an `@EventListener` for the -`AckRemoteApplicationEvent` and `SentApplicationEvent` types to your app (and enable -tracing). Alternatively, you could tap into the `TraceRepository` and mine the data from -there. - -NOTE: Any Bus application can trace acks. However, sometimes, it is -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. - -[[broadcasting-your-own-events]] -== Broadcasting Your Own Events - -The Bus can carry any event of type `RemoteApplicationEvent`. 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, you must put it in a subpackage of -`org.springframework.cloud.bus.event`. - -To customise the event name, you can use `@JsonTypeName` on your custom class or rely on -the default strategy, which is to use the simple name of the class. - -NOTE: Both the producer and the consumer need access to the class definition. - -[[registering-events-in-custom-packages]] -=== Registering events in custom packages - -If you cannot or do not want to use a subpackage of `org.springframework.cloud.bus.event` -for your custom events, you must specify which packages to scan for events of type -`RemoteApplicationEvent` by using the `@RemoteApplicationEventScan` annotation. Packages -specified with `@RemoteApplicationEventScan` include subpackages. - -For example, consider the following custom event, called `MyEvent`: - -[source,java] ----- -package com.acme; - -public class MyEvent extends RemoteApplicationEvent { - ... -} ----- - -You can register that event with the deserializer in the following way: - -[source,java] ----- -package com.acme; - -@Configuration -@RemoteApplicationEventScan -public class BusConfiguration { - ... -} ----- - -Without specifying a value, the package of the class where `@RemoteApplicationEventScan` -is used is registered. In this example, `com.acme` is registered by using the package of -`BusConfiguration`. - -You can also explicitly specify the packages to scan by using the `value`, `basePackages` -or `basePackageClasses` properties on `@RemoteApplicationEventScan`, as shown in the -following example: - -[source,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 { - ... -} ----- - -All of the preceding examples of `@RemoteApplicationEventScan` are equivalent, in that the -`com.acme` package is registered by explicitly specifying the packages on -`@RemoteApplicationEventScan`. - -NOTE: You can specify multiple base packages to scan. - -[[configuration-properties]] -== Configuration properties - -To see the list of all Bus related configuration properties please check link:appendix.html[the Appendix page]. +*{spring-cloud-version}* diff --git a/docs/modules/ROOT/pages/spring-cloud-bus/addressing.adoc b/docs/modules/ROOT/pages/spring-cloud-bus/addressing.adoc new file mode 100644 index 0000000..9fea533 --- /dev/null +++ b/docs/modules/ROOT/pages/spring-cloud-bus/addressing.adoc @@ -0,0 +1,43 @@ +[[addressing]] += Addressing Instances +:page-section-summary-toc: 1 + +[[addressing-an-instance]] +== Addressing an Instance + +Each instance of the application has a service ID, whose value can be set with +`spring.cloud.bus.id` and whose value is expected to be a colon-separated list of +identifiers, in order from least specific to most specific. The default value is +constructed from the environment as a combination of the `spring.application.name` and +`server.port` (or `spring.application.index`, if set). The default value of the ID is +constructed in the form of `app:index:id`, where: + +* `app` is the `vcap.application.name`, if it exists, or `spring.application.name` +* `index` is the `vcap.application.instance_index`, if it exists, +`spring.application.index`, `local.server.port`, `server.port`, or `0` (in that order). +* `id` is the `vcap.application.instance_id`, if it exists, or a random value. + +The HTTP endpoints accept a "`destination`" path parameter, such as +`/busrefresh/customers:9000`, where `destination` is a service ID. If the ID +is owned by an instance on the bus, it processes the message, and all other instances +ignore it. + +[[addressing-all-instances-of-a-service]] +== Addressing All Instances of a Service + +The "`destination`" parameter is used in a Spring `PathMatcher` (with the path separator +as a colon -- `:`) to determine if an instance processes the message. Using the example +from earlier, `/busenv/customers:**` targets all instances of the +"`customers`" service regardless of the rest of the service ID. + +[[service-id-must-be-unique]] +== Service ID Must Be Unique + +The bus tries twice to eliminate processing an event -- once from the original +`ApplicationEvent` and once from the queue. To do so, it checks the sending service ID +against the current service ID. If multiple instances of a service have the same ID, +events are not processed. When running on a local machine, each service is on a different +port, and that port is part of the ID. Cloud Foundry supplies an index to differentiate. +To ensure that the ID is unique outside Cloud Foundry, set `spring.application.index` to +something unique for each instance of a service. + diff --git a/docs/modules/ROOT/pages/spring-cloud-bus/bus-endpoints.adoc b/docs/modules/ROOT/pages/spring-cloud-bus/bus-endpoints.adoc new file mode 100644 index 0000000..76ff885 --- /dev/null +++ b/docs/modules/ROOT/pages/spring-cloud-bus/bus-endpoints.adoc @@ -0,0 +1,44 @@ +[[bus-endpoints]] += Bus Endpoints +:page-section-summary-toc: 1 + +Spring Cloud Bus provides two endpoints, `/actuator/busrefresh` and `/actuator/busenv` +that correspond to individual actuator endpoints in Spring Cloud Commons, +`/actuator/refresh` and `/actuator/env` respectively. + +[[bus-refresh-endpoint]] +== Bus Refresh Endpoint +The `/actuator/busrefresh` endpoint clears the `RefreshScope` cache and rebinds +`@ConfigurationProperties`. See the <> documentation for +more information. + +To expose the `/actuator/busrefresh` endpoint, you need to add following configuration to your +application: + +[source,properties] +---- +management.endpoints.web.exposure.include=busrefresh +---- + +[[bus-env-endpoint]] +== Bus Env Endpoint +The `/actuator/busenv` endpoint updates each instances environment with the specified +key/value pair across multiple instances. + +To expose the `/actuator/busenv` endpoint, you need to add following configuration to your +application: + +[source,properties] +---- +management.endpoints.web.exposure.include=busenv +---- + +The `/actuator/busenv` endpoint accepts `POST` requests with the following shape: + +[source,json] +---- +{ + "name": "key1", + "value": "value1" +} +---- \ No newline at end of file diff --git a/docs/modules/ROOT/pages/spring-cloud-bus/configuration.adoc b/docs/modules/ROOT/pages/spring-cloud-bus/configuration.adoc new file mode 100644 index 0000000..30e86eb --- /dev/null +++ b/docs/modules/ROOT/pages/spring-cloud-bus/configuration.adoc @@ -0,0 +1,76 @@ +[[configuration]] += Configuration +:page-section-summary-toc: 1 + +[[customizing-the-message-broker]] +== Customizing the Message Broker + +Spring Cloud Bus uses https://cloud.spring.io/spring-cloud-stream[Spring Cloud Stream] to +broadcast the messages. So, to get messages to flow, you need only include the binder +implementation of your choice in the classpath. There are convenient starters for the bus +with AMQP (RabbitMQ) and Kafka (`spring-cloud-starter-bus-[amqp|kafka]`). Generally +speaking, Spring Cloud Stream relies on Spring Boot autoconfiguration conventions for +configuring middleware. For instance, the AMQP broker address can be changed with +`spring.rabbitmq.{asterisk}` configuration properties. Spring Cloud Bus has a handful of +native configuration properties in `spring.cloud.bus.{asterisk}` (for example, +`spring.cloud.bus.destination` is the name of the topic to use as the external +middleware). Normally, the defaults suffice. + +To learn more about how to customize the message broker settings, consult the Spring Cloud +Stream documentation. + +[[tracing-bus-events]] +== Tracing Bus Events + +Bus events (subclasses of `RemoteApplicationEvent`) can be traced by setting +`spring.cloud.bus.trace.enabled=true`. If you do so, the Spring Boot `TraceRepository` +(if it is present) shows each event sent and all the acks from each service instance. The +following example comes from the `/trace` endpoint: + +[source,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": "*:**" + } +} +---- + +The preceding trace shows that a `RefreshRemoteApplicationEvent` was sent from +`customers:9000`, broadcast to all services, and received (acked) by `customers:9000` and +`stores:8081`. + +To handle the ack signals yourself, you could add an `@EventListener` for the +`AckRemoteApplicationEvent` and `SentApplicationEvent` types to your app (and enable +tracing). Alternatively, you could tap into the `TraceRepository` and mine the data from +there. + +NOTE: Any Bus application can trace acks. However, sometimes, it is +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. + diff --git a/docs/modules/ROOT/pages/spring-cloud-bus/custom-events.adoc b/docs/modules/ROOT/pages/spring-cloud-bus/custom-events.adoc new file mode 100644 index 0000000..985b99e --- /dev/null +++ b/docs/modules/ROOT/pages/spring-cloud-bus/custom-events.adoc @@ -0,0 +1,76 @@ +[[custom-events]] += Custom Events +:page-section-summary-toc: 1 + +[[broadcasting-your-own-events]] +== Broadcasting Your Own Events + +The Bus can carry any event of type `RemoteApplicationEvent`. 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, you must put it in a subpackage of +`org.springframework.cloud.bus.event`. + +To customise the event name, you can use `@JsonTypeName` on your custom class or rely on +the default strategy, which is to use the simple name of the class. + +NOTE: Both the producer and the consumer need access to the class definition. + +[[registering-events-in-custom-packages]] +=== Registering events in custom packages + +If you cannot or do not want to use a subpackage of `org.springframework.cloud.bus.event` +for your custom events, you must specify which packages to scan for events of type +`RemoteApplicationEvent` by using the `@RemoteApplicationEventScan` annotation. Packages +specified with `@RemoteApplicationEventScan` include subpackages. + +For example, consider the following custom event, called `MyEvent`: + +[source,java] +---- +package com.acme; + +public class MyEvent extends RemoteApplicationEvent { + ... +} +---- + +You can register that event with the deserializer in the following way: + +[source,java] +---- +package com.acme; + +@Configuration +@RemoteApplicationEventScan +public class BusConfiguration { + ... +} +---- + +Without specifying a value, the package of the class where `@RemoteApplicationEventScan` +is used is registered. In this example, `com.acme` is registered by using the package of +`BusConfiguration`. + +You can also explicitly specify the packages to scan by using the `value`, `basePackages` +or `basePackageClasses` properties on `@RemoteApplicationEventScan`, as shown in the +following example: + +[source,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 { + ... +} +---- + +All of the preceding examples of `@RemoteApplicationEventScan` are equivalent, in that the +`com.acme` package is registered by explicitly specifying the packages on +`@RemoteApplicationEventScan`. + +NOTE: You can specify multiple base packages to scan. +