From 46967fbd71480fa50cc5bc195f321de4f179e684 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 24 Mar 2016 16:12:37 +0000 Subject: [PATCH] Sync docs from master to gh-pages --- spring-cloud.html | 5295 ++++++++++++++++++++++++++++----------------- 1 file changed, 3347 insertions(+), 1948 deletions(-) diff --git a/spring-cloud.html b/spring-cloud.html index 75e0f550..d4a5ce09 100644 --- a/spring-cloud.html +++ b/spring-cloud.html @@ -456,6 +456,7 @@ body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-b
  • Key Management
  • Creating a Key Store for Testing
  • Using Multiple Keys and Key Rotation
  • +
  • Serving Encrypted Properties
  • Serving Plain Text
  • @@ -541,153 +542,70 @@ body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-b
  • Polyglot support with Sidecar
  • -
  • Metrics: Spectator, Servo, and Atlas +
  • RxJava with Spring MVC
  • +
  • Metrics: Spectator, Servo, and Atlas
  • -
  • Spring Cloud Stream +
  • Spring Cloud Stream
  • +
  • Spring Cloud Stream Reference Manual -
  • -
  • Spring Cloud Task
  • -
  • Spring Cloud Bus - -
  • -
  • Spring Cloud Sleuth - -
  • -
  • Spring Cloud Consul - -
  • -
  • Spring Cloud Zookeeper - -
  • -
  • Spring Boot Cloud CLI - -
  • -
  • Spring Cloud Security - -
  • -
  • Spring Cloud for Cloud Foundry - -
  • -
  • Spring Cloud Cluster -
  • @@ -1110,14 +1028,14 @@ re-initialized from the refreshed @Configuration).

    Encryption and Decryption

    -

    The Config Client has an Environment pre-processor for decrypting +

    Spring Cloud has an Environment pre-processor for decrypting property values locally. It follows the same rules as the Config Server, and has the same external configuration via encrypt.*. Thus you can use encrypted values in the form {cipher}* and as long as there is a valid key then they will be decrypted before the main application context gets the Environment. To use the encryption -features in a client you need to include Spring Security RSA in your -classpath (Maven co-ordinates +features in an application you need to include Spring Security RSA in +your classpath (Maven co-ordinates "org.springframework.security:spring-security-rsa") and you also need the full strength JCE extensions in your JVM.

    @@ -1174,12 +1092,33 @@ the full strength JCE extensions in your JVM.

    Spring RestTemplate as a Load Balancer Client

    -

    You can use Ribbon indirectly via an autoconfigured RestTemplate -when RestTemplate is on the classpath and a LoadBalancerClient bean is defined):

    +

    RestTemplate can be automatically configured to use ribbon. To create a load balanced RestTemplate create a RestTemplate @Bean and use the @LoadBalanced qualifier.

    +
    +
    + + + + + +
    +
    Warning
    +
    +A RestTemplate bean is no longer created via auto configuration. It must be created by individual applications. +
    -
    public class MyClass {
    +
    @Configuration
    +public class MyConfiguration {
    +
    +    @LoadBalanced
    +    @Bean
    +    RestTemplate restTemplate() {
    +        return new RestTemplate();
    +    }
    +}
    +
    +public class MyClass {
         @Autowired
         private RestTemplate restTemplate;
     
    @@ -1201,12 +1140,40 @@ for details of how the RestTemplate is set up.

    Multiple RestTemplate objects

    If you want a RestTemplate that is not load balanced, create a RestTemplate -bean and inject it as normal. To access the load balanced RestTemplate use -the provided `@LoadBalanced Qualifier:

    +bean and inject it as normal. To access the load balanced RestTemplate use +the `@LoadBalanced qualifier when you create your @Bean.

    +
    +
    + + + + + +
    +
    Important
    +
    +Notice the @Primary annotation on the plain RestTemplate declaration in the example below, to disambiguate the unqualified @Autowired injection. +
    -
    public class MyClass {
    +
    @Configuration
    +public class MyConfiguration {
    +
    +    @LoadBalanced
    +    @Bean
    +    RestTemplate loadBalanced() {
    +        return new RestTemplate();
    +    }
    +
    +    @Primary
    +    @Bean
    +    RestTemplate restTemplate() {
    +        return new RestTemplate();
    +    }
    +}
    +
    +public class MyClass {
         @Autowired
         private RestTemplate restTemplate;
     
    @@ -1224,6 +1191,18 @@ the provided `@LoadBalanced Qualifier:

    }
    +
    + + + + + +
    +
    Tip
    +
    +If you see errors like java.lang.IllegalArgumentException: Can not set org.springframework.web.client.RestTemplate field com.my.app.Foo.restTemplate to com.sun.proxy.$Proxy89 try injecting RestOperations instead or setting spring.aop.proxyTargetClass=true. +
    +

    Ignore Network Interfaces

    @@ -1952,7 +1931,7 @@ is the same as file:/tmp/config,file:/tmp/config/{label}

    -

    Sharing Configiration With All Applications

    +

    Sharing Configuration With All Applications

    With file-based (i.e. git, svn and native) repositories, resources with file names in application* are shared between all client @@ -2351,6 +2330,19 @@ handle all encryption as well as decryption.

    +
    +

    Serving Encrypted Properties

    +
    +

    Sometimes you want the clients to decrypt the configuration locally, +instead of doing it in the server. In that case you can still have +/encrypt and /decrypt endpoints (if you provide the encrypt.* +configuration to locate a key), but you need to explicitly switch off +the decryption of outgoing properties using +spring.cloud.config.server.encrypt.enabled=false. If you don’t care +about the endpoints, then it should work if you configure neither the +key nor the enabled flag.

    +
    +
    @@ -2622,7 +2614,7 @@ for a Config Server that is a Eureka client:

    instance: ... metadataMap: - username: osufhalskjrtl + user: osufhalskjrtl password: lviuhlszvaorhvlo5847 configPath: /config
    @@ -3101,7 +3093,7 @@ to Netflix, e.g.

    private DiscoveryClient discoveryClient; public String serviceUrl() { - List<ServiceInstance> list = client.getInstances("STORES"); + List<ServiceInstance> list = discoveryClient.getInstances("STORES"); if (list != null && list.size() > 0 ) { return list.get(0).getUri(); } @@ -3748,7 +3740,7 @@ public interface StoreClient { an arbitrary client name, which is used to create a Ribbon load balancer (see below for details of Ribbon support). You can also specify a URL using the url attribute -(absolute value or just a hostname).

    +(absolute value or just a hostname). The name of the bean in the application context is the fully qualified name of the interface. An alias is also created which is the 'name' attribute plus 'FeignClient'. For the example above, @Qualifier("storesFeignClient") could be used to reference the bean.

    The Ribbon client above will want to discover the physical addresses @@ -3877,7 +3869,7 @@ public interface StoreClient {

    @Configuration
     public class FooConfiguration {
         @Bean
    -    public Contract feignContractg() {
    +    public Contract feignContract() {
             return new feign.Contract.Default();
         }
     
    @@ -4665,7 +4657,105 @@ info:
     
    -

    Metrics: Spectator, Servo, and Atlas

    +

    RxJava with Spring MVC

    +
    +
    +

    Spring Cloud Netflix includes the RxJava.

    +
    +
    +
    +
    +

    RxJava is a Java VM implementation of Reactive Extensions: a library for composing asynchronous and event-based programs by using observable sequences.

    +
    +
    +
    +
    +

    Spring Cloud Netflix provides support for returning rx.Single objects from Spring MVC Controllers. It also supports using rx.Observable objects for Server-sent events (SSE). This can be very convenient if your internal APIs are already built using RxJava (see Feign Hystrix Support for examples).

    +
    +
    +

    Here are some examples of using rx.Single:

    +
    +
    +
    +
    @RequestMapping(method = RequestMethod.GET, value = "/single")
    +public Single<String> single() {
    +    return Single.just("single value");
    +}
    +
    +@RequestMapping(method = RequestMethod.GET, value = "/singleWithResponse")
    +public ResponseEntity<Single<String>> singleWithResponse() {
    +    return new ResponseEntity<>(Single.just("single value"), HttpStatus.NOT_FOUND);
    +}
    +
    +@RequestMapping(method = RequestMethod.GET, value = "/throw")
    +public Single<Object> error() {
    +    return Single.error(new RuntimeException("Unexpected"));
    +}
    +
    +
    +
    +

    If you have an Observable, rather than a single, you can use .toSingle() or .toList().toSingle(). Here are some examples:

    +
    +
    +
    +
    @RequestMapping(method = RequestMethod.GET, value = "/single")
    +public Single<String> single() {
    +    return Observable.just("single value").toSingle();
    +}
    +
    +@RequestMapping(method = RequestMethod.GET, value = "/multiple")
    +public Single<List<String>> multiple() {
    +    return Observable.just("multiple", "values").toList().toSingle();
    +}
    +
    +@RequestMapping(method = RequestMethod.GET, value = "/responseWithObservable")
    +public ResponseEntity<Single<String>> responseWithObservable() {
    +
    +    Observable<String> observable = Observable.just("single value");
    +    HttpHeaders headers = new HttpHeaders();
    +    headers.setContentType(APPLICATION_JSON_UTF8);
    +    return new ResponseEntity<>(observable.toSingle(), headers, HttpStatus.CREATED);
    +}
    +
    +@RequestMapping(method = RequestMethod.GET, value = "/timeout")
    +public Observable<String> timeout() {
    +    return Observable.timer(1, TimeUnit.MINUTES).map(new Func1<Long, String>() {
    +        @Override
    +        public String call(Long aLong) {
    +            return "single value";
    +        }
    +    });
    +}
    +
    +
    +
    +

    If you have a streaming endpoint and client, SSE could be an option. To convert rx.Observable to a Spring SseEmitter use RxResponse.sse(). Here are some examples:

    +
    +
    +
    +
    @RequestMapping(method = RequestMethod.GET, value = "/sse")
    +public SseEmitter single() {
    +    return RxResponse.sse(Observable.just("single value"));
    +}
    +
    +@RequestMapping(method = RequestMethod.GET, value = "/messages")
    +public SseEmitter messages() {
    +    return RxResponse.sse(Observable.just("message 1", "message 2", "message 3"));
    +}
    +
    +@RequestMapping(method = RequestMethod.GET, value = "/events")
    +public SseEmitter event() {
    +    return RxResponse.sse(APPLICATION_JSON_UTF8, Observable.just(
    +            new EventDto("Spring io", getDate(2016, 5, 19)),
    +            new EventDto("SpringOnePlatform", getDate(2016, 8, 1))
    +    ));
    +}
    +
    +
    +
    +
    +
    +

    Metrics: Spectator, Servo, and Atlas

    When used together, Spectator/Servo and Atlas provide a near real-time operational insight platform.

    @@ -4765,7 +4855,7 @@ info:
    -

    Metrics Collection: Spectator

    +

    Metrics Collection: Spectator

    To enable Spectator metrics, include a dependency on spring-boot-starter-spectator:

    @@ -4863,7 +4953,7 @@ ds.record(request.sizeInBytes());
    -

    Metrics Collection: Servo

    +

    Metrics Collection: Servo

    @@ -4902,7 +4992,7 @@ monitorRegistry.register(timer);
    -

    Metrics Backend: Atlas

    +

    Metrics Backend: Atlas

    Atlas was developed by Netflix to manage dimensional time series data for near real-time operational insight. Atlas features in-memory data storage, allowing it to gather and report very large numbers of metrics, very quickly.

    @@ -4984,24 +5074,30 @@ After executing several requests against your service, you can gather some very

    Spring Cloud Stream

    -
    -

    Spring Cloud Stream Overview

    -
    -
    -

    Introducing Spring Cloud Stream

    +

    Spring Cloud Stream Reference Manual

    +
    +
    -

    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). -Spring Cloud Stream applications connect to the physical broker through bindings, which link Spring Integration -channels to physical broker destinations, for either input (consumer bindings) or output (producer bindings). -The creation of the bindings, and therefore their broker-specific implementation is handled by a binder, which is -another important abstraction of Spring Cloud Stream. Binders abstract out the broker-specific implementation details. -In order to connect to a specific type of broker (e.g. Rabbit or Kafka) you just need to have the relevant binder -implementation on the classpath.

    +

    This section goes into more detail about how you can work with Spring Cloud Stream. It covers topics +such as creating and running stream applications.

    +
    +
    +
    +
    +

    Introducing Spring Cloud Stream

    +
    +
    +

    Spring Cloud Stream is a framework for building message-driven microservices. +Spring Cloud Stream builds upon Spring Boot to create DevOps friendly microservice applications and Spring Integration to provide connectivity to message brokers. +Spring Cloud Stream provides an opinionated configuration of message brokers, introducing the concepts of persistent pub/sub semantics, consumer groups and partitions across several middleware vendors. +This opinionated configuration provides the basis to create stream processing applications.

    -

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

    +

    By adding @EnableBinding to your main application, you get immediate connectivity to a message broker and by adding @StreamListener to a method, you will receive events for stream processing.

    +
    +
    +

    Here’s a sample sink application for receiving external messages:

    @@ -5013,7 +5109,429 @@ public class StreamApplication { } } -@EnableBinding(Source.class) +@EnableBinding(Sink.class) +public class TimerSource { + + ... + + @StreamListener(Sink.INPUT) + public void processVote(Vote vote) { + votingService.recordVote(vote); + } +} +
    +
    +
    +

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

    +
    +
    +
    +
    public interface Sink {
    +  String INPUT = "input";
    +
    +  @Input(Sink.INPUT)
    +  SubscribableChannel input();
    +}
    +
    +
    +
    +

    The @Input annotation is used to identify input channels (messages entering the app), and @Output is used to identify output channels (messages leaving the app). +These annotations are optionally parameterized by a channel name. If the name is not provided then 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 = StreamApplication.class)
    +@WebAppConfiguration
    +@DirtiesContext
    +public class StreamApplicationTests {
    +
    +  @Autowired
    +  private Sink sink;
    +
    +  @Test
    +  public void contextLoads() {
    +    assertNotNull(this.sink.input());
    +  }
    +}
    +
    +
    +
    +
    +
    +

    Spring Cloud Stream Main Concepts

    +
    +
    +

    Spring Cloud Stream provides a number of abstractions and primitives that simplify writing message-driven microservices. +In this section we will provide an overview of:

    +
    +
    +
      +
    • +

      Spring Cloud Stream application model together with the Binder abstraction

      +
    • +
    • +

      Persistent publish-subscribe and consumer group support

      +
    • +
    • +

      Partitioning

      +
    • +
    • +

      Pluggable Binder API

      +
    • +
    +
    +
    +

    Application structure

    +
    +

    A Spring Cloud Stream application consists of a middleware-neutral core that communicates with the outside world through input and output channels. +The channels are managed and injected into it by the framework, and a Binder connects them to the external brokers. +Different Binder implementations exist for different types of middleware, such as Kafka, Rabbit MQ, Redis or Gemfire, and an extensible API allows you to write your own Binder. There is also TestSupportBinder that leaves the channel as-is so a test author can interact with the channels directly and easily assert on what is received.

    +
    +
    +
    +SCSt with binder +
    +
    Figure 4. Spring Cloud Stream Application
    +
    +
    +

    Spring Cloud Stream uses Spring Boot for configuration, and the Binder makes it possible for Spring Cloud Stream applications to be flexible in terms of how it connects to the middleware. +For example, deployers can dynamically choose the destinations that these channels connect to at runtime (e.g. Kafka topics or Rabbit MQ exchanges). +This can be done through external configuration properties in any form that is supported by Spring Boot (application arguments, environment variables, application.yml files, etc). +Taking the sink example from the previous section, providing the spring.cloud.stream.bindings.input.destination=raw-sensor-data property to the application will cause it to read from the raw-sensor-data Kafka topic, or from a queue bound to the raw-sensor-data exchange in Rabbit MQ. See Binding properties for more information on the available binder properties you can configure. You are also able to configure middleware specific properties, see [binder-spe cific-configuration] for more information.

    +
    +
    +

    Spring Cloud Stream will automatically detect and use a binder that is found on the classpath, so you can easily use different types of middleware with the same code, just by including a different binder at build time. +For more complex use cases, Spring Cloud Stream also provides the ability of packaging multiple binders within the same application and choosing what type of binder should be used at runtime, and even if multiple binders should be used at runtime for different channels.

    +
    +
    +

    Fat JAR

    +
    +

    Spring Cloud Stream applications can be 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 for Maven or Gradle.

    +
    +
    +
    +
    +

    Persistent publish subscribe and consumer groups

    +
    +

    Communication between different applications follows a publish-subscribe pattern, with data being broadcast through shared topics. +This can be seen in the following picture, which shows a typical deployment for a set of interacting Spring Cloud Stream applications.

    +
    +
    +
    +SCSt with binder +
    +
    Figure 5. Spring Cloud Stream Application topologies
    +
    +
    +

    Data reported by sensors to an HTTP endpoint is sent to a common destination named raw-sensor-data, from where it is independently processed by a microservice that computes time windowed averages, as well as by a microservice that ingests the raw data into HDFS. +In order to do so, both applications will declare the topic as their input at runtime. +The publish-subscribe communication model reduces the complexity of both the producer and the consumer, and allows adding new applications to the topology without disrupting the existing flow. +For example, downstream from the average calculator we can have a component that calculates the highest temperature values in order to display and monitor them. +Later on, we can add an application that interprets the very same flow of averages for fault detection. +The fact that all the communication is done through shared topics rather than point to point queues reduces the coupling between microservices.

    +
    +
    +

    While the concept of publish-subscribe messaging is not new, Spring Cloud Stream takes the extra step of making it an opinionated choice for its application model. +It also makes it easy for users to work with it across different platform by using the native support of the middleware.

    +
    +
    +

    Consumer Groups

    +
    +

    While the publish subscribe model ensures that it is easy to connect multiple application by sharing a topic, it is equally important to be able to scale up by creating multiple instances of a given application. +When doing so, the different instances would find themselves in a competing consumer relationship with each other: only one of the instances is expected to handle the message. +Spring Cloud Stream models this behavior through the concept of a consumer group, which is similar to (and inspired by) the notion of consumer groups in Kafka. +Each consumer binding can specify a group name such as spring.cloud.stream.bindings.input.group=hdfsWrite or spring.cloud.stream.bindings.input.group=average, as shown in the picture. +All groups that subscribe to a given destination will receive a copy of the published data, but only one member of the group will receive a given message from that destination. +By default, when a group is not specified, Spring Cloud Stream assigns the application to an anonymous, independent, single-member consumer group that will be in a publish-subscribe relationship with all the other consumer groups.

    +
    +
    +
    +SCSt groups +
    +
    Figure 6. Spring Cloud Stream Consumer Groups
    +
    +
    +
    +

    Durability

    +
    +

    Consistent with the opinionated application model of Spring Cloud Stream, consumer group subscriptions are durable. +This is to say that the binder implementation will ensure that group subscriptions are persistent and, once at least one subscription for a group has been created, that group will receive messages, even if they are sent while all the applications of the group were stopped. +Anonymous subscriptions are non-durable by nature. For some binder implementations (e.g. Rabbit) it is possible to have non-durable group subscriptions.

    +
    +
    +

    In general, it is preferable to always specify a consumer group when binding an application to a given destination. +When scaling up a Spring Cloud Stream application, a consumer group must be specified for each of its input bindings, in order to prevent its instances from receiving duplicate messages (unless that behavior is desired, which is a less common use case).

    +
    +
    +
    +
    +

    Partitioning

    +
    +

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

    +
    +
    +
    +SCSt partitioning +
    +
    Figure 7. Spring Cloud Stream Partitioning
    +
    +
    +

    Partitioning is a critical concept in stateful processing, where ensuring that all the related data is processed together is critical for either performance or consistency. +For example, in the time-windowed average calculation example, it is important that measurements from the same sensor land in the same application instance.

    +
    +
    +

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

    +
    +
    +
    +
    +
    +

    Programming model

    +
    +
    +

    This section will describe the programming model of Spring Cloud Stream, which consists from a number of predefined annotations that can be used to declare bound inputs and output channels, as well as how to listen to them.

    +
    +
    +

    Declaring and binding channels

    +
    +

    Triggering binding via @EnableBinding

    +
    +

    A Spring application becomes a Spring Cloud Stream application when the @EnableBinding annotation is applied to one of its configuration classes. @EnableBinding itself is meta-annotated with @Configuration, and triggers the configuration of Spring Cloud Stream infrastructure as follows:

    +
    +
    +
    +
    ...
    +@Import(...)
    +@Configuration
    +@EnableIntegration
    +public @interface EnableBinding {
    +    ...
    +    Class<?>[] value() default {};
    +}
    +
    +
    +
    +

    @EnableBinding can be parameterized with one or more interface classes, containing methods that represent bindable components (typically message channels).

    +
    +
    +
    + + + + +
    +
    Note
    +
    +As of version 1.0, the only supported bindable component is the Spring Messaging MessageChannel and its extensions SubscribableChannel and PollableChannel. +It is intended for future versions to extend support to other types of components, using the same mechanism. In this documentation, we will continue to refer to channels. +
    +
    +
    +
    +

    @Input and @Output

    +
    +

    A Spring Cloud Stream application can have an arbitrary number of input and output channels defined as @Input and @Output methods in an interface, as follows:

    +
    +
    +
    +
    public interface Barista {
    +
    +    @Input
    +    SubscribableChannel orders();
    +
    +    @Output
    +    MessageChannel hotDrinks();
    +
    +    @Output
    +    MessageChannel coldDrinks();
    +}
    +
    +
    +
    +

    Using this interface as a parameter to @EnableBinding, as in the following example, will trigger the creation of three bound channels named orders, hotDrinks and coldDrinks respectively.

    +
    +
    +
    +
    @EnableBinding(Barista.class)
    +public class CafeConfiguration {
    +
    +   ...
    +}
    +
    +
    +
    +
    Customizing channel names
    +
    +

    Both @Input and @Output allow specifying a customized name for the channel, as follows:

    +
    +
    +
    +
    public interface Barista {
    +    ...
    +    @Input("inboundOrders")
    +    SubscribableChannel orders();
    +}
    +
    +
    +
    +

    In this case, the name of the bound channel being created will be inboundOrders.

    +
    +
    +
    +
    Source, Sink, and Processor
    +
    +

    For ease of addressing the most common use cases that involve either an input or an output channel, or both, out of the box Spring Cloud Stream provides three predefined interfaces.

    +
    +
    +

    Source can be used for applications that have a single outbound channel.

    +
    +
    +
    +
    public interface Source {
    +
    +	String OUTPUT = "output";
    +
    +	@Output(Source.OUTPUT)
    +	MessageChannel output();
    +
    +}
    +
    +
    +
    +

    Sink can be used for applications that have a single inbound channel.

    +
    +
    +
    +
    public interface Sink {
    +
    +	String INPUT = "input";
    +
    +	@Input(Sink.INPUT)
    +	SubscribableChannel input();
    +
    +}
    +
    +
    +
    +

    Processor can be used for applications that have both an inbound and an outbound channel.

    +
    +
    +
    +
    public interface Processor extends Source, Sink {
    +}
    +
    +
    +
    +

    There is no special handling for either of these interfaces in Spring Cloud Stream, besides of the fact that they are provided out of the box.

    +
    +
    +
    +
    +

    Accessing bound channels

    +
    +
    Injecting the bound interfaces
    +
    +

    For each of the bound interfaces, Spring Cloud Stream will generate a bean that implements it, and for which invoking an @Input or @Output annotated method will return the bound channel. +For example, the bean in the following example will send a message on the output channel every time its hello method is invoked, using the injected Source bean, and invoking output() to retrieve the target channel.

    +
    +
    +
    +
    @Component
    +public class SendingBean {
    +
    +    private Source source;
    +
    +    @Autowired
    +    public SendingBean(Source source) {
    +        this.source = source;
    +    }
    +
    +    public void sayHello(String name) {
    +		     source.output().send(MessageBuilder.withPayload(body).build());
    +	  }
    +}
    +
    +
    +
    +
    +
    Injecting channels directly
    +
    +

    Bound channels can be also injected directly. For example:

    +
    +
    +
    +
    @Component
    +public class SendingBean {
    +
    +    private MessageChannel output;
    +
    +    @Autowired
    +    public SendingBean(MessageChannel output) {
    +        this.output = output;
    +    }
    +
    +    public void sayHello(String name) {
    +		     output.send(MessageBuilder.withPayload(body).build());
    +	  }
    +}
    +
    +
    +
    +

    Note that if the name of the channel is customized on the declaring annotation, that name should be used instead of the method name. Considering this declaration:

    +
    +
    +
    +
    public interface CustomSource {
    +    ...
    +    @Output("customOutput")
    +    MessageChannel output();
    +}
    +
    +
    +
    +

    The channel will be injected as follows:

    +
    +
    +
    +
    @Component
    +public class SendingBean {
    +
    +    @Autowired
    +    private MessageChannel output;
    +
    +    @Autowired @Qualifier("customOutput")
    +    public SendingBean(MessageChannel output) {
    +        this.output = output;
    +    }
    +
    +    public void sayHello(String name) {
    +		     customOutput.send(MessageBuilder.withPayload(body).build());
    +	  }
    +}
    +
    +
    +
    +
    +
    +

    Programming model

    +
    +

    Spring Cloud Stream allows you to write applications by either using Spring Integration annotations or Spring Cloud Stream’s @StreamListener annotation which is modeled after other Spring Messaging annotations (e.g. @MessageMapping, @JmsListener, @RabbitListener, etc.) but add content type management and type coercion features.

    +
    +
    +
    Native Spring Integration support
    +
    +

    Due to the fact that Spring Cloud Stream is Spring Integration based, it completely inherits its foundation and infrastructure, as well as the component. For example, the output channel of a Source can be attached to a MessageSource, as follows:

    +
    +
    +
    +
    @EnableBinding(Source.class)
     public class TimerSource {
     
       @Value("${format}")
    @@ -5028,235 +5546,578 @@ public class TimerSource {
     
    -

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

    +

    Or, the channels of a processor can be used in a transformer, as follows:

    -
    public interface Source {
    -  String OUTPUT = "output";
    -
    -  @Output(Source.OUTPUT)
    -  MessageChannel output();
    +
    @EnableBinding(Processor.class)
    +public class TransformProcessor {
    +	@Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)
    +	public Object transform(String message) {
    +		return message.toUpper();
    +	}
     }
    -
    -

    The @Output annotation is used to identify output channels (messages leaving the app), and @Input is used to -identify input channels (messages entering the app). 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 = StreamApplication.class)
    -@WebAppConfiguration
    -@DirtiesContext
    -public class StreamApplicationTests {
    -
    -  @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 application from some others, you can use the -@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 stream app 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 with -@Input or @Output, and their names will be converted to external destination names on the broker. It is common to -specify the channel names at runtime in order to have multiple applications communicate over well known destination -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 any of the other -mechanisms supported by Spring Boot.

    -
    -
    -

    For example, you can have two MessageChannels called "default" and "tap" in an application with -spring.cloud.stream.bindings.default.destination=foo and spring.cloud.stream.bindings.tap.destination=bar, -and the result is 2 bindings to an external broker with destinations called "foo" and "bar".

    -
    -
    -
    -

    Inter-app Communication

    -
    -

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

    -
    -
    -

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

    -
    -
    -
    -

    Consumer Group Support

    -
    -

    Spring Cloud Stream is a library focusing on building message-driven microservices, and more specifically stream -processing applications. In such scenarios, communication between different logical applications follows a -publish-subscribe pattern, with data being broadcast through a shared topic, but at the same time, it is important to -be able to scale up by creating multiple instances of a given application, which are in a competing consumer -relationship with each other.

    -
    -
    -

    Spring Cloud Stream models this behavior through the concept of a consumer group, which is similar to the notion of -consumer groups in Kafka. Each consumer binding can specify a group name such as -spring.cloud.stream.bindings.input.group=foo (the actual name of the binding may vary). Each consumer group bound to -a given destination will receive a copy of the published data, but within the group, only one application will receive -each specific message.

    -
    -
    -

    If no consumer group is specified for a given binding, then the binding is treated as if belonging to an anonymous, -independent, single-member consumer group. Otherwise said, if no consumer group is specified for a binding, it will be -in a publish-subscribe relationship with any other consumer groups.

    -
    -
    -

    In general, it is preferable to always specify a consumer group when binding an application to a given destination. -When scaling up a Spring Cloud Stream application, a consumer group must be specified for each of its input bindings, -in order to prevent its instances from receiving duplicate messages (unless that behavior is desired, which is a less -common use case).

    -
    -
    - - - - - -
    -
    Note
    -
    -This feature has been introduced since version 1.0.0.M4. -
    -
    -
    -
    -

    Instance Index and Instance Count

    -
    -

    When scaling up Spring Cloud Stream applications, each instance can receive information about how many other instances -of the same application exist and what its own instance index is. This is done through the -spring.cloud.stream.instanceCount and spring.cloud.stream.instanceIndex properties. For example, if there are 3 -instances of the HDFS sink application, all three will have spring.cloud.stream.instanceCount set to 3, and the -applications will have spring.cloud.stream.instanceIndex set to 0, 1 and 2, respectively. When Spring Cloud Stream -applications are deployed via Spring Cloud Data Flow, these properties are configured automatically, but when Spring -Cloud Stream applications are launched independently, these properties must be set correctly. By default -spring.cloud.stream.instanceCount is 1, and spring.cloud.stream.instanceIndex is 0.

    -
    -
    -

    Setting up the two properties correctly on scale up scenarios is important for addressing partitioning behavior in -general (see below), and they are always required by certain types of binders (e.g. the Kafka binder) in order to -ensure that data is split correctly across multiple consumer instances.

    -
    -
    -
    -

    Advanced Binding Properties

    -
    -

    The input and output destination names are the primary properties to set in order to have Spring Cloud Stream -applications communicate with each other as their channels are bound to an external message broker automatically. -However, there are a number of scenarios where it is required to configure other attributes besides the destination -name. This is done using the following naming scheme: -spring.cloud.stream.bindings.<channelName>.<attributeName>=<attributeValue>. The destination attribute is one such -example: spring.cloud.stream.bindings.input.destination=foo. A shorthand equivalent can be used as follows: -spring.cloud.stream.bindings.input=foo, but that shorthand can only 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.

    -
    Partitioning
    +
    @StreamListener for automatic content type handling
    -

    Spring Cloud Stream provides support for partitioning data between multiple instances of a given application. In a -partitioned scenario, one or more producer apps will send data to one or more consumer apps, 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 of whether the broker type is naturally -partitioned (e.g. Kafka) or not (e.g. Rabbit), Spring Cloud Stream provides a common abstraction for implementing -partitioned processing use cases in a uniform fashion.

    +

    Complementary to the Spring Integration support, Spring Cloud Stream provides a @StreamListener annotation of its own modeled by the other similar Spring Messaging annotations (e.g. @MessageMapping, @JmsListener, @RabbitListener, etc.). +It provides a simpler model for handling inbound messages, especially for dealing with use cases that involve content type management and type coercion. +Spring Cloud Stream provides an extensible MessageConverter mechanism for handling data conversion by bound channels and, in this case, for dispatching to @StreamListener annotated methods.

    -

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

    +

    For example, an application that processes external Vote events can be declared as follows:

    +
    +
    +
    +
    @EnableBinding(Sink.class)
    +public class VoteHandler {
    +
    +  @Autowired
    +  VotingService votingService;
    +
    +  @StreamListener(Sink.INPUT)
    +	public void handle(Vote vote) {
    +		votingService.record(vote);
    +	}
    +}
    -
    -
    Configuring Output Bindings for Partitioning
    -
    -

    An output binding 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, setting -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 sufficient for your needs, you can instead calculate the partition key -value by setting the property partitionKeyExtractorClass. This class must implement the interface -org.springframework.cloud.stream.binder.PartitionKeyExtractorStrategy. While, in general, the SpEL expression should -suffice, more complex cases may use the custom implementation strategy.

    +

    The distinction between this approach and a Spring Integration @ServiceActivator becomes relevant if one considers an inbound Message with a String payload and a contentType header of application/json. +For @StreamListener, the MessageConverter mechanism will use the contentType header to parse the String into a Vote object.

    -

    Once the message key is calculated, the partition selection process will determine the target partition as a value -between 0 and partitionCount - 1. 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.

    +

    Just as with the other Spring Messaging methods, method arguments can be annotated with @Payload, @Headers and @Header. +For methods that return data, @SendTo must be used for specifying the output binding destination for data returned by the methods as follows:

    -
    -

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

    +
    +
    +
    @EnableBinding(Processor.class)
    +public class TransformProcessor {
    +
    +  @Autowired
    +  VotingService votingService;
    +
    +  @StreamListener(Processor.INPUT)
    +  @SendTo(Processor.OUTPUT)
    +	public VoteResult handle(Vote vote) {
    +		return votingService.record(vote);
    +	}
    +}
    -
    -
    Configuring Input Bindings for Partitioning
    -
    -

    An input binding is configured to receive partitioned data by setting its partitioned property, as well as the -instance index and instance count properties on the app itself, 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 app instances between which the data needs to be partitioned, -whereas instance index must be a unique value across the multiple instances, between 0 and instanceCount - 1. The -instance index helps each app instance to identify the unique partition (or in the case of Kafka, the partition set) -from which it receives data. It is important that both values are set correctly in order to ensure that all the data is -consumed, and that the app instances 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.

    -
    +
    + + + + + +
    +
    Note
    +
    +Content type headers can be set by external applications in the case of Rabbit MQ, and they are supported as part of an extended internal protocol by Spring Cloud Stream for any type of transport (even the ones that do not support headers normally, like Kafka). +
    -

    Binder Selection

    +

    Binder SPI

    +
    +

    As described above, Spring Cloud Stream provides a binder abstraction for connecting to physical destinations. This +section will provide more information about the main concepts behind the Binder SPI, its main components, as well as +details specific to different implementations.

    +
    +
    +

    Producers and Consumers

    +
    +
    +producers consumers +
    +
    Figure 8. Producers and Consumers
    +
    +
    +

    A producer is any component that sends messages to a channel. That channel can be bound to an external message broker +via a Binder implementation for that broker. When invoking the bindProducer method, the first parameter is the name +of the destination within that broker. The second parameter is the local channel instance to which the producer will be +sending messages, and the third parameter contains properties to be used within the adapter that is created for that +channel, such as a partition key expression.

    +
    +
    +

    A consumer is any component that receives messages from a channel. As with the producer, the consumer’s channel can be +bound to an external message broker, and the first parameter for the bindConsumer method is the destination name. +However, on the consumer side, a second parameter provides the name of a logical group of consumers. Each group +represented by consumer bindings for a given destination will receive a copy of each message that a producer sends to +that destination (i.e. pub/sub semantics). If there are multiple consumer instances bound using the same group name, +then messages will be load balanced across those consumer instances so that each message sent by a producer would only +be consumed by a single consumer instance within each group (i.e. queue semantics).

    +
    +
    +
    +

    Kafka Binder

    +
    +
    +kafka binder +
    +
    Figure 9. Kafka Binder
    +
    +
    +

    The Kafka Binder implementation maps the destination to a Kafka topic, and the consumer group maps directly to the same +Kafka concept. Spring Cloud Stream does not use the high level consumer, but implements a similar concept for the +simple consumer.

    +
    +
    +
    +

    RabbitMQ Binder

    +
    +
    +rabbit binder +
    +
    Figure 10. RabbitMQ Binder
    +
    +
    +

    The RabbitMQ Binder implementation maps the destination to a TopicExchange, and for each consumer group, a Queue +will be bound to that TopicExchange. Each consumer instance that binds will trigger creation of a corresponding +RabbitMQ Consumer instance for its group’s Queue.

    +
    +
    +
    +
    +
    +
    +

    Configuration options

    +
    +
    +

    Spring Cloud Stream supports general configuration options, as well as configuration for bindings and binders. Some binders allow additional properties for the bindings, supporting middleware-specific features.

    +
    +
    +

    All configuration options can be provided to Spring Cloud Stream applications via all the mechanisms supported by Spring Boot: application arguments, environment variables, YML files etc.

    +
    +
    +

    Spring Cloud Stream Properties

    +
    +
    +
    spring.cloud.stream.instanceCount
    +
    +

    The number of deployed instances of the same application. Must be set for partitioning and with Kafka. Default value is 1.

    +
    +
    spring.cloud.stream.instanceIndex
    +
    +

    The instance index of the application, a number from 0 to instanceCount-1. Used for partitioning and with Kafka. Automatically set in Cloud Foundry to match the instance index of the application.

    +
    +
    spring.cloud.stream.dynamicDestinations
    +
    +

    A list of destinations that can be bound dynamically, for example in a dynamic routing scenario. Only listed destinations can be bound if set. Default empty, allowing any destination to be bound.

    +
    +
    spring.cloud.stream.defaultBinder
    +
    +

    The default binder to use, if there are multiple binders configured. See multiple binders.

    +
    +
    +
    +
    +
    +

    Binding properties

    +
    +

    Binding properties are supplied using the format spring.cloud.stream.bindings.<channelName>.<property>=<value>.<channelName> represents the name of the channel being configured, e.g. output for a Source. +In what follows, we will indicate where the spring.cloud.stream.bindings.<channelName>. prefix is omitted and focus just on the property name, with the understanding that the prefix will be included at runtime.

    +
    +
    +

    Properties for the use of Spring Cloud Stream

    +
    +

    The following binding properties are available for both input and output bindings and +must be prefixed with spring.cloud.stream.bindings.<channelName>. .

    +
    +
    +
    +
    destination
    +
    +

    The target destination of channel on the bound middleware, e.g. Rabbit MQ exchange or +Kafka topic. If not set, the channel name will be used instead.

    +
    +
    group
    +
    +

    The consumer group of the channel. This property applies only to inbound bindings. +By default it is null, and indicates an anonymous consumer. See consumer groups.

    +
    +
    contentType
    +
    +

    The content type of the channel. By default it is null and no type +coercion is performed. See [content type management].

    +
    +
    binder
    +
    +

    The binder used by this binding. By default, it is set to null and will +use the default binder, if one exists. See Multiple Binders on the Classpath for details.

    +
    +
    +
    +
    +
    +

    Consumer properties

    +
    +

    The following binding properties are available for input bindings only and must be prefixed with spring.cloud.stream.bindings.<channelName>.consumer:

    +
    +
    +
    +
    concurrency
    +
    +

    The concurrency of the inbound consumer. By default, set to 1.

    +
    +
    partitioned
    +
    +

    Must be set to true if the consumer is receiving data from a partitioned +producer. By default it is set to false.

    +
    +
    maxAttempts
    +
    +

    The number of attempts of re-processing an inbound message. Default '3'. (Ignored by Kafka, currently).

    +
    +
    backOffInitialInterval
    +
    +

    The backoff initial interval on retry. Default 1000.(Ignored by Kafka, currently).

    +
    +
    backOffMaxInterval
    +
    +

    The maximum backoff interval. Default 10000.(Ignored by Kafka, currently).

    +
    +
    backOffMultiplier
    +
    +

    The backoff multiplier. Default 2.0.

    +
    +
    +
    +
    +
    +

    Producer properties

    +
    +

    The following binding properties are available for output bindings only and must be prefixed with spring.cloud.stream.bindings.<channelName>.producer:

    +
    +
    +
    +
    partitionKeyExpression
    +
    +

    A SpEL expression for partitioning outbound data. Default: null. If either this property is set or +partitionKeyExtractorClass is present, outbound data on this channel will be partitioned, +and partitionCount must be set to a value larger than 1 to be effective. +The two options are mutually exclusive. See Partitioning.

    +
    +
    partitionKeyExtractorClass
    +
    +

    A PartitionKeyExtractorStrategy implementation. Default: null. If either this property is set or +partitionKeyExpression is present, outbound data on this channel will be partitioned, +and partitionCount must be set to a value larger than 1 to be effective. +The two options are mutually exclusive. See Partitioning.

    +
    +
    partitionSelectorClass
    +
    +

    A PartitionSelectorStrategy implementation. Default null. Mutually exclusive with +partitionSelectorExpression. If none is set, the partition will be selected as the +hashCode(key) % partitionCount, where key is computed via either partitionKeyExpression +or partitionKeyExtractorClass.

    +
    +
    partitionSelectorExpression
    +
    +

    A SpEL expression for customizing partition selection. Default null. Mutually exclusive with +partitionSelectorClass. If none is set, the partition will be selected as the +hashCode(key) % partitionCount, where key is computed via either partitionKeyExpression +or partitionKeyExtractorClass.

    +
    +
    partitionCount
    +
    +

    The number of target partitions for the data, if partitioning is enabled. Default 1. Must be +set to a value higher than 1 if the producer is partitioned. On Kafka it is interpreted as a +hint, and the larger of this and the partition count of the target topic will be used instead.

    +
    +
    requiredGroups
    +
    +

    A comma separated list of groups that the producer must ensure message delivery even if they +start after it has been created (e.g. by pre-creating durable queues in Rabbit MQ).

    +
    +
    +
    +
    +
    +
    +
    +
    +

    Binder-specific configuration

    +
    +
    +

    This captures the binder, consumer and producer properties that are specific for several binder +implementations.

    +
    +
    +

    Rabbit-specific settings

    +
    +

    Rabbit MQ Binder properties

    +
    +

    The binder supports the all Spring Boot properties for Rabbit MQ configuration.

    +
    +
    +

    In addition to that, it also supports the following properties:

    +
    +
    +
    +
    spring.cloud.stream.rabbit.binder.addresses
    +
    +

    A comma-separated list of RabbitMQ server addresses (used only for clustering and in conjunction with nodes). Default empty. +spring.cloud.stream.rabbit.binder.adminAddresses. Default empty. + A comma-separated list of RabbitMQ management plugin URLs - only used when nodes contains more than one entry. Entries in this list must correspond to the corresponding entry in addresses. Default empty.

    +
    +
    spring.cloud.stream.rabbit.binder.nodes
    +
    +

    A comma-separated list of RabbitMQ node names; when more than one entry, used to locate the server address where a queue is located. Entries in this list must correspond to the corresponding entry in addresses. Default empty.

    +
    +
    spring.cloud.stream.rabbit.rabbit.username
    +
    +

    The user name. Default null.

    +
    +
    spring.cloud.stream.rabbit.binder.password
    +
    +

    The password. Default null.

    +
    +
    spring.cloud.stream.rabbit.binder.vhost
    +
    +

    The virtual host. Default null.

    +
    +
    spring.cloud.stream.rabbit.binder.useSSL
    +
    +

    True if Rabbit MQ should use SSL.

    +
    +
    spring.cloud.stream.rabbit.binder.sslPropertiesLocation
    +
    +

    The location of the SSL properties file, when certificate exchange is used.

    +
    +
    spring.cloud.stream.rabbit.binder.compressionLevel
    +
    +

    Compression level for compressed bindings. Defaults to 1 (BEST_LEVEL). See java.util.zip.Deflater.

    +
    +
    +
    +
    +
    +

    Rabbit MQ Consumer Properties

    +
    +

    The following properties are available for Rabbit consumers only and +must be prefixed with spring.cloud.stream.rabbit.bindings.<channelName>.consumer .

    +
    +
    +
    +
    acknowledgeMode
    +
    +

    The acknowledge mode. Default AUTO.

    +
    +
    autoBindDlq
    +
    +

    Whether to automatically declare the DLQ and bind it to the binder DLX. Default false.

    +
    +
    durableSubscription
    +
    +

    Whether subscription should be durable. Only effective if group is also set. Default true. +maxConcurrency: + Default 1. +prefetch: + Prefetch count. Default 1.

    +
    +
    prefix
    +
    +

    A prefix to be added to the name of the destination and queues. Default "".

    +
    +
    requeueRejected
    +
    +

    Whether delivery failures should be requeued. Default true.

    +
    +
    requestHeaderPatterns
    +
    +

    The request headers to be transported. Default [STANDARD_REQUEST_HEADERS,'*'].

    +
    +
    replyHeaderPatterns
    +
    +

    The reply headers to be transported. Default [STANDARD_REQUEST_HEADERS,'*']

    +
    +
    republishToDlq
    +
    +

    By default, failed messages after retries are exhausted are rejected. If a dead-letter queue (DLQ) is configured, rabbitmq will route the failed message (unchanged) to the DLQ. Setting this property to true instructs the bus to republish failed messages to the DLQ, with additional headers, including the exception message and stack trace from the cause of the final failure.

    +
    +
    transacted
    +
    +

    Whether to use transacted channels. Default false.

    +
    +
    txSize
    +
    +

    The number of deliveries between acks. Default 1.

    +
    +
    +
    +
    +
    +

    Rabbit Producer Properties

    +
    +

    The following properties are available for Rabbit producers only and +must be prefixed with spring.cloud.stream.rabbit.bindings.<channelName>.producer .

    +
    +
    +
    +
    autoBindDlq
    +
    +

    Whether to automatically declare the DLQ and bind it to the binder DLX. Default false.

    +
    +
    batchingEnabled
    +
    +

    True to enable message batching by producers. Default false.

    +
    +
    batchSize
    +
    +

    The number of message to buffer when batching is enabled. Default 100.

    +
    +
    batchBufferLimit
    +
    +

    Default 10000.

    +
    +
    batchTimeout
    +
    +

    Default 5000.

    +
    +
    compress
    +
    +

    Whether data should be compressed when sent. Default false.

    +
    +
    deliveryMode
    +
    +

    Delivery mode. Default PERSISTENT.

    +
    +
    prefix
    +
    +

    A prefix to be added to the name of the destination exchange. Default "".

    +
    +
    requestHeaderPatterns
    +
    +

    The request headers to be transported. Default [STANDARD_REQUEST_HEADERS,'*'].

    +
    +
    replyHeaderPatterns
    +
    +

    The reply headers to be transported. Default [STANDARD_REQUEST_HEADERS,'*']

    +
    +
    +
    +
    +
    +
    +

    Kafka-specific settings

    +
    +

    Kafka binder properties

    +
    +
    +
    spring.cloud.stream.kafka.binder.brokers
    +
    +

    A list of brokers that the Kafka binder will connect to. Default localhost.

    +
    +
    spring.cloud.stream.kafka.binder.defaultBrokerPort
    +
    +

    The list of brokers allows to specify hosts with or without port information, i.e. host1,host2:port2. This configuration sets the default port when no port is configured in the broker list. Default 9092.

    +
    +
    spring.cloud.stream.kafka.binder.zkNodes
    +
    +

    A list of Zookeeper nodes for the Kafka binder to connect to. Default localhost.

    +
    +
    spring.cloud.stream.kafka.binder.defaultZkPort
    +
    +

    The list of Zookeeper nodes allows to specify hosts with or without port information, i.e. host1,host2:port2. This configuration sets the default port when no port is configured in the node list. Default 2181.

    +
    +
    spring.cloud.stream.kafka.binder.headers
    +
    +

    The list of custom that will be transported by the binder. Default empty.

    +
    +
    spring.cloud.stream.kafka.binder.offsetUpdateTimeWindow
    +
    +

    The frequency in milliseconds with which offsets are saved. Ignored if 0. Default 10000.

    +
    +
    spring.cloud.stream.kafka.binder.offsetUpdateCount
    +
    +

    The frequency in number of updates, which which consumed offsets are persisted. Ignored if 0. Default 0. Mutually exclusive with offsetUpdateTimeWindow.

    +
    +
    spring.cloud.stream.kafka.binder.requiredAcks
    +
    +

    The number of required acks on the broker.

    +
    +
    +
    +
    +
    +

    Kafka Consumer Properties

    +
    +

    The following properties are available for Kafka consumers only and +must be prefixed with spring.cloud.stream.kafka.bindings.<channelName>.consumer .

    +
    +
    +
    +
    autoCommitOffset
    +
    +

    True to autocommit offsets when a message has been processed. If set to false, an Acknowledgment header will be available in the message headers for late acknowledgment. Default true.

    +
    +
    mode
    +
    +

    When set to raw, will disable header parsing on input. Useful when inbound data is coming from outside Spring Cloud Stream applications. Default embeddedHeaders.

    +
    +
    resetOffsets
    +
    +

    True to reset offsets on the consumer to the value provided by startOffset. Default false.

    +
    +
    startOffset
    +
    +

    The starting offset for new groups or when resetOffsets is true. Allowed values: earliest,latest. Defaults to null (equivalent to earliest).

    +
    +
    minPartitionCount
    +
    +

    The minimum number of partitions expected by the consumer if it creates the consumed topic automatically. Defaults to 1.

    +
    +
    +
    +
    +
    +

    Kafka Producer Properties

    +
    +

    The following properties are available for Kafka producers only and +must be prefixed with spring.cloud.stream.kafka.bindings.<channelName>.producer .

    +
    +
    +
    +
    bufferSize
    +
    +

    This is an upper limit of how much data the Kafka Producer will attempt to batch before sending – specified in bytes. Default 16384.

    +
    +
    sync
    +
    +

    Whether the producer is synchronous. Defaults to false.

    +
    +
    batchTimeout
    +
    +

    How long will the producer wait before sending in order to allow more messages to get accumulated in the same batch. Normally the producer will not wait at all, and simply send all the messages that accumulated while the previous send was in progress. A non-zero value may increase throughput at the expense of latency. Default 0.

    +
    +
    mode
    +
    +

    When set to raw, disable header propagation on output. Useful when producing data for non-Spring Cloud Stream applications. Default embeddedHeaders.

    +
    +
    +
    +
    +
    +
    +
    +
    +

    Binder detection

    +

    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 Kafka, RabbitMQ and Redis.

    -
    -
    Classpath Detection
    +
    +

    Classpath Detection

    By default, Spring Cloud Stream relies on Spring Boot’s auto-configuration to configure the binding process. If a single binder implementation is found on the classpath, Spring Cloud Stream will use it automatically. So, for example, @@ -5271,11 +6132,10 @@ a Spring Cloud Stream project that aims to bind only to RabbitMQ can simply add

    -
    -
    Multiple Binders on the Classpath
    +
    +

    Multiple Binders on the Classpath

    -

    When multiple binders are present on the classpath, the application must indicate which binder is to be used for each -channel binding. Each binder configuration contains a META-INF/spring.binders, which is a simple properties file:

    +

    When multiple binders are present on the classpath, the application must indicate which binder is to be used for each channel binding. Each binder configuration contains a META-INF/spring.binders, which is a simple properties file:

    @@ -5284,7 +6144,7 @@ org.springframework.cloud.stream.binder.rabbit.config.RabbitServiceAutoConfigura
    -

    Similar files exist for the other binder implementations (i.e. Kafka and Redis), and it is expected that custom binder +

    Similar files exist for the other binder implementations (e.g. Kafka), 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.

    @@ -5298,8 +6158,8 @@ the value is a comma-separated list of configuration classes that contain one an spring.cloud.stream.bindings.input.binder=kafka,spring.cloud.stream.bindings.output.binder=rabbit.

    -
    -
    Connecting to Multiple Systems
    +
    +

    Connecting to Multiple Systems

    By default, binders share the Spring Boot auto-configuration of the application and create one instance of each binder found on the classpath. In scenarios where an application should connect to more than one broker of the same type, @@ -5339,229 +6199,335 @@ all the binders in use must be included in the configuration.

    +
    +
    +

    Content Type and Transformation

    +
    +
    +

    Spring Cloud Stream allows to propagate information about the content type of the messages it produces by attaching by default a contentType header to outbound messages. +For middleware that does not directly support headers, Spring Cloud Stream provides its own mechanism of wrapping outbound messages in an envelope of its own, automatically. +For middleware that does support headers, Spring Cloud Stream applications may receive messages with a given content type from non-Spring Cloud Stream applications.

    +
    +
    +

    Spring Cloud Stream can handle messages based on this information in two ways:

    +
    +
    +
      +
    • +

      through its contentType settings on inbound and outbound channels;

      +
    • +
    • +

      through its argument mapping done for @StreamListener-annotated methods.

      +
    • +
    +
    -

    Managed vs Standalone

    +

    Type converting message channels

    + +
    +
    +

    @StreamListener and conversion

    + +
    +
    +
    +
    +

    Inter-app Communication

    +
    +
    +

    Connecting multiple application instances

    -

    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, -Heroku, Azure, etc.). Spring Cloud Data Flow helps orchestrate the communication between instances, so the aspects of -configuration that deal with application interconnection will be configured transparently.

    +

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

    -
    -

    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 for Maven or Gradle.

    +

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

    +
    +

    Instance Index and Instance Count

    +
    +

    When scaling up Spring Cloud Stream applications, each instance can receive information about how many other instances +of the same application exist and what its own instance index is. This is done through the +spring.cloud.stream.instanceCount and spring.cloud.stream.instanceIndex properties. For example, if there are 3 +instances of the HDFS sink application, all three will have spring.cloud.stream.instanceCount set to 3, and the +applications will have spring.cloud.stream.instanceIndex set to 0, 1 and 2, respectively. When Spring Cloud Stream +applications are deployed via Spring Cloud Data Flow, these properties are configured automatically, but when Spring +Cloud Stream applications are launched independently, these properties must be set correctly. By default +spring.cloud.stream.instanceCount is 1, and spring.cloud.stream.instanceIndex is 0.

    +
    +
    +

    Setting up the two properties correctly on scale up scenarios is important for addressing partitioning behavior in +general (see below), and they are always required by certain types of binders (e.g. the Kafka binder) in order to +ensure that data is split correctly across multiple consumer instances.

    +
    +
    +
    +

    Partitioning

    -

    Health Indicator

    +

    Configuring Output Bindings for Partitioning

    +
    +

    An output binding 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, setting +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 sufficient for your needs, you can instead calculate the partition key +value by setting the property partitionKeyExtractorClass. This class must implement the interface +org.springframework.cloud.stream.binder.PartitionKeyExtractorStrategy. While, in general, the SpEL expression should +suffice, 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 - 1. 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 Bindings for Partitioning
    +
    +

    An input binding is configured to receive partitioned data by setting its partitioned property, as well as the +instance index and instance count properties on the app itself, 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 app instances between which the data needs to be partitioned, +whereas instance index must be a unique value across the multiple instances, between 0 and instanceCount - 1. The +instance index helps each app instance to identify the unique partition (or in the case of Kafka, the partition set) +from which it receives data. It is important that both values are set correctly in order to ensure that all the data is +consumed, and that the app instances 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.

    +
    +
    +
    +
    +
    +
    +
    +

    Health Indicator

    +

    Spring Cloud Stream provides a health indicator for the binders, registered under the name of binders. It can be enabled or disabled using the management.health.binders.enabled property.

    -
    -

    Binder SPI

    -
    -

    As described above, Spring Cloud Stream provides a binder abstraction for connecting to physical destinations. This -section will provide more information about the main concepts behind the Binder SPI, its main components, as well as -details specific to different implementations.

    -
    -
    -

    Producers and Consumers

    -
    -
    -producers consumers -
    -
    Figure 4. Producers and Consumers
    -
    -
    -

    A producer is any component that sends messages to a channel. That channel can be bound to an external message broker -via a Binder implementation for that broker. When invoking the bindProducer method, the first parameter is the name -of the destination within that broker. The second parameter is the local channel instance to which the producer will be -sending messages, and the third parameter contains properties to be used within the adapter that is created for that -channel, such as a partition key expression.

    -
    -
    -

    A consumer is any component that receives messages from a channel. As with the producer, the consumer’s channel can be -bound to an external message broker, and the first parameter for the bindConsumer method is the destination name. -However, on the consumer side, a second parameter provides the name of a logical group of consumers. Each group -represented by consumer bindings for a given destination will receive a copy of each message that a producer sends to -that destination (i.e. pub/sub semantics). If there are multiple consumer instances bound using the same group name, -then messages will be load balanced across those consumer instances so that each message sent by a producer would only -be consumed by a single consumer instance within each group (i.e. queue semantics).

    -
    -
    -
    -

    Kafka Binder

    -
    -
    -kafka binder -
    -
    Figure 5. Kafka Binder
    -
    -
    -

    The Kafka Binder implementation maps the destination to a Kafka topic, and the consumer group maps directly to the same -Kafka concept. Spring Cloud Stream does not use the high level consumer, but implements a similar concept for the -simple consumer.

    -
    -
    -
    -

    RabbitMQ Binder

    -
    -
    -rabbit binder -
    -
    Figure 6. RabbitMQ Binder
    -
    -
    -

    The RabbitMQ Binder implementation maps the destination to a TopicExchange, and for each consumer group, a Queue -will be bound to that TopicExchange. Each consumer instance that binds will trigger creation of a corresponding -RabbitMQ Consumer instance for its group’s Queue.

    -
    -
    -
    -

    Redis Binder

    -
    -
    -redis binder -
    -
    Figure 7. Redis Binder
    -
    -
    - - - - - -
    -
    Note
    -
    -we recommend only using the Redis Binder for development -
    -
    -
    -

    The Redis Binder creates a LIST (which performs the role of a queue) for each consumer group. A consumer binding will -trigger BRPOP operations on its group’s LIST. A producer binding will consult a ZSET to determine what groups -currently have active consumers, and then for each message being sent, an LPUSH operation will be executed on each of -those group’s LISTs.

    -
    -
    -
    -
    -

    Samples

    +
    +

    Samples

    +

    For Spring Cloud Stream samples, please refer: https://github.com/spring-cloud/spring-cloud-stream-samples

    -
    -

    Spring Cloud Task

    -
    -
    -Unresolved directive in spring-cloud.adoc - include::../../../task/spring-cloud-task-docs/src/main/asciidoc/getting-started.adoc[leveloffset=+1] -Unresolved directive in spring-cloud.adoc - include::../../../task/spring-cloud-task-docs/src/main/asciidoc/features.adoc[leveloffset=+1] -
    -
    -

    Spring Cloud Bus

    -
    -
    -Spring Cloud Bus links nodes of a distributed system with a lightweight message broker. This can then be used to broadcast state changes (e.g. configuration changes) or other management instructions. A key idea is that the Bus is like a distributed Actuator for a Spring Boot application that is scaled out, but it can also be used as a communication channel between apps. The only implementation currently is with an AMQP broker as the transport, but the same basic feature set (and some more depending on the transport) is on the roadmap for other transports. -
    -
    -

    Quick Start

    +

    Getting Started

    -

    Spring Cloud Bus works by adding Spring Boot autconfiguration if it detects itself on the classpath. All you need to do to enable the bus is to add spring-cloud-starter-bus-amqp to your dependency management and Spring Cloud takes care of the rest. Make sure RabbitMQ is available and configured to provide a ConnectionFactory: running on localhost you shouldn’t have to do anything, but if you are running remotely use Spring Cloud Connectors, or Spring Boot conventions to define the broker credentials, e.g.

    +

    To get started creating Spring Cloud Stream applications, head over to https://start.spring.io and create a new project named GreetingSource. +Select the Spring Boot Version to be 1.3.4 (SNAPSHOT as of the time of this release) and tick the checkbox for Stream Kafka as we will be using Kafka for messaging. +Next create a new class GreetingSource in the same package as the class GreetingSourceApplication with the following code:

    -
    application.yml
    -
    spring:
    +
    import org.springframework.cloud.stream.annotation.EnableBinding;
    +import org.springframework.cloud.stream.messaging.Source;
    +import org.springframework.integration.annotation.InboundChannelAdapter;
    +
    +@EnableBinding(Source.class)
    +public class GreetingSource {
    +
    +    @InboundChannelAdapter(Source.OUTPUT)
    +    public String greet() {
    +        return "hello world " + System.currentTimeMillis();
    +    }
    +}
    +
    +
    +
    +

    The annotation @EnableBinding is what triggers the creation of Spring Integration infrastructure components. +Specifically, it will create a Kafka Connection Factory, Kafka Outbound Channel Adapter, and the Message Channel defined inside the Source interface.

    +
    +
    +
    +
    public interface Source {
    +
    +  String OUTPUT = "output";
    +
    +  @Output(Source.OUTPUT)
    +  MessageChannel output();
    +
    +}
    +
    +
    +
    +

    Furthermore, the auto configuration creates a default poller so that the greet method will be invoked once a second. +The standard Spring Integration InboundChannelAdapter annotation sends a message to the source’s output channel using the return value as the payload of the message.

    +
    +
    +

    To test drive this setup run a Kafka Message Broker. An easy way to do this is using a docker image.

    +
    +
    +
    +
    # on mac
    +docker run -p 2181:2181 -p 9092:9092 --env ADVERTISED_HOST=`docker-machine ip \`docker-machine active\`` --env ADVERTISED_PORT=9092 spotify/kafka
    +
    +# on linux
    +docker run -p 2181:2181 -p 9092:9092 --env ADVERTISED_HOST=localhost --env ADVERTISED_PORT=9092 spotify/kafka
    +
    +
    +
    +

    Build the application using ./mvnw clean package

    +
    +
    +

    The consumer application is coded in a similar manner, go back to https://start.spring.io and create a new project named LoggerSink. Then create a new class LoggingSink in the same package as the class LoggingSinkApplication with the following code

    +
    +
    +
    +
    import org.springframework.cloud.stream.annotation.EnableBinding;
    +import org.springframework.cloud.stream.annotation.StreamListener;
    +import org.springframework.cloud.stream.messaging.Sink;
    +
    +@EnableBinding(Sink.class)
    +public class LoggingSink {
    +
    +    @StreamListener(Sink.INPUT)
    +    public void log(String message) {
    +        System.out.println(message);
    +    }
    +}
    +
    +
    +
    +

    Build the application using ./mvnw clean package

    +
    +
    +

    To connect the Source application to the Sink application, each application needs to share the same destination name. Starting up both applications as shown below you will see the consumer application printing ‘hello world’ and the timestamp to the console.

    +
    +
    +
    +
    cd GreetingSource
    +java -jar target/GreetingSource-0.0.1-SNAPSHOT.jar --spring.cloud.stream.bindings.output.destination=mydest
    +
    +cd LoggingSink
    +java -jar target/LoggingSink-0.0.1-SNAPSHOT.jar --server.port=8090 --spring.cloud.stream.bindings.input.destination=mydest
    +
    +
    +
    +

    The different server port is avoid collisions of the http port used to service the boot actuator endpoints.

    +
    +
    +

    The output of the logging sink will look something like

    +
    +
    +
    +
    [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8090 (http)
    +[           main] com.example.LoggingSinkApplication       : Started LoggingSinkApplication in 6.828 seconds (JVM running for 7.371)
    +hello world 1458595076731
    +hello world 1458595077732
    +hello world 1458595078733
    +hello world 1458595079734
    +hello world 1458595080735
    +
    += Spring Cloud Task
    +Unresolved directive in spring-cloud.adoc - include::../../../task/spring-cloud-task-docs/src/main/asciidoc/getting-started.adoc[leveloffset=+1]
    +Unresolved directive in spring-cloud.adoc - include::../../../task/spring-cloud-task-docs/src/main/asciidoc/features.adoc[leveloffset=+1]
    +
    += Spring Cloud Bus
    +:github: https://github.com/spring-cloud/spring-cloud-config
    +:githubmaster: {github}/tree/master
    +:docslink: {githubmaster}/docs/src/main/asciidoc
    +:toc:
    +
    +Spring Cloud Bus links nodes of a distributed system with a lightweight message broker. This can then be used to broadcast state changes (e.g. configuration changes) or other management instructions. A key idea is that the Bus is like a distributed Actuator for a Spring Boot application that is scaled out, but it can also be used as a communication channel between apps. The only implementation currently is with an AMQP broker as the transport, but the same basic feature set (and some more depending on the transport) is on the roadmap for other transports.
    +
    +
    +
    +== Quick Start
    +
    +Spring Cloud Bus works by adding Spring Boot autconfiguration if it detects itself on the classpath. All you need to do to enable the bus is to add `spring-cloud-starter-bus-amqp` to your dependency management and Spring Cloud takes care of the rest. Make sure RabbitMQ is available and configured to provide a `ConnectionFactory`: running on localhost you shouldn't have to do anything, but if you are running remotely use Spring Cloud Connectors, or Spring Boot conventions to define the broker credentials, e.g.
    +
    +.application.yml
    +
    +
    +
    +

    spring: rabbitmq: host: mybroker.com port: 5672 username: user - password: secret -

    -
    -
    -

    The bus currently supports sending messages to all nodes listening or all nodes for a particular service (as defined by Eureka). More selector criteria will be added in the future (ie. only service X nodes in data center Y, etc…​). The http endpoints are under the /bus/* actuator namespace. There are currently two implemented. The first, /bus/env, sends key/values pairs to update each nodes Spring Environment. The second, /bus/refresh, will reload each application’s configuration, just as if they had all been pinged on their /refresh endpoint.

    -
    -
    -
    -
    -

    Addressing an Instance

    -
    -
    -

    The HTTP endpoints accept a "destination" parameter, e.g. "/bus/refresh?destination=customers:9000", where the destination is an ApplicationContext ID. If the ID is owned by an instance on the Bus then it will process the message and all other instances will ignore it. Spring Boot sets the ID for you in the ContextIdApplicationContextInitializer to a combination of the spring.application.name, active profiles and server.port by default.

    -
    -
    -
    -
    -

    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 will process the message. Using the example from above, "/bus/refresh?destination=customers:**" will target all instances of the "customers" service regardless of the profiles and ports set as the ApplicationContext ID.

    -
    -
    -
    -
    -

    Application Context ID must be unique

    -
    -
    -

    The bus tries to eliminate processing an event twice, once from the original ApplicationEvent and once from the queue. To do this, it checks the sending application context id againts the current application context id. If multiple instances of a service have the same application context id, events will not be processed. Running on a local machine, each service will be on a different port and that will be part of the application context id. Cloud Foundry supplies an index to differentiate. To ensure that the application context id is the unique, set spring.application.index to something unique for each instance of a service. For example, in lattice, set spring.application.index=${INSTANCE_INDEX} in application.properties (or bootstrap.properties if using configserver).

    -
    -
    -
    -
    -

    Customizing the Message Broker

    -
    -
    -

    Spring Cloud Bus uses -Spring Cloud Stream to -broadcast the messages so to get messages to flow you only need to -include the binder implementation of your choice in the -classpath. There are convenient starters specifically for the bus with -AMQP, Kafka and Redis -(spring-cloud-starter-bus-[amqp,kafka,redis]). Generally speaking -Spring Cloud Stream relies on Spring Boot autoconfiguration -conventions for configuring middleware, so for instance the AMQP -broker address can be changed with spring.rabbitmq.* -configuration properties. Spring Cloud Bus has a handful of native -configuration properties in spring.cloud.bus.* -(e.g. spring.cloud.bus.destination is the name of the topic to use -the the externall middleware). Normally the defaults will suffice.

    -
    -
    -

    To lean more about how to customize the message broker settings -consult the Spring Cloud Stream documentation.

    -
    -
    -
    -
    -

    Tracing Bus Events

    -
    -
    -

    Bus events (subclasses of RemoteApplicationEvent) can be traced by -setting spring.cloud.bus.trace.enabled=true. If you do this then the -Spring Boot TraceRepository (if it is present) will show each event -sent and all the acks from each service instance. Example (from the -/trace endpoint):

    + password: secret

    -
    {
    +
    The bus currently supports sending messages to all nodes listening or all nodes for a particular service (as defined by Eureka).  More selector criteria will be added in the future (ie. only service X nodes in data center Y, etc...). The http endpoints are under the `/bus/*` actuator namespace.  There are currently two implemented.  The first, `/bus/env`, sends key/values pairs to update each nodes Spring Environment.  The second, `/bus/refresh`, will reload each application's configuration, just as if they had all been pinged on their `/refresh` endpoint.
    +
    +== Addressing an Instance
    +
    +The HTTP endpoints accept a "destination" parameter, e.g. "/bus/refresh?destination=customers:9000", where the destination is an `ApplicationContext` ID. If the ID is owned by an instance on the Bus then it will process the message and all other instances will ignore it. Spring Boot sets the ID for you in the `ContextIdApplicationContextInitializer` to a combination of the `spring.application.name`, active profiles and `server.port` by default.
    +
    +== 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 will process the message.   Using the example from above, "/bus/refresh?destination=customers:**" will  target  all instances of the "customers" service regardless of the profiles and ports set as the `ApplicationContext` ID.
    +
    +== Application Context ID must be unique
    +
    +The bus tries to eliminate processing an event twice, once from the original `ApplicationEvent` and once from the queue.  To do this, it checks the sending application context id againts the current application context id.  If multiple instances of a service have the same application context id, events will not be processed.  Running on a local machine, each service will be on a different port and that will be part of the application context id.  Cloud Foundry supplies an index to differentiate.  To ensure that the application context id is the unique, set `spring.application.index` to something unique for each instance of a service.  For example, in lattice, set `spring.application.index=${INSTANCE_INDEX}` in application.properties (or bootstrap.properties if using configserver).
    +
    +== 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 only need to
    +include the binder implementation of your choice in the
    +classpath. There are convenient starters specifically for the bus with
    +AMQP (RabbitMQ) and Kafka
    +(`spring-cloud-starter-bus-[amqp,kafka]`). Generally speaking
    +Spring Cloud Stream relies on Spring Boot autoconfiguration
    +conventions for configuring middleware, so for instance the AMQP
    +broker address can be changed with `spring.rabbitmq.{asterisk}`
    +configuration properties. Spring Cloud Bus has a handful of native
    +configuration properties in `spring.cloud.bus.{asterisk}`
    +(e.g. `spring.cloud.bus.destination` is the name of the topic to use
    +the the externall middleware). Normally the defaults will suffice.
    +
    +To lean more about how to customize the message broker settings
    +consult the Spring Cloud Stream documentation.
    +
    +== Tracing Bus Events
    +
    +Bus events (subclasses of `RemoteApplicationEvent`) can be traced by
    +setting `spring.cloud.bus.trace.enabled=true`. If you do this then the
    +Spring Boot `TraceRepository` (if it is present) will show each event
    +sent and all the acks from each service instance. Example (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": "*:**" + "destination": ":" } }, { @@ -5571,7 +6537,7 @@ sent and all the acks from each service instance. Example (from the "type": "RefreshRemoteApplicationEvent", "id": "c4d374b7-58ea-4928-a312-31984def293b", "origin": "customers:9000", - "destination": "*:**" + "destination": ":" } }, { @@ -5581,122 +6547,239 @@ sent and all the acks from each service instance. Example (from the "type": "RefreshRemoteApplicationEvent", "id": "c4d374b7-58ea-4928-a312-31984def293b", "origin": "customers:9000", - "destination": "*:**" + "destination": ":*" } -} +}

    -
    -
    -

    This trace shows that a RefreshRemoteApplicationEvent was sent from -customers:9000, broadcast to all services, and it was received -(acked) by customers:9000 and stores:8081.

    -
    -
    -

    To handle the ack signals yourself you could add an @EventListener -for the AckRemoteAppplicationEvent and SentApplicationEvent types -to your app (and enable tracing). Or you could tap into the -TraceRepository and mine the data from there.

    -
    -
    - - - - - -
    -
    Note
    -
    -Any Bus application can trace acks, but sometimes it will be -useful to do this in a central service that can do more complex -queries on the data. Or forward it to a specialized tracing service. -
    -
    -
    -
    -

    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] ...
      +
      This trace shows that a `RefreshRemoteApplicationEvent` was sent from
      +`customers:9000`, broadcast to all services, and it was 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). Or you could tap into the
      +`TraceRepository` and mine the data from there.
      +
      +NOTE: Any Bus application can trace acks, but sometimes it will be
      +useful to do this in a central service that can do more complex
      +queries on the data. Or forward it to a specialized tracing service.
      +
      +== Broadcasting Your Own Events
      +
      +The Bus can carry any event of type `RemoteApplicationEvent`, but the
      +default transport is JSON and the deserializer needs to know which
      +types are going to be used ahead of time. To register a new type you
      +can use `@JsonTypeName` on your custom class.
      +
      +:github-tag: master
      +:github-repo: spring-cloud/spring-cloud-sleuth
      +:github-raw: http://raw.github.com/{github-repo}/{github-tag}
      +:github-code: http://github.com/{github-repo}/tree/{github-tag}
      +:toc: left
      +
      +Spring Cloud Sleuth
      +====================
      +Adrian Cole, Spencer Gibb, Marcin Grzejszczak, Dave Syer
      +:doctype: book
      +
      +Spring Cloud Sleuth implements a distributed tracing solution for http://cloud.spring.io[Spring Cloud].
      +
      +=== Terminology
      +
      +Spring Cloud Sleuth borrows http://research.google.com/pubs/pub36356.html[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.
      +
      +*Annotation:*  is used to record existence of an event in time. Some of the core annotations used to define
      +the start and stop of a request are:
      +
      +    - *cs* - Client Sent - The client has made a request. This annotation depicts the start of the span.
      +    - *sr* - Server Received -  The server side got the request and will start processing it.
      +    If one subtracts the cs timestamp from this timestamp one will receive the network latency.
      +    - *ss* - Server Sent -  Annotated upon completion of request processing (when the response
      +    got sent back to the client). If one subtracts the sr timestamp from this timestamp one
      +    will receive the time needed by the server side to process the request.
      +    - *cr* - Client Received - Signifies the end of the span. The client has successfully received the
      +    response from the server side. If one subtracts the cs timestamp from this timestamp one
      +    will receive the whole time needed by the client to receive the response from the server.
      +
      +Visualization of what *Span* and *Trace* will look in a system together with the Zipkin annotations:
      +
      +image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/trace-id.png[Trace Info propagation]
      +
      +Each color of a note signifies a span (7 spans - from *A* to *G*). If you have such information in the note:
      +
      +[source]
      +Trace Id = X
      +Span Id = D
      +Client Sent
      +
      +That means that the current span has *Trace-Id* set to *X*, *Span-Id* set to *D*. It also has emitted
      + *Client Sent* event.
      +
      +This is how the visualization of the parent / child relationship of spans would look like:
      +
      +image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/parents.png[Parent child relationship]
      +
      +=== Purpose
      +
      +In the following sections the example from the image above will be taken into consideration.
      +
      +==== Distributed tracing with Zipkin
      +
      +Altogether there are *10 spans* . If you go to traces in Zipkin you will see this number:
      +
      +image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/zipkin-traces.png[Traces]
      +
      +However if you pick a particular trace then you will see *7 spans*:
      +
      +image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/zipkin-ui.png[Traces Info propagation]
      +
      +NOTE: When picking a particular trace you will see merged spans. That means that if there were 2 spans sent to
      +Zipkin with Server Received and Server Sent / Client Received and Client Sent
      +annotations then they will presented as a single span.
      +
      +In the image depicting the visualization of what *Span* and *Trace* is you can see 20
      +colorful labels. How does it happen that in Zipkin 10 spans are received?
      +
      +    - 2 span *A* labels signify span started and closed. Upon closing a single span is sent to Zipkin.
      +    - 4 span *B* labels are in fact are single span with 4 annotations. However this span is composed of
      +        two separate instances. One sent from service 1 and one from service 2. So in fact two span instances will be sent
      +        to Zipkin and merged there.
      +    - 2 span *C* labels signify span started and closed. Upon closing a single span is sent to Zipkin.
      +    - 4 span *B* labels are in fact are single span with 4 annotations. However this span is composed of
      +        two separate instances. One sent from service 2 and one from service 3. So in fact two span instances will be sent
      +        to Zipkin and merged there.
      +    - 2 span *E* labels signify span started and closed. Upon closing a single span is sent to Zipkin.
      +    - 4 span *B* labels are in fact are single span with 4 annotations. However this span is composed of
      +        two separate instances. One sent from service 2 and one from service 4. So in fact two span instances will be sent
      +        to Zipkin and merged there.
      +    - 2 span *G* labels signify span started and closed. Upon closing a single span is sent to Zipkin.
      +
      +So 1 span from *A*, 2 spans from *B*, 1 span from *C*, 2 spans from *D*, 1 span from *E*, 2 spans from *F* and 1 from *G*.
      +Altogether *10* spans.
      +
      +==== Log correlation
      +
      +When grepping the logs of those four applications by trace id equal to e.g. `2485ec27856c56f4` one would get the following:
      +
      +[source]
      +service1.log:2016-02-26 11:15:47.561  INFO [service1,2485ec27856c56f4,2485ec27856c56f4,true] 68058 --- [nio-8081-exec-1] i.s.c.sleuth.docs.service1.Application   : Hello from service1. Calling service2
      +service2.log:2016-02-26 11:15:47.710  INFO [service2,2485ec27856c56f4,9aa10ee6fbde75fa,true] 68059 --- [nio-8082-exec-1] i.s.c.sleuth.docs.service2.Application   : Hello from service2. Calling service3 and then service4
      +service3.log:2016-02-26 11:15:47.895  INFO [service3,2485ec27856c56f4,1210be13194bfe5,true] 68060 --- [nio-8083-exec-1] i.s.c.sleuth.docs.service3.Application   : Hello from service3
      +service2.log:2016-02-26 11:15:47.924  INFO [service2,2485ec27856c56f4,9aa10ee6fbde75fa,true] 68059 --- [nio-8082-exec-1] i.s.c.sleuth.docs.service2.Application   : Got response from service3 [Hello from service3]
      +service4.log:2016-02-26 11:15:48.134  INFO [service4,2485ec27856c56f4,1b1845262ffba49d,true] 68061 --- [nio-8084-exec-1] i.s.c.sleuth.docs.service4.Application   : Hello from service4
      +service2.log:2016-02-26 11:15:48.156  INFO [service2,2485ec27856c56f4,9aa10ee6fbde75fa,true] 68059 --- [nio-8082-exec-1] i.s.c.sleuth.docs.service2.Application   : Got response from service4 [Hello from service4]
      +service1.log:2016-02-26 11:15:48.182  INFO [service1,2485ec27856c56f4,2485ec27856c56f4,true] 68058 --- [nio-8081-exec-1] i.s.c.sleuth.docs.service1.Application   : Got response from service2 [Hello from service2, response from service3 [Hello from service3] and from service4 [Hello from service4]]
      +
      +If you're using a log aggregating tool like https://www.elastic.co/products/kibana[Kibana],
      +http://www.splunk.com/[Splunk] etc. you can order the events that took place. An example of
      +Kibana would look like this:
      +
      +image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/kibana.png[Log correlation with Kibana]
      +
      +If you want to use https://www.elastic.co/guide/en/logstash/current/index.html[Logstash] here is the Grok pattern for Logstash:
      +
      +[source]
      +filter {
      +       # pattern matching logback pattern
      +       grok {
      +              match => { "message" => "%{TIMESTAMP_ISO8601:timestamp}\s+%{LOGLEVEL:severity}\s+\[%{DATA:service},%{DATA:trace},%{DATA:span},%{DATA:exportable}\]\s+%{DATA:pid}---\s+\[%{DATA:thread}\]\s+%{DATA:class}\s+:\s+%{GREEDYDATA:rest}" }
      +       }
      +}
      +
      +NOTE: If you want to use Grok together with the logs from Cloud Foundry you have to use this pattern:
      +[source]
      +filter {
      +       # pattern matching logback pattern
      +       grok {
      +              match => { "message" => "(?m)OUT\s+%{TIMESTAMP_ISO8601:timestamp}\s+%{LOGLEVEL:severity}\s+\[%{DATA:service},%{DATA:trace},%{DATA:span},%{DATA:exportable}\]\s+%{DATA:pid}---\s+\[%{DATA:thread}\]\s+%{DATA:class}\s+:\s+%{GREEDYDATA:rest}" }
      +       }
      +}
      +
      +=== Adding to the project
      +
      +In general if you want to profit only from Spring Cloud Sleuth without the Zipkin integration just add
      +the *spring-cloud-starter-sleuth* module to your project.
      +
      +If you want both Sleuth and Zipkin just add the *spring-cloud-starter-zipkin* dependency.
      +
      +== 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:
      ++
      -

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

      +

      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] …​

      -
    • -
    • -

      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%).

    -
    -
    - - - - - -
    -
    Note
    -
    -the SLF4J MDC is always set and logback users will immediately see the trace and span ids in logs per the example above. Other logging systems have to configure their own formatter to get the same result. The default is logging.pattern.level set to %clr(%5p) %clr([${spring.application.name:},%X{X-Trace-Id:-},%X{X-Span-Id:-},%X{X-Span-Export:-}]){yellow} (this is a Spring Boot feature for logback users). -
    -
    -
    -
    -
    -

    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 +

    +
    +
    +
    +notice the `[appname,traceId,spanId,exportable]` entries from the MDC:
    +
    +    - *spanId* - the id of a specific operation that took place
    +    - *appname* - the name of the application that logged the span
    +    - *traceId* - the id of the latency graph that contains the span
    +    - *exportable* - whether the log should be exported to Zipkin or not. When would you like the span not to be
    +    exportable? In the case in which you want to wrap some operation in a Span and have it written to the logs
    +    only.
    +
    +* 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.
    +
    +* Sleuth records timing information to aid in latency analysis. Using sleuth, you can pinpoint causes of
    +latency in your applications. Sleuth is written to not log too much, and to not cause your production application to crash.
    +  - propagates structural data about your call-graph in-band, and the rest out-of-band.
    +  - includes opinionated instrumentation of layers such as HTTP
    +  - includes sampling policy to manage volume
    +  - can report to a Zipkin system for query and visualization
    +
    +* Instruments common ingress and egress points from Spring applications (servlet filter, async endpoints,
    +rest template, scheduled actions, message channels, zuul filters, feign client).
    +
    +* Sleuth includes default logic to join a trace across http or messaging boundaries. For example, http propagation
    +works via Zipkin-compatible request headers. This propagation logic is defined and customized via
    +`SpanInjector` and `SpanExtractor` implementations.
    +
    +* Provides simple metrics of accepted / dropped spans.
    +
    +* If `spring-cloud-sleuth-zipkin` then the app will generate and collect Zipkin-compatible traces.
    +By default it sends them via HTTP to a Zipkin server on localhost (port 9411).
    +Configure the location of the service using `spring.zipkin.baseUrl`.
    +
    +* If `spring-cloud-sleuth-stream` then the app will generate and collect traces via https://github.com/spring-cloud/spring-cloud-stream[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).
    +
    +IMPORTANT: If using Zipkin or Stream, configure the percentage of spans exported using `spring.sleuth.sampler.percentage`
    +(default 0.1, i.e. 10%). *Otherwise you might think that Sleuth is not working cause it's omitting some spans.*
    +
    +NOTE: the SLF4J MDC is always set and logback users will immediately see the trace and span ids in logs per the example
    + above. Other logging systems have to configure their own formatter to get the same result. The default is
    + `logging.pattern.level` set to `%clr(%5p) %clr([${spring.application.name:},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}]){yellow}`
    + (this is a Spring Boot feature for logback users).
    + *This means that if you're not using SLF4J this pattern WILL NOT be automatically applied*.
    +
    +== 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
    +`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
    @@ -5705,121 +6788,439 @@ 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.

    +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: + +[source,java]
    -
    - - - - - -
    -
    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
    +

    @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 +

    +
    +
    == 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 +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 +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). -
    + +NOTE: Currently the instrumentation in Spring Cloud Sleuth is eager - it means that +we're actively trying to pass the tracing context between threads. Also timing events +are captured even when sleuth isn't exporting data to a tracing system. +This approach may change in the future towards being lazy on this matter. + +== Span lifecycle + +You can do the following operations on the Span by means of *Tracer* interface: + +- <<creating-and-closing-spans, start>> - when you start a span its name is assigned and start timestamp is recorded. +- <<creating-and-closing-spans, close>> - the span gets finished (the end time of the span is recorded) and if +the span is *exportable* then it will be eligible for collection to Zipkin. +The span is also removed from the current thread. +- <<continuing-spans, continue>> - a new instance of span will be created whereas it will be a copy of the +one that it continues. +- <<continuing-spans, detach>> - the span doesn't get stopped or closed. It only gets removed from the current thread. +- <<creating-spans-with-explicit-parent, create with explicit parent>> - you can create a new span and set an explicit parent to it + +=== Creating and closing spans [[creating-and-closing-spans]] + +You can manually create spans by using the *Tracer* interface. + +[source,java]
    -
    -
    -

    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

    +

    Span newSpan = this.tracer.createSpan("calculateTax"); +try { + // …​ + // You can tag a span + this.tracer.addTag("taxValue", taxValue); + // …​ + // You can log an event on a span + newSpan.logEvent("taxCalculated"); +} finally { + // Once done remember to close the span. This will allow collecting + // the span to send it to Zipkin + this.tracer.close(newSpan); +}

    -
    @SpringBootApplication
    +
    In this example we could see how to create a new instance of span. Assuming that there already
    +was a span present in this thread then it would become the parent of that span.
    +
    +IMPORTANT: Always clean after you create a span! Don't forget to close a span if you want to send it to Zipkin.
    +
    +=== Continuing spans [[continuing-spans]]
    +
    +Sometimes you don't want to create a new span but you want to continue one. Example of such a
    +situation might be (of course it all depends on the use-case):
    +
    +    - *AOP* - If there was already a span created before an aspect was reached then you might not want to create a new span.
    +    - *Hystrix* - executing a Hystrix command is most likely a logical part of the current processing. It's in fact
    +    only a technical implementation detail that you wouldn't necessarily want to reflect in tracing as a separate being.
    +
    +The continued instance of span is equal to the one that it continues:
    +[source,java]
    +
    +
    +
    +

    Span continuedSpan = this.tracer.continueSpan(spanToContinue); +assertThat(continuedSpan).isEqualTo(spanToContinue);

    +
    +
    +
    +
    To continue a span you can use the *Tracer* interface.
    +
    +[source,java]
    +
    +
    +
    +

    Span continuedSpan = this.tracer.continueSpan(initialSpan); +try { + // …​ + // You can tag a span + this.tracer.addTag("taxValue", taxValue); + // …​ + // You can log an event on a span + continuedSpan.logEvent("taxCalculated"); +} finally { + // Once done remember to detach the span. That way you’ll + // safely remove it from the current thread without closing it + this.tracer.detach(continuedSpan); +}

    +
    +
    +
    +
    IMPORTANT: Always clean after you create a span! Don't forget to detach a span if some work was done started in one
    + thread (e.g. thread X) and it's waiting for other threads (e.g. Y, Z) to finish.
    + Then the spans in the threads Y, Z should be detached at the end of their work. When the results are collected
    + the span in thread X should be closed.
    +
    +=== Creating spans with an explicit parent [[creating-spans-with-explicit-parent]]
    +
    +There is a possibility that you want to start a new span and provide an explicit parent of that span.
    +Let's assume that the parent of a span is in one thread and you want to start a new span in another thread. The
    +`startSpan` method of the `Tracer` interface is the method you are looking for.
    +
    +[source,java]
    +
    +
    +
    +

    Span newSpan = this.tracer.createSpan("calculateCommission", initialSpan); +try { + // …​ + // You can tag a span + this.tracer.addTag("commissionValue", commissionValue); + // …​ + // You can log an event on a span + newSpan.logEvent("commissionCalculated"); +} finally { + // Once done remember to close the span. This will allow collecting + // the span to send it to Zipkin. The tags and events set on the + // newSpan will not be present on the parent + this.tracer.close(newSpan); +}

    +
    +
    +
    +
    IMPORTANT: After having created such a span remember to close it. Otherwise you will see a lot of warnings in your logs
    + related to the fact that you have a span present in the current thread other than the one you're trying to close.
    + What's worse your spans won't get closed properly thus will not get collected to Zipkin.
    +
    +== Naming spans
    +
    +Picking a span name is not a trivial task. Span name should depict an operation name. The name should
    +be low cardinality (e.g. not include identifiers).
    +
    +Since there is a lot of instrumentation going on some of the span names will be
    +artificial like:
    +
    +- `http:path` when received an http request on a given path
    +- `async` for asynchronous operations done via wrapped `Callable` and `Runnable`.
    +- `@Scheduled` annotated methods will return the simple name of the class.
    +
    +Fortunately, for the asynchronous processing you can provide explicit naming.
    +
    +=== @SpanName annotation
    +
    +You can do name the span explicitly via the `@SpanName` annotation.
    +
    +[source,java]
    +
    +
    +
    +

    @SpanName("calculateTax") +class TaxCountingRunnable implements Runnable {

    +
    +
    +
    +
        @Override public void run() {
    +        // perform logic
    +    }
    +}
    +
    +
    +
    +
    +
    In this case, when processed in the following manner:
    +
    +[source,java]
    +
    +
    +
    +

    Runnable runnable = new TraceRunnable(tracer, spanNamer, new TaxCountingRunnable()); +Future<?> future = executorService.submit(runnable); +future.get();

    +
    +
    +
    +
    The span will be named `calculateTax`.
    +
    +=== toString() method
    +
    +It's pretty rare to create separate classes for `Runnable` or `Callable`. Typically one creates an anonymous
    +instance of those classes. You can't annotate such classes thus to override that, if there is no `@SpanName` annotation present,
    +we're checking if the class has a custom implementation of the `toString()` method.
    +
    +So executing such code:
    +
    +[source,java]
    +
    +
    +
    +

    Runnable runnable = new TraceRunnable(tracer, spanNamer, new Runnable() { + @Override public void run() { + // perform logic + }

    +
    +
    +
    +
        @Override public String toString() {
    +        return "calculateTax";
    +    }
    +});
    +Future<?> future = executorService.submit(runnable);
    +// ... some additional logic ...
    +future.get();
    +
    +
    +
    +
    +
    will lead in creating a span named `calculateTax`.
    +
    +== Customizations
    +
    +Thanks to the `SpanInjector` and `SpanExtractor` you can customize the way spans
    +are created and propagated.
    +
    +There are currently two built-in ways to pass tracing information between processes:
    +
    + * via Spring Integration
    + * via HTTP
    +
    +Span ids are extracted from Zipkin-compatible (B3) headers (either `Message`
    +or HTTP headers), to start or join an existing trace. Trace information is
    +injected into any outbound requests so the next hop can extract them.
    +
    +=== Spring Integration
    +
    +For Spring Integration these are the beans responsible for creation of a Span from a `Message`
    + and filling in the `MessageBuilder` with tracing information.
    +
    +[source,java]
    +
    +
    +
    +

    @Bean +public SpanExtractor<Message> messagingSpanExtractor() { + …​ +}

    +
    +
    +

    @Bean +public SpanInjector<MessageBuilder> messagingSpanInjector() { + …​ +}

    +
    +
    +
    +
    You can override them by providing your own implementation and by adding a `@Primary` annotation
    +to your bean definition.
    +
    +=== HTTP
    +
    +For HTTP these are the beans responsible for creation of a Span from a `HttpServletRequest`
    +  and filling in the `HttpServletResponse` with tracing information.
    +
    +[source,java]
    +
    +
    +
    +

    @Bean +public SpanExtractor<HttpServletRequest> httpServletRequestSpanExtractor() { + …​ +}

    +
    +
    +

    @Bean +public SpanInjector<HttpServletResponse> httpServletResponseSpanInjector() { + …​ +}

    +
    +
    +
    +
    You can override them by providing your own implementation and by adding a `@Primary` annotation
    +to your bean definition.
    +
    +=== Example
    +
    +Let's assume that instead of the standard Zipkin compatible tracing HTTP header names
    +you have
    +
    +* for trace id - `correlationId`
    +* for span id - `mySpanId`
    +
    +This is a an example of a `SpanExtractor`
    +
    +[source,java]
    +
    +
    +
    +

    static class CustomHttpServletRequestSpanExtractor + implements SpanExtractor<HttpServletRequest> {

    +
    +
    +
    +
        @Override
    +    public Span joinTrace(HttpServletRequest carrier) {
    +        long traceId = Span.hexToId(carrier.getHeader("correlationId"));
    +        long spanId = Span.hexToId(carrier.getHeader("mySpanId"));
    +        // extract all necessary headers
    +        Span.SpanBuilder builder = Span.builder().traceId(traceId).spanId(spanId);
    +        // build rest of the Span
    +        return builder.build();
    +    }
    +}
    +
    +
    +
    +
    +
    The following `SpanInjector` could be created
    +
    +[source,java]
    +
    +
    +
    +

    static class CustomHttpServletResponseSpanInjector + implements SpanInjector<HttpServletResponse> {

    +
    +
    +
    +
        @Override
    +    public void inject(Span span, HttpServletResponse carrier) {
    +        carrier.addHeader("correlationId", Span.idToHex(span.getTraceId()));
    +        carrier.addHeader("mySpanId", Span.idToHex(span.getSpanId()));
    +        // inject the rest of Span values to the header
    +    }
    +}
    +
    +
    +
    +
    +
    And you could register them like this:
    +
    +[source,java]
    +
    +
    +
    +

    @Bean +@Primary +SpanExtractor<HttpServletRequest> customHttpServletRequestSpanExtractor() { + return new CustomHttpServletRequestSpanExtractor(); +}

    +
    +
    +

    @Bean +@Primary +SpanInjector<HttpServletResponse> customHttpServletResponseSpanInjector() { + return new CustomHttpServletResponseSpanInjector(); +}

    +
    +
    +
    +
    == Span Data as Messages
    +
    +You can accumulate and send span data over
    +http://cloud.spring.io/spring-cloud-stream[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
    +
    +[source,java]
    +
    +
    +
    +

    @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.:

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

    -
    spring:
    +
    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
    +https://github.com/openzipkin/zipkin-java[Zipkin server], which hosts
    +the UI and api on port 9411.
    +
    +The default `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.:
    +
    +[source,yaml]
    +
    +
    +
    +

    spring: rabbitmq: host: ${RABBIT_HOST:localhost} datasource: @@ -5834,66 +7235,243 @@ started quickly). For a more robust solution you can add MySQL and 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:

    + type: mysql

    -
    @EnableBinding(SleuthSink.class)
    +
    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:
    +
    +[source,java]
    +
    +
    +
    +

    @EnableBinding(SleuthSink.class) @SpringBootApplication(exclude = SleuthStreamAutoConfiguration.class) @MessageEndpoint -public class Consumer { - - @ServiceActivator(inputChannel = SleuthSink.INPUT) +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, +
    +
    +
    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).
    -
    + +== Metrics + +Currently Spring Cloud Sleuth registers very simple metrics related to spans. +It's using the http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-metrics.html#production-ready-recording-metrics[Spring Boot's metrics support] +to calculate the number of accepted and dropped spans. Each time a span gets +sent to Zipkin the number of accepted spans will increase. If there's an error then +the number of dropped spans will get increased. + +== Integrations + +=== Runnable and Callable + +If you're wrapping your logic in `Runnable` or `Callable` it's enough to wrap those classes in their Sleuth representative. + +Example for `Runnable`: + +[source,java]
    +
    +

    Runnable runnable = new Runnable() { + @Override + public void run() { + // do some work + }

    -
    -

    Spring Cloud Consul

    -
    +
    +
        @Override
    +    public String toString() {
    +        return "spanNameFromToStringMethod";
    +    }
    +};
    +// Manual `TraceRunnable` creation with explicit "calculateTax" Span name
    +Runnable traceRunnable = new TraceRunnable(tracer, spanNamer, runnable, "calculateTax");
    +// Wrapping `Runnable` with `Tracer`. The Span name will be taken either from the
    +// `@SpanName` annotation or from `toString` method
    +Runnable traceRunnableFromTracer = tracer.wrap(runnable);
    +
    +
    +
    +
    +
    Example for `Callable`:
    +
    +[source,java]
    +
    +
    +
    +

    Callable<String> callable = new Callable<String>() { + @Override + public String call() throws Exception { + return someLogic(); + }

    +
    +
    +
    +
        @Override
    +    public String toString() {
    +        return "spanNameFromToStringMethod";
    +    }
    +};
    +// Manual `TraceCallable` creation with explicit "calculateTax" Span name
    +Callable<String> traceCallable = new TraceCallable<>(tracer, spanNamer, callable, "calculateTax");
    +// Wrapping `Callable` with `Tracer`. The Span name will be taken either from the
    +// `@SpanName` annotation or from `toString` method
    +Callable<String> traceCallableFromTracer = tracer.wrap(callable);
    +
    +
    +
    +
    +
    That way you will ensure that a new Span is created and closed for each execution.
    +
    +=== Hystrix
    +
    +==== Custom Concurrency Strategy
    +
    +We're registering a custom https://github.com/Netflix/Hystrix/wiki/Plugins#concurrencystrategy[`HystrixConcurrencyStrategy`]
    +that wraps all `Callable` instances into their Sleuth representative -
    +the `TraceCallable`. The strategy either starts or continues a span depending on the fact whether tracing was already going
    +on before the Hystrix command was called. To disable the custom Hystrix Concurrency Strategy set the `spring.sleuth.hystrix.strategy.enabled` to `false`.
    +
    +==== Manual Command setting
    +
    +Assuming that you have the following `HystrixCommand`:
    +
    +[source,java]
    +
    +
    +
    +

    HystrixCommand<String> hystrixCommand = new HystrixCommand<String>(setter) { + @Override + protected String run() throws Exception { + return someLogic(); + } +};

    +
    +
    +
    +
    In order to pass the tracing information you have to wrap the same logic in the Sleuth version of the `HystrixCommand` which is the
    +`TraceCommand`:
    +
    +[source,java]
    +
    +
    +
    +

    TraceCommand<String> traceCommand = new TraceCommand<String>(tracer, traceKeys, setter) { + @Override + public String doRun() throws Exception { + return someLogic(); + } +};

    +
    +
    +
    +
    === HTTP integration
    +
    +Features from this section can be disabled by providing the `spring.sleuth.web.enabled` property with value equal to `false`.
    +
    +==== HTTP Filter
    +
    +Via the `TraceFilter` all sampled incoming requests result in creation of a Span. That Span's name is `http:` + the path to which
    + the request was sent. E.g. if the request was sent to `/foo/bar` then the name will be `http:/foo/bar`. You can configure which URIs you would
    + like to skip via the `spring.sleuth.web.skipPattern` property. If you have `ManagementServerProperties` on classpath then
    + its value of `contextPath` gets appended to the provided skip pattern.
    +
    +==== Async Servlet support
    +
    +If your controller returns a `Callable` or a `WebAsyncTask` Spring Cloud Sleuth will continue the existing span instead of creating a new one.
    +
    +=== HTTP client integration
    +
    +==== Synchronous Rest Template
    +
    +We're injecting a `RestTemplate` interceptor that ensures that all the tracing information is passed to the requests. Each time a
    +call is made a new Span is created. It gets closed upon receiving the response. In order to block the synchronous `RestTemplate` features
    +just set `spring.sleuth.web.client.enabled` to `false`.
    +
    +==== Asynchronous Rest Template
    +
    +Custom instrumentation is set to create and close Spans upon sending and receiving requests. To block the `AsyncRestTemplate`
    +features set `spring.sleuth.web.async.client.enabled` to `false`.
    +
    +=== Feign
    +
    +By default Spring Cloud Sleuth provides integration with feign via the `TraceFeignClientAutoConfiguration`. You can disable it entirely
    +by setting `spring.sleuth.feign.enabled` to false. If you do so then no Feign related instrumentation will take place.
    +
    +Part of Feign instrumentation is done via a `FeignBeanPostProcessor`. You can disable it by providing the `spring.sleuth.feign.processor.enabled` equal to `false`.
    +If you set it like this then Spring Cloud Sleuth will not instrument any of your custom Feign components. All the default instrumentation
    +however will be still there.
    +
    +=== Asynchronous communication
    +
    +==== @Async annotated methods
    +
    +In Spring Cloud Sleuth we're instrumenting async related components so that the tracing information is passed between threads. You can disable this behaviour
    +by setting the value of `spring.sleuth.async.enabled` to `false`.
    +
    +If you annotate your method with `@Async` then we'll automatically create a new Span with the following characteristics:
    +
    +    - the Span name will be the annotated method name
    +    - the Span will be tagged with that method's class name and the method name too
    +
    +==== @Scheduled annotated methods
    +
    +In Spring Cloud Sleuth we're instrumenting scheduled method execution so that the tracing information is passed between threads. You can disable this behaviour
    +by setting the value of `spring.sleuth.scheduled.enabled` to `false`.
    +
    +If you annotate your method with `@Scheduled` then we'll automatically create a new Span with the following characteristics:
    +
    +    - the Span name will be the annotated method name
    +    - the Span will be tagged with that method's class name and the method name too
    +
    +If you want to skip Span creation for some `@Scheduled` annotated classes you can set the
    +`spring.sleuth.scheduled.skipPattern` with a regular expression that will match the fully qualified name of the
    +`@Scheduled` annotated class.
    +
    +==== Executor, ExecutorService and ScheduledExecutorService
    +
    +We're providing `LazyTraceExecutor`, `TraceableExecutorService` and `TraceableScheduledExecutorService`. Those implementations
    +are creating Spans each time a new task is submitted, invoked or scheduled.
    +
    +=== Messaging
    +
    +Spring Cloud Sleuth integrates with http://projects.spring.io/spring-integration/[Spring Integration]. It creates spans for publish and
    +subscribe events. To disable Spring Integration instrumentation, set `spring.sleuth.integration.enabled` to false.
    +
    +=== Zuul
    +
    +We're registering Zuul filters to propagate the tracing information (the request header is enriched with tracing data).
    +To disable Zuul support set the `spring.sleuth.zuul.enabled` property to `false`.
    +
    +:github-tag: master
    +:github-repo: spring-cloud/spring-cloud-consul
    +:github-raw: http://raw.github.com/{github-repo}/{github-tag}
    +:github-code: http://github.com/{github-repo}/tree/{github-tag}
    += 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
    @@ -5901,362 +7479,352 @@ application and build large distributed systems with Consul based components. Th
     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.
    +
    +
    +[[spring-cloud-consul-install]]
    +== Install Consul
    +Please see the https://www.consul.io/intro/getting-started/install.html[installation documentation] for instructions on how to install Consul.
    +
    +[[spring-cloud-consul-agent]]
    +== 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 https://consul.io/docs/agent/basics.html[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:
    -
    -

    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
    -
    ./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
    +
    +[[spring-cloud-consul-discovery]]
    +== 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 https://www.consul.io/docs/agent/http.html[HTTP API] and https://www.consul.io/docs/agent/dns.html[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 https://www.consul.io/docs/internals/architecture.html[cluster] that communicates via a https://www.consul.io/docs/internals/gossip.html[gossip protocol] and uses the https://www.consul.io/docs/internals/consensus.html[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 https://www.consul.io/docs/agent/checks.html[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:
    +
    +[source,java,indent=0]
    -

    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
    +

    @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); - } - -}

    +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:
    +
    (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:

    + port: 8500

    -
    application.yml
    -
    spring:
    +
    CAUTION: If you use <<spring-cloud-consul-config,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:

    + healthCheckInterval: 15s

    -
    application.yml
    -
    spring:
    +
    ==== 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.

    + instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}}

    -
    @Autowired
    -private DiscoveryClient discoveryClient;
    +
    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.
     
    -public String serviceUrl() {
    +=== Using the DiscoveryClient
    +Spring Cloud has support for https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-feign[Feign] (a REST client builder) and also https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-ribbon[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/
    +
    [[spring-cloud-consul-config]]
    +== Distributed Configuration with Consul
    +
    +Consul provides a https://consul.io/docs/agent/http/kv.html[Key/Value Store] for storing configuration and other metadata.  Spring Cloud Consul Config is an alternative to the https://github.com/spring-cloud/spring-cloud-config[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:

    +config/application/

    -
    bootstrap.yml
    -
    spring:
    +
    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:

    + profileSeparator: '::'

    -
    bootstrap.yml
    -
    spring:
    +
    * `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
    +
    +
    +[[spring-cloud-consul-config-format]]
    +== 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:

    + format: YAML

    -
    config/testApp,dev/data
    +
    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.

    -
    -
    -
    -
    -

    Fail Fast

    -
    -
    -

    It may be convenient in certain circumstances (like local development or certain test scenarios) to not fail if consul isn’t available for configuration. Setting spring.cloud.consul.config.failFast=false in bootstrap.yml will cause the configuration module to log a warning rather than throw an exception. This will allow the application to continue startup normally.

    -
    -
    -
    -
    -

    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

    -
    -
    -

    Coming in a later release.

    -
    -
    -
    -
    -

    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:

    +config/application/data

    -
    pom.xml
    -
    <dependency>
    +
    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`.
    +
    +[[spring-cloud-consul-config-git2consul]]
    +== git2consul with Config
    +git2consul is a Consul community project that loads files from a git repository to individual keys into Consul. By default the names of the keys are names of the files. YAML and Properties files are supported with file extensions of `.yml` and `.properties` respectively.  Set the `spring.cloud.consul.config.format` property to `FILES`. For example:
    +
    +.bootstrap.yml
    +
    +
    +
    +

    spring: + cloud: + consul: + config: + format: FILES

    +
    +
    +
    +
    Given the following keys in `/config`, the `development` profile and an application name of `foo`:
    +
    +
    +
    +
    gitignore
    +

    application.yml +bar.properties +foo-development.properties +foo-production.yml +foo.properties +master.ref

    +
    +
    +
    +
    the following property sources would be created:
    +
    +
    +
    +

    config/foo-development.properties +config/foo.properties +config/application.yml

    +
    +
    +
    +
    The value of each key needs to be a properly formatted YAML or Properties file.
    +
    +
    +[[spring-cloud-consul-failfast]]
    +== Fail Fast
    +
    +It may be convenient in certain circumstances (like local development or certain test scenarios) to not fail if consul isn't available for configuration. Setting `spring.cloud.consul.config.failFast=false` in `bootstrap.yml` will cause the configuration module to log a warning rather than throw an exception. This will allow the application to continue startup normally.
    +
    +[[spring-cloud-consul-retry]]
    +== 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-consul-bus]]
    +== Spring Cloud Bus with Consul
    +
    +Coming in a later release.
    +
    +[[spring-cloud-consul-hystrix]]
    +== 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 http://projects.spring.io/spring-cloud/spring-cloud.html#_circuit_breaker_hystrix_clients[the documentation] for more details.
    +
    +
    +[[spring-cloud-consul-turbine]]
    +== 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> +</dependency>

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

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

    -
    -
    -
    application.yml
    -
    -
    spring.application.name: turbine
    +

    spring.application.name: turbine applications: consulhystrixclient turbine: aggregator: clusterConfig: ${applications} - appConfig: ${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
    -

    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
    +

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

    +}

    -
    -
    -
    -

    Spring Cloud Zookeeper

    -
    +
    +
    :github-tag: master
    +:github-repo: spring-cloud/spring-cloud-zookeeper
    +:github-raw: http://raw.github.com/{github-repo}/{github-tag}
    +:github-code: http://github.com/{github-repo}/tree/{github-tag}
    +:toc: left
    +
    += 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
    @@ -6264,145 +7832,124 @@ application and build large distributed systems with Zookeeper based components.
     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.
    +
    +
    +[[spring-cloud-zookeeper-install]]
    +== Install Zookeeper
    +Please see the http://zookeeper.apache.org/doc/current/zookeeperStarted.html[installation documentation] for instructions on how to install Zookeeper.
    +
    +[[spring-cloud-zookeeper-discovery]]
    +== 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. http://curator.apache.org[Curator](A java library for Zookeeper) provides Service Discovery services via http://curator.apache.org/curator-x-discovery/[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:
    +
    +[source,java,indent=0]
    -
    -

    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
    +

    @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); - } - -}

    +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:
    +
    (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.

    + connect-string: localhost:2181

    -
    @Autowired
    -private DiscoveryClient discoveryClient;
    +
    CAUTION: If you use <<spring-cloud-zookeeper-config,Spring Cloud Zookeeper Config>>, the above values will need to be placed in `bootstrap.yml` instead of `application.yml`.
     
    -public String serviceUrl() {
    +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 https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-feign[Feign] (a REST client builder) and also https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-ribbon[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]]
    +
    +== Zookeeper Dependencies
    +
    +=== 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 https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-feign[Feign] (a REST client builder)
    +and also https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-ribbon[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: @@ -6422,467 +7969,355 @@ spring.cloud.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:

    + required: true

    -
    @FeignClient("newsletter")
    +
    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
    +
    ==== 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`:
    -

    and the following version:

    +

    application/vnd.newsletter.$version+json

    -
    v1
    +
    and the following `version`:
    -

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

    +

    v1

    -
    application/vnd.newsletter.v1+json
    +
    Will result in setting up of a `Content-Type` header for each request:
    -
    -
    -

    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:

    +

    application/vnd.newsletter.v1+json

    -
    headers:
    +
    ==== 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

    + - no-cache

    -
    stubs: org.springframework:foo:stubs
    +
    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]]
    +
    +== 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:
    -
    -

    means that for a particular dependencies can be found under:

    +
    +
    +
    void stateChanged(String dependencyName, DependencyState newState);
    -
    -
      -
    • -

      groupId: org.springframework

      -
    • -
    • -

      artifactId: foo

      -
    • -
    • -

      classifier: stubs - this is the default value

      -
    • -
    -
    -
    -

    This is actually equal to

    -
    stubs: org.springframework:foo
    +
    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`.
    +
    +
    +[[spring-cloud-zookeeper-config]]
    +
    +== Distributed Configuration with Zookeeper
    +
    +Zookeeper provides a http://zookeeper.apache.org/doc/current/zookeeperOver.html#sc_dataModelNameSpace[hierarchical namespace] that allows clients to store arbitrary data, such as configuration data.  Spring Cloud Zookeeper Config is an alternative to the https://github.com/spring-cloud/spring-cloud-config[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:
    -

    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,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:

    +config/application

    -
    bootstrap.yml
    -
    spring:
    +
    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: '::' + 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

    -
    +
    -Spring Boot CLI provides Spring Boot command line features for -Spring Cloud. You can write Groovy scripts to run Spring Cloud component applications -(e.g. @EnableEurekaServer). You can also easily do things like encryption and decryption to support Spring Cloud +
    * `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
    +:github: https://github.com/spring-cloud/spring-cloud-cli
    +:githubmaster: {github}/tree/master
    +:docslink: {githubmaster}/docs/src/main/asciidoc
    +
    +Spring Boot CLI provides http://projects.spring.io/spring-boot[Spring Boot] command line features for
    +https://github.com/spring-cloud[Spring Cloud]. You can write Groovy scripts to run Spring Cloud component applications
    +(e.g. `@EnableEurekaServer`). You can also easily do things like encryption and decryption to support Spring Cloud
     Config clients with secret configuration values.
    -
    -
    -
    -

    Installation

    -
    -
    -

    To install, make + + + +== Installation + +To install, make sure you have -Spring Boot CLI -(1.3.0 or better):

    -
    -
    -
    -
    $ spring version
    -Spring CLI v1.3.2.RELEASE
    -
    -
    -
    -

    E.g. for SDKMan users

    -
    -
    -
    -
    $ sdk install springboot 1.3.2.RELEASE
    -$ sdk use springboot 1.3.2.RELEASE
    -
    -
    -
    -

    and install the Spring Cloud plugin:

    -
    -
    -
    -
    $ mvn install
    -$ spring install org.springframework.cloud:spring-cloud-cli:1.1.0.BUILD-SNAPSHOT
    -
    -
    -
    - - - - - -
    -
    Important
    -
    -Prerequisites: to use the encryption and decryption features -you need the full-strength JCE installed in your JVM (it’s not there by default). +https://github.com/spring-projects/spring-boot[Spring Boot CLI] +(1.3.0 or better): + + $ spring version + Spring CLI v1.3.2.RELEASE + +E.g. for SDKMan users + +``` +$ sdk install springboot 1.3.2.RELEASE +$ sdk use springboot 1.3.2.RELEASE +``` + +and install the Spring Cloud plugin: + +``` +$ mvn install +$ spring install org.springframework.cloud:spring-cloud-cli:1.1.0.RC1 +``` + +IMPORTANT: **Prerequisites:** to use the encryption and decryption features +you need the full-strength JCE installed in your JVM (it's not there by default). You can download the "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files" from Oracle, and follow instructions for installation (essentially replace the 2 policy files in the JRE lib/security directory with the ones that you downloaded). -
    -
    -
    -
    -
    -

    Writing Groovy Scripts and Running Applications

    -
    -
    -

    Spring Cloud CLI has support for most of the Spring Cloud declarative -features, such as the @Enable* class of annotations. For example, -here is a fully functional Eureka server

    -
    -
    -
    app.groovy
    -
    -
    @EnableEurekaServer
    -class Eureka {}
    + +== Writing Groovy Scripts and Running Applications + +Spring Cloud CLI has support for most of the Spring Cloud declarative +features, such as the `@Enable*` class of annotations. For example, +here is a fully functional Eureka server + +.app.groovy +[source,groovy,indent=0]
    -

    which you can run from the command line like this

    +

    @EnableEurekaServer +class Eureka {}

    -
    $ spring run app.groovy
    +
    which you can run from the command line like this
    -

    To include additional dependencies, often it suffices just to add the -appropriate feature-enabling annotation, e.g. @EnableConfigServer, -@EnableOAuth2Sso or @EnableEurekaClient. To manually include a -dependency you can use a @Grab with the special "Spring Boot" short +

    $ spring run app.groovy

    +
    +
    +
    +
    To include additional dependencies, often it suffices just to add the
    +appropriate feature-enabling annotation, e.g. `@EnableConfigServer`,
    +`@EnableOAuth2Sso` or `@EnableEurekaClient`. To manually include a
    +dependency you can use a `@Grab` with the special "Spring Boot" short
     style artifact co-ordinates, i.e. with just the artifact ID (no need
     for group or version information), e.g. to set up a client app to
    -listen on AMQP for management events from the Spring CLoud Bus:

    +listen on AMQP for management events from the Spring CLoud Bus: + +.app.groovy +[source,groovy,indent=0]
    -
    -
    app.groovy
    -
    -
    @Grab('spring-cloud-starter-bus-amqp')
    +
    +
    +

    @Grab('spring-cloud-starter-bus-amqp') @RestController class Service { @RequestMapping('/') def home() { [message: 'Hello'] } -} -

    -
    -
    -
    -
    -

    Encryption and Decryption

    -
    -
    -

    The Spring Cloud CLI comes with an "encrypt" and a "decrypt" -command. Both accept arguments in the same form with a key specified -as a mandatory "--key", e.g.

    +}

    -
    $ spring encrypt mysecret --key foo
    +
    == Encryption and Decryption
    +
    +The Spring Cloud CLI comes with an "encrypt" and a "decrypt"
    +command. Both accept arguments in the same form with a key specified
    +as a mandatory "--key", e.g.
    +
    +
    +
    +

    $ spring encrypt mysecret --key foo 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda $ spring decrypt --key foo 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda -mysecret -

    -
    -
    -

    To use a key in a file (e.g. an RSA public key for encyption) prepend -the key value with "@" and provide the file path, e.g.

    +mysecret

    -
    $ spring encrypt mysecret --key @${HOME}/.ssh/id_rsa.pub
    -AQAjPgt3eFZQXwt8tsHAVv/QHiY5sI2dRcR+...
    +
    To use a key in a file (e.g. an RSA public key for encyption) prepend
    +the key value with "@" and provide the file path, e.g.
    +
    +

    $ spring encrypt mysecret --key @${HOME}/.ssh/id_rsa.pub +AQAjPgt3eFZQXwt8tsHAVv/QHiY5sI2dRcR+…​

    -
    -

    Spring Cloud Security

    -
    +
    +
    = Spring Cloud Security
    +:github: https://github.com/spring-cloud/spring-cloud-security
    +:githubmaster: {github}/tree/master
    +:docslink: {githubmaster}/src/main/asciidoc
    +
     Spring Cloud Security offers a set of primitives for building secure
     applications and services with minimum fuss. A declarative model which
     can be heavily configured externally (or centrally) lends itself to
    @@ -6892,520 +8327,484 @@ easy to use in a service platform like Cloud Foundry. Building on
     Spring Boot and Spring Security OAuth2 we can quickly create systems that
     implement common patterns like single sign on, token relay and token
     exchange.
    +
    +
    +== Quickstart
    +
    +=== OAuth2 Single Sign On
    +
    +Here's a Spring Cloud "Hello World" app with HTTP Basic
    +authentication and a single user account:
    +
    +.app.groovy
    +[source,java]
    -
    -

    Quickstart

    -
    -
    -

    OAuth2 Single Sign On

    -

    Here’s a Spring Cloud "Hello World" app with HTTP Basic -authentication and a single user account:

    -
    -
    -
    app.groovy
    -
    -
    @Grab('spring-boot-starter-security')
    +

    @Grab('spring-boot-starter-security') @Controller -class Application { - - @RequestMapping('/') - String home() { - 'Hello World' - } - -}

    +class Application {

    +
    +
    +
    +
    @RequestMapping('/')
    +String home() {
    +  'Hello World'
    +}
    -

    You can run it with spring run app.groovy and watch the logs for the password (username is "user"). So far this is just the default for a Spring Boot app.

    -
    -
    -

    Here’s a Spring Cloud app with OAuth2 SSO:

    +

    }

    -
    app.groovy
    -
    @Controller
    +
    You can run it with `spring run app.groovy` and watch the logs for the password (username is "user"). So far this is just the default for a Spring Boot app.
    +
    +Here's a Spring Cloud app with OAuth2 SSO:
    +
    +.app.groovy
    +[source,java]
    +
    +
    +
    +

    @Controller @EnableOAuth2Sso -class Application { - - @RequestMapping('/') - String home() { - 'Hello World' - } - -} +class Application {

    +
    +
    +
    +
    @RequestMapping('/')
    +String home() {
    +  'Hello World'
    +}
    -

    Spot the difference? This app will actually behave exactly the same as -the previous one, because it doesn’t know it’s OAuth2 credentals -yet.

    +

    }

    -
    -

    You can register an app in github quite easily, so try that if you +

    +
    +
    Spot the difference? This app will actually behave exactly the same as
    +the previous one, because it doesn't know it's OAuth2 credentals
    +yet.
    +
    +You can register an app in github quite easily, so try that if you
     want a production app on your own domain. If you are happy to test on
     localhost:8080, then set up these properties in your application
    -configuration:

    +configuration: + +.application.yml +[source,yaml]
    -
    -
    application.yml
    -
    -
    spring:
    +
    +
    +

    spring: oauth2: client: clientId: bd1c0a783ccdd1c9b9e4 clientSecret: 1a9030fbca47a5b2c28e92f19050bb77824b5ad1 - accessTokenUri: https://github.com/login/oauth/access_token - userAuthorizationUri: https://github.com/login/oauth/authorize + accessTokenUri: https://github.com/login/oauth/access_token + userAuthorizationUri: https://github.com/login/oauth/authorize clientAuthenticationScheme: form resource: - userInfoUri: https://api.github.com/user - preferTokenInfo: false + userInfoUri: https://api.github.com/user + preferTokenInfo: false

    -
    -
    -

    run the app above and it will redirect to github for authorization. If -you are already signed into github you won’t even notice that it has +

    +
    +
    run the app above and it will redirect to github for authorization. If
    +you are already signed into github you won't even notice that it has
     authenticated.  These credentials will only work if your app is
    -running on port 8080.

    -
    -
    -

    To limit the scope that the client asks for when it obtains an access token -you can set spring.oauth2.client.scope (comma separated or an array in YAML). By +running on port 8080. + +To limit the scope that the client asks for when it obtains an access token +you can set `spring.oauth2.client.scope` (comma separated or an array in YAML). By default the scope is empty and it is up to to Authorization Server to decide what the defaults should be, usually depending on the settings in -the client registration that it holds.

    -
    -
    - - - - - -
    -
    Note
    -
    -The examples above are all Groovy scripts. If you want to write the +the client registration that it holds. + +NOTE: The examples above are all Groovy scripts. If you want to write the same code in Java (or Groovy) you need to add Spring Security OAuth2 to the classpath (e.g. see the -sample here). -
    +https://github.com/spring-cloud-samples/sso[sample here]). + +=== OAuth2 Protected Resource + +You want to protect an API resource with an OAuth2 token? Here's a +simple example (paired with the client above): + +.app.groovy +[source,java]
    -
    -

    OAuth2 Protected Resource

    -

    You want to protect an API resource with an OAuth2 token? Here’s a -simple example (paired with the client above):

    -
    -
    -
    app.groovy
    -
    -
    @Grab('spring-cloud-starter-security')
    +

    @Grab('spring-cloud-starter-security') @RestController @EnableResourceServer -class Application { - - @RequestMapping('/') - def home() { - [message: 'Hello World'] - } - -}

    +class Application {

    +
    +
    +
    +
    @RequestMapping('/')
    +def home() {
    +  [message: 'Hello World']
    +}
    -

    and

    +

    }

    -
    application.yml
    -
    spring:
    +
    and
    +
    +.application.yml
    +[source,yaml]
    +
    +
    +
    +

    spring: oauth2: resource: - userInfoUri: https://api.github.com/user - preferTokenInfo: false + userInfoUri: https://api.github.com/user + preferTokenInfo: false

    -
    -
    -
    -
    -
    -

    More Detail

    -
    -
    -

    Single Sign On

    -
    - - - - - -
    -
    Note
    -
    -All of the OAuth2 SSO and resource server features moved to Spring Boot +
    +
    +
    == More Detail
    +
    +=== 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.
    -
    -
    -
    -
    -

    Token Relay

    -
    -

    A Token Relay is where an OAuth2 consumer acts as a Client and +http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/[Spring Boot user guide]. + +=== Token Relay + +A Token Relay is where an OAuth2 consumer acts as a Client and forwards the incoming token to outgoing resource requests. The consumer can be a pure Client (like an SSO application) or a Resource -Server.

    -
    -
    -

    Client Token Relay

    -
    -

    If your app has a -Spring -Cloud Zuul embedded reverse proxy (using @EnableZuulProxy) then you +Server. + +==== Client Token Relay + +If your app has a +http://cloud.spring.io/spring-cloud.html#netflix-zuul-reverse-proxy[Spring +Cloud Zuul] embedded reverse proxy (using `@EnableZuulProxy`) then you can ask it to forward OAuth2 access tokens downstream to the services -it is proxying. Thus the SSO app above can be enhanced simply like this:

    +it is proxying. Thus the SSO app above can be enhanced simply like this: + +.app.groovy +[source,java]
    -
    -
    app.groovy
    -
    -
    @Controller
    +
    +
    +

    @Controller @EnableOAuth2Sso @EnableZuulProxy -class Application { - -} -

    +class Application {

    -

    and it will (in addition to loggin the user in and grabbing a token) -pass the authentication token downstream to the /proxy/* -services. If those services are implemented with -@EnableOAuth2Resource then they will get a valid token in the -correct header.

    -
    -
    -

    How does it work? The @EnableOAuth2Sso annotation pulls in -spring-cloud-starter-security (which you could do manually in a -traditional app), and that in turn triggers some autoconfiguration for -a ZuulFilter, which itself is activated because Zuul is on the -classpath (via @EnableZuulProxy). The -filter -just extracts an access token from the currently authenticated user, -and puts it in a request header for the downstream requests.

    -
    -
    -
    -

    Resource Server Token Relay

    -
    -

    If your app has @EnableOAuth2Resource and also is a Client (i.e. it -has a spring.oauth2.client.clientId, even if it doesn’t use it), -then the OAuth2RestOperations that is provided for @Autowired -users by Spring Cloud (it is declared as @Primary) will also forward -tokens. If you don’t want to forward tokens (and that is a valid -choice, since you might want to act as yourself, rather than the -client that sent you the token), then you only need to create your own -OAuth2RestOperations instead of autowiring the default one. Here’s -a basic example showing the use of the autowired rest template ("foo.com" -is a Resource Server accepting the same tokens as the surrounding app):

    +

    }

    -
    MyController.java
    -
    @Autowired
    -private OAuth2RestOperations restTemplate;
    +
    and it will (in addition to loggin the user in and grabbing a token)
    +pass the authentication token downstream to the `/proxy/*`
    +services. If those services are implemented with
    +`@EnableOAuth2Resource` then they will get a valid token in the
    +correct header.
     
    -@RequestMapping("/relay")
    +How does it work? The `@EnableOAuth2Sso` annotation pulls in
    +`spring-cloud-starter-security` (which you could do manually in a
    +traditional app), and that in turn triggers some autoconfiguration for
    +a `ZuulFilter`, which itself is activated because Zuul is on the
    +classpath (via `@EnableZuulProxy`). The
    +{githubmaster}/src/main/java/org/springframework/cloud/security/oauth2/proxy/OAuth2TokenRelayFilter.java[filter]
    +just extracts an access token from the currently authenticated user,
    +and puts it in a request header for the downstream requests.
    +
    +==== Resource Server Token Relay
    +
    +If your app has `@EnableOAuth2Resource` and also is a Client (i.e. it
    +has a `spring.oauth2.client.clientId`, even if it doesn't use it),
    +then the `OAuth2RestOperations` that is provided for `@Autowired`
    +users by Spring Cloud (it is declared as `@Primary`) will also forward
    +tokens. If you don't want to forward tokens (and that is a valid
    +choice, since you might want to act as yourself, rather than the
    +client that sent you the token), then you only need to create your own
    +`OAuth2RestOperations` instead of autowiring the default one. Here's
    +a basic example showing the use of the autowired rest template ("foo.com"
    +is a Resource Server accepting the same tokens as the surrounding app):
    +
    +.MyController.java
    +[source,java]
    +
    +
    +
    +

    @Autowired +private OAuth2RestOperations restTemplate;

    +
    +
    +

    @RequestMapping("/relay") public String relay() { ResponseEntity<String> response = restTemplate.getForEntity("https://foo.com/bar", String.class); return "Success! (" + response.getBody() + ")"; -} -

    -
    -
    -
    -
    -
    -
    -

    Configuring Authentication Downstream of a Zuul Proxy

    -
    -
    -

    You can control the authorization behaviour downstream of an -@EnableZuulProxy through the proxy.auth.* settings. Example:

    +}

    -
    application.yml
    -
    proxy:
    +
    == Configuring Authentication Downstream of a Zuul Proxy
    +
    +You can control the authorization behaviour downstream of an
    +`@EnableZuulProxy` through the `proxy.auth.*` settings. Example:
    +
    +.application.yml
    +[source,yaml]
    +
    +
    +
    +

    proxy: auth: routes: customers: oauth2 stores: passthru - recommendations: none + recommendations: none

    -
    -
    -

    In this example the "customers" service gets an OAuth2 token relay, +

    +
    +
    In this example the "customers" service gets an OAuth2 token relay,
     the "stores" service gets a passthrough (the authorization header is
     just passed downstream), and the "recommendations" service has its
     authorization header removed. The default behaviour is to do a token
    -relay if there is a token available, and passthru otherwise.

    -
    -
    -

    See - -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 +relay if there is a token available, and passthru otherwise. + +See +{githubmaster}/src/main/java/org/springframework/cloud/security/oauth2/proxy/ProxyAuthenticationProperties[ +ProxyAuthenticationProperties] for full details. + += Spring Cloud for Cloud Foundry + +Spring Cloud for Cloudfoundry makes it easy to run +https://github.com/spring-cloud[Spring Cloud] apps in +https://github.com/cloudfoundry[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 +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.

    +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 +[source,java] +
    -

    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')
    +

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

    +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
    +
    If you run it without any service bindings:
    -

    It will show its app name in the home page.

    +

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

    -
    -

    Single Sign On

    -
    - - - - - -
    -
    Note
    -
    -All of the OAuth2 SSO and resource server features moved to Spring Boot +
    +
    +
    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 +http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/[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

    -
    -
    +`@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
    +== 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 <<spring-cloud-cluster-leaderelection-zookeeper>>,
    +<<spring-cloud-cluster-leaderelection-hazelcast>> and
    +<<spring-cloud-cluster-leaderelection-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:
    +[source,java]
    +
    +
    +
    +

    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
    +
    and then create it as a bean.
    +
    +[source,java]
    +
    +
    +
    +

    @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;
    +
    For simply log events you can also use a utility class
    +`LoggingListener` which allows easy configuration.
     
    -@Configuration
    +[source,java]
    +
    +
    +
    +

    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 +

    +
    +
    [[spring-cloud-cluster-leaderelection-zookeeper]]
    +=== 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 properties `spring.cloud.cluster.zookeeper.namespace` and
    +`spring.cloud.cluster.zookeeper.connect` can be used to set the
    +zookeeper base namespace path and connect string.
    +
    +[[spring-cloud-cluster-leaderelection-hazelcast]]
    +=== Hazelcast
    +`Candidate` implementation for hazelcast 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

    +`spring.cloud.cluster.hazelcast.config-location` to tell location of a +Hazelcast xml configuration file. `config-location` is a normal spring +`Resource`. + +[[spring-cloud-cluster-leaderelection-etcd]] +=== 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`
    @@ -7413,7 +8812,7 @@ created during auto-configuration.