You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
344 lines
51 KiB
344 lines
51 KiB
<html><head> |
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> |
|
<title>2. Spring Cloud Commons: Common Abstractions</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-commons.html" title="Cloud Native Applications"><link rel="up" href="multi_spring-cloud-commons.html" title="Cloud Native Applications"><link rel="prev" href="multi__spring_cloud_context_application_context_services.html" title="1. Spring Cloud Context: Application Context Services"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">2. Spring Cloud Commons: Common Abstractions</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__spring_cloud_context_application_context_services.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> </td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_spring_cloud_commons_common_abstractions" href="#_spring_cloud_commons_common_abstractions"></a>2. Spring Cloud Commons: Common Abstractions</h1></div></div></div><p>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 (for example, discovery with Eureka or Consul).</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_enablediscoveryclient" href="#_enablediscoveryclient"></a>2.1 @EnableDiscoveryClient</h2></div></div></div><p>Spring Cloud Commons provides the <code class="literal">@EnableDiscoveryClient</code> annotation. |
|
This looks for implementations of the <code class="literal">DiscoveryClient</code> interface with <code class="literal">META-INF/spring.factories</code>. |
|
Implementations of the Discovery Client add a configuration class to <code class="literal">spring.factories</code> under the <code class="literal">org.springframework.cloud.client.discovery.EnableDiscoveryClient</code> key. |
|
Examples of <code class="literal">DiscoveryClient</code> implementations include <a class="link" href="https://cloud.spring.io/spring-cloud-netflix/" target="_top">Spring Cloud Netflix Eureka</a>, <a class="link" href="https://cloud.spring.io/spring-cloud-consul/" target="_top">Spring Cloud Consul Discovery</a>, and <a class="link" href="https://cloud.spring.io/spring-cloud-zookeeper/" target="_top">Spring Cloud Zookeeper Discovery</a>.</p><p>By default, implementations of <code class="literal">DiscoveryClient</code> auto-register the local Spring Boot server with the remote discovery server. |
|
This behavior can be disabled by setting <code class="literal">autoRegister=false</code> in <code class="literal">@EnableDiscoveryClient</code>.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p><code class="literal">@EnableDiscoveryClient</code> is no longer required. |
|
You can put a <code class="literal">DiscoveryClient</code> implementation on the classpath to cause the Spring Boot application to register with the service discovery server.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_health_indicator" href="#_health_indicator"></a>2.1.1 Health Indicator</h3></div></div></div><p>Commons creates a Spring Boot <code class="literal">HealthIndicator</code> that <code class="literal">DiscoveryClient</code> implementations can participate in by implementing <code class="literal">DiscoveryHealthIndicator</code>. |
|
To disable the composite <code class="literal">HealthIndicator</code>, set <code class="literal">spring.cloud.discovery.client.composite-indicator.enabled=false</code>. |
|
A generic <code class="literal">HealthIndicator</code> based on <code class="literal">DiscoveryClient</code> is auto-configured (<code class="literal">DiscoveryClientHealthIndicator</code>). |
|
To disable it, set <code class="literal">spring.cloud.discovery.client.health-indicator.enabled=false</code>. |
|
To disable the description field of the <code class="literal">DiscoveryClientHealthIndicator</code>, set <code class="literal">spring.cloud.discovery.client.health-indicator.include-description=false</code>. |
|
Otherwise, it can bubble up as the <code class="literal">description</code> of the rolled up <code class="literal">HealthIndicator</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_ordering_discoveryclient_instances" href="#_ordering_discoveryclient_instances"></a>2.1.2 Ordering <code class="literal">DiscoveryClient</code> instances</h3></div></div></div><p><code class="literal">DiscoveryClient</code> interface extends <code class="literal">Ordered</code>. This is useful when using multiple discovery |
|
clients, as it allows you to define the order of the returned discovery clients, similar to |
|
how you can order the beans loaded by a Spring application. By default, the order of any <code class="literal">DiscoveryClient</code> is set to |
|
<code class="literal">0</code>. If you want to set a different order for your custom <code class="literal">DiscoveryClient</code> implementations, you just need to override |
|
the <code class="literal">getOrder()</code> method so that it returns the value that is suitable for your setup. Apart from this, you can use |
|
properties to set the order of the <code class="literal">DiscoveryClient</code> |
|
implementations provided by Spring Cloud, among others <code class="literal">ConsulDiscoveryClient</code>, <code class="literal">EurekaDiscoveryClient</code> and |
|
<code class="literal">ZookeeperDiscoveryClient</code>. In order to do it, you just need to set the |
|
<code class="literal">spring.cloud.{clientIdentifier}.discovery.order</code> (or <code class="literal">eureka.client.order</code> for Eureka) property to the desired value.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_serviceregistry" href="#_serviceregistry"></a>2.2 ServiceRegistry</h2></div></div></div><p>Commons now provides a <code class="literal">ServiceRegistry</code> interface that provides methods such as <code class="literal">register(Registration)</code> and <code class="literal">deregister(Registration)</code>, which let you provide custom registered services. |
|
<code class="literal">Registration</code> is a marker interface.</p><p>The following example shows the <code class="literal">ServiceRegistry</code> in use:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation> |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableDiscoveryClient(autoRegister=false)</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyConfiguration { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> ServiceRegistry registry; |
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> MyConfiguration(ServiceRegistry registry) { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.registry = registry; |
|
} |
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// called through some external process, such as an event or a custom actuator endpoint</span> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> register() { |
|
Registration registration = constructRegistration(); |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.registry.register(registration); |
|
} |
|
}</pre><p>Each <code class="literal">ServiceRegistry</code> implementation has its own <code class="literal">Registry</code> implementation.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">ZookeeperRegistration</code> used with <code class="literal">ZookeeperServiceRegistry</code></li><li class="listitem"><code class="literal">EurekaRegistration</code> used with <code class="literal">EurekaServiceRegistry</code></li><li class="listitem"><code class="literal">ConsulRegistration</code> used with <code class="literal">ConsulServiceRegistry</code></li></ul></div><p>If you are using the <code class="literal">ServiceRegistry</code> interface, you are going to need to pass the |
|
correct <code class="literal">Registry</code> implementation for the <code class="literal">ServiceRegistry</code> implementation you |
|
are using.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_serviceregistry_auto_registration" href="#_serviceregistry_auto_registration"></a>2.2.1 ServiceRegistry Auto-Registration</h3></div></div></div><p>By default, the <code class="literal">ServiceRegistry</code> implementation auto-registers the running service. |
|
To disable that behavior, you can set: |
|
* <code class="literal">@EnableDiscoveryClient(autoRegister=false)</code> to permanently disable auto-registration. |
|
* <code class="literal">spring.cloud.service-registry.auto-registration.enabled=false</code> to disable the behavior through configuration.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_serviceregistry_auto_registration_events" href="#_serviceregistry_auto_registration_events"></a>ServiceRegistry Auto-Registration Events</h4></div></div></div><p>There are two events that will be fired when a service auto-registers. The first event, called |
|
<code class="literal">InstancePreRegisteredEvent</code>, is fired before the service is registered. The second |
|
event, called <code class="literal">InstanceRegisteredEvent</code>, is fired after the service is registered. You can register an |
|
<code class="literal">ApplicationListener</code>(s) to listen to and react to these events.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>These events will not be fired if <code class="literal">spring.cloud.service-registry.auto-registration.enabled</code> is set to <code class="literal">false</code>.</p></td></tr></table></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_service_registry_actuator_endpoint" href="#_service_registry_actuator_endpoint"></a>2.2.2 Service Registry Actuator Endpoint</h3></div></div></div><p>Spring Cloud Commons provides a <code class="literal">/service-registry</code> actuator endpoint. |
|
This endpoint relies on a <code class="literal">Registration</code> bean in the Spring Application Context. |
|
Calling <code class="literal">/service-registry</code> with GET returns the status of the <code class="literal">Registration</code>. |
|
Using POST to the same endpoint with a JSON body changes the status of the current <code class="literal">Registration</code> to the new value. |
|
The JSON body has to include the <code class="literal">status</code> field with the preferred value. |
|
Please see the documentation of the <code class="literal">ServiceRegistry</code> implementation you use for the allowed values when updating the status and the values returned for the status. |
|
For instance, Eureka’s supported statuses are <code class="literal">UP</code>, <code class="literal">DOWN</code>, <code class="literal">OUT_OF_SERVICE</code>, and <code class="literal">UNKNOWN</code>.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_spring_resttemplate_as_a_load_balancer_client" href="#_spring_resttemplate_as_a_load_balancer_client"></a>2.3 Spring RestTemplate as a Load Balancer Client</h2></div></div></div><p><code class="literal">RestTemplate</code> can be automatically configured to use a Load-balancer client under the hood. |
|
To create a load-balanced <code class="literal">RestTemplate</code>, create a <code class="literal">RestTemplate</code> <code class="literal">@Bean</code> and use the <code class="literal">@LoadBalanced</code> qualifier, as shown in the following example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyConfiguration { |
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@LoadBalanced</xslthl:annotation> |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation> |
|
RestTemplate restTemplate() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RestTemplate(); |
|
} |
|
} |
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyClass { |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> RestTemplate restTemplate; |
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String doOtherStuff() { |
|
String results = restTemplate.getForObject(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://stores/stores"</span>, String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>); |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> results; |
|
} |
|
}</pre><div class="caution" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Caution"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Caution]" src="images/caution.png"></td><th align="left">Caution</th></tr><tr><td align="left" valign="top"><p>A <code class="literal">RestTemplate</code> bean is no longer created through auto-configuration. |
|
Individual applications must create it.</p></td></tr></table></div><p>The URI needs to use a virtual host name (that is, a service name, not a host name). |
|
The Ribbon client is used to create a full physical address. |
|
See <a class="link" href="https://github.com/spring-cloud/spring-cloud-netflix/blob/master/spring-cloud-netflix-ribbon/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonAutoConfiguration.java" target="_top">RibbonAutoConfiguration</a> for details of how the <code class="literal">RestTemplate</code> is set up.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>In order to use a load-balanced <code class="literal">RestTemplate</code>, you need to have a load-balancer implementation in your classpath. |
|
The recommended implementation is <code class="literal">BlockingLoadBalancerClient</code> |
|
- add <code class="literal">org.springframework.cloud:spring-cloud-loadbalancer</code> in order to use it. |
|
The |
|
<code class="literal">RibbonLoadBalancerClient</code> also can be used, but it’s now under maintenance and we do not recommend adding it to new projects.</p></td></tr></table></div><div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Warning"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="images/warning.png"></td><th align="left">Warning</th></tr><tr><td align="left" valign="top"><p>If you want to use <code class="literal">BlockingLoadBalancerClient</code>, make sure you do not have |
|
<code class="literal">RibbonLoadBalancerClient</code> in the project classpath, as for backward compatibility reasons, it will be used by default.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_spring_webclient_as_a_load_balancer_client" href="#_spring_webclient_as_a_load_balancer_client"></a>2.4 Spring WebClient as a Load Balancer Client</h2></div></div></div><p><code class="literal">WebClient</code> can be automatically configured to use a load-balancer client. |
|
To create a load-balanced <code class="literal">WebClient</code>, create a <code class="literal">WebClient.Builder</code> <code class="literal">@Bean</code> and use the <code class="literal">@LoadBalanced</code> qualifier, as shown in the following example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyConfiguration { |
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation> |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@LoadBalanced</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> WebClient.Builder loadBalancedWebClientBuilder() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> WebClient.builder(); |
|
} |
|
} |
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyClass { |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> WebClient.Builder webClientBuilder; |
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Mono<String> doOtherStuff() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> webClientBuilder.build().get().uri(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://stores/stores"</span>) |
|
.retrieve().bodyToMono(String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>); |
|
} |
|
}</pre><p>The URI needs to use a virtual host name (that is, a service name, not a host name). |
|
The Ribbon client is used to create a full physical address.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>If you want to use a <code class="literal">@LoadBalanced WebClient.Builder</code>, you need to have a loadbalancer |
|
implementation in the classpath. It is recommended that you add the |
|
<code class="literal">org.springframework.cloud:spring-cloud-loadbalancer</code> dependency to your project. |
|
Then, <code class="literal">ReactiveLoadBalancer</code> will be used underneath. |
|
Alternatively, this functionality will also work with spring-cloud-starter-netflix-ribbon, but the request |
|
will be handled by a non-reactive <code class="literal">LoadBalancerClient</code> under the hood. Additionally, |
|
spring-cloud-starter-netflix-ribbon is already in maintenance mode, so we do not recommned |
|
adding it to new projects.</p></td></tr></table></div><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>The <code class="literal">ReactorLoadBalancer</code> used underneath supports caching. If <code class="literal">cacheManager</code> is detected, |
|
cached version of <code class="literal">ServiceInstanceSupplier</code> will be used. If not, we will retrieve instances |
|
from discovery service without caching them. We recommend <a class="link" href="https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-caching.html" target="_top">enabling caching</a> in your project |
|
if you use <code class="literal">ReactiveLoadBalancer</code>.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_retrying_failed_requests" href="#_retrying_failed_requests"></a>2.4.1 Retrying Failed Requests</h3></div></div></div><p>A load-balanced <code class="literal">RestTemplate</code> can be configured to retry failed requests. |
|
By default, this logic is disabled. |
|
You can enable it by adding <a class="link" href="https://github.com/spring-projects/spring-retry" target="_top">Spring Retry</a> to your application’s classpath. |
|
The load-balanced <code class="literal">RestTemplate</code> honors some of the Ribbon configuration values related to retrying failed requests. |
|
You can use <code class="literal">client.ribbon.MaxAutoRetries</code>, <code class="literal">client.ribbon.MaxAutoRetriesNextServer</code>, and <code class="literal">client.ribbon.OkToRetryOnAllOperations</code> properties. |
|
If you would like to disable the retry logic with Spring Retry on the classpath, you can set <code class="literal">spring.cloud.loadbalancer.retry.enabled=false</code>. |
|
See the <a class="link" href="https://github.com/Netflix/ribbon/wiki/Getting-Started#the-properties-file-sample-clientproperties" target="_top">Ribbon documentation</a> for a description of what these properties do.</p><p>If you would like to implement a <code class="literal">BackOffPolicy</code> in your retries, you need to create a bean of type <code class="literal">LoadBalancedRetryFactory</code> and override the <code class="literal">createBackOffPolicy</code> method:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyConfiguration { |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation> |
|
LoadBalancedRetryFactory retryFactory() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> LoadBalancedRetryFactory() { |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> BackOffPolicy createBackOffPolicy(String service) { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ExponentialBackOffPolicy(); |
|
} |
|
}; |
|
} |
|
}</pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p><code class="literal">client</code> in the preceding examples should be replaced with your Ribbon client’s name.</p></td></tr></table></div><p>If you want to add one or more <code class="literal">RetryListener</code> implementations to your retry functionality, you need to |
|
create a bean of type <code class="literal">LoadBalancedRetryListenerFactory</code> and return the <code class="literal">RetryListener</code> array |
|
you would like to use for a given service, as shown in the following example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyConfiguration { |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation> |
|
LoadBalancedRetryListenerFactory retryListenerFactory() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> LoadBalancedRetryListenerFactory() { |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> RetryListener[] createRetryListeners(String service) { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RetryListener[]{<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RetryListener() { |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <T, E <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> Throwable> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">boolean</span> open(RetryContext context, RetryCallback<T, E> callback) { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//TODO Do you business...</span> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> true; |
|
} |
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <T, E <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> Throwable> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//TODO Do you business...</span> |
|
} |
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <T, E <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> Throwable> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//TODO Do you business...</span> |
|
} |
|
}}; |
|
} |
|
}; |
|
} |
|
}</pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_multiple_resttemplate_objects" href="#_multiple_resttemplate_objects"></a>2.5 Multiple RestTemplate objects</h2></div></div></div><p>If you want a <code class="literal">RestTemplate</code> that is not load-balanced, create a <code class="literal">RestTemplate</code> bean and inject it. |
|
To access the load-balanced <code class="literal">RestTemplate</code>, use the <code class="literal">@LoadBalanced</code> qualifier when you create your <code class="literal">@Bean</code>, as shown in the following example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyConfiguration { |
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@LoadBalanced</xslthl:annotation> |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation> |
|
RestTemplate loadBalanced() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RestTemplate(); |
|
} |
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Primary</xslthl:annotation> |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation> |
|
RestTemplate restTemplate() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RestTemplate(); |
|
} |
|
} |
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyClass { |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> RestTemplate restTemplate; |
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation> |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@LoadBalanced</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> RestTemplate loadBalanced; |
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String doOtherStuff() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> loadBalanced.getForObject(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://stores/stores"</span>, String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>); |
|
} |
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String doStuff() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> restTemplate.getForObject(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"https://example.com"</span>, String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>); |
|
} |
|
}</pre><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>Notice the use of the <code class="literal">@Primary</code> annotation on the plain <code class="literal">RestTemplate</code> declaration in the preceding example to disambiguate the unqualified <code class="literal">@Autowired</code> injection.</p></td></tr></table></div><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>If you see errors such as <code class="literal">java.lang.IllegalArgumentException: Can not set org.springframework.web.client.RestTemplate field com.my.app.Foo.restTemplate to com.sun.proxy.$Proxy89</code>, try injecting <code class="literal">RestOperations</code> or setting <code class="literal">spring.aop.proxyTargetClass=true</code>.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_multiple_webclient_objects" href="#_multiple_webclient_objects"></a>2.6 Multiple WebClient Objects</h2></div></div></div><p>If you want a <code class="literal">WebClient</code> that is not load-balanced, create a <code class="literal">WebClient</code> bean and inject it. |
|
To access the load-balanced <code class="literal">WebClient</code>, use the <code class="literal">@LoadBalanced</code> qualifier when you create your <code class="literal">@Bean</code>, as shown in the following example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyConfiguration { |
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@LoadBalanced</xslthl:annotation> |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation> |
|
WebClient.Builder loadBalanced() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> WebClient.builder(); |
|
} |
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Primary</xslthl:annotation> |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation> |
|
WebClient.Builder webClient() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> WebClient.builder(); |
|
} |
|
} |
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyClass { |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> WebClient.Builder webClientBuilder; |
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation> |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@LoadBalanced</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> WebClient.Builder loadBalanced; |
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Mono<String> doOtherStuff() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> loadBalanced.build().get().uri(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://stores/stores"</span>) |
|
.retrieve().bodyToMono(String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>); |
|
} |
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Mono<String> doStuff() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> webClientBuilder.build().get().uri(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://example.com"</span>) |
|
.retrieve().bodyToMono(String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>); |
|
} |
|
}</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="loadbalanced-webclient" href="#loadbalanced-webclient"></a>2.7 Spring WebFlux WebClient as a Load Balancer Client</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="webflux-with-reactive-loadbalancer" href="#webflux-with-reactive-loadbalancer"></a>2.7.1 Spring WebFlux WebClient with Reactive Load Balancer</h3></div></div></div><p><code class="literal">WebClient</code> can be configured to use the <code class="literal">ReactiveLoadBalancer</code>. |
|
If you add <code class="literal">org.springframework.cloud:spring-cloud-loadbalancer</code> to your project, |
|
<code class="literal">ReactorLoadBalancerExchangeFilterFunction</code> is auto-configured if <code class="literal">spring-webflux</code> is on the classpath. |
|
The following example shows how to configure a <code class="literal">WebClient</code> to use reactive load balancer under the hood:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyClass { |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> ReactorLoadBalancerExchangeFilterFunction lbFunction; |
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Mono<String> doOtherStuff() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> WebClient.builder().baseUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://stores"</span>) |
|
.filter(lbFunction) |
|
.build() |
|
.get() |
|
.uri(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/stores"</span>) |
|
.retrieve() |
|
.bodyToMono(String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>); |
|
} |
|
}</pre><p>The URI needs to use a virtual host name (that is, a service name, not a host name). |
|
The <code class="literal">ReactorLoadBalancerClient</code> is used to create a full physical address.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_spring_webflux_webclient_with_non_reactive_load_balancer_client" href="#_spring_webflux_webclient_with_non_reactive_load_balancer_client"></a>2.7.2 Spring WebFlux WebClient with non-reactive Load Balancer Client</h3></div></div></div><p>If you you don’t have <code class="literal">org.springframework.cloud:spring-cloud-loadbalancer</code> in your project, |
|
but you do have spring-cloud-starter-netflix-ribbon, you can still use <code class="literal">WebClient</code> with <code class="literal">LoadBalancerClient</code>. <code class="literal">LoadBalancerExchangeFilterFunction</code> |
|
will be auto-configured if <code class="literal">spring-webflux</code> is on the classpath. Please note, however, that this is |
|
uses a non-reactive client under the hood. |
|
The following example shows how to configure a <code class="literal">WebClient</code> to use load balancer:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyClass { |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> LoadBalancerExchangeFilterFunction lbFunction; |
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Mono<String> doOtherStuff() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> WebClient.builder().baseUrl(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://stores"</span>) |
|
.filter(lbFunction) |
|
.build() |
|
.get() |
|
.uri(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/stores"</span>) |
|
.retrieve() |
|
.bodyToMono(String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>); |
|
} |
|
}</pre><p>The URI needs to use a virtual host name (that is, a service name, not a host name). |
|
The <code class="literal">LoadBalancerClient</code> is used to create a full physical address.</p><p>WARN: This approach is now deprecated. |
|
We suggest you use <a class="link" href="multi__spring_cloud_commons_common_abstractions.html#webflux-with-reactive-loadbalancer" title="2.7.1 Spring WebFlux WebClient with Reactive Load Balancer">WebFlux with reactive Load-Balancer</a> |
|
instead.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_passing_your_own_load_balancer_client_configuration" href="#_passing_your_own_load_balancer_client_configuration"></a>2.7.3 Passing your own Load-Balancer Client configuration</h3></div></div></div><p>You can also use the <code class="literal">@LoadBalancerClient</code> annotation to pass your own load-balancer client configuration, passing the name of the load-balancer client and the configuration class, like so:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation> |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@LoadBalancerClient(value = "stores", configuration = StoresLoadBalancerClientConfiguration.class)</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyConfiguration { |
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation> |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@LoadBalanced</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> WebClient.Builder loadBalancedWebClientBuilder() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> WebClient.builder(); |
|
} |
|
}</pre><p>It is also possible to pass together multiple configurations (for more than one load-balancer client) via the <code class="literal">@LoadBalancerClients</code> annotation, as shown below:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation> |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@LoadBalancerClients({@LoadBalancerClient(value = "stores", configuration = StoresLoadBalancerClientConfiguration.class), @LoadBalancerClient(value = "customers", configuration = CustomersLoadBalancerClientConfiguration.class)})</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyConfiguration { |
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation> |
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@LoadBalanced</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> WebClient.Builder loadBalancedWebClientBuilder() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> WebClient.builder(); |
|
} |
|
}</pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ignore-network-interfaces" href="#ignore-network-interfaces"></a>2.8 Ignore Network Interfaces</h2></div></div></div><p>Sometimes, it is useful to ignore certain named network interfaces so that they can be excluded from Service Discovery registration (for example, when running in a Docker container). |
|
A list of regular expressions can be set to cause the desired network interfaces to be ignored. |
|
The following configuration ignores the <code class="literal">docker0</code> interface and all interfaces that start with <code class="literal">veth</code>:</p><p><b>application.yml. </b> |
|
</p><pre class="screen">spring: |
|
cloud: |
|
inetutils: |
|
ignoredInterfaces: |
|
- docker0 |
|
- veth.*</pre><p> |
|
</p><p>You can also force the use of only specified network addresses by using a list of regular expressions, as shown in the following example:</p><p><b>bootstrap.yml. </b> |
|
</p><pre class="screen">spring: |
|
cloud: |
|
inetutils: |
|
preferredNetworks: |
|
- 192.168 |
|
- 10.0</pre><p> |
|
</p><p>You can also force the use of only site-local addresses, as shown in the following example: |
|
.application.yml</p><pre class="screen">spring: |
|
cloud: |
|
inetutils: |
|
useOnlySiteLocalInterfaces: true</pre><p>See <a class="link" href="https://docs.oracle.com/javase/8/docs/api/java/net/Inet4Address.html#isSiteLocalAddress--" target="_top">Inet4Address.html.isSiteLocalAddress()</a> for more details about what constitutes a site-local address.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="http-clients" href="#http-clients"></a>2.9 HTTP Client Factories</h2></div></div></div><p>Spring Cloud Commons provides beans for creating both Apache HTTP clients (<code class="literal">ApacheHttpClientFactory</code>) and OK HTTP clients (<code class="literal">OkHttpClientFactory</code>). |
|
The <code class="literal">OkHttpClientFactory</code> bean is created only if the OK HTTP jar is on the classpath. |
|
In addition, Spring Cloud Commons provides beans for creating the connection managers used by both clients: <code class="literal">ApacheHttpClientConnectionManagerFactory</code> for the Apache HTTP client and <code class="literal">OkHttpClientConnectionPoolFactory</code> for the OK HTTP client. |
|
If you would like to customize how the HTTP clients are created in downstream projects, you can provide your own implementation of these beans. |
|
In addition, if you provide a bean of type <code class="literal">HttpClientBuilder</code> or <code class="literal">OkHttpClient.Builder</code>, the default factories use these builders as the basis for the builders returned to downstream projects. |
|
You can also disable the creation of these beans by setting <code class="literal">spring.cloud.httpclientfactories.apache.enabled</code> or <code class="literal">spring.cloud.httpclientfactories.ok.enabled</code> to <code class="literal">false</code>.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="enabled-features" href="#enabled-features"></a>2.10 Enabled Features</h2></div></div></div><p>Spring Cloud Commons provides a <code class="literal">/features</code> actuator endpoint. |
|
This endpoint returns features available on the classpath and whether they are enabled. |
|
The information returned includes the feature type, name, version, and vendor.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_feature_types" href="#_feature_types"></a>2.10.1 Feature types</h3></div></div></div><p>There are two types of 'features': abstract and named.</p><p>Abstract features are features where an interface or abstract class is defined and that an implementation the creates, such as <code class="literal">DiscoveryClient</code>, <code class="literal">LoadBalancerClient</code>, or <code class="literal">LockService</code>. |
|
The abstract class or interface is used to find a bean of that type in the context. |
|
The version displayed is <code class="literal">bean.getClass().getPackage().getImplementationVersion()</code>.</p><p>Named features are features that do not have a particular class they implement, such as "Circuit Breaker", "API Gateway", "Spring Cloud Bus", and others. These features require a name and a bean type.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_declaring_features" href="#_declaring_features"></a>2.10.2 Declaring features</h3></div></div></div><p>Any module can declare any number of <code class="literal">HasFeature</code> beans, as shown in the following examples:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> HasFeatures commonsFeatures() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> HasFeatures.abstractFeatures(DiscoveryClient.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>, LoadBalancerClient.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>); |
|
} |
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation> |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> HasFeatures consulFeatures() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> HasFeatures.namedFeatures( |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> NamedFeature(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Spring Cloud Bus"</span>, ConsulBusAutoConfiguration.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>), |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> NamedFeature(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Circuit Breaker"</span>, HystrixCommandAspect.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)); |
|
} |
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation> |
|
HasFeatures localFeatures() { |
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> HasFeatures.builder() |
|
.abstractFeature(Foo.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>) |
|
.namedFeature(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> NamedFeature(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Bar Feature"</span>, Bar.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>)) |
|
.abstractFeature(Baz.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>) |
|
.build(); |
|
}</pre><p>Each of these beans should go in an appropriately guarded <code class="literal">@Configuration</code>.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_spring_cloud_compatibility_verification" href="#_spring_cloud_compatibility_verification"></a>2.11 Spring Cloud Compatibility Verification</h2></div></div></div><p>Due to the fact that some users have problem with setting up Spring Cloud application, we’ve decided |
|
to add a compatibility verification mechanism. It will break if your current setup is not compatible |
|
with Spring Cloud requirements, together with a report, showing what exactly went wrong.</p><p>At the moment we verify which version of Spring Boot is added to your classpath.</p><p>Example of a report</p><pre class="screen">*************************** |
|
APPLICATION FAILED TO START |
|
*************************** |
|
|
|
Description: |
|
|
|
Your project setup is incompatible with our requirements due to following reasons: |
|
|
|
- Spring Boot [2.1.0.RELEASE] is not compatible with this Spring Cloud release train |
|
|
|
|
|
Action: |
|
|
|
Consider applying the following actions: |
|
|
|
- Change Spring Boot version to one of the following versions [1.2.x, 1.3.x] . |
|
You can find the latest Spring Boot versions here [https://spring.io/projects/spring-boot#learn]. |
|
If you want to learn more about the Spring Cloud Release train compatibility, you can visit this page [https://spring.io/projects/spring-cloud#overview] and check the [Release Trains] section.</pre><p>In order to disable this feature, set <code class="literal">spring.cloud.compatibility-verifier.enabled</code> to <code class="literal">false</code>. |
|
If you want to override the compatible Spring Boot versions, just set the |
|
<code class="literal">spring.cloud.compatibility-verifier.compatible-boot-versions</code> property with a comma separated list |
|
of compatible Spring Boot versions.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__spring_cloud_context_application_context_services.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> </td></tr><tr><td width="40%" align="left" valign="top">1. Spring Cloud Context: Application Context Services </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-commons.html">Home</a></td><td width="40%" align="right" valign="top"> </td></tr></table></div></body></html> |