From 90aa42e68bc316511588268532186d6bf8ba353e Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 3 Feb 2016 17:07:57 +0000 Subject: [PATCH] Sync docs from master to gh-pages --- ghpages.sh | 2 +- spring-cloud.html | 1994 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 1994 insertions(+), 2 deletions(-) diff --git a/ghpages.sh b/ghpages.sh index aa9a60ad..b96a721b 100644 --- a/ghpages.sh +++ b/ghpages.sh @@ -1,6 +1,6 @@ #!/bin/bash -x -git remote add docs https://github.com/spring-projects/spring-cloud-static +git remote add docs https://github.com/spring-cloud/spring-cloud-static if ! (git fetch docs && git checkout --track docs/gh-pages); then echo "No gh-pages, error" diff --git a/spring-cloud.html b/spring-cloud.html index 2722723f..533160ec 100644 --- a/spring-cloud.html +++ b/spring-cloud.html @@ -550,6 +550,36 @@ body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-b +
  • Spring Cloud Stream Reference Guide
  • +
  • Reference Guide + +
  • +
  • Samples + +
  • +
  • Appendices + +
  • Spring Cloud Bus
  • +
  • Spring Cloud Sleuth + +
  • +
  • Spring Cloud Consul + +
  • +
  • Spring Cloud Zookeeper + +
  • Spring Boot Cloud CLI
  • +
  • Spring Cloud for Cloud Foundry + +
  • +
  • Spring Cloud Cluster + +
  • @@ -4741,6 +4860,518 @@ After executing several requests against your service, you can gather some very +

    Spring Cloud Stream Reference Guide

    +
    +
    +Sabby Anandan, Marius Bogoevici, Eric Bottard, Mark Fisher, Ilayaperumal Gopinathan, Gunnar Hillert, Mark Pollack, Patrick Peralta, Glenn Renfro, Thomas Risberg, Dave Syer, David Turanski, Janne Valkealahti +:doctype: book +:toc: +:toclevels: 4 +:source-highlighter: prettify +:numbered: +:icons: font +:hide-uri-scheme: +:spring-cloud-dataflow-repo: snapshot +:github-tag: master +:spring-cloud-dataflow-docs-version: current +:spring-cloud-dataflow-docs: http://docs.spring.io/spring-cloud-dataflow/docs/{spring-cloud-dataflow-docs-version}/reference +:spring-cloud-dataflow-docs-current: http://docs.spring.io/spring-cloud-dataflow/docs/current-SNAPSHOT/reference/html/ +:github-repo: spring-projects/spring-cloud-dataflow +:github-raw: http://raw.github.com/spring-cloud/spring-cloud-netflix/master +:github-code: http://github.com/spring-cloud/spring-cloud-netflix/tree/master +:github-wiki: http://github.com/spring-cloud/spring-cloud-netflix/wiki +:github-master-code: http://github.com/spring-cloud/spring-cloud-netflix/tree/master +:sc-ext: java +:sc-spring-boot: http://github.com/spring-cloud/spring-cloud-netflix/tree/master/spring-boot/src/main/java/org/springframework/boot +:dc-ext: html +:dc-root: http://docs.spring.io/spring-cloud-dataflow/docs/{spring-cloud-dataflow-docs-version}/api +:dc-spring-boot: {dc-root}/org/springframework/boot +:dependency-management-plugin: https://github.com/spring-gradle-plugins/dependency-management-plugin +:dependency-management-plugin-documentation: {dependency-management-plugin}/blob/master/README.md +:spring-boot-maven-plugin-site: http://docs.spring.io/spring-boot/docs/{spring-boot-docs-version}/maven-plugin +:spring-reference: http://docs.spring.io/spring/docs/{spring-docs-version}/spring-framework-reference/htmlsingle +:spring-security-reference: http://docs.spring.io/spring-security/site/docs/{spring-security-docs-version}/reference/htmlsingle +:spring-javadoc: http://docs.spring.io/spring/docs/{spring-docs-version}/javadoc-api/org/springframework +:spring-amqp-javadoc: http://docs.spring.io/spring-amqp/docs/current/api/org/springframework/amqp +:spring-data-javadoc: http://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa +:spring-data-commons-javadoc: http://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data +:spring-data-mongo-javadoc: http://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb +:spring-data-rest-javadoc: http://docs.spring.io/spring-data/rest/docs/current/api/org/springframework/data/rest +:gradle-userguide: http://www.gradle.org/docs/current/userguide +:propdeps-plugin: https://github.com/spring-projects/gradle-plugins/tree/master/propdeps-plugin +:ant-manual: http://ant.apache.org/manual +
    +
    +

    Reference Guide

    +
    +

    Spring Cloud Stream Overview

    +
    + +
    +

    Introducing Spring Cloud Stream

    +
    +

    The Spring Cloud Stream project allows a user to develop and run messaging microservices using Spring Integration. Just add @EnableBinding and run your app as a Spring Boot app (single application context). You just need to connect to the physical broker for the bindings, which is automatic if the relevant binder implementation is available on the classpath. The sample uses Redis.

    +
    +
    +

    Here’s a sample source module (output channel only):

    +
    +
    +
    +
    @SpringBootApplication
    +@ComponentScan(basePackageClasses=TimerSource.class)
    +public class ModuleApplication {
    +
    +  public static void main(String[] args) {
    +    SpringApplication.run(ModuleApplication.class, args);
    +  }
    +
    +}
    +
    +@Configuration
    +@EnableBinding(Source.class)
    +public class TimerSource {
    +
    +  @Value("${format}")
    +  private String format;
    +
    +  @Bean
    +  @InboundChannelAdapter(value = Source.OUTPUT, poller = @Poller(fixedDelay = "${fixedDelay}", maxMessagesPerPoll = "1"))
    +  public MessageSource<String> timerMessageSource() {
    +    return () -> new GenericMessage<>(new SimpleDateFormat(format).format(new Date()));
    +  }
    +
    +}
    +
    +
    +
    +

    @EnableBinding is parameterized by one or more interfaces (in this case a single Source interface), which declares input and output channels. The interfaces Source, Sink and Processor are provided off the shelf, but you can define others. Here’s the definition of Source:

    +
    +
    +
    +
    public interface Source {
    +  @Output("output")
    +  MessageChannel output();
    +}
    +
    +
    +
    +

    The @Output annotation is used to identify output channels (messages leaving the module) and @Input is used to identify input channels (messages entering the module). It is optionally parameterized by a channel name - if the name is not provided the method name is used instead. An implementation of the interface is created for you and can be used in the application context by autowiring it, e.g. into a test case:

    +
    +
    +
    +
    @RunWith(SpringJUnit4ClassRunner.class)
    +@SpringApplicationConfiguration(classes = ModuleApplication.class)
    +@WebAppConfiguration
    +@DirtiesContext
    +public class ModuleApplicationTests {
    +
    +	@Autowired
    +	private Source source
    +
    +	@Test
    +	public void contextLoads() {
    +		assertNotNull(this.source.output());
    +	}
    +
    +}
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +In this case there is only one Source in the application context so there is no need to qualify it when it is autowired. If there is ambiguity, e.g. if you are composing one module from some others, you can use @Bindings qualifier to inject a specific channel set. The @Bindings qualifier takes a parameter which is the class that carries the @EnableBinding annotation (in this case the TimerSource). +
    +
    +
    +

    Multiple Input or Output Channels

    +
    +

    A module can have multiple input or output channels defined as @Input and @Output methods in an interface. Instead of just one channel named "input" or "output" you can add multiple MessageChannel methods annotated @Input or @Output and their names will be converted to external channel names on the broker. It is common to specify the channel names at runtime in order to have multiple modules communicate over a well known channel names. Channel names can be specified as properties that consist of the channel names prefixed with spring.cloud.stream.bindings (e.g. spring.cloud.stream.bindings.input or spring.cloud.stream.bindings.output). These properties can be specified though environment variables, the application YAML file or the other mechanism supported by Spring Boot.

    +
    +
    +

    Channel names can also have a channel type as a colon-separated prefix, and the semantics of the external bus channel changes accordingly. For example, you can have two MessageChannels called "output" and "foo" in a module with spring.cloud.stream.bindings.output=bar and spring.cloud.stream.bindings.foo=topic:foo, and the result is 2 external channels called "bar" and "topic:foo". The queue prefix for point to point semantics is also supported. Note, that in a future release only topic (pub/sub) semantics will be supported.

    +
    +
    +
    +

    Inter-module communication

    +
    +

    While Spring Cloud Stream makes it easy for individual modules to connect to messaging systems, the typical scenario for Spring Cloud Stream is the creation of multi-module pipelines, where modules are sending data to each other. This can be achieved by correlating the input and output destinations of adjacent modules, as in the following example.

    +
    +
    +

    Supposing that the design calls for the time-source module to send data to the log-sink module, we will use a common destination named foo for both modules. time-source will set spring.cloud.stream.bindings.output=foo and log-sink will set spring.cloud.stream.bindings.input=foo.

    +
    +
    +
    +

    Advanced binding properties

    +
    +

    The input and output channel names are the common properties to set in order to have Spring Cloud Stream applications communicate with each other as the channels are bound to an external message broker automatically. However, there are a number of scenarios when it is required to configure other attributes besides the channel name. This is done using the following naming scheme: spring.cloud.stream.bindings.<channelName>.<attributeName>=<attributeValue>. The destination attribute can also be used for configuring the external channel, as follows: spring.cloud.stream.bindings.input.destination=foo. This is equivalent to spring.cloud.stream.bindings.input=foo, but the latter can be used only when there are no other attributes to set on the binding. In other words, spring.cloud.stream.bindings.input.destination=foo,spring.cloud.stream.bindings.input.partitioned=true is a valid setup, whereas spring.cloud.stream.bindings.input=foo,spring.cloud.stream.bindings.input.partitioned=true is not valid.

    +
    +
    +
    Partitioning
    +
    +

    Spring Cloud Stream provides support for partitioning data between multiple instances of a given application. In a partitioned scenario, one or more producer modules will send data to one or more consumer modules, ensuring that data with common characteristics is processed by the same consumer instance. The physical communication medium (i.e. the broker topic or queue) is viewed as structured into multiple partitions. Regardless whether the broker type is naturally partitioned (e.g. Kafka) or not (e.g. Rabbit or Redis), Spring Cloud Stream provides a common abstraction for implementing partitioned processing use cases in a uniform fashion.

    +
    +
    +

    Setting up a partitioned processing scenario requires configuring both the data producing and the data consuming end.

    +
    +
    +
    Configuring output channels for partitioning
    +
    +

    An output channel is configured to send partitioned data, by setting one and only one of its partitionKeyExpression or partitionKeyExtractorClass properties, as well as its partitionCount property. For example seting spring.cloud.stream.bindings.output.partitionKeyExpression=payload.id,spring.cloud.stream.bindings.output.partitionCount=5 is a valid and typical configuration.

    +
    +
    +

    Based on this configuration, the data will be sent to the target partition using the following logic. A partition key’s value is calculated for each message sent to a partitioned output channel based on the partitionKeyExpression. The partitionKeyExpression is a SpEL expression that is evaluated against the outbound message for extracting the partitioning key. If a SpEL expression is not sufficent for your needs, you can instead calculate the partition key value by setting the the property partitionKeyExtractorClass. This class must implement the interface org.springframework.cloud.stream.binder.PartitionKeyExtractorStrategy. While, in general, the SpEL expression is enough, more complex cases may use the custom implementation strategy.

    +
    +
    +

    Once the message key is calculated, the partition selection process will determine the target partition as a value between 0 and partitionCount. The default calculation, applicable in most scenarios is based on the formula key.hashCode() % partitionCount. This can be customized on the binding, either by setting a SpEL expression to be evaluated against the key via the partitionSelectorExpression property, or by setting a org.springframework.cloud.stream.binder.PartitionSelectorStrategy implementation via the partitionSelectorClass property.

    +
    +
    +

    Additional properties can be configured for more advanced scenarios, as described in the following section.

    +
    +
    +
    +
    Configuring input channels for partitioning
    +
    +

    An input channel is configured to receive partitioned data by setting its partitioned binding property, as well as the instance index and instance count properties on the module, as follows: spring.cloud.stream.bindings.input.partitioned=true,spring.cloud.stream.instanceIndex=3,spring.cloud.stream.instanceCount=5. The instance count value represents the total number of similar modules between which the data needs to be partitioned, whereas instance index must be value unique across the multiple instances between 0 and instanceCount - 1. The instance index helps each module to identify the unique partition (or in the case of Kafka, the partition set) that they receive data from. It is important that both values are set correctly in order to ensure that all the data is consumed, as well as that the modules receive mutually exclusive datasets.

    +
    +
    +

    While setting up multiple instances for partitioned data processing may be complex in the standalone case, Spring Cloud Data Flow can simplify the process significantly, by populating both the input and output values correctly, as well as relying on the runtime infrastructure to provide information about the instance index and instance count.

    +
    +
    +
    +
    +
    +
    +

    Binder selection

    +
    +

    Spring Cloud Stream relies on implementations of the Binder SPI to perform the task of connecting channels to message brokers. Each binder implementation typically connects to one type of messaging system. Spring Cloud Stream provides out of the box binders for Redis, Rabbit and Kafka.

    +
    +
    +
    Classpath detection
    +
    +

    By default, Spring Cloud Stream relies on Spring Boot’s auto-configuration configure the binding process. If a single binder implementation is found on the classpath, Spring Cloud Stream will use it automatically. So, for example, a Spring Cloud Stream project that aims to connect to Rabbit MQ can simply add the following dependency to their application:

    +
    +
    +
    +
    <dependency>
    +  <groupId>org.springframework.cloud</groupId>
    +  <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
    +</dependency>
    +
    +
    +
    +
    +
    Multiple binders on the classpath
    +
    +

    When multiple binders are present on the classpath, the application must indicate what binder has to be used for the channel. Each binder configuration contains a META-INF/spring.binders, which is in fact a property file:

    +
    +
    +
    +
    rabbit:\
    +org.springframework.cloud.stream.binder.rabbit.config.RabbitServiceAutoConfiguration
    +
    +
    +
    +

    Similar files exist for the other binder implementations (i.e. Kafka and Redis), and it is expected that custom binder implementations will provide them, too. The key represents an identifying name for the binder implementation, whereas the value is a comma-separated list of configuration classes that contain one and only one bean definition of the type org.springframework.cloud.stream.binder.Binder.

    +
    +
    +

    Selecting the binder can be done globally by either using the spring.cloud.stream.defaultBinder property, e.g. spring.cloud.stream.defaultBinder=redis, or by individually configuring them on each channel.

    +
    +
    +

    For instance, a processor module that reads from Rabbit and writes to Redis can specify the following configuration: spring.cloud.stream.bindings.input.binder=rabbit,spring.cloud.stream.bindings.output.binder=redis.

    +
    +
    +
    +
    Connecting to multiple systems
    +
    +

    By default, binders share the Spring Boot autoconfiguration of the application module and create one instance of each binder found on the classpath. In scenarios where a module should connect to more than one broker of the same type, Spring Cloud Stream allows you to specify multiple binder configurations, with different environment settings. Please note that turning on explicit binder configuration will disable the default binder configuration process altogether, so all the binders in use must be included in the configuration.

    +
    +
    +

    For example, this is the typical configuration for a processor that connects to two rabbit instances:

    +
    +
    +
    +
    spring:
    +  cloud:
    +    stream:
    +      bindings:
    +        input:
    +          destination: foo
    +          binder: rabbit1
    +        output:
    +          destination: bar
    +          binder: rabbit2
    +      binders:
    +        rabbit1:
    +          type: rabbit
    +          environment:
    +            spring:
    +              rabbit:
    +                host: <host1>
    +        rabbit2:
    +          type: rabbit
    +          environment:
    +            spring:
    +              rabbit:
    +                host: <host2>
    +
    +
    +
    +
    +
    +

    Managed vs standalone

    +
    +

    Code using the Spring Cloud Stream library can be deployed as a standalone application or be used as a Spring Cloud Data Flow module. In standalone mode your application will run happily as a service or in any PaaS (Cloud Foundry, Lattice, Heroku, Azure, etc.). Spring Cloud Data Flow helps orchestrating the communication between instances, so the aspects of module configuration that deal with module interconnection will be configured transparently.

    +
    +
    +

    Fat JAR

    +
    +

    You can run in standalone mode from your IDE for testing. To run in production you can create an executable (or "fat") JAR using the standard Spring Boot tooling provided by Maven or Gradle.

    +
    +
    +
    +
    +
    +

    Samples

    +
    +

    Sample Applications

    +
    +
    +

    There are several samples, all running on the redis transport (so you need redis running locally to test them).

    +
    +
    +
      +
    • +

      source is a Java config version of the classic "timer" module from Spring XD. It has a "fixedDelay" option (in milliseconds) for the period between emitting messages.

      +
    • +
    • +

      sink is a Java config version of the classic "log" module from Spring XD. It has no options (but some could easily be added), and just logs incoming messages at INFO level.

      +
    • +
    • +

      transform is a simple pass through logging transformer (just logs the incoming message and passes it on).

      +
    • +
    • +

      double is a combination of 2 modules defined locally (a source and a sink, so the whole app is self contained).

      +
    • +
    • +

      extended is a multi-module mashup of source | transform | transform | sink, where the modules are defined in the other samples and referred to in this app just as dependencies.

      +
    • +
    +
    +
    +

    If you run the source and the sink and point them at the same redis instance (e.g. do nothing to get the one on localhost, or the one they are both bound to as a service on Cloud Foundry) then they will form a "stream" and start talking to each other. All the samples have friendly JMX and Actuator endpoints for inspecting what is going on in the system.

    +
    +
    +
    +

    Appendices

    +
    +

    Appendix A: Building

    +
    +
    +

    Basic Compile and Test

    +
    +

    To build the source you will need to install JDK 1.7.

    +
    +
    +

    The build uses the Maven wrapper so you don’t have to install a specific +version of Maven. To enable the tests for Redis, Rabbit, and Kafka bindings you +should have those servers running before building. See below for more +information on running the servers.

    +
    +
    +

    The main build command is

    +
    +
    +
    +
    $ ./mvnw clean install
    +
    +
    +
    +

    You can also add '-DskipTests' if you like, to avoid running the tests.

    +
    +
    + + + + + +
    +
    Note
    +
    +You can also install Maven (>=3.3.3) yourself and run the mvn command +in place of ./mvnw in the examples below. If you do that you also +might need to add -P spring if your local Maven settings do not +contain repository declarations for spring pre-release artifacts. +
    +
    +
    + + + + + +
    +
    Note
    +
    +Be aware that you might need to increase the amount of memory +available to Maven by setting a MAVEN_OPTS environment variable with +a value like -Xmx512m -XX:MaxPermSize=128m. We try to cover this in +the .mvn configuration, so if you find you have to do it to make a +build succeed, please raise a ticket to get the settings added to +source control. +
    +
    +
    +

    The projects that require middleware generally include a +docker-compose.yml, so consider using +Docker Compose to run the middeware servers +in Docker containers. See the README in the +scripts demo +repository for specific instructions about the common cases of mongo, +rabbit and redis.

    +
    +
    +
    +

    Documentation

    +
    +

    There is a "full" profile that will generate documentation.

    +
    +
    +
    +

    Working with the code

    +
    +

    If you don’t have an IDE preference we would recommend that you use +Spring Tools Suite or +Eclipse when working with the code. We use the +m2eclipe eclipse plugin for maven support. Other IDEs and tools +should also work without issue.

    +
    +
    +

    Importing into eclipse with m2eclipse

    +
    +

    We recommend the m2eclipe eclipse plugin when working with +eclipse. If you don’t already have m2eclipse installed it is available from the "eclipse +marketplace".

    +
    +
    +

    Unfortunately m2e does not yet support Maven 3.3, so once the projects +are imported into Eclipse you will also need to tell m2eclipse to use +the .settings.xml file for the projects. If you do not do this you +may see many different errors related to the POMs in the +projects. Open your Eclipse preferences, expand the Maven +preferences, and select User Settings. In the User Settings field +click Browse and navigate to the Spring Cloud project you imported +selecting the .settings.xml file in that project. Click Apply and +then OK to save the preference changes.

    +
    +
    + + + + + +
    +
    Note
    +
    +Alternatively you can copy the repository settings from .settings.xml into your own ~/.m2/settings.xml. +
    +
    +
    +
    +

    Importing into eclipse without m2eclipse

    +
    +

    If you prefer not to use m2eclipse you can generate eclipse project metadata using the +following command:

    +
    +
    +
    +
    $ ./mvnw eclipse:eclipse
    +
    +
    +
    +

    The generated eclipse projects can be imported by selecting import existing projects +from the file menu. +[[contributing] +== Contributing

    +
    +
    +

    Spring Cloud is released under the non-restrictive Apache 2.0 license, +and follows a very standard Github development process, using Github +tracker for issues and merging pull requests into master. If you want +to contribute even something trivial please do not hesitate, but +follow the guidelines below.

    +
    +
    +
    +
    +

    Sign the Contributor License Agreement

    +
    +

    Before we accept a non-trivial patch or pull request we will need you to sign the +contributor’s agreement. +Signing the contributor’s agreement does not grant anyone commit rights to the main +repository, but it does mean that we can accept your contributions, and you will get an +author credit if we do. Active contributors might be asked to join the core team, and +given the ability to merge pull requests.

    +
    +
    +
    +

    Code Conventions and Housekeeping

    +
    +

    None of these is essential for a pull request, but they will all help. They can also be +added after the original pull request but before a merge.

    +
    +
    +
      +
    • +

      Use the Spring Framework code format conventions. If you use Eclipse +you can import formatter settings using the +eclipse-code-formatter.xml file from the +Spring +Cloud Build project. If using IntelliJ, you can use the +Eclipse Code Formatter +Plugin to import the same file.

      +
    • +
    • +

      Make sure all new .java files to have a simple Javadoc class comment with at least an +@author tag identifying you, and preferably at least a paragraph on what the class is +for.

      +
    • +
    • +

      Add the ASF license header comment to all new .java files (copy from existing files +in the project)

      +
    • +
    • +

      Add yourself as an @author to the .java files that you modify substantially (more +than cosmetic changes).

      +
    • +
    • +

      Add some Javadocs and, if you change the namespace, some XSD doc elements.

      +
    • +
    • +

      A few unit tests would help a lot as well — someone has to do it.

      +
    • +
    • +

      If no-one else is using your branch, please rebase it against the current master (or +other target branch in the main project).

      +
    • +
    • +

      When writing a commit message please follow these conventions, +if you are fixing an existing issue please add Fixes gh-XXXX at the end of the commit +message (where XXXX is the issue number).

      +
    • +
    +
    +
    +

    Unresolved directive in spring-cloud.adoc - include::../../../task/spring-cloud-task-docs/src/main/asciidoc/index.adoc[]

    +
    +
    +
    +

    Spring Cloud Bus

    @@ -4894,6 +5525,1120 @@ queries on the data. Or forward it to a specialized tracing service.
    +

    Spring Cloud Sleuth

    +
    +

    Spring Cloud Sleuth

    +
    +
    +

    Spring Cloud Sleuth implements a distributed tracing solution for Spring Cloud.

    +
    +
    +

    Terminology

    +
    +

    Spring Cloud Sleuth borrows Dapper’s terminology.

    +
    +
    +

    Span: The basic unit of work. For example, sending an RPC is a new span, as is sending a response to an RPC. Span’s are identified by a unique 64-bit ID for the span and another 64-bit ID for the trace the span is a part of. Spans also have other data, such as descriptions, timestamped events, key-value annotations (tags), the ID of the span that caused them, and process ID’s (normally IP address).

    +
    +
    +

    Spans are started and stopped, and they keep track of their timing information. Once you create a span, you must stop it at some point in the future.

    +
    +
    +

    Trace: A set of spans forming a tree-like structure. For example, if you are running a distributed big-data store, a trace might be formed by a put request.

    +
    +
    +
    +
    +
    +

    Features

    +
    +
    +
      +
    • +

      Adds trace and span ids to the Slf4J MDC, so you can extract all the logs from a given trace or span in a log aggregator. Example logs:

      +
      +
      +
      2016-02-02 15:30:57.902  INFO [bar,6bfd228dc00d216b,6bfd228dc00d216b,false] 23030 --- [nio-8081-exec-3] ...
      +2016-02-02 15:30:58.372 ERROR [bar,6bfd228dc00d216b,6bfd228dc00d216b,false] 23030 --- [nio-8081-exec-3] ...
      +2016-02-02 15:31:01.936  INFO [bar,46ab0d418373cbc9,46ab0d418373cbc9,false] 23030 --- [nio-8081-exec-4] ...
      +
      +
      +
      +

      (notice the [appname,traceId,spanId,exportable] entries from the MDC).

      +
      +
    • +
    • +

      Optionally log span data in JSON format for harvesting in a log aggregator (set spring.sleuth.log.json.enabled=true).

      +
    • +
    • +

      Provides an abstraction over common distributed tracing data models: traces, spans (forming a DAG), annotations, key-value annotations. Loosely based on HTrace, but Zipkin (Dapper) compatible.

      +
    • +
    • +

      Instruments common ingress and egress points from Spring applications (servlet filter, rest template, scheduled actions, message channels, zuul filters, feign client).

      +
    • +
    • +

      If spring-cloud-sleuth-zipkin then the app will generate and collect Zipkin-compatible traces (using Brave). By default it sends them via HTTP to a Zipkin server on localhost (port 9411). Configure the location of the service using spring.zipkin.[host,port].

      +
    • +
    • +

      If spring-cloud-sleuth-stream then the app will generate and collect traces via Spring Cloud Stream. Your app automatically becomes a producer of tracer messages that are sent over your broker of choice (e.g. RabbitMQ, Apache Kafka, Redis).

      +
    • +
    +
    +
    +

    If using Zipkin or Stream, configure the percentage of spans exported using spring.sleuth.sampler.percentage (default 0.1, i.e. 10%).

    +
    +
    +
    +
    +

    Sampling

    +
    +
    +

    In distributed tracing the data volumes can be very high so sampling +can be important (you usually don’t need to export all spans to get a +good picture of what is happening). Spring Cloud Sleuth has a +Sampler strategy that you can implement to take control of the +sampling algorithm. Samplers do not stop span (correlation) ids from +being generated, but they do prevent the tags and events being +attached and exported. By default you get a strategy that continues to +trace if a span is already active, but new ones are always marked as +non-exportable. If all your apps run with this sampler you will see +traces in logs, but not in any remote store. For testing the default +is often enough, and it probably is all you need if you are only using +the logs (e.g. with an ELK aggregator). If you are exporting span data +to Zipkin or Spring Cloud Stream, there is also an AlwaysSampler +that exports everything and a PercentageBasedSampler that samples a +fixed fraction of spans.

    +
    +
    + + + + + +
    +
    Note
    +
    +the PercentageBasedSampler is the default if you are using +spring-cloud-sleuth-zipkin or spring-cloud-sleuth-stream. You can +configure the exports using spring.sleuth.sampler.percentage. +
    +
    +
    +

    A sampler can be installed just by creating a bean definition, e.g:

    +
    +
    +
    +
    @Bean
    +public Sampler<?> defaultSampler() {
    +    return new AlwaysSampler();
    +}
    +
    +
    +
    +
    +
    +

    Instrumentation

    +
    +
    +

    Spring Cloud Sleuth instruments all your Spring application +automatically, so you shouldn’t have to do anything to activate +it. The instrumentation is added using a variety of technologies +according to the stack that is available, e.g. for a servlet web +application we use a Filter, and for Spring Integration we use +ChannelInterceptors.

    +
    +
    +

    You can customize the keys used in span tags. To limit the volume of +span data, by default an HTTP request will be tagged only with a +handful of metadata like the status code, host and URL. You can add +request headers by configuring spring.sleuth.keys.http.headers (a +list of header names).

    +
    +
    + + + + + +
    +
    Note
    +
    +Remember that tags are only collected and exported if there is a +Sampler that allows it (by default there is not, so there is no +danger of accidentally collecting too much data without configuring +something). +
    +
    +
    +
    +
    +

    Span Data as Messages

    +
    +
    +

    You can accumulate and send span data over +Spring Cloud Stream by +including the spring-cloud-sleuth-stream jar as a dependency, and +adding a Channel Binder implementation +(e.g. spring-cloud-starter-stream-rabbit for RabbitMQ or +spring-cloud-starter-stream-kafka for Kafka). This will +automatically turn your app into a producer of messages with payload +type Spans.

    +
    +
    +

    Zipkin Consumer

    +
    +

    There is a special convenience annotation for setting up a message consumer +for the Span data and pushing it into a Zipkin SpanStore. This application

    +
    +
    +
    +
    @SpringBootApplication
    +@EnableZipkinStreamServer
    +public class Consumer {
    +  public static void main(String[] args) {
    +    SpringApplication.run(Consumer.class, args);
    +  }
    +}
    +
    +
    +
    +

    will listen for the Span data on whatever transport you provide via a +Spring Cloud Stream Binder (e.g. include +spring-cloud-starter-stream-rabbit for RabbitMQ, and similar +starters exist for Redis and Kafka). The app will also be a +Zipkin query server, so you +can point a standard Zipkin UI at it (e.g. run the consumer app on +port 9411 if you want the query server on the same host and the +default configuration).

    +
    +
    +

    The deafult SpanStore is in-memory (good for demos and getting +started quickly). For a more robust solution you can add MySQL and +spring-boot-starter-jdbc to your classpath and enable the JDBC +SpanStore via configuration, e.g.:

    +
    +
    +
    +
    spring:
    +  rabbitmq:
    +    host: ${RABBIT_HOST:localhost}
    +  datasource:
    +    schema: classpath:/mysql.sql
    +    url: jdbc:mysql://${MYSQL_HOST:localhost}/test
    +    username: root
    +    password: root
    +# Switch this on to create the schema on startup:
    +    initialize: true
    +    continueOnError: true
    +  sleuth:
    +    enabled: false
    +zipkin:
    +  store:
    +    type: mysql
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +The @EnableZipkinStreamServer is also annotated with +@EnableZipkinServer so the process will also expose the standard +Zipkin server endpoints for collecting spans over HTTP, and for +querying in the Zipkin Web UI. +
    +
    +
    +
    +

    Custom Consumer

    +
    +

    A custom consumer can also easily be implemented using +spring-cloud-sleuth-stream and binding to the SleuthSink. Example:

    +
    +
    +
    +
    @EnableBinding(SleuthSink.class)
    +@SpringBootApplication(exclude = SleuthStreamAutoConfiguration.class)
    +@MessageEndpoint
    +public class Consumer {
    +
    +    @ServiceActivator(inputChannel = SleuthSink.INPUT)
    +    public void sink(Spans input) throws Exception {
    +        // ... process spans
    +    }
    +}
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +the sample consumer application above explicitly excludes +SleuthStreamAutoConfiguration so it doesn’t send messages to itself, +but this is optional (you might actually want to trace requests into +the consumer app). +
    +
    +
    +
    +
    +

    Spring Cloud Consul

    +
    +
    +This project provides Consul integrations for Spring Boot apps through autoconfiguration +and binding to the Spring Environment and other Spring programming model idioms. With a few +simple annotations you can quickly enable and configure the common patterns inside your +application and build large distributed systems with Consul based components. The +patterns provided include Service Discovery, Control Bus and Configuration. +Intelligent Routing (Zuul) and Client Side Load Balancing (Ribbon), Circuit Breaker +(Hystrix) are provided by integration with Spring Cloud Netflix. +
    +
    +
    +

    Install Consul

    +
    +
    +

    Please see the installation documentation for instructions on how to install Consul.

    +
    +
    +
    +
    +

    Consul Agent

    +
    +
    +

    A Consul Agent client must be available to all Spring Cloud Consul applications. By default, the Agent client is expected to be at localhost:8500. See the Agent documentation for specifics on how to start an Agent client and how to connect to a cluster of Consul Agent Servers. For development, after you have installed consul, you may start a Consul Agent using the following command:

    +
    +
    +
    +
    ./src/main/bash/local_run_consul.sh
    +
    +
    +
    +

    This will start an agent in server mode on port 8500, with the ui available at http://localhost:8500

    +
    +
    +
    +
    +

    Service Discovery with Consul

    +
    +
    +

    Service Discovery is one of the key tenets of a microservice based architecture. Trying to hand configure each client or some form of convention can be very difficult to do and can be very brittle. Consul provides Service Discovery services via an HTTP API and DNS. Spring Cloud Consul leverages the HTTP API for service registration and discovery. This does not prevent non-Spring Cloud applications from leveraging the DNS interface. Consul Agents servers are run in a cluster that communicates via a gossip protocol and uses the Raft consensus protocol.

    +
    +
    +

    Registering with Consul

    +
    +

    When a client registers with Consul, it provides meta-data about itself such as host and port, id, name and tags. An HTTP Check is created by default that Consul hits the /health endpoint every 10 seconds. If the health check fails, the service instance is marked as critical.

    +
    +
    +

    Example Consul client:

    +
    +
    +
    +
    @SpringBootApplication
    +@EnableDiscoveryClient
    +@RestController
    +public class Application {
    +
    +    @RequestMapping("/")
    +    public String home() {
    +        return "Hello world";
    +    }
    +
    +    public static void main(String[] args) {
    +        new SpringApplicationBuilder(Application.class).web(true).run(args);
    +    }
    +
    +}
    +
    +
    +
    +

    (i.e. utterly normal Spring Boot app). If the Consul client is located somewhere other than localhost:8500, the configuration is required to locate the client. Example:

    +
    +
    +
    application.yml
    +
    +
    spring:
    +  cloud:
    +    consul:
    +      host: localhost
    +      port: 8500
    +
    +
    +
    + + + + + +
    +
    Caution
    +
    +If you use Spring Cloud Consul Config, the above values will need to be placed in bootstrap.yml instead of application.yml. +
    +
    +
    +

    The default service name, instance id and port, taken from the Environment, are ${spring.application.name}, the Spring Context ID and ${server.port} respectively.

    +
    +
    +

    @EnableDiscoveryClient make the app into both a Consul "service" (i.e. it registers itself) and a "client" (i.e. it can query Consul to locate other services).

    +
    +
    +
    +

    HTTP Health Check

    +
    +

    The health check for a Consul instance defaults to "/health", which is the default locations of a useful endpoint in a Spring Boot Actuator application. You need to change these, even for an Actuator application if you use a non-default context path or servlet path (e.g. server.servletPath=/foo) or management endpoint path (e.g. management.contextPath=/admin). The interval that Consul uses to check the health endpoint may also be configured. "10s" and "1m" represent 10 seconds and 1 minute respectively. Example:

    +
    +
    +
    application.yml
    +
    +
    spring:
    +  cloud:
    +    consul:
    +      discovery:
    +        healthCheckPath: ${management.contextPath}/health
    +        healthCheckInterval: 15s
    +
    +
    +
    +

    Making the Consul Instance ID Unique

    +
    +

    By default a consul instance is registered with an ID that is equal to its Spring Application Context ID. By default, the Spring Application Context ID is ${spring.application.name}:comma,separated,profiles:${server.port}. For most cases, this will allow multiple instances of one service to run on one machine. If further uniqueness is required, Using Spring Cloud you can override this by providing a unique identifier in spring.cloud.consul.discovery.instanceId. For example:

    +
    +
    +
    application.yml
    +
    +
    spring:
    +  cloud:
    +    consul:
    +      discovery:
    +        instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}}
    +
    +
    +
    +

    With this metadata, and multiple service instances deployed on localhost, the random value will kick in there to make the instance unique. In Cloudfoundry the spring.application.instance_id will be populated automatically in a Spring Boot Actuator application, so the random value will not be needed.

    +
    +
    +
    +
    +

    Using the DiscoveryClient

    +
    +

    Spring Cloud has support for Feign (a REST client builder) and also Spring RestTemplate using the logical service names instead of physical URLs.

    +
    +
    +

    You can also use the org.springframework.cloud.client.discovery.DiscoveryClient which provides a simple API for discovery clients that is not specific to Netflix, e.g.

    +
    +
    +
    +
    @Autowired
    +private DiscoveryClient discoveryClient;
    +
    +public String serviceUrl() {
    +    List<ServiceInstance> list = client.getInstances("STORES");
    +    if (list != null && list.size() > 0 ) {
    +        return list.get(0).getUri();
    +    }
    +    return null;
    +}
    +
    +
    +
    +
    +
    +
    +

    Distributed Configuration with Consul

    +
    +
    +

    Consul provides a Key/Value Store for storing configuration and other metadata. Spring Cloud Consul Config is an alternative to the Config Server and Client. Configuration is loaded into the Spring Environment during the special "bootstrap" phase. Configuration is stored in the /config folder by default. Multiple PropertySource instances are created based on the application’s name and the active profiles that mimicks the Spring Cloud Config order of resolving properties. For example, an application with the name "testApp" and with the "dev" profile will have the following property sources created:

    +
    +
    +
    +
    config/testApp,dev/
    +config/testApp/
    +config/application,dev/
    +config/application/
    +
    +
    +
    +

    The most specific property source is at the top, with the least specific at the bottom. Properties is the config/application folder are applicable to all applications using consul for configuration. Properties in the config/testApp folder are only available to the instances of the service named "testApp".

    +
    +
    +

    Configuration is currently read on startup of the application. Sending a HTTP POST to /refresh will cause the configuration to be reloaded. Watching the key value store (which Consul supports) is not currently possible, but will be a future addition to this project.

    +
    +
    +

    How to activate

    +
    +

    Including a dependency on org.springframework.cloud:spring-cloud-consul-config will enable auto-configuration that will setup Spring Cloud Consul Config.

    +
    +
    +
    +

    Customizing

    +
    +

    Consul Config may be customized using the following properties:

    +
    +
    +
    bootstrap.yml
    +
    +
    spring:
    +  cloud:
    +    consul:
    +      config:
    +        enabled: true
    +        prefix: configuration
    +        defaultContext: apps
    +        profileSeparator: '::'
    +
    +
    +
    +
      +
    • +

      enabled setting this value to "false" disables Consul Config

      +
    • +
    • +

      prefix sets the base folder for configuration values

      +
    • +
    • +

      defaultContext sets the folder name used by all applications

      +
    • +
    • +

      profileSeparator sets the value of the separator used to separate the profile name in property sources with profiles

      +
    • +
    +
    +
    +
    +
    +
    +

    YAML or Properties with Config

    +
    +
    +

    It may be more convenient to store a blob of properties in YAML or Properties format as opposed to individual key/value pairs. Set the spring.cloud.consul.config.format property to YAML or PROPERTIES. For example to use YAML:

    +
    +
    +
    bootstrap.yml
    +
    +
    spring:
    +  cloud:
    +    consul:
    +      config:
    +        format: YAML
    +
    +
    +
    +

    YAML must be set in the appropriate data key in consul. Using the defaults above the keys would look like:

    +
    +
    +
    +
    config/testApp,dev/data
    +config/testApp/data
    +config/application,dev/data
    +config/application/data
    +
    +
    +
    +

    You could store a YAML document in any of the keys listed above.

    +
    +
    +

    You can change the data key using spring.cloud.consul.config.data-key.

    +
    +
    +
    +
    +

    Consul Retry

    +
    +
    +

    If you expect that the consul agent may occasionally be unavailable when +your app starts, you can ask it to keep trying after a failure. You need to add +spring-retry and spring-boot-starter-aop to your classpath. The default +behaviour is to retry 6 times with an initial backoff interval of 1000ms and an +exponential multiplier of 1.1 for subsequent backoffs. You can configure these +properties (and others) using spring.cloud.consul.retry.* configuration properties. +This works with both Spring Cloud Consul Config and Discovery registration.

    +
    +
    + + + + + +
    +
    Tip
    +
    +To take full control of the retry add a @Bean of type +RetryOperationsInterceptor with id "consulRetryInterceptor". Spring +Retry has a RetryInterceptorBuilder that makes it easy to create one. +
    +
    +
    +
    +
    +

    Spring Cloud Bus with Consul

    +
    +
    +

    TODO: document Spring Cloud Consul Bus

    +
    +
    +
    +
    +

    Circuit Breaker with Hystrix

    +
    +
    +

    Applications can use the Hystrix Circuit Breaker provided by the Spring Cloud Netflix project by including this starter in the projects pom.xml: spring-cloud-starter-hystrix. Hystrix doesn’t depend on the Netflix Discovery Client. The @EnableHystrix annotation should be placed on a configuration class (usually the main class). Then methods can be annotated with @HystrixCommand to be protected by a circuit breaker. See the documentation for more details.

    +
    +
    +
    +
    +

    Hystrix metrics aggregation with Turbine and Consul

    +
    +
    +

    Turbine (provided by the Spring Cloud Netflix project), aggregates multiple instances Hystrix metrics streams, so the dashboard can display an aggregate view. Turbine uses the DiscoveryClient interface to lookup relevant instances. To use Turbine with Spring Cloud Consul, configure the Turbine application in a manner similar to the following examples:

    +
    +
    +
    pom.xml
    +
    +
    <dependency>
    +    <groupId>org.springframework.cloud</groupId>
    +    <artifactId>spring-cloud-netflix-turbine</artifactId>
    +</dependency>
    +<dependency>
    +    <groupId>org.springframework.cloud</groupId>
    +    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
    +</dependency>
    +
    +
    +
    +

    Notice that the Turbine dependency is not a starter. The turbine starter includes support for Netflix Eureka.

    +
    +
    +
    application.yml
    +
    +
    spring.application.name: turbine
    +applications: consulhystrixclient
    +turbine:
    +  aggregator:
    +    clusterConfig: ${applications}
    +  appConfig: ${applications}
    +
    +
    +
    +

    The clusterConfig and appConfig sections must match, so it’s useful to put the comma-separated list of service ID’s into a separate configuration property.

    +
    +
    +
    Turbine.java
    +
    +
    @EnableTurbine
    +@EnableDiscoveryClient
    +@SpringBootApplication
    +public class Turbine {
    +    public static void main(String[] args) {
    +        SpringApplication.run(DemoturbinecommonsApplication.class, args);
    +    }
    +}
    +
    +
    +
    +
    +

    Spring Cloud Zookeeper

    +
    +
    +This project provides Zookeeper integrations for Spring Boot apps through autoconfiguration +and binding to the Spring Environment and other Spring programming model idioms. With a few +simple annotations you can quickly enable and configure the common patterns inside your +application and build large distributed systems with Zookeeper based components. The +patterns provided include Service Discovery and Configuration. +Intelligent Routing (Zuul) and Client Side Load Balancing (Ribbon), Circuit Breaker +(Hystrix) are provided by integration with Spring Cloud Netflix. +
    +
    +
    +

    Install Zookeeper

    +
    +
    +

    Please see the installation documentation for instructions on how to install Zookeeper.

    +
    +
    +
    +
    +

    Service Discovery with Zookeeper

    +
    +
    +

    Service Discovery is one of the key tenets of a microservice based architecture. Trying to hand configure each client or some form of convention can be very difficult to do and can be very brittle. Curator(A java library for Zookeeper) provides Service Discovery services via Service Discovery Extension. Spring Cloud Zookeeper leverages this extension for service registration and discovery.

    +
    +
    +

    How to activate

    +
    +

    Including a dependency on org.springframework.cloud:spring-cloud-starter-zookeeper-discovery will enable auto-configuration that will setup Spring Cloud Zookeeper Discovery.

    +
    +
    +
    +

    Registering with Zookeeper

    +
    +

    When a client registers with Zookeeper, it provides meta-data about itself such as host and port, id and name.

    +
    +
    +

    Example Zookeeper client:

    +
    +
    +
    +
    @SpringBootApplication
    +@EnableDiscoveryClient
    +@RestController
    +public class Application {
    +
    +    @RequestMapping("/")
    +    public String home() {
    +        return "Hello world";
    +    }
    +
    +    public static void main(String[] args) {
    +        new SpringApplicationBuilder(Application.class).web(true).run(args);
    +    }
    +
    +}
    +
    +
    +
    +

    (i.e. utterly normal Spring Boot app). If Zookeeper is located somewhere other than localhost:2181, the configuration is required to locate the server. Example:

    +
    +
    +
    application.yml
    +
    +
    spring:
    +  cloud:
    +    zookeeper:
    +      connect-string: localhost:2181
    +
    +
    +
    + + + + + +
    +
    Caution
    +
    +If you use Spring Cloud Zookeeper Config, the above values will need to be placed in bootstrap.yml instead of application.yml. +
    +
    +
    +

    The default service name, instance id and port, taken from the Environment, are ${spring.application.name}, the Spring Context ID and ${server.port} respectively.

    +
    +
    +

    @EnableDiscoveryClient makes the app into both a Zookeeper "service" (i.e. it registers itself) and a "client" (i.e. it can query Zookeeper to locate other services).

    +
    +
    +
    +

    Using the DiscoveryClient

    +
    +

    Spring Cloud has support for Feign (a REST client builder) and also Spring RestTemplate using the logical service names instead of physical URLs.

    +
    +
    +

    You can also use the org.springframework.cloud.client.discovery.DiscoveryClient which provides a simple API for discovery clients that is not specific to Netflix, e.g.

    +
    +
    +
    +
    @Autowired
    +private DiscoveryClient discoveryClient;
    +
    +public String serviceUrl() {
    +    List<ServiceInstance> list = discoveryClient.getInstances("STORES");
    +    if (list != null && list.size() > 0 ) {
    +        return list.get(0).getUri().toString();
    +    }
    +    return null;
    +}
    +
    +
    +
    +
    +

    Using the Zookeeper Dependencies

    +
    +

    Spring Cloud Zookeeper gives you a possibility to provide dependencies of your application as properties. As dependencies you can understand other applications that are registered +in Zookeeper and which you would like to call via Feign (a REST client builder) +and also Spring RestTemplate.

    +
    +
    +

    You can also benefit from the Zookeeper Dependency Watchers functionality that lets you control and monitor what is the state of your dependencies and decide what to do with that.

    +
    +
    +
    +

    How to activate Zookeeper Dependencies

    +
    +
      +
    • +

      Including a dependency on org.springframework.cloud:spring-cloud-starter-zookeeper-discovery will enable auto-configuration that will setup Spring Cloud Zookeeper Dependencies.

      +
    • +
    • +

      In addition to that you have to set the property spring.cloud.zookeeper.dependencies.enabled to true (defaults to true if not set explicitly).

      +
    • +
    • +

      You have to have the spring.cloud.zookeeper.dependencies section properly set up - check the subsequent section for more details.

      +
    • +
    +
    +
    +
    +

    Setting up Zookeeper Dependencies

    +
    +

    Let’s take a closer look at an example of dependencies representation:

    +
    +
    +
    application.yml
    +
    +
    spring.application.name: yourServiceName
    +spring.cloud.zookeeper:
    +  dependencies:
    +    newsletter:
    +      path: /path/where/newsletter/has/registered/in/zookeeper
    +      loadBalancerType: ROUND_ROBIN
    +      contentTypeTemplate: application/vnd.newsletter.$version+json
    +      version: v1
    +      headers:
    +        header1:
    +            - value1
    +        header2:
    +            - value2
    +      required: false
    +      stubs: org.springframework:foo:stubs
    +    mailing:
    +      path: /path/where/mailing/has/registered/in/zookeeper
    +      loadBalancerType: ROUND_ROBIN
    +      contentTypeTemplate: application/vnd.mailing.$version+json
    +      version: v1
    +      required: true
    +
    +
    +
    +

    Let’s now go through each part of the dependency one by one. The root property name is spring.cloud.zookeeper.dependencies.

    +
    +
    +

    Aliases

    +
    +

    Below the root property you have to represent each dependency has by an alias due to the constraints of Ribbon (the application id has to be placed in the URL +thus you can’t pass any complex path like /foo/bar/name). The alias will be the name that you will use instead of serviceId for DiscoveryClient, Feign or RestTemplate.

    +
    +
    +

    In the aforementioned examples the aliases are newsletter and mailing. Example of Feign usage with newsletter would be:

    +
    +
    +
    +
    @FeignClient("newsletter")
    +public interface NewsletterService {
    +        @RequestMapping(method = RequestMethod.GET, value = "/newsletter")
    +        String getNewsletters();
    +}
    +
    +
    +
    +
    +

    Path

    +
    +

    Represented by path yaml property.

    +
    +
    +

    Path is the path under which the dependency is registered under Zookeeper. Like presented before Ribbon operates on URLs thus this path is not compliant with its requirement. +That is why Spring Cloud Zookeeper maps the alias to the proper path.

    +
    +
    +
    +

    Load balancer type

    +
    +

    Represented by loadBalancerType yaml property.

    +
    +
    +

    If you know what kind of load balancing strategy has to be applied when calling this particular dependency then you can provide it in the yaml file and it will be automatically applied. +You can choose one of the following load balancing strategies

    +
    +
    +
      +
    • +

      STICKY - once chosen the instance will always be called

      +
    • +
    • +

      RANDOM - picks an instance randomly

      +
    • +
    • +

      ROUND_ROBIN - iterates over instances over and over again

      +
    • +
    +
    +
    +
    +

    Content-Type template and version

    +
    +

    Represented by contentTypeTemplate and version yaml property.

    +
    +
    +

    If you version your api via the Content-Type header then you don’t want to add this header to each of your requests. Also if you want to call a new version of the API you don’t want to +roam around your code to bump up the API version. That’s why you can provide a contentTypeTemplate with a special $version placeholder. That placeholder will be filled by the value of the +version yaml property. Let’s take a look at an example.

    +
    +
    +

    Having the following contentTypeTemplate:

    +
    +
    +
    +
    application/vnd.newsletter.$version+json
    +
    +
    +
    +

    and the following version:

    +
    +
    +
    +
    v1
    +
    +
    +
    +

    Will result in setting up of a Content-Type header for each request:

    +
    +
    +
    +
    application/vnd.newsletter.v1+json
    +
    +
    +
    +
    +

    Default headers

    +
    +

    Represented by headers map in yaml

    +
    +
    +

    Sometimes each call to a dependency requires setting up of some default headers. In order not to do that in code you can set them up in the yaml file. +Having the following headers section:

    +
    +
    +
    +
    headers:
    +    Accept:
    +        - text/html
    +        - application/xhtml+xml
    +    Cache-Control:
    +        - no-cache
    +
    +
    +
    +

    Results in adding the Accept and Cache-Control headers with appropriate list of values in your HTTP request.

    +
    +
    +
    +

    Obligatory dependencies

    +
    +

    Represented by required property in yaml

    +
    +
    +

    If one of your dependencies is required to be up and running when your application is booting then it’s enough to set up the required: true property in the yaml file.

    +
    +
    +

    If your application can’t localize the required dependency during boot time it will throw an exception and the Spring Context will fail to set up. +In other words your application won’t be able to start if the required dependency is not registered in Zookeeper.

    +
    +
    +

    You can read more about Spring Cloud Zookeeper Presence Checker in the following sections.

    +
    +
    +
    +
    +

    Stubs

    +
    +

    You can provide a colon separated path to the JAR containing stubs of the dependency. Example

    +
    +
    +
    +
    stubs: org.springframework:foo:stubs
    +
    +
    +
    +

    means that for a particular dependencies can be found under:

    +
    +
    +
      +
    • +

      groupId: org.springframework

      +
    • +
    • +

      artifactId: foo

      +
    • +
    • +

      classifier: stubs - this is the default value

      +
    • +
    +
    +
    +

    This is actually equal to

    +
    +
    +
    +
    stubs: org.springframework:foo
    +
    +
    +
    +

    since stubs is the default classifier.

    +
    +
    +
    +

    Configuring Spring Cloud Zookeeper Dependencies

    +
    +

    There is a bunch of properties that you can set to enable / disable parts of Zookeeper Dependencies functionalities.

    +
    +
    +
      +
    • +

      spring.cloud.zookeeper.dependencies - if you don’t set this property you won’t benefit from Zookeeper Dependencies

      +
    • +
    • +

      spring.cloud.zookeeper.dependencies.ribbon.enabled (enabled by default) - Ribbon requires explicit global configuration or a particular one for a dependency. By turning on this property +runtime load balancing strategy resolution is possible and you can profit from the loadBalancerType section of the Zookeeper Dependencies. The configuration that needs this property +has an implementation of LoadBalancerClient that delegates to the ILoadBalancer presented in the next bullet

      +
    • +
    • +

      spring.cloud.zookeeper.dependencies.ribbon.loadbalancer (enabled by default) - thanks to this property the custom ILoadBalancer knows that the part of the URI passed to Ribbon might +actually be the alias that has to be resolved to a proper path in Zookeeper. Without this property you won’t be able to register applications under nested paths.

      +
    • +
    • +

      spring.cloud.zookeeper.dependencies.headers.enabled (enabled by default) - this property registers such a RibbonClient that automatically will append appropriate headers and content +types with version as presented in the Dependency configuration. Without this setting of those two parameters will not be operational.

      +
    • +
    • +

      spring.cloud.zookeeper.dependencies.resttemplate.enabled (enabled by default) - when enabled will modify the request headers of @LoadBalanced annotated RestTemplate so that it passes +headers and content type with version set in Dependency configuration. Wihtout this setting of those two parameters will not be operational.

      +
    • +
    +
    +
    +
    +

    Spring Cloud Zookeeper Dependency Watcher

    +
    +

    The Dependency Watcher mechanism allows you to register listeners to your dependencies. The functionality is in fact an implementation of the Observator pattern. When a dependency changes +its state (UP or DOWN) then some custom logic can be applied.

    +
    +
    +
    +

    How to activate

    +
    +

    Spring Cloud Zookeeper Dependencies functionality needs to be enabled to profit from Dependency Watcher mechanism.

    +
    +
    +
    +

    Registering a listener

    +
    +

    In order to register a listener you have to implement an interface org.springframework.cloud.zookeeper.discovery.watcher.DependencyWatcherListener and register it as a bean. +The interface gives you one method:

    +
    +
    +
    +
        /**
    +    * Method executed upon state change of a dependency
    +    *
    +    * @param dependencyName - alias from microservice configuration {@see ZookeeperDependencies}
    +    * @param newState
    +    */
    +    void stateChanged(String dependencyName, DependencyState newState);
    +
    +
    +
    +

    If you want to register a listener for a particular dependency then the dependencyName would be the discriminator for your concrete implementation. newState will provide you with information + whether your dependency has changed to CONNECTED or DISCONNECTED.

    +
    +
    +
    +

    Presence Checker

    +
    +

    Bound with Dependency Watcher is the functionality called Presence Checker. It allows you to provide custom behaviour upon booting of your application to react accordingly to the state +of your dependencies.

    +
    +
    +

    The default implementation of the abstract org.springframework.cloud.zookeeper.discovery.watcher.presence.DependencyPresenceOnStartupVerifier class is the +org.springframework.cloud.zookeeper.discovery.watcher.presence.DefaultDependencyPresenceOnStartupVerifier which works in the following way.

    +
    +
    +
      +
    • +

      If the dependency is marked us required and it’s not in Zookeeper then upon booting your application will throw an exception and shutdown

      +
    • +
    • +

      If dependency is not required the org.springframework.cloud.zookeeper.discovery.watcher.presence.LogMissingDependencyChecker will log that application is missing at WARN level

      +
    • +
    +
    +
    +

    The functionality can be overriden since the DefaultDependencyPresenceOnStartupVerifier is registered only when there is no bean of DependencyPresenceOnStartupVerifier.

    +
    +
    +
    +
    +
    +

    Distributed Configuration with Zookeeper

    +
    +
    +

    Zookeeper provides a hierarchical namespace that allows clients to store arbitrary data, such as configuration data. Spring Cloud Zookeeper Config is an alternative to the Config Server and Client. Configuration is loaded into the Spring Environment during the special "bootstrap" phase. Configuration is stored in the /config namespace by default. Multiple PropertySource instances are created based on the application’s name and the active profiles that mimicks the Spring Cloud Config order of resolving properties. For example, an application with the name "testApp" and with the "dev" profile will have the following property sources created:

    +
    +
    +
    +
    config/testApp,dev
    +config/testApp
    +config/application,dev
    +config/application
    +
    +
    +
    +

    The most specific property source is at the top, with the least specific at the bottom. Properties is the config/application namespace are applicable to all applications using zookeeper for configuration. Properties in the config/testApp namespace are only available to the instances of the service named "testApp".

    +
    +
    +

    Configuration is currently read on startup of the application. Sending a HTTP POST to /refresh will cause the configuration to be reloaded. Watching the configuration namespace (which Zookeeper supports) is not currently implemented, but will be a future addition to this project.

    +
    +
    +

    How to activate

    +
    +

    Including a dependency on org.springframework.cloud:spring-cloud-starter-zookeeper-config will enable auto-configuration that will setup Spring Cloud Zookeeper Config.

    +
    +
    +
    +

    Customizing

    +
    +

    Zookeeper Config may be customized using the following properties:

    +
    +
    +
    bootstrap.yml
    +
    +
    spring:
    +  cloud:
    +    zookeeper:
    +      config:
    +        enabled: true
    +        root: configuration
    +        defaultContext: apps
    +        profileSeparator: '::'
    +
    +
    +
    +
      +
    • +

      enabled setting this value to "false" disables Zookeeper Config

      +
    • +
    • +

      root sets the base namespace for configuration values

      +
    • +
    • +

      defaultContext sets the name used by all applications

      +
    • +
    • +

      profileSeparator sets the value of the separator used to separate the profile name in property sources with profiles

      +
    • +
    +
    +
    +
    +

    Spring Boot Cloud CLI

    @@ -5320,10 +7065,257 @@ ProxyAuthenticationProperties for full details.

    +

    Spring Cloud for Cloud Foundry

    +
    +
    +
    +

    Spring Cloud for Cloudfoundry makes it easy to run +Spring Cloud apps in +Cloud Foundry (the Platform as a +Service). Cloud Foundry has the notion of a "service", which is +middlware that you "bind" to an app, essentially providing it with an +environment variable containing credentials (e.g. the location and +username to use for the service).

    +
    +
    +

    The spring-cloud-cloudfoundry-web project provides basic support for +some enhanced features of webapps in Cloud Foundry: binding +automatically to single-sign-on services and optionally enabling +sticky routing for discovery.

    +
    +
    +

    The spring-cloud-cloudfoundry-discovery project provides an +implementation of Spring Cloud Commons DiscoveryClient so you can +@EnableDiscoveryClient and provide your credentials as +spring.cloud.cloudfoundry.discovery.[email,password] and then you +can use the DiscoveryClient directly or via a LoadBalancerClient +(also *.url if you are not connecting to [Pivotal Web +Services](https://run.pivotal.io)).

    +
    +
    +

    The first time you use it the discovery client might be slow owing to +the fact that it has to get an access token from Cloud Foundry.

    +
    +
    +
    +
    +

    Quickstart

    +
    +
    +

    Here’s a Spring Cloud app with Cloud Foundry discovery:

    +
    +
    +
    app.groovy
    +
    +
    @Grab('org.springframework.cloud:spring-cloud-cloudfoundry')
    +@RestController
    +@EnableDiscoveryClient
    +class Application {
    +
    +  @Autowired
    +  DiscoveryClient client
    +
    +  @RequestMapping('/')
    +  String home() {
    +    'Hello from ' + client.getLocalServiceInstance()
    +  }
    +
    +}
    +
    +
    +
    +

    If you run it without any service bindings:

    +
    +
    +
    +
    $ spring jar app.jar app.groovy
    +$ cf push -p app.jar
    +
    +
    +
    +

    It will show its app name in the home page.

    +
    +
    +

    Single Sign On

    +
    + + + + + +
    +
    Note
    +
    +All of the OAuth2 SSO and resource server features moved to Spring Boot +in version 1.3. You can find documentation in the +Spring Boot user guide. +
    +
    +
    +

    This project provides automatic binding from CloudFoundry service +credentials to the Spring Boot features. If you have a CloudFoundry +service called "sso", for instance, with credentials containing +"client_id", "client_secret" and "auth_domain", it will bind +automatically to the Spring OAuth2 client that you enable with +@EnableOAuth2Sso (from Spring Boot). The name of the service can be +parameterized using spring.oauth2.sso.serviceId.

    +
    +
    +
    +
    +

    Spring Cloud Cluster

    +
    +
    +Spring Cloud Cluster offers a set of primitives for building "cluster" +features into a distributed system. Example are leadership election, +consistent storage of cluster state, global locks and one-time tokens. +
    +
    +
    +

    Leader Election

    +
    +
    +

    Leader election allows application to work together with other +applications to coordinate a cluster leadership via a third party system. +Currently we provide integrations with zookeeper, hazelcast and etcd.

    +
    +
    +

    From user perspective election is working via interfaces +org.springframework.cloud.cluster.leader.Candidate and +org.springframework.cloud.cluster.leader.Context. Candidate +contains access to leadership’s role and id and also have methods +onGranted and onRevoked. These callback methods are useful if +default Candidate implementation is changed.

    +
    +
    +

    Leader election is auto-configured if spring-cloud-cluster-autoconfigure +and either spring-cloud-cluster-hazelcast, spring-cloud-cluster-zookeeper +or spring-cloud-cluster-etcd jars are found from a classpath. In +case where both jars are found leader election is created using both +systems. See sections Zookeeper, +Hazelcast and +Etcd for more +information about a created beans.

    +
    +
    +

    Default Candidate created from auto-configuration is +org.springframework.cloud.cluster.leader.DefaultCandidate which +currently only logs granted and revoked events.

    +
    +
    +

    If there’s a need for disable all leader related auto-configuration, +a spring.cloud.cluster.leader.enabled can be set to false which +then allows to do manual configuration even if the jars an on a +classpath. Properties spring.cloud.cluster.leader.id and +spring.cloud.cluster.leader.role can be used to set default +identifier and role.

    +
    +
    +

    If you are interested to simple get notification of granted and +revoked events one option is to attach event listener into spring +application context. Events OnGrantedEvent and OnRevokedEvent are +sent as spring event objects.

    +
    +
    +

    Simply create your own event listener class:

    +
    +
    +
    +
    class MyEventListener implements ApplicationListener<AbstractLeaderEvent> {
    +
    +  @Override
    +  public void onApplicationEvent(AbstractLeaderEvent event) {
    +    // do something with OnGrantedEvent or OnRevokedEvent
    +  }
    +}
    +
    +
    +
    +

    and then create it as a bean.

    +
    +
    +
    +
    @Configuration
    +static class Config {
    +  @Bean
    +  public MyEventListener myEventListener() {
    +    return new MyEventListener();
    +  }
    +}
    +
    +
    +
    +

    For simply log events you can also use a utility class +LoggingListener which allows easy configuration.

    +
    +
    +
    +
    import org.springframework.cloud.cluster.leader.event.LoggingListener;
    +
    +@Configuration
    +static class Config {
    +  @Bean
    +  public LoggingListener loggingListener() {
    +    return new LoggingListener("info");
    +  }
    +}
    +
    +
    +
    +

    Zookeeper

    +
    +

    Candidate implementation for zookeeper is created with a bean name +zookeeperLeaderCandidate which can be used to override the one +created during auto-configuration.

    +
    +
    +

    Zookeeper based election can be explicitly disabled using property +spring.cloud.cluster.zookeeper.leader.enabled.

    +
    +
    +

    Other propertys spring.cloud.cluster.zookeeper.namespace and +spring.cloud.cluster.zookeeper.connect can be used to set the +zookeeper base namespace path and connect string.

    +
    +
    +
    +

    Hazelcast

    +
    +

    Candidate implementation for zookeeper is created with a bean name +hazelcastLeaderCandidate which can be used to override the one +created during auto-configuration.

    +
    +
    +

    Hazelcast based election can be explicitly disabled using property +spring.cloud.cluster.hazelcast.leader.enabled. If you want to provide xml +based configuration for Hazelcast instance use property +spring.cloud.cluster.hazelcast.config-location to tell location of a +Hazelcast xml configuration file. config-location is a normal spring +Resource.

    +
    +
    +
    +

    Etcd

    +
    +

    Candidate implementation for etcd is created with a bean name +etcdLeaderCandidate which can be used to override the one +created during auto-configuration.

    +
    +
    +

    Etcd based election can be explicitly disabled using property +spring.cloud.cluster.etcd.leader.enabled.

    +
    +
    +

    Multiple etcd cluster uris can be specified using property +spring.cloud.cluster.etcd.connect

    +
    +
    +
    +