diff --git a/images/spring-cloud-launcher-eureka-dashboard.png b/images/spring-cloud-launcher-eureka-dashboard.png new file mode 100644 index 00000000..dbd12c59 Binary files /dev/null and b/images/spring-cloud-launcher-eureka-dashboard.png differ diff --git a/images/spring-cloud-launcher-log.png b/images/spring-cloud-launcher-log.png new file mode 100644 index 00000000..916ce243 Binary files /dev/null and b/images/spring-cloud-launcher-log.png differ diff --git a/spring-cloud.html b/spring-cloud.html index a79ab9f5..4857ffe0 100644 --- a/spring-cloud.html +++ b/spring-cloud.html @@ -434,6 +434,8 @@ body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-b
  • Spring Cloud Commons: Common Abstractions
  • Span Data as Messages @@ -741,7 +745,11 @@ body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-b
  • Spring Boot Cloud CLI @@ -1132,10 +1140,10 @@ application that includes that jar on its classpath.

    Environment Changes

    -

    The application will listen for an EnvironmentChangedEvent and react +

    The application will listen for an EnvironmentChangeEvent and react to the change in a couple of standard ways (additional ApplicationListeners can be added as @Beans by the user in the -normal way). When an EnvironmentChangedEvent is observed it will +normal way). When an EnvironmentChangeEvent is observed it will have a list of key values that have changed, and the application will use those to:

    @@ -1154,13 +1162,13 @@ use those to:

    the Environment, and generally we would not recommend that approach for detecting changes (although you could set it up with a @Scheduled annotation). If you have a scaled-out client application -then it is better to broadcast the EnvironmentChangedEvent to all +then it is better to broadcast the EnvironmentChangeEvent to all the instances instead of having them polling for changes (e.g. using the Spring Cloud Bus).

    -

    The EnvironmentChangedEvent covers a large class of refresh use +

    The EnvironmentChangeEvent covers a large class of refresh use cases, as long as you can actually make a change to the Environment and publish the event (those APIs are public and part of core Spring). You can verify the changes are bound to @@ -1286,6 +1294,27 @@ the full strength JCE extensions in your JVM.

    Patterns such as service discovery, load balancing and circuit breakers lend themselves to a common abstraction layer that can be consumed by all Spring Cloud clients, independent of the implementation (e.g. discovery via Eureka or Consul).

    +

    @EnableDiscoveryClient

    +
    +

    Commons provides the @EnableDiscoveryClient annotation. This looks for implementations of the DiscoveryClient interface via META-INF/spring.factories. Implementations of Discovery Client will add a configuration class to spring.factories under the org.springframework.cloud.client.discovery.EnableDiscoveryClient key. Examples of DiscoveryClient implementations: are Spring Cloud Netflix Eureka, Spring Cloud Consul Discovery and Spring Cloud Zookeeper Discovery.

    +
    +
    +

    By default, implementations of DiscoveryClient will auto-register the local Spring Boot server with the remote discovery server. This can be disabled by setting autoRegister=false in @EnableDiscoveryClient.

    +
    +
    +
    +

    ServiceRegistry

    +
    +

    Commons now provides a ServiceRegistry interface which provides methods like register(Registration) and deregister(Registration) which allow you to provide custom registered services. Registration is a marker interface.

    +
    +
    +

    Service Registry Actuator Endpoint

    +
    +

    A /service-registry actuator endpoint is provided by Commons. This endpoint relys on a Registration bean in the Spring Application Context. Calling /service-registry/instance-status via a GET will return the status of the Registration. A POST to the same endpoint with a String body will change the status of the current Registration to the new value. Please see the documentation of the ServiceRegistry implementation you are using for the allowed values for updating the status and the values retured for the status.

    +
    +
    +
    +

    Spring RestTemplate as a Load Balancer Client

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

    @@ -1331,6 +1360,32 @@ The Ribbon client is used to create a full physical address. See RibbonAutoConfiguration for details of how the RestTemplate is set up.

    +
    +

    Retrying Failed Requests

    +
    +

    A load balanced RestTemplate can be configured to retry failed requests. +By default this logic is disabled, you can enable it by setting +spring.cloud.loadbalancer.retry.enabled=true. The load balanced RestTemplate will +honor some of the Ribbon configuration values related to retrying failed requests. +The properties you can use are client.ribbon.MaxAutoRetries, +client.ribbon.MaxAutoRetriesNextServer, and client.ribbon.OkToRetryOnAllOperations. +See the Ribbon documentation +for a description of what there properties do.

    +
    +
    + + + + + +
    +
    Note
    +
    +client in the above examples should be replaced with your Ribbon client’s +name. +
    +
    +

    Multiple RestTemplate objects

    @@ -8034,7 +8089,7 @@ will receive the whole time needed by the client to receive the response from th
    -Trace Info propagation +Trace Info propagation
    @@ -8056,7 +8111,7 @@ Client Sent
    -Parent child relationship +Parent child relationship
    @@ -8068,19 +8123,19 @@ Client Sent

    Distributed tracing with Zipkin

    -

    Altogether there are 10 spans . If you go to traces in Zipkin you will see this number:

    +

    Altogether there are 7 spans . If you go to traces in Zipkin you will see this number in the second trace:

    -Traces +Traces
    -

    However if you pick a particular trace then you will see 7 spans:

    +

    However if you pick a particular trace then you will see 4 spans:

    -Traces Info propagation +Traces Info propagation
    @@ -8098,47 +8153,71 @@ 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?

    +

    Why is there a difference between the 7 and 4 spans in this case?

    • -

      2 span A labels signify span started and closed. Upon closing a single span is sent to Zipkin.

      +

      2 spans come from http:/start span. It has the Server Received (SR) and Server Sent (SS) annotations.

    • -

      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 spans come from the RPC call from service1 to service2 to the http:/foo endpoint. It has the Client Sent (CS) +and Client Received (CR) annotations on service1 side. It also has Server Received (SR) and Server Sent (SS) annotations +on the service2 side. Physically there are 2 spans but they form 1 logical span related to an RPC call.

    • -

      2 span C labels signify span started and closed. Upon closing a single span is sent to Zipkin.

      +

      2 spans come from the RPC call from service2 to service3 to the http:/bar endpoint. It has the Client Sent (CS) +and Client Received (CR) annotations on service2 side. It also has Server Received (SR) and Server Sent (SS) annotations +on the service3 side. Physically there are 2 spans but they form 1 logical span related to an RPC call.

    • -

      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.

      +

      2 spans come from the RPC call from service2 to service4 to the http:/baz endpoint. It has the Client Sent (CS) +and Client Received (CR) annotations on service2 side. It also has Server Received (SR) and Server Sent (SS) annotations +on the service4 side. Physically there are 2 spans but they form 1 logical span related to an RPC call.

    -

    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.

    +

    So if we count the physical spans we have 1 from http:/start, 2 from service1 calling service2, 2 form service2 +calling service3 and 2 from service2 calling service4. Altogether 7 spans.

    +
    +
    +

    Logically we see the information of Total Spans: 4 because we have 1 span related to the incoming request +to service1 and 3 spans related to RPC calls.

    +
    +
    +
    +

    Visualizing errors

    +
    +

    Zipkin allows you to visualize errors in your trace. When an exception was thrown and wasn’t caught then we’re +setting proper tags on the span which Zipkin can properly colorize. You could see in the list of traces one + trace that was in red color. That’s because there was an exception thrown.

    +
    +
    +

    If you click that trace then you’ll see a similar picture

    -Zipkin deployed on Pivotal Web Services +Error Traces +
    +
    +
    +

    Then if you click on one of the spans you’ll see the following

    +
    +
    +
    +Error Traces Info propagation +
    +
    +
    +

    As you can see you can easily see the reason for an error and the whole stacktrace related to it.

    +
    +
    +
    +

    Live examples

    +
    +
    +Zipkin deployed on Pivotal Web Services
    Click Pivotal Web Services icon to see it live!Click Pivotal Web Services icon to see it live!
    @@ -8147,12 +8226,12 @@ Altogether 10 spans.

    -Dependencies +Dependencies
    -Zipkin deployed on Pivotal Web Services +Zipkin deployed on Pivotal Web Services
    Click Pivotal Web Services icon to see it live!Click Pivotal Web Services icon to see it live!
    @@ -8180,7 +8259,7 @@ Kibana would look like this:

    -Log correlation with Kibana +Log correlation with Kibana
    @@ -8241,7 +8320,7 @@ we’re passing the dependencies in the groupId:artifactId:versionLogback setup

    -

    Below you can find an example of a Logback configuration (file named logback-spring.xml) that:

    +

    Below you can find an example of a Logback configuration (file named logback-spring.xml) that:

      @@ -8591,6 +8670,22 @@ the Spring BOM

    +

    Additional resources

    +
    +
    +

    Marcin Grzejszczak talking about Spring Cloud Sleuth and Zipkin

    +
    +
    +
    + +
    +
    + +
    +
    +

    Features

    @@ -8734,7 +8829,9 @@ fixed fraction of spans.

    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. +configure the exports using spring.sleuth.sampler.percentage. The passed +value needs to be a double from 0.0 to 1.0 so it’s not a percentage. +For backwards compatibility reasons we’re not changing the property name. @@ -9134,19 +9231,13 @@ 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.

    +

    For HTTP these are the beans responsible for creation of a Span from a HttpServletRequest.

    @Bean
     public SpanExtractor<HttpServletRequest> httpServletRequestSpanExtractor() {
         ...
    -}
    -
    -@Bean
    -public SpanInjector<HttpServletResponse> httpServletResponseSpanInjector() {
    -    ...
     }
    @@ -9192,7 +9283,20 @@ you have

    -

    The following SpanInjector could be created

    +

    And you could register it like this:

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

    Spring Cloud Sleuth does not add trace/span related headers to the Http Response for security reasons. If you need the headers then a custom SpanInjector +that injects the headers into the Http Response and a Servlet filter which makes use of this can be added the following way:

    @@ -9201,9 +9305,27 @@ you have

    @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 + carrier.addHeader(Span.TRACE_ID_NAME, span.traceIdString()); + carrier.addHeader(Span.SPAN_ID_NAME, Span.idToHex(span.getSpanId())); + } +} + +static class HttpResponseInjectingTraceFilter extends GenericFilterBean { + + private final Tracer tracer; + private final SpanInjector<HttpServletResponse> spanInjector; + + public HttpResponseInjectingTraceFilter(Tracer tracer, SpanInjector<HttpServletResponse> spanInjector) { + this.tracer = tracer; + this.spanInjector = spanInjector; + } + + @Override + public void doFilter(ServletRequest request, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletResponse response = (HttpServletResponse) servletResponse; + Span currentSpan = this.tracer.getCurrentSpan(); + this.spanInjector.inject(currentSpan, response); + filterChain.doFilter(request, response); } }
    @@ -9214,15 +9336,13 @@ you have

    @Bean
    -@Primary
    -SpanExtractor<HttpServletRequest> customHttpServletRequestSpanExtractor() {
    -    return new CustomHttpServletRequestSpanExtractor();
    +SpanInjector<HttpServletResponse> customHttpServletResponseSpanInjector() {
    +    return new CustomHttpServletResponseSpanInjector();
     }
     
     @Bean
    -@Primary
    -SpanInjector<HttpServletResponse> customHttpServletResponseSpanInjector() {
    -    return new CustomHttpServletResponseSpanInjector();
    +HttpResponseInjectingTraceFilter responseInjectingTraceFilter(Tracer tracer) {
    +    return new HttpResponseInjectingTraceFilter(tracer, customHttpServletResponseSpanInjector());
     }
    @@ -9265,6 +9385,21 @@ Remember not to add both peer.service tag and the SA t
    +
    +

    Custom service name

    +
    +

    By default Sleuth assumes that when you send a span to Zipkin, you want the span’s service name + to be equal to spring.application.name value. That’s not always the case though. There + are situations in which you want to explicitly provide a different service name for all spans coming + from your application. To achieve that it’s enough to just pass the following property + to your application to override that value (example for foo service name):

    +
    +
    +
    +
    spring.zipkin.service.name: foo
    +
    +
    +
    @@ -9576,6 +9711,21 @@ If you create a RestTemplate instance with a new keywo

    Asynchronous Rest Template

    +
    + + + + + +
    +
    Important
    +
    +A traced version of an AsyncRestTemplate bean is registered for you out of the box. If you +have your own bean you have to wrap it in a TraceAsyncRestTemplate representation. The best solution +is to only customize the ClientHttpRequestFactory and / or AsyncClientHttpRequestFactory. +If you have your own AsyncRestTemplate and you don’t wrap it your calls WILL NOT GET TRACED. +
    +

    Custom instrumentation is set to create and close Spans upon sending and receiving requests. You can customize the ClientHttpRequestFactory and the AsyncClientHttpRequestFactory by registering your beans. Remember to use tracing compatible implementations (e.g. don’t forget to @@ -9664,6 +9814,18 @@ by setting the value of spring.sleuth.scheduled.enabled to fa spring.sleuth.scheduled.skipPattern with a regular expression that will match the fully qualified name of the @Scheduled annotated class.

    +
    + + + + + +
    +
    Tip
    +
    +If you are using spring-cloud-sleuth-stream and spring-cloud-netflix-hystrix-stream together, Span will be created for each Hystrix metrics and sent to Zipkin. This may be annoying. You can prevent this by setting spring.sleuth.scheduled.skipPattern=org.springframework.cloud.netflix.hystrix.stream.HystrixStreamTask +
    +

    Executor, ExecutorService and ScheduledExecutorService

    @@ -10673,12 +10835,12 @@ development time).

    To install, make sure you have Spring Boot CLI -(1.3.5 or better):

    +(1.4.1 or better):

    $ spring version
    -Spring CLI v1.3.5.RELEASE
    +Spring CLI v1.4.1.RELEASE
    @@ -10686,18 +10848,17 @@ Spring CLI v1.3.5.RELEASE
    -
    $ sdk install springboot 1.3.5.RELEASE
    -$ sdk use springboot 1.3.5.RELEASE
    +
    $ sdk install springboot 1.4.1.RELEASE
    +$ sdk use springboot 1.4.1.RELEASE
    -

    and install the Spring Cloud plugins (they are independent, so you can install one or the other or both):

    +

    and install the Spring Cloud plugin

    $ mvn install
    -$ spring install org.springframework.cloud:spring-cloud-cli:1.2.0.BUILD-SNAPSHOT
    -$ spring install org.springframework.cloud.launcher:spring-cloud-launcher-cli:1.2.0.BUILD-SNAPSHOT
    +$ spring install org.springframework.cloud:spring-cloud-cli:1.2.3.BUILD-SNAPSHOT
    @@ -10798,7 +10959,7 @@ just list them on the command line, e.g.

    Each of these apps can be configured using a local YAML file with the same name (in the current -working directory or a subdirectory called "config"). E.g. in configserver.yml you might want to +working directory or a subdirectory called "config" or in ~/.spring-cloud). E.g. in configserver.yml you might want to do something like this to locate a local git repository for the backend:

    @@ -10814,6 +10975,40 @@ do something like this to locate a local git repository for the backend:

    uri: file://${user.home}/dev/demo/config-repo
    +
    +

    Adding Additional Applications

    +
    +

    Additional applications can be added to ./config/cloud.yml (not +./config.yml because that would replace the defaults), e.g. with

    +
    +
    +
    config/cloud.yml
    +
    +
    spring:
    +  cloud:
    +    launcher:
    +      deployables:
    +        source:
    +          coordinates: maven://com.example:source:0.0.1-SNAPSHOT
    +          port: 7000
    +        sink:
    +          coordinates: maven://com.example:sink:0.0.1-SNAPSHOT
    +          port: 7001
    +
    +
    +
    +

    when you list the apps:

    +
    +
    +
    +
    $ spring cloud --list
    +source sink configserver dataflow eureka h2 hystrixdashboard kafka zipkin
    +
    +
    +
    +

    (notice the additional apps at the start of the list).

    +
    +
    @@ -11082,6 +11277,22 @@ always forward the access token downstream, also refreshing the access token automatically if it expires. (These are features of Spring Security and Spring Boot.)

    +
    + + + + + +
    +
    Note
    +
    +Spring Boot (1.4.1) does not create an +OAuth2ProtectedResourceDetails automatically if you are using +client_credentials tokens. In that case you need to create your own +ClientCredentialsResourceDetails and configure it with +@ConfigurationProperties("security.oauth2.client"). +
    +

    Client Token Relay in Zuul Proxy