spring-cloud-commons.md 97.1 KB
Newer Older
茶陵後's avatar
茶陵後 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
# Cloud Native Applications

Table of Contents

* [1. Spring Cloud Context: Application Context Services](#spring-cloud-context-application-context-services)
  * [1.1. The Bootstrap Application Context](#the-bootstrap-application-context)
  * [1.2. Application Context Hierarchies](#application-context-hierarchies)
  * [1.3. Changing the Location of Bootstrap Properties](#customizing-bootstrap-properties)
  * [1.4. Overriding the Values of Remote Properties](#overriding-bootstrap-properties)
  * [1.5. Customizing the Bootstrap Configuration](#customizing-the-bootstrap-configuration)
  * [1.6. Customizing the Bootstrap Property Sources](#customizing-bootstrap-property-sources)
  * [1.7. Logging Configuration](#logging-configuration)
  * [1.8. Environment Changes](#environment-changes)
  * [1.9. Refresh Scope](#refresh-scope)
  * [1.10. Encryption and Decryption](#encryption-and-decryption)
  * [1.11. Endpoints](#endpoints)

* [2. Spring Cloud Commons: Common Abstractions](#spring-cloud-commons-common-abstractions)
  * [2.1. The `@EnableDiscoveryClient` Annotation](#discovery-client)
    * [2.1.1. Health Indicators](#health-indicators)
      * [DiscoveryClientHealthIndicator](#discoveryclienthealthindicator)
      * [DiscoveryCompositeHealthContributor](#discoverycompositehealthcontributor)

    * [2.1.2. Ordering `DiscoveryClient` instances](#ordering-discoveryclient-instances)
    * [2.1.3. SimpleDiscoveryClient](#simplediscoveryclient)

  * [2.2. ServiceRegistry](#serviceregistry)
    * [2.2.1. ServiceRegistry Auto-Registration](#serviceregistry-auto-registration)
      * [ServiceRegistry Auto-Registration Events](#serviceregistry-auto-registration-events)

    * [2.2.2. Service Registry Actuator Endpoint](#service-registry-actuator-endpoint)

  * [2.3. Spring RestTemplate as a Load Balancer Client](#rest-template-loadbalancer-client)
  * [2.4. Spring WebClient as a Load Balancer Client](#webclinet-loadbalancer-client)
    * [2.4.1. Retrying Failed Requests](#retrying-failed-requests)

  * [2.5. Multiple `RestTemplate` Objects](#multiple-resttemplate-objects)
  * [2.6. Multiple WebClient Objects](#multiple-webclient-objects)
  * [2.7. Spring WebFlux `WebClient` as a Load Balancer Client](#loadbalanced-webclient)
    * [2.7.1. Spring WebFlux `WebClient` with `ReactorLoadBalancerExchangeFilterFunction`](#webflux-with-reactive-loadbalancer)
    * [2.7.2. Spring WebFlux `WebClient` with a Non-reactive Load Balancer Client](#load-balancer-exchange-filter-function)

  * [2.8. Ignore Network Interfaces](#ignore-network-interfaces)
  * [2.9. HTTP Client Factories](#http-clients)
  * [2.10. Enabled Features](#enabled-features)
    * [2.10.1. Feature types](#feature-types)
    * [2.10.2. Declaring features](#declaring-features)

  * [2.11. Spring Cloud Compatibility Verification](#spring-cloud-compatibility-verification)

* [3. Spring Cloud LoadBalancer](#spring-cloud-loadbalancer)
  * [3.1. Switching between the load-balancing algorithms](#switching-between-the-load-balancing-algorithms)
  * [3.2. Spring Cloud LoadBalancer integrations](#spring-cloud-loadbalancer-integrations)
  * [3.3. Spring Cloud LoadBalancer Caching](#loadbalancer-caching)
    * [3.3.1. Caffeine-backed LoadBalancer Cache Implementation](#caffeine-backed-loadbalancer-cache-implementation)
    * [3.3.2. Default LoadBalancer Cache Implementation](#default-loadbalancer-cache-implementation)
    * [3.3.3. LoadBalancer Cache Configuration](#loadbalancer-cache-configuration)

  * [3.4. Zone-Based Load-Balancing](#zone-based-load-balancing)
  * [3.5. Instance Health-Check for LoadBalancer](#instance-health-check-for-loadbalancer)
  * [3.6. Same instance preference for LoadBalancer](#same-instance-preference-for-loadbalancer)
  * [3.7. Request-based Sticky Session for LoadBalancer](#request-based-sticky-session-for-loadbalancer)
  * [3.8. Spring Cloud LoadBalancer Hints](#spring-cloud-loadbalancer-hints)
  * [3.9. Hint-Based Load-Balancing](#hints-based-loadbalancing)
  * [3.10. Transform the load-balanced HTTP request](#transform-the-load-balanced-http-request)
  * [3.11. Spring Cloud LoadBalancer Starter](#spring-cloud-loadbalancer-starter)
  * [3.12. Passing Your Own Spring Cloud LoadBalancer Configuration](#custom-loadbalancer-configuration)
  * [3.13. Spring Cloud LoadBalancer Lifecycle](#loadbalancer-lifecycle)
  * [3.14. Spring Cloud LoadBalancer Statistics](#loadbalancer-micrometer-stats-lifecycle)
  * [3.15. Configuring Individual LoadBalancerClients](#configuring-individual-loadbalancerclients)

* [4. Spring Cloud Circuit Breaker](#spring-cloud-circuit-breaker)
  * [4.1. Introduction](#introduction)
    * [4.1.1. Supported Implementations](#supported-implementations)

  * [4.2. Core Concepts](#core-concepts)
    * [4.2.1. Circuit Breakers In Reactive Code](#circuit-breakers-in-reactive-code)

  * [4.3. Configuration](#configuration)

* [5. CachedRandomPropertySource](#cachedrandompropertysource)
* [6. Security](#spring-cloud-security)
  * [6.1. Single Sign On](#spring-cloud-security-single-sign-on)
    * [6.1.1. Client Token Relay](#spring-cloud-security-client-token-relay)
    * [6.1.2. Resource Server Token Relay](#spring-cloud-security-resource-server-token-relay)

* [7. Configuration Properties](#configuration-properties)
M
Mao 已提交
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110

[Cloud Native](https://pivotal.io/platform-as-a-service/migrating-to-cloud-native-application-architectures-ebook) is a style of application development that encourages easy adoption of best practices in the areas of continuous delivery and value-driven development.
A related discipline is that of building [12-factor Applications](https://12factor.net/), in which development practices are aligned with delivery and operations goals — for instance, by using declarative programming and management and monitoring.
Spring Cloud facilitates these styles of development in a number of specific ways.
The starting point is a set of features to which all components in a distributed system need easy access.

Many of those features are covered by [Spring Boot](https://projects.spring.io/spring-boot), on which Spring Cloud builds. Some more features are delivered by Spring Cloud as two libraries: Spring Cloud Context and Spring Cloud Commons.
Spring Cloud Context provides utilities and special services for the `ApplicationContext` of a Spring Cloud application (bootstrap context, encryption, refresh scope, and environment endpoints). Spring Cloud Commons is a set of abstractions and common classes used in different Spring Cloud implementations (such as Spring Cloud Netflix and Spring Cloud Consul).

If you get an exception due to "Illegal key size" and you use Sun’s JDK, you need to install the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files.
See the following links for more information:

* [Java 6 JCE](https://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html)

* [Java 7 JCE](https://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html)

* [Java 8 JCE](https://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html)

Extract the files into the JDK/jre/lib/security folder for whichever version of JRE/JDK x64/x86 you use.

|   |Spring Cloud is released under the non-restrictive Apache 2.0 license.<br/>If you would like to contribute to this section of the documentation or if you find an error, you can find the source code and issue trackers for the project at {docslink}[github].|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
111
## [](#spring-cloud-context-application-context-services)[1. Spring Cloud Context: Application Context Services](#spring-cloud-context-application-context-services)
M
Mao 已提交
112 113 114 115 116

Spring Boot has an opinionated view of how to build an application with Spring.
For instance, it has conventional locations for common configuration files and has endpoints for common management and monitoring tasks.
Spring Cloud builds on top of that and adds a few features that many components in a system would use or occasionally need.

茶陵後's avatar
茶陵後 已提交
117
### [](#the-bootstrap-application-context)[1.1. The Bootstrap Application Context](#the-bootstrap-application-context)
M
Mao 已提交
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145

A Spring Cloud application operates by creating a “bootstrap” context, which is a parent context for the main application.
This context is responsible for loading configuration properties from the external sources and for decrypting properties in the local external configuration files.
The two contexts share an `Environment`, which is the source of external properties for any Spring application.
By default, bootstrap properties (not `bootstrap.properties` but properties that are loaded during the bootstrap phase) are added with high precedence, so they cannot be overridden by local configuration.

The bootstrap context uses a different convention for locating external configuration than the main application context.
Instead of `application.yml` (or `.properties`), you can use `bootstrap.yml`, keeping the external configuration for bootstrap and main context nicely separate.
The following listing shows an example:

Example 1. bootstrap.yml

```
spring:
  application:
    name: foo
  cloud:
    config:
      uri: ${SPRING_CONFIG_URI:http://localhost:8888}
```

If your application needs any application-specific configuration from the server, it is a good idea to set the `spring.application.name` (in `bootstrap.yml` or `application.yml`).
For the property `spring.application.name` to be used as the application’s context ID, you must set it in `bootstrap.[properties | yml]`.

If you want to retrieve specific profile configuration, you should also set `spring.profiles.active` in `bootstrap.[properties | yml]`.

You can disable the bootstrap process completely by setting `spring.cloud.bootstrap.enabled=false` (for example, in system properties).

茶陵後's avatar
茶陵後 已提交
146
### [](#application-context-hierarchies)[1.2. Application Context Hierarchies](#application-context-hierarchies)
M
Mao 已提交
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174

If you build an application context from `SpringApplication` or `SpringApplicationBuilder`, the Bootstrap context is added as a parent to that context.
It is a feature of Spring that child contexts inherit property sources and profiles from their parent, so the “main” application context contains additional property sources, compared to building the same context without Spring Cloud Config.
The additional property sources are:

* “bootstrap”: If any `PropertySourceLocators` are found in the bootstrap context and if they have non-empty properties, an optional `CompositePropertySource` appears with high priority.
  An example would be properties from the Spring Cloud Config Server.
  See “[Customizing the Bootstrap Property Sources](#customizing-bootstrap-property-sources)” for how to customize the contents of this property source.

* “applicationConfig: [classpath:bootstrap.yml]” (and related files if Spring profiles are active): If you have a `bootstrap.yml` (or `.properties`), those properties are used to configure the bootstrap context.
  Then they get added to the child context when its parent is set.
  They have lower precedence than the `application.yml` (or `.properties`) and any other property sources that are added to the child as a normal part of the process of creating a Spring Boot application.
  See “[Changing the Location of Bootstrap Properties](#customizing-bootstrap-properties)” for how to customize the contents of these property sources.

Because of the ordering rules of property sources, the “bootstrap” entries take precedence.
However, note that these do not contain any data from `bootstrap.yml`, which has very low precedence but can be used to set defaults.

You can extend the context hierarchy by setting the parent context of any `ApplicationContext` you create — for example, by using its own interface or with the `SpringApplicationBuilder` convenience methods (`parent()`, `child()` and `sibling()`).
The bootstrap context is the parent of the most senior ancestor that you create yourself.
Every context in the hierarchy has its own “bootstrap” (possibly empty) property source to avoid promoting values inadvertently from parents down to their descendants.
If there is a config server, every context in the hierarchy can also (in principle) have a different `spring.application.name` and, hence, a different remote property source.
Normal Spring application context behavior rules apply to property resolution: properties from a child context override those in
the parent, by name and also by property source name.
(If the child has a property source with the same name as the parent, the value from the parent is not included in the child).

Note that the `SpringApplicationBuilder` lets you share an `Environment` amongst the whole hierarchy, but that is not the default.
Thus, sibling contexts (in particular) do not need to have the same profiles or property sources, even though they may share common values with their parent.

茶陵後's avatar
茶陵後 已提交
175
### [](#customizing-bootstrap-properties)[1.3. Changing the Location of Bootstrap Properties](#customizing-bootstrap-properties)
M
Mao 已提交
176 177 178 179 180 181 182 183 184

The `bootstrap.yml` (or `.properties`) location can be specified by setting `spring.cloud.bootstrap.name` (default: `bootstrap`), `spring.cloud.bootstrap.location` (default: empty) or `spring.cloud.bootstrap.additional-location` (default: empty) — for example, in System properties.

Those properties behave like the `spring.config.*` variants with the same name.
With `spring.cloud.bootstrap.location` the default locations are replaced and only the specified ones are used.
To add locations to the list of default ones, `spring.cloud.bootstrap.additional-location` could be used.
In fact, they are used to set up the bootstrap `ApplicationContext` by setting those properties in its `Environment`.
If there is an active profile (from `spring.profiles.active` or through the `Environment` API in the context you are building), properties in that profile get loaded as well, the same as in a regular Spring Boot app — for example, from `bootstrap-development.properties` for a `development` profile.

茶陵後's avatar
茶陵後 已提交
185
### [](#overriding-bootstrap-properties)[1.4. Overriding the Values of Remote Properties](#overriding-bootstrap-properties)
M
Mao 已提交
186 187 188 189 190 191 192 193 194 195

The property sources that are added to your application by the bootstrap context are often “remote” (from example, from Spring Cloud Config Server).
By default, they cannot be overridden locally.
If you want to let your applications override the remote properties with their own system properties or config files, the remote property source has to grant it permission by setting `spring.cloud.config.allowOverride=true` (it does not work to set this locally).
Once that flag is set, two finer-grained settings control the location of the remote properties in relation to system properties and the application’s local configuration:

* `spring.cloud.config.overrideNone=true`: Override from any local property source.

* `spring.cloud.config.overrideSystemProperties=false`: Only system properties, command line arguments, and environment variables (but not the local config files) should override the remote settings.

茶陵後's avatar
茶陵後 已提交
196
### [](#customizing-the-bootstrap-configuration)[1.5. Customizing the Bootstrap Configuration](#customizing-the-bootstrap-configuration)
M
Mao 已提交
197 198 199 200 201 202 203 204 205 206 207 208 209 210

The bootstrap context can be set to do anything you like by adding entries to `/META-INF/spring.factories` under a key named `org.springframework.cloud.bootstrap.BootstrapConfiguration`.
This holds a comma-separated list of Spring `@Configuration` classes that are used to create the context.
Any beans that you want to be available to the main application context for autowiring can be created here.
There is a special contract for `@Beans` of type `ApplicationContextInitializer`.
If you want to control the startup sequence, you can mark classes with the `@Order` annotation (the default order is `last`).

|   |When adding custom `BootstrapConfiguration`, be careful that the classes you add are not `@ComponentScanned` by mistake into your “main” application context, where they might not be needed.<br/>Use a separate package name for boot configuration classes and make sure that name is not already covered by your `@ComponentScan` or `@SpringBootApplication` annotated configuration classes.|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

The bootstrap process ends by injecting initializers into the main `SpringApplication` instance (which is the normal Spring Boot startup sequence, whether it runs as a standalone application or is deployed in an application server).
First, a bootstrap context is created from the classes found in `spring.factories`.
Then, all `@Beans` of type `ApplicationContextInitializer` are added to the main `SpringApplication` before it is started.

茶陵後's avatar
茶陵後 已提交
211
### [](#customizing-bootstrap-property-sources)[1.6. Customizing the Bootstrap Property Sources](#customizing-bootstrap-property-sources)
M
Mao 已提交
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239

The default property source for external configuration added by the bootstrap process is the Spring Cloud Config Server, but you can add additional sources by adding beans of type `PropertySourceLocator` to the bootstrap context (through `spring.factories`).
For instance, you can insert additional properties from a different server or from a database.

As an example, consider the following custom locator:

```
@Configuration
public class CustomPropertySourceLocator implements PropertySourceLocator {

    @Override
    public PropertySource<?> locate(Environment environment) {
        return new MapPropertySource("customProperty",
                Collections.<String, Object>singletonMap("property.from.sample.custom.source", "worked as intended"));
    }

}
```

The `Environment` that is passed in is the one for the `ApplicationContext` about to be created — in other words, the one for which we supply additional property sources.
It already has its normal Spring Boot-provided property sources, so you can use those to locate a property source specific to this `Environment` (for example, by keying it on `spring.application.name`, as is done in the default Spring Cloud Config Server property source locator).

If you create a jar with this class in it and then add a `META-INF/spring.factories` containing the following setting, the `customProperty` `PropertySource` appears in any application that includes that jar on its classpath:

```
org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomPropertySourceLocator
```

茶陵後's avatar
茶陵後 已提交
240
### [](#logging-configuration)[1.7. Logging Configuration](#logging-configuration)
M
Mao 已提交
241 242 243 244 245 246

If you use Spring Boot to configure log settings, you should place this configuration in `bootstrap.[yml | properties]` if you would like it to apply to all events.

|   |For Spring Cloud to initialize logging configuration properly, you cannot use a custom prefix.<br/>For example, using `custom.loggin.logpath` is not recognized by Spring Cloud when initializing the logging system.|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
247
### [](#environment-changes)[1.8. Environment Changes](#environment-changes)
M
Mao 已提交
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266

The application listens for an `EnvironmentChangeEvent` and reacts to the change in a couple of standard ways (additional `ApplicationListeners` can be added as `@Beans` in the normal way).
When an `EnvironmentChangeEvent` is observed, it has a list of key values that have changed, and the application uses those to:

* Re-bind any `@ConfigurationProperties` beans in the context.

* Set the logger levels for any properties in `logging.level.*`.

Note that the Spring Cloud Config Client does not, by default, poll for changes in the `Environment`.
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, it is better to broadcast the `EnvironmentChangeEvent` to all the instances instead of having them polling for changes (for example, by using the [Spring Cloud Bus](https://github.com/spring-cloud/spring-cloud-bus)).

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.
Note that those APIs are public and part of core Spring).
You can verify that the changes are bound to `@ConfigurationProperties` beans by visiting the `/configprops` endpoint (a standard Spring Boot Actuator feature).
For instance, a `DataSource` can have its `maxPoolSize` changed at runtime (the default `DataSource` created by Spring Boot is a `@ConfigurationProperties` bean) and grow capacity dynamically.
Re-binding `@ConfigurationProperties` does not cover another large class of use cases, where you need more control over the refresh and where you need a change to be atomic over the whole `ApplicationContext`.
To address those concerns, we have `@RefreshScope`.

茶陵後's avatar
茶陵後 已提交
267
### [](#refresh-scope)[1.9. Refresh Scope](#refresh-scope)
M
Mao 已提交
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299

When there is a configuration change, a Spring `@Bean` that is marked as `@RefreshScope` gets special treatment.
This feature addresses the problem of stateful beans that get their configuration injected only when they are initialized.
For instance, if a `DataSource` has open connections when the database URL is changed through the `Environment`, you probably want the holders of those connections to be able to complete what they are doing.
Then, the next time something borrows a connection from the pool, it gets one with the new URL.

Sometimes, it might even be mandatory to apply the `@RefreshScope` annotation on some beans that can be only initialized once.
If a bean is “immutable”, you have to either annotate the bean with `@RefreshScope` or specify the classname under the property key: `spring.cloud.refresh.extra-refreshable`.

|   |If you hava a `DataSource` bean that is a `HikariDataSource`, it can not be<br/>refreshed. It is the default value for `spring.cloud.refresh.never-refreshable`. Choose a<br/>different `DataSource` implementation if you need it to be refreshed.|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

Refresh scope beans are lazy proxies that initialize when they are used (that is, when a method is called), and the scope acts as a cache of initialized values.
To force a bean to re-initialize on the next method call, you must invalidate its cache entry.

The `RefreshScope` is a bean in the context and has a public `refreshAll()` method to refresh all beans in the scope by clearing the target cache.
The `/refresh` endpoint exposes this functionality (over HTTP or JMX).
To refresh an individual bean by name, there is also a `refresh(String)` method.

To expose the `/refresh` endpoint, you need to add following configuration to your application:

```
management:
  endpoints:
    web:
      exposure:
        include: refresh
```

|   |`@RefreshScope` works (technically) on a `@Configuration` class, but it might lead to surprising behavior.<br/>For example, it does not mean that all the `@Beans` defined in that class are themselves in `@RefreshScope`.<br/>Specifically, anything that depends on those beans cannot rely on them being updated when a refresh is initiated, unless it is itself in `@RefreshScope`.<br/>In that case, it is rebuilt on a refresh and its dependencies are re-injected.<br/>At that point, they are re-initialized from the refreshed `@Configuration`).|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
300
### [](#encryption-and-decryption)[1.10. Encryption and Decryption](#encryption-and-decryption)
M
Mao 已提交
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317

Spring Cloud has an `Environment` pre-processor for decrypting property values locally.
It follows the same rules as the Spring Cloud Config Server and has the same external configuration through `encrypt.*`.
Thus, you can use encrypted values in the form of `{cipher}*`, and, as long as there is a valid key, they are decrypted before the main application context gets the `Environment` settings.
To use the encryption 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.

If you get an exception due to "Illegal key size" and you use Sun’s JDK, you need to install the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files.
See the following links for more information:

* [Java 6 JCE](https://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html)

* [Java 7 JCE](https://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html)

* [Java 8 JCE](https://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html)

Extract the files into the JDK/jre/lib/security folder for whichever version of JRE/JDK x64/x86 you use.

茶陵後's avatar
茶陵後 已提交
318
### [](#endpoints)[1.11. Endpoints](#endpoints)
M
Mao 已提交
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333

For a Spring Boot Actuator application, some additional management endpoints are available. You can use:

* `POST` to `/actuator/env` to update the `Environment` and rebind `@ConfigurationProperties` and log levels.
  To enabled this endpoint you must set `management.endpoint.env.post.enabled=true`.

* `/actuator/refresh` to re-load the boot strap context and refresh the `@RefreshScope` beans.

* `/actuator/restart` to close the `ApplicationContext` and restart it (disabled by default).

* `/actuator/pause` and `/actuator/resume` for calling the `Lifecycle` methods (`stop()` and `start()` on the `ApplicationContext`).

|   |If you disable the `/actuator/restart` endpoint then the `/actuator/pause` and `/actuator/resume` endpoints<br/>will also be disabled since they are just a special case of `/actuator/restart`.|
|---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
334
## [](#spring-cloud-commons-common-abstractions)[2. Spring Cloud Commons: Common Abstractions](#spring-cloud-commons-common-abstractions)
M
Mao 已提交
335 336 337

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

茶陵後's avatar
茶陵後 已提交
338
### [](#discovery-client)[2.1. The `@EnableDiscoveryClient` Annotation](#discovery-client)
M
Mao 已提交
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354

Spring Cloud Commons provides the `@EnableDiscoveryClient` annotation.
This looks for implementations of the `DiscoveryClient` and `ReactiveDiscoveryClient` interfaces with `META-INF/spring.factories`.
Implementations of the discovery client add a configuration class to `spring.factories` under the `org.springframework.cloud.client.discovery.EnableDiscoveryClient` key.
Examples of `DiscoveryClient` implementations include [Spring Cloud Netflix Eureka](https://cloud.spring.io/spring-cloud-netflix/), [Spring Cloud Consul Discovery](https://cloud.spring.io/spring-cloud-consul/), and [Spring Cloud Zookeeper Discovery](https://cloud.spring.io/spring-cloud-zookeeper/).

Spring Cloud will provide both the blocking and reactive service discovery clients by default.
You can disable the blocking and/or reactive clients easily by setting `spring.cloud.discovery.blocking.enabled=false` or `spring.cloud.discovery.reactive.enabled=false`.
To completely disable service discovery you just need to set `spring.cloud.discovery.enabled=false`.

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

|   |`@EnableDiscoveryClient` is no longer required.<br/>You can put a `DiscoveryClient` implementation on the classpath to cause the Spring Boot application to register with the service discovery server.|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
355
#### [](#health-indicators)[2.1.1. Health Indicators](#health-indicators)
M
Mao 已提交
356 357 358

Commons auto-configures the following Spring Boot health indicators.

茶陵後's avatar
茶陵後 已提交
359
##### [](#discoveryclienthealthindicator)[DiscoveryClientHealthIndicator](#discoveryclienthealthindicator)
M
Mao 已提交
360 361 362 363 364 365 366 367 368 369 370 371

This health indicator is based on the currently registered `DiscoveryClient` implementation.

* To disable entirely, set `spring.cloud.discovery.client.health-indicator.enabled=false`.

* To disable the description field, set `spring.cloud.discovery.client.health-indicator.include-description=false`.
  Otherwise, it can bubble up as the `description` of the rolled up `HealthIndicator`.

* To disable service retrieval, set `spring.cloud.discovery.client.health-indicator.use-services-query=false`.
  By default, the indicator invokes the client’s `getServices` method. In deployments with many registered services it may too
  costly to retrieve all services during every check. This will skip the service retrieval and instead use the client’s `probe` method.

茶陵後's avatar
茶陵後 已提交
372
##### [](#discoverycompositehealthcontributor)[DiscoveryCompositeHealthContributor](#discoverycompositehealthcontributor)
M
Mao 已提交
373 374 375 376

This composite health indicator is based on all registered `DiscoveryHealthIndicator` beans. To disable,
set `spring.cloud.discovery.client.composite-indicator.enabled=false`.

茶陵後's avatar
茶陵後 已提交
377
#### [](#ordering-discoveryclient-instances)[2.1.2. Ordering `DiscoveryClient` instances](#ordering-discoveryclient-instances)
M
Mao 已提交
378 379 380 381 382 383 384

`DiscoveryClient` interface extends `Ordered`. 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 `DiscoveryClient` is set to`0`. If you want to set a different order for your custom `DiscoveryClient` implementations, you just need to override
the `getOrder()` 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 `DiscoveryClient`implementations provided by Spring Cloud, among others `ConsulDiscoveryClient`, `EurekaDiscoveryClient` and`ZookeeperDiscoveryClient`. In order to do it, you just need to set the`spring.cloud.{clientIdentifier}.discovery.order` (or `eureka.client.order` for Eureka) property to the desired value.

茶陵後's avatar
茶陵後 已提交
385
#### [](#simplediscoveryclient)[2.1.3. SimpleDiscoveryClient](#simplediscoveryclient)
M
Mao 已提交
386 387 388 389 390 391 392 393

If there is no Service-Registry-backed `DiscoveryClient` in the classpath, `SimpleDiscoveryClient`instance, that uses properties to get information on service and instances, will be used.

The information about the available instances should be passed to via properties in the following format:`spring.cloud.discovery.client.simple.instances.service1[0].uri=http://s11:8080`, where`spring.cloud.discovery.client.simple.instances` is the common prefix, then `service1` stands
for the ID of the service in question, while `[0]` indicates the index number of the instance
(as visible in the example, indexes start with `0`), and then the value of `uri` is
the actual URI under which the instance is available.

茶陵後's avatar
茶陵後 已提交
394
### [](#serviceregistry)[2.2. ServiceRegistry](#serviceregistry)
M
Mao 已提交
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429

Commons now provides a `ServiceRegistry` interface that provides methods such as `register(Registration)` and `deregister(Registration)`, which let you provide custom registered services.`Registration` is a marker interface.

The following example shows the `ServiceRegistry` in use:

```
@Configuration
@EnableDiscoveryClient(autoRegister=false)
public class MyConfiguration {
    private ServiceRegistry registry;

    public MyConfiguration(ServiceRegistry registry) {
        this.registry = registry;
    }

    // called through some external process, such as an event or a custom actuator endpoint
    public void register() {
        Registration registration = constructRegistration();
        this.registry.register(registration);
    }
}
```

Each `ServiceRegistry` implementation has its own `Registry` implementation.

* `ZookeeperRegistration` used with `ZookeeperServiceRegistry`

* `EurekaRegistration` used with `EurekaServiceRegistry`

* `ConsulRegistration` used with `ConsulServiceRegistry`

If you are using the `ServiceRegistry` interface, you are going to need to pass the
correct `Registry` implementation for the `ServiceRegistry` implementation you
are using.

茶陵後's avatar
茶陵後 已提交
430
#### [](#serviceregistry-auto-registration)[2.2.1. ServiceRegistry Auto-Registration](#serviceregistry-auto-registration)
M
Mao 已提交
431 432 433 434 435 436

By default, the `ServiceRegistry` implementation auto-registers the running service.
To disable that behavior, you can set:
\* `@EnableDiscoveryClient(autoRegister=false)` to permanently disable auto-registration.
\* `spring.cloud.service-registry.auto-registration.enabled=false` to disable the behavior through configuration.

茶陵後's avatar
茶陵後 已提交
437
##### [](#serviceregistry-auto-registration-events)[ServiceRegistry Auto-Registration Events](#serviceregistry-auto-registration-events)
M
Mao 已提交
438 439 440 441 442 443 444

There are two events that will be fired when a service auto-registers. The first event, called`InstancePreRegisteredEvent`, is fired before the service is registered. The second
event, called `InstanceRegisteredEvent`, is fired after the service is registered. You can register an`ApplicationListener`(s) to listen to and react to these events.

|   |These events will not be fired if the `spring.cloud.service-registry.auto-registration.enabled` property is set to `false`.|
|---|---------------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
445
#### [](#service-registry-actuator-endpoint)[2.2.2. Service Registry Actuator Endpoint](#service-registry-actuator-endpoint)
M
Mao 已提交
446 447 448 449 450 451 452 453 454

Spring Cloud Commons provides a `/service-registry` actuator endpoint.
This endpoint relies on a `Registration` bean in the Spring Application Context.
Calling `/service-registry` with GET returns the status of the `Registration`.
Using POST to the same endpoint with a JSON body changes the status of the current `Registration` to the new value.
The JSON body has to include the `status` field with the preferred value.
Please see the documentation of the `ServiceRegistry` 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 `UP`, `DOWN`, `OUT_OF_SERVICE`, and `UNKNOWN`.

茶陵後's avatar
茶陵後 已提交
455
### [](#rest-template-loadbalancer-client)[2.3. Spring RestTemplate as a Load Balancer Client](#rest-template-loadbalancer-client)
M
Mao 已提交
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490

You can configure a `RestTemplate` to use a Load-balancer client.
To create a load-balanced `RestTemplate`, create a `RestTemplate` `@Bean` and use the `@LoadBalanced` qualifier, as the following example shows:

```
@Configuration
public class MyConfiguration {

    @LoadBalanced
    @Bean
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

public class MyClass {
    @Autowired
    private RestTemplate restTemplate;

    public String doOtherStuff() {
        String results = restTemplate.getForObject("http://stores/stores", String.class);
        return results;
    }
}
```

|   |A `RestTemplate` bean is no longer created through auto-configuration.<br/>Individual applications must create it.|
|---|------------------------------------------------------------------------------------------------------------------|

The URI needs to use a virtual host name (that is, a service name, not a host name).
The BlockingLoadBalancerClient is used to create a full physical address.

|   |To use a load-balanced `RestTemplate`, you need to have a load-balancer implementation in your classpath.<br/>Add [Spring Cloud LoadBalancer starter](#spring-cloud-loadbalancer-starter) to your project in order to use it.|
|---|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
491
### [](#webclinet-loadbalancer-client)[2.4. Spring WebClient as a Load Balancer Client](#webclinet-loadbalancer-client)
M
Mao 已提交
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523

You can configure `WebClient` to automatically use a load-balancer client.
To create a load-balanced `WebClient`, create a `WebClient.Builder` `@Bean` and use the `@LoadBalanced` qualifier, as follows:

```
@Configuration
public class MyConfiguration {

    @Bean
    @LoadBalanced
    public WebClient.Builder loadBalancedWebClientBuilder() {
        return WebClient.builder();
    }
}

public class MyClass {
    @Autowired
    private WebClient.Builder webClientBuilder;

    public Mono<String> doOtherStuff() {
        return webClientBuilder.build().get().uri("http://stores/stores")
                        .retrieve().bodyToMono(String.class);
    }
}
```

The URI needs to use a virtual host name (that is, a service name, not a host name).
The Spring Cloud LoadBalancer is used to create a full physical address.

|   |If you want to use a `@LoadBalanced WebClient.Builder`, you need to have a load balancer<br/>implementation in the classpath. We recommend that you add the[Spring Cloud LoadBalancer starter](#spring-cloud-loadbalancer-starter) to your project.<br/>Then, `ReactiveLoadBalancer` is used underneath.|
|---|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
524
#### [](#retrying-failed-requests)[2.4.1. Retrying Failed Requests](#retrying-failed-requests)
M
Mao 已提交
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606

A load-balanced `RestTemplate` can be configured to retry failed requests.
By default, this logic is disabled.
For the non-reactive version (with `RestTemplate`), you can enable it by adding [Spring Retry](https://github.com/spring-projects/spring-retry) to your application’s classpath. For the reactive version (with `WebTestClient), you need to set `spring.cloud.loadbalancer.retry.enabled=true`.

If you would like to disable the retry logic with Spring Retry or Reactive Retry on the classpath, you can set `spring.cloud.loadbalancer.retry.enabled=false`.

For the non-reactive implementation, if you would like to implement a `BackOffPolicy` in your retries, you need to create a bean of type `LoadBalancedRetryFactory` and override the `createBackOffPolicy()` method.

For the reactive implementation, you just need to enable it by setting `spring.cloud.loadbalancer.retry.backoff.enabled` to `false`.

You can set:

* `spring.cloud.loadbalancer.retry.maxRetriesOnSameServiceInstance` - indicates how many times a request should be retried on the same `ServiceInstance` (counted separately for every selected instance)

* `spring.cloud.loadbalancer.retry.maxRetriesOnNextServiceInstance` - indicates how many times a request should be retried a newly selected `ServiceInstance`

* `spring.cloud.loadbalancer.retry.retryableStatusCodes` - the status codes on which to always retry a failed request.

For the reactive implementation, you can additionally set:
- `spring.cloud.loadbalancer.retry.backoff.minBackoff` - Sets the minimum backoff duration (by default, 5 milliseconds)
- `spring.cloud.loadbalancer.retry.backoff.maxBackoff` - Sets the maximum backoff duration (by default, max long value of milliseconds)
- `spring.cloud.loadbalancer.retry.backoff.jitter` - Sets the jitter used for calculationg the actual backoff duration for each call (by default, 0.5).

For the reactive implementation, you can also implement your own `LoadBalancerRetryPolicy` to have more detailed control over the load-balanced call retries.

|   |Individual Loadbalancer clients may be configured individually with the same properties as above except the prefix is `spring.cloud.loadbalancer.clients.<clientId>.*` where `clientId` is the name of the loadbalancer.|
|---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

|   |For load-balanced retries, by default, we wrap the `ServiceInstanceListSupplier` bean with `RetryAwareServiceInstanceListSupplier` to select a different instance from the one previously chosen, if available. You can disable this behavior by setting the value of `spring.cloud.loadbalancer.retry.avoidPreviousInstance` to `false`.|
|---|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

```
@Configuration
public class MyConfiguration {
    @Bean
    LoadBalancedRetryFactory retryFactory() {
        return new LoadBalancedRetryFactory() {
            @Override
            public BackOffPolicy createBackOffPolicy(String service) {
                return new ExponentialBackOffPolicy();
            }
        };
    }
}
```

If you want to add one or more `RetryListener` implementations to your retry functionality, you need to
create a bean of type `LoadBalancedRetryListenerFactory` and return the `RetryListener` array
you would like to use for a given service, as the following example shows:

```
@Configuration
public class MyConfiguration {
    @Bean
    LoadBalancedRetryListenerFactory retryListenerFactory() {
        return new LoadBalancedRetryListenerFactory() {
            @Override
            public RetryListener[] createRetryListeners(String service) {
                return new RetryListener[]{new RetryListener() {
                    @Override
                    public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {
                        //TODO Do you business...
                        return true;
                    }

                    @Override
                     public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
                        //TODO Do you business...
                    }

                    @Override
                    public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
                        //TODO Do you business...
                    }
                }};
            }
        };
    }
}
```

茶陵後's avatar
茶陵後 已提交
607
### [](#multiple-resttemplate-objects)[2.5. Multiple `RestTemplate` Objects](#multiple-resttemplate-objects)
M
Mao 已提交
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652

If you want a `RestTemplate` that is not load-balanced, create a `RestTemplate` bean and inject it.
To access the load-balanced `RestTemplate`, use the `@LoadBalanced` qualifier when you create your `@Bean`, as the following example shows:

```
@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;

    @Autowired
    @LoadBalanced
    private RestTemplate loadBalanced;

    public String doOtherStuff() {
        return loadBalanced.getForObject("http://stores/stores", String.class);
    }

    public String doStuff() {
        return restTemplate.getForObject("http://example.com", String.class);
    }
}
```

|   |Notice the use of the `@Primary` annotation on the plain `RestTemplate` declaration in the preceding example to disambiguate the unqualified `@Autowired` injection.|
|---|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|

|   |If you see errors such as `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` or setting `spring.aop.proxyTargetClass=true`.|
|---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
653
### [](#multiple-webclient-objects)[2.6. Multiple WebClient Objects](#multiple-webclient-objects)
M
Mao 已提交
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694

If you want a `WebClient` that is not load-balanced, create a `WebClient` bean and inject it.
To access the load-balanced `WebClient`, use the `@LoadBalanced` qualifier when you create your `@Bean`, as the following example shows:

```
@Configuration
public class MyConfiguration {

    @LoadBalanced
    @Bean
    WebClient.Builder loadBalanced() {
        return WebClient.builder();
    }

    @Primary
    @Bean
    WebClient.Builder webClient() {
        return WebClient.builder();
    }
}

public class MyClass {
    @Autowired
    private WebClient.Builder webClientBuilder;

    @Autowired
    @LoadBalanced
    private WebClient.Builder loadBalanced;

    public Mono<String> doOtherStuff() {
        return loadBalanced.build().get().uri("http://stores/stores")
                        .retrieve().bodyToMono(String.class);
    }

    public Mono<String> doStuff() {
        return webClientBuilder.build().get().uri("http://example.com")
                        .retrieve().bodyToMono(String.class);
    }
}
```

茶陵後's avatar
茶陵後 已提交
695
### [](#loadbalanced-webclient)[2.7. Spring WebFlux `WebClient` as a Load Balancer Client](#loadbalanced-webclient)
M
Mao 已提交
696 697 698 699 700 701 702

The Spring WebFlux can work with both reactive and non-reactive `WebClient` configurations, as the topics describe:

* [Spring WebFlux `WebClient` with `ReactorLoadBalancerExchangeFilterFunction`](#webflux-with-reactive-loadbalancer)

* [[load-balancer-exchange-filter-functionload-balancer-exchange-filter-function]](#load-balancer-exchange-filter-functionload-balancer-exchange-filter-function)

茶陵後's avatar
茶陵後 已提交
703
#### [](#webflux-with-reactive-loadbalancer)[2.7.1. Spring WebFlux `WebClient` with `ReactorLoadBalancerExchangeFilterFunction`](#webflux-with-reactive-loadbalancer)
M
Mao 已提交
704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729

You can configure `WebClient` to use the `ReactiveLoadBalancer`.
If you add [Spring Cloud LoadBalancer starter](#spring-cloud-loadbalancer-starter) to your project
and if `spring-webflux` is on the classpath, `ReactorLoadBalancerExchangeFilterFunction` is auto-configured.
The following example shows how to configure a `WebClient` to use reactive load-balancer:

```
public class MyClass {
    @Autowired
    private ReactorLoadBalancerExchangeFilterFunction lbFunction;

    public Mono<String> doOtherStuff() {
        return WebClient.builder().baseUrl("http://stores")
            .filter(lbFunction)
            .build()
            .get()
            .uri("/stores")
            .retrieve()
            .bodyToMono(String.class);
    }
}
```

The URI needs to use a virtual host name (that is, a service name, not a host name).
The `ReactorLoadBalancer` is used to create a full physical address.

茶陵後's avatar
茶陵後 已提交
730
#### [](#load-balancer-exchange-filter-function)[2.7.2. Spring WebFlux `WebClient` with a Non-reactive Load Balancer Client](#load-balancer-exchange-filter-function)
M
Mao 已提交
731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758

If `spring-webflux` is on the classpath, `LoadBalancerExchangeFilterFunction`is auto-configured. Note, however, that this
uses a non-reactive client under the hood.
The following example shows how to configure a `WebClient` to use load-balancer:

```
public class MyClass {
    @Autowired
    private LoadBalancerExchangeFilterFunction lbFunction;

    public Mono<String> doOtherStuff() {
        return WebClient.builder().baseUrl("http://stores")
            .filter(lbFunction)
            .build()
            .get()
            .uri("/stores")
            .retrieve()
            .bodyToMono(String.class);
    }
}
```

The URI needs to use a virtual host name (that is, a service name, not a host name).
The `LoadBalancerClient` is used to create a full physical address.

WARN: This approach is now deprecated.
We suggest that you use [WebFlux with reactive Load-Balancer](#webflux-with-reactive-loadbalancer)instead.

茶陵後's avatar
茶陵後 已提交
759
### [](#ignore-network-interfaces)[2.8. Ignore Network Interfaces](#ignore-network-interfaces)
M
Mao 已提交
760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801

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 `docker0` interface and all interfaces that start with `veth`:

Example 2. application.yml

```
spring:
  cloud:
    inetutils:
      ignoredInterfaces:
        - docker0
        - veth.*
```

You can also force the use of only specified network addresses by using a list of regular expressions, as the following example shows:

Example 3. bootstrap.yml

```
spring:
  cloud:
    inetutils:
      preferredNetworks:
        - 192.168
        - 10.0
```

You can also force the use of only site-local addresses, as the following example shows:

Example 4. application.yml

```
spring:
  cloud:
    inetutils:
      useOnlySiteLocalInterfaces: true
```

See [Inet4Address.html.isSiteLocalAddress()](https://docs.oracle.com/javase/8/docs/api/java/net/Inet4Address.html#isSiteLocalAddress--) for more details about what constitutes a site-local address.

茶陵後's avatar
茶陵後 已提交
802
### [](#http-clients)[2.9. HTTP Client Factories](#http-clients)
M
Mao 已提交
803 804 805 806 807 808 809 810

Spring Cloud Commons provides beans for creating both Apache HTTP clients (`ApacheHttpClientFactory`) and OK HTTP clients (`OkHttpClientFactory`).
The `OkHttpClientFactory` 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: `ApacheHttpClientConnectionManagerFactory` for the Apache HTTP client and `OkHttpClientConnectionPoolFactory` 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 `HttpClientBuilder` or `OkHttpClient.Builder`, 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 `spring.cloud.httpclientfactories.apache.enabled` or `spring.cloud.httpclientfactories.ok.enabled` to `false`.

茶陵後's avatar
茶陵後 已提交
811
### [](#enabled-features)[2.10. Enabled Features](#enabled-features)
M
Mao 已提交
812 813 814 815 816

Spring Cloud Commons provides a `/features` 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.

茶陵後's avatar
茶陵後 已提交
817
#### [](#feature-types)[2.10.1. Feature types](#feature-types)
M
Mao 已提交
818 819 820 821 822 823 824 825 826

There are two types of 'features': abstract and named.

Abstract features are features where an interface or abstract class is defined and that an implementation the creates, such as `DiscoveryClient`, `LoadBalancerClient`, or `LockService`.
The abstract class or interface is used to find a bean of that type in the context.
The version displayed is `bean.getClass().getPackage().getImplementationVersion()`.

Named features are features that do not have a particular class they implement. These features include “Circuit Breaker”, “API Gateway”, “Spring Cloud Bus”, and others. These features require a name and a bean type.

茶陵後's avatar
茶陵後 已提交
827
#### [](#declaring-features)[2.10.2. Declaring features](#declaring-features)
M
Mao 已提交
828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855

Any module can declare any number of `HasFeature` beans, as the following examples show:

```
@Bean
public HasFeatures commonsFeatures() {
  return HasFeatures.abstractFeatures(DiscoveryClient.class, LoadBalancerClient.class);
}

@Bean
public HasFeatures consulFeatures() {
  return HasFeatures.namedFeatures(
    new NamedFeature("Spring Cloud Bus", ConsulBusAutoConfiguration.class),
    new NamedFeature("Circuit Breaker", HystrixCommandAspect.class));
}

@Bean
HasFeatures localFeatures() {
  return HasFeatures.builder()
      .abstractFeature(Something.class)
      .namedFeature(new NamedFeature("Some Other Feature", Someother.class))
      .abstractFeature(Somethingelse.class)
      .build();
}
```

Each of these beans should go in an appropriately guarded `@Configuration`.

茶陵後's avatar
茶陵後 已提交
856
### [](#spring-cloud-compatibility-verification)[2.11. Spring Cloud Compatibility Verification](#spring-cloud-compatibility-verification)
M
Mao 已提交
857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889

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.

At the moment we verify which version of Spring Boot is added to your classpath.

Example of a report

```
***************************
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.
```

In order to disable this feature, set `spring.cloud.compatibility-verifier.enabled` to `false`.
If you want to override the compatible Spring Boot versions, just set the`spring.cloud.compatibility-verifier.compatible-boot-versions` property with a comma separated list
of compatible Spring Boot versions.

茶陵後's avatar
茶陵後 已提交
890
## [](#spring-cloud-loadbalancer)[3. Spring Cloud LoadBalancer](#spring-cloud-loadbalancer)
M
Mao 已提交
891 892 893 894 895 896 897 898

Spring Cloud provides its own client-side load-balancer abstraction and implementation. For the load-balancing
mechanism, `ReactiveLoadBalancer` interface has been added and a **Round-Robin-based** and **Random** implementations
have been provided for it. In order to get instances to select from reactive `ServiceInstanceListSupplier`is used. Currently we support a service-discovery-based implementation of `ServiceInstanceListSupplier`that retrieves available instances from Service Discovery using a [Discovery Client](#discovery-client) available in the classpath.

|   |It is possible to disable Spring Cloud LoadBalancer by setting the value of `spring.cloud.loadbalancer.enabled` to `false`.|
|---|---------------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
899
### [](#switching-between-the-load-balancing-algorithms)[3.1. Switching between the load-balancing algorithms](#switching-between-the-load-balancing-algorithms)
M
Mao 已提交
900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921

The `ReactiveLoadBalancer` implementation that is used by default is `RoundRobinLoadBalancer`. To switch to a different implementation, either for selected services or all of them, you can use the [custom LoadBalancer configurations mechanism](#custom-loadbalancer-configuration).

For example, the following configuration can be passed via `@LoadBalancerClient` annotation to switch to using the `RandomLoadBalancer`:

```
public class CustomLoadBalancerConfiguration {

    @Bean
    ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
            LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return new RandomLoadBalancer(loadBalancerClientFactory
                .getLazyProvider(name, ServiceInstanceListSupplier.class),
                name);
    }
}
```

|   |The classes you pass as `@LoadBalancerClient` or `@LoadBalancerClients` configuration arguments should either not be annotated with `@Configuration` or be outside component scan scope.|
|---|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
922
### [](#spring-cloud-loadbalancer-integrations)[3.2. Spring Cloud LoadBalancer integrations](#spring-cloud-loadbalancer-integrations)
M
Mao 已提交
923 924 925 926 927 928 929 930 931 932

In order to make it easy to use Spring Cloud LoadBalancer, we provide `ReactorLoadBalancerExchangeFilterFunction` that can be used with `WebClient` and `BlockingLoadBalancerClient` that works with `RestTemplate`.
You can see more information and examples of usage in the following sections:

* [Spring RestTemplate as a Load Balancer Client](#rest-template-loadbalancer-client)

* [Spring WebClient as a Load Balancer Client](#webclinet-loadbalancer-client)

* [Spring WebFlux WebClient with `ReactorLoadBalancerExchangeFilterFunction`](#webflux-with-reactive-loadbalancer)

茶陵後's avatar
茶陵後 已提交
933
### [](#loadbalancer-caching)[3.3. Spring Cloud LoadBalancer Caching](#loadbalancer-caching)
M
Mao 已提交
934 935 936

Apart from the basic `ServiceInstanceListSupplier` implementation that retrieves instances via `DiscoveryClient` each time it has to choose an instance, we provide two caching implementations.

茶陵後's avatar
茶陵後 已提交
937
#### [](#caffeine-backed-loadbalancer-cache-implementation)[3.3.1. ](#caffeine-backed-loadbalancer-cache-implementation)[Caffeine](https://github.com/ben-manes/caffeine)-backed LoadBalancer Cache Implementation
M
Mao 已提交
938 939 940 941 942 943 944 945

If you have `com.github.ben-manes.caffeine:caffeine` in the classpath, Caffeine-based implementation will be used.
See the [LoadBalancerCacheConfiguration](#loadbalancer-cache-configuration) section for information on how to configure it.

If you are using Caffeine, you can also override the default Caffeine Cache setup for the LoadBalancer by passing your own [Caffeine Specification](https://static.javadoc.io/com.github.ben-manes.caffeine/caffeine/2.2.2/com/github/benmanes/caffeine/cache/CaffeineSpec.html)in the `spring.cloud.loadbalancer.cache.caffeine.spec` property.

WARN: Passing your own Caffeine specification will override any other LoadBalancerCache settings, including [General LoadBalancer Cache Configuration](#loadbalancer-cache-configuration) fields, such as `ttl` and `capacity`.

茶陵後's avatar
茶陵後 已提交
946
#### [](#default-loadbalancer-cache-implementation)[3.3.2. Default LoadBalancer Cache Implementation](#default-loadbalancer-cache-implementation)
M
Mao 已提交
947 948 949 950 951 952 953

If you do not have Caffeine in the classpath, the `DefaultLoadBalancerCache`, which comes automatically with `spring-cloud-starter-loadbalancer`, will be used.
See the [LoadBalancerCacheConfiguration](#loadbalancer-cache-configuration) section for information on how to configure it.

|   |To use Caffeine instead of the default cache, add the `com.github.ben-manes.caffeine:caffeine` dependency to classpath.|
|---|-----------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
954
#### [](#loadbalancer-cache-configuration)[3.3.3. LoadBalancer Cache Configuration](#loadbalancer-cache-configuration)
M
Mao 已提交
955 956 957 958 959 960 961 962 963 964 965 966

You can set your own `ttl` value (the time after write after which entries should be expired), expressed as `Duration`, by passing a `String` compliant with the [Spring Boot `String` to `Duration` converter syntax](https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-conversion-duration).
as the value of the `spring.cloud.loadbalancer.cache.ttl` property.
You can also set your own LoadBalancer cache initial capacity by setting the value of the `spring.cloud.loadbalancer.cache.capacity` property.

The default setup includes `ttl` set to 35 seconds and the default `initialCapacity` is `256`.

You can also altogether disable loadBalancer caching by setting the value of `spring.cloud.loadbalancer.cache.enabled`to `false`.

|   |Although the basic, non-cached, implementation is useful for prototyping and testing, it’s much less efficient than the cached versions, so we recommend always using the cached version in production. If the caching is already done by the `DiscoveryClient` implementation, for example `EurekaDiscoveryClient`, the load-balancer caching should be disabled to prevent double caching.|
|---|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
967
### [](#zone-based-load-balancing)[3.4. Zone-Based Load-Balancing](#zone-based-load-balancing)
M
Mao 已提交
968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005

To enable zone-based load-balancing, we provide the `ZonePreferenceServiceInstanceListSupplier`.
We use `DiscoveryClient`-specific `zone` configuration (for example, `eureka.instance.metadata-map.zone`) to pick the zone that the client tries to filter available service instances for.

|   |You can also override `DiscoveryClient`-specific zone setup by setting the value of `spring.cloud.loadbalancer.zone` property.|
|---|------------------------------------------------------------------------------------------------------------------------------|

|   |For the time being, only Eureka Discovery Client is instrumented to set the LoadBalancer zone. For other discovery client, set the `spring.cloud.loadbalancer.zone` property. More instrumentations coming shortly.|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

|   |To determine the zone of a retrieved `ServiceInstance`, we check the value under the `"zone"` key in its metadata map.|
|---|----------------------------------------------------------------------------------------------------------------------|

The `ZonePreferenceServiceInstanceListSupplier` filters retrieved instances and only returns the ones within the same zone.
If the zone is `null` or there are no instances within the same zone, it returns all the retrieved instances.

In order to use the zone-based load-balancing approach, you will have to instantiate a `ZonePreferenceServiceInstanceListSupplier` bean in a [custom configuration](#custom-loadbalancer-configuration).

We use delegates to work with `ServiceInstanceListSupplier` beans.
We suggest passing a `DiscoveryClientServiceInstanceListSupplier` delegate in the constructor of `ZonePreferenceServiceInstanceListSupplier` and, in turn, wrapping the latter with a `CachingServiceInstanceListSupplier` to leverage [LoadBalancer caching mechanism](#loadbalancer-caching).

You could use this sample configuration to set it up:

```
public class CustomLoadBalancerConfiguration {

    @Bean
    public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
            ConfigurableApplicationContext context) {
        return ServiceInstanceListSupplier.builder()
                    .withDiscoveryClient()
                    .withZonePreference()
                    .withCaching()
                    .build(context);
    }
}
```

茶陵後's avatar
茶陵後 已提交
1006
### [](#instance-health-check-for-loadbalancer)[3.5. Instance Health-Check for LoadBalancer](#instance-health-check-for-loadbalancer)
M
Mao 已提交
1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055

It is possible to enable a scheduled HealthCheck for the LoadBalancer. The `HealthCheckServiceInstanceListSupplier`is provided for that. It regularly verifies if the instances provided by a delegate`ServiceInstanceListSupplier` are still alive and only returns the healthy instances,
unless there are none - then it returns all the retrieved instances.

|   |This mechanism is particularly helpful while using the `SimpleDiscoveryClient`. For the<br/>clients backed by an actual Service Registry, it’s not necessary to use, as we already get<br/>healthy instances after querying the external ServiceDiscovery.|
|---|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

|   |This supplier is also recommended for setups with a small number of instances per service<br/>in order to avoid retrying calls on a failing instance.|
|---|-----------------------------------------------------------------------------------------------------------------------------------------------------|

|   |If using any of the Service Discovery-backed suppliers, adding this health-check mechanism is usually not necessary, as we retrieve the health state of the instances directly<br/>from the Service Registry.|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

|   |The `HealthCheckServiceInstanceListSupplier` relies on having updated instances provided by a delegate flux. In the rare cases when you want to use a delegate that does not refresh the instances, even though the list of instances may change (such as the `DiscoveryClientServiceInstanceListSupplier` provided by us), you can set `spring.cloud.loadbalancer.health-check.refetch-instances` to `true` to have the instance list refreshed by the `HealthCheckServiceInstanceListSupplier`. You can then also adjust the refretch intervals by modifying the value of `spring.cloud.loadbalancer.health-check.refetch-instances-interval` and opt to disable the additional healthcheck repetitions by setting `spring.cloud.loadbalancer.health-check.repeat-health-check` to `false` as every instances refetch<br/>will also trigger a healthcheck.|
|---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

`HealthCheckServiceInstanceListSupplier` uses properties prefixed with`spring.cloud.loadbalancer.health-check`. You can set the `initialDelay` and `interval`for the scheduler. You can set the default path for the healthcheck URL by setting
the value of the `spring.cloud.loadbalancer.health-check.path.default` property. You can also set a specific value for any given service by setting the value of the `spring.cloud.loadbalancer.health-check.path.[SERVICE_ID]` property, substituting `[SERVICE_ID]` with the correct ID of your service. If the `[SERVICE_ID]` is not specified, `/actuator/health` is used by default. If the `[SERVICE_ID]` is set to `null` or empty as a value, then the health check will not be executed. You can also set a custom port for health-check requests by setting the value of `spring.cloud.loadbalancer.health-check.port`. If none is set, the port under which the requested service is available at the service instance.

|   |If you rely on the default path (`/actuator/health`), make sure you add `spring-boot-starter-actuator` to your collaborator’s dependencies, unless you are planning to add such an endpoint on your own.|
|---|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

In order to use the health-check scheduler approach, you will have to instantiate a `HealthCheckServiceInstanceListSupplier` bean in a [custom configuration](#custom-loadbalancer-configuration).

We use delegates to work with `ServiceInstanceListSupplier` beans.
We suggest passing a `DiscoveryClientServiceInstanceListSupplier` delegate in the constructor of `HealthCheckServiceInstanceListSupplier`.

You could use this sample configuration to set it up:

```
public class CustomLoadBalancerConfiguration {

    @Bean
    public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
            ConfigurableApplicationContext context) {
        return ServiceInstanceListSupplier.builder()
                    .withDiscoveryClient()
                    .withHealthChecks()
                    .build(context);
        }
    }
```

|   |For the non-reactive stack, create this supplier with the `withBlockingHealthChecks()`.<br/>You can also pass your own `WebClient` or `RestTemplate` instance to be used for the checks.|
|---|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

|   |`HealthCheckServiceInstanceListSupplier` has its own caching mechanism based on Reactor Flux `replay()`. Therefore, if it’s being used, you may want to skip wrapping that supplier with `CachingServiceInstanceListSupplier`.|
|---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
1056
### [](#same-instance-preference-for-loadbalancer)[3.6. Same instance preference for LoadBalancer](#same-instance-preference-for-loadbalancer)
M
Mao 已提交
1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078

You can set up the LoadBalancer in such a way that it prefers the instance that was previously selected, if that instance is available.

For that, you need to use `SameInstancePreferenceServiceInstanceListSupplier`. You can configure it either by setting the value of `spring.cloud.loadbalancer.configurations` to `same-instance-preference` or by providing your own `ServiceInstanceListSupplier` bean — for example:

```
public class CustomLoadBalancerConfiguration {

    @Bean
    public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
            ConfigurableApplicationContext context) {
        return ServiceInstanceListSupplier.builder()
                    .withDiscoveryClient()
                    .withSameInstancePreference()
                    .build(context);
        }
    }
```

|   |This is also a replacement for Zookeeper `StickyRule`.|
|---|------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
1079
### [](#request-based-sticky-session-for-loadbalancer)[3.7. Request-based Sticky Session for LoadBalancer](#request-based-sticky-session-for-loadbalancer)
M
Mao 已提交
1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105

You can set up the LoadBalancer in such a way that it prefers the instance with `instanceId` provided in a request cookie. We currently support this if the request is being passed to the LoadBalancer through either `ClientRequestContext` or `ServerHttpRequestContext`, which are used by the SC LoadBalancer exchange filter functions and filters.

For that, you need to use the `RequestBasedStickySessionServiceInstanceListSupplier`. You can configure it either by setting the value of `spring.cloud.loadbalancer.configurations` to `request-based-sticky-session` or by providing your own `ServiceInstanceListSupplier` bean — for example:

```
public class CustomLoadBalancerConfiguration {

    @Bean
    public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
            ConfigurableApplicationContext context) {
        return ServiceInstanceListSupplier.builder()
                    .withDiscoveryClient()
                    .withRequestBasedStickySession()
                    .build(context);
        }
    }
```

For that functionality, it is useful to have the selected service instance (which can be different from the one in the original request cookie if that one is not available) to be updated before sending the request forward. To do that, set the value of `spring.cloud.loadbalancer.sticky-session.add-service-instance-cookie` to `true`.

By default, the name of the cookie is `sc-lb-instance-id`. You can modify it by changing the value of the `spring.cloud.loadbalancer.instance-id-cookie-name` property.

|   |This feature is currently supported for WebClient-backed load-balancing.|
|---|------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
1106
### [](#spring-cloud-loadbalancer-hints)[3.8. Spring Cloud LoadBalancer Hints](#spring-cloud-loadbalancer-hints)
M
Mao 已提交
1107 1108 1109 1110 1111 1112

Spring Cloud LoadBalancer lets you set `String` hints that are passed to the LoadBalancer within the `Request` object and that can later be used in `ReactiveLoadBalancer` implementations that can handle them.

You can set a default hint for all services by setting the value of the `spring.cloud.loadbalancer.hint.default` property. You can also set a specific value
for any given service by setting the value of the `spring.cloud.loadbalancer.hint.[SERVICE_ID]` property, substituting `[SERVICE_ID]` with the correct ID of your service. If the hint is not set by the user, `default` is used.

茶陵後's avatar
茶陵後 已提交
1113
### [](#hints-based-loadbalancing)[3.9. Hint-Based Load-Balancing](#hints-based-loadbalancing)
M
Mao 已提交
1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141

We also provide a `HintBasedServiceInstanceListSupplier`, which is a `ServiceInstanceListSupplier` implementation for hint-based instance selection.

`HintBasedServiceInstanceListSupplier` checks for a hint request header (the default header-name is `X-SC-LB-Hint`, but you can modify it by changing the value of the `spring.cloud.loadbalancer.hint-header-name` property) and, if it finds a hint request header, uses the hint value passed in the header to filter service instances.

If no hint header has been added, `HintBasedServiceInstanceListSupplier` uses [hint values from properties](#spring-cloud-loadbalancer-hints) to filter service instances.

If no hint is set, either by the header or by properties, all service instances provided by the delegate are returned.

While filtering, `HintBasedServiceInstanceListSupplier` looks for service instances that have a matching value set under the `hint` key in their `metadataMap`. If no matching instances are found, all instances provided by the delegate are returned.

You could use the following sample configuration to set it up:

```
public class CustomLoadBalancerConfiguration {

    @Bean
    public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
            ConfigurableApplicationContext context) {
        return ServiceInstanceListSupplier.builder()
                    .withDiscoveryClient()
                    .withHints()
                    .withCaching()
                    .build(context);
    }
}
```

茶陵後's avatar
茶陵後 已提交
1142
### [](#transform-the-load-balanced-http-request)[3.10. Transform the load-balanced HTTP request](#transform-the-load-balanced-http-request)
M
Mao 已提交
1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186

You can use the selected `ServiceInstance` to transform the load-balanced HTTP Request.

For `RestTemplate`, you need to implement and define `LoadBalancerRequestTransformer` as follows:

```
@Bean
public LoadBalancerRequestTransformer transformer() {
    return new LoadBalancerRequestTransformer() {
        @Override
        public HttpRequest transformRequest(HttpRequest request, ServiceInstance instance) {
            return new HttpRequestWrapper(request) {
                @Override
                public HttpHeaders getHeaders() {
                    HttpHeaders headers = new HttpHeaders();
                    headers.putAll(super.getHeaders());
                    headers.add("X-InstanceId", instance.getInstanceId());
                    return headers;
                }
            };
        }
    };
}
```

For `WebClient`, you need to implement and define `LoadBalancerClientRequestTransformer` as follows:

```
@Bean
public LoadBalancerClientRequestTransformer transformer() {
    return new LoadBalancerClientRequestTransformer() {
        @Override
        public ClientRequest transformRequest(ClientRequest request, ServiceInstance instance) {
            return ClientRequest.from(request)
                    .header("X-InstanceId", instance.getInstanceId())
                    .build();
        }
    };
}
```

If multiple transformers are defined, they are applied in the order in which Beans are defined.
Alternatively, you can use `LoadBalancerRequestTransformer.DEFAULT_ORDER` or `LoadBalancerClientRequestTransformer.DEFAULT_ORDER` to specify the order.

茶陵後's avatar
茶陵後 已提交
1187
### [](#spring-cloud-loadbalancer-starter)[3.11. Spring Cloud LoadBalancer Starter](#spring-cloud-loadbalancer-starter)
M
Mao 已提交
1188 1189 1190 1191 1192 1193 1194

We also provide a starter that allows you to easily add Spring Cloud LoadBalancer in a Spring Boot app.
In order to use it, just add `org.springframework.cloud:spring-cloud-starter-loadbalancer` to your Spring Cloud dependencies in your build file.

|   |Spring Cloud LoadBalancer starter includes[Spring Boot Caching](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-caching.html)and [Evictor](https://github.com/stoyanr/Evictor).|
|---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
1195
### [](#custom-loadbalancer-configuration)[3.12. Passing Your Own Spring Cloud LoadBalancer Configuration](#custom-loadbalancer-configuration)
M
Mao 已提交
1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244

You can also use the `@LoadBalancerClient` annotation to pass your own load-balancer client configuration, passing the name of the load-balancer client and the configuration class, as follows:

```
@Configuration
@LoadBalancerClient(value = "stores", configuration = CustomLoadBalancerConfiguration.class)
public class MyConfiguration {

    @Bean
    @LoadBalanced
    public WebClient.Builder loadBalancedWebClientBuilder() {
        return WebClient.builder();
    }
}
```

TIP

In order to make working on your own LoadBalancer configuration easier, we have added a `builder()` method to the `ServiceInstanceListSupplier` class.

TIP

You can also use our alternative predefined configurations in place of the default ones by setting the value of `spring.cloud.loadbalancer.configurations` property to `zone-preference` to use `ZonePreferenceServiceInstanceListSupplier` with caching or to `health-check` to use `HealthCheckServiceInstanceListSupplier` with caching.

You can use this feature to instantiate different implementations of `ServiceInstanceListSupplier` or `ReactorLoadBalancer`, either written by you, or provided by us as alternatives (for example `ZonePreferenceServiceInstanceListSupplier`) to override the default setup.

You can see an example of a custom configuration [here](#zoned-based-custom-loadbalancer-configuration).

|   |The annotation `value` arguments (`stores` in the example above) specifies the service id of the service that we should send the requests to with the given custom configuration.|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

You can also pass multiple configurations (for more than one load-balancer client) through the `@LoadBalancerClients` annotation, as the following example shows:

```
@Configuration
@LoadBalancerClients({@LoadBalancerClient(value = "stores", configuration = StoresLoadBalancerClientConfiguration.class), @LoadBalancerClient(value = "customers", configuration = CustomersLoadBalancerClientConfiguration.class)})
public class MyConfiguration {

    @Bean
    @LoadBalanced
    public WebClient.Builder loadBalancedWebClientBuilder() {
        return WebClient.builder();
    }
}
```

|   |The classes you pass as `@LoadBalancerClient` or `@LoadBalancerClients` configuration arguments should either not be annotated with `@Configuration` or be outside component scan scope.|
|---|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
1245
### [](#loadbalancer-lifecycle)[3.13. Spring Cloud LoadBalancer Lifecycle](#loadbalancer-lifecycle)
M
Mao 已提交
1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258

One type of bean that it may be useful to register using [Custom LoadBalancer configuration](#custom-loadbalancer-configuration) is `LoadBalancerLifecycle`.

The `LoadBalancerLifecycle` beans provide callback methods, named `onStart(Request<RC> request)`, `onStartRequest(Request<RC> request, Response<T> lbResponse)` and `onComplete(CompletionContext<RES, T, RC> completionContext)`, that you should implement to specify what actions should take place before and after load-balancing.

`onStart(Request<RC> request)` takes a `Request` object as a parameter. It contains data that is used to select an appropriate instance, including the downstream client request and [hint](#spring-cloud-loadbalancer-hints). `onStartRequest` also takes the `Request` object and, additionally, the `Response<T>` object as parameters. On the other hand, a `CompletionContext` object is provided to the `onComplete(CompletionContext<RES, T, RC> completionContext)` method. It contains the LoadBalancer `Response`, including the selected service instance, the `Status` of the request executed against that service instance and (if available) the response returned to the downstream client, and (if an exception has occurred) the corresponding `Throwable`.

The `supports(Class requestContextClass, Class responseClass,
Class serverTypeClass)` method can be used to determine whether the processor in question handles objects of provided types. If not overridden by the user, it returns `true`.

|   |In the preceding method calls, `RC` means `RequestContext` type, `RES` means client response type, and `T` means returned server type.|
|---|--------------------------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
1259
### [](#loadbalancer-micrometer-stats-lifecycle)[3.14. Spring Cloud LoadBalancer Statistics](#loadbalancer-micrometer-stats-lifecycle)
M
Mao 已提交
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286

We provide a `LoadBalancerLifecycle` bean called `MicrometerStatsLoadBalancerLifecycle`, which uses Micrometer to provide statistics for load-balanced calls.

In order to get this bean added to your application context,
set the value of the `spring.cloud.loadbalancer.stats.micrometer.enabled` to `true` and have a `MeterRegistry` available (for example, by adding [Spring Boot Actuator](https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html) to your project).

`MicrometerStatsLoadBalancerLifecycle` registers the following meters in `MeterRegistry`:

* `loadbalancer.requests.active`: A gauge that allows you to monitor the number of currently active requests for any service instance (service instance data available via tags);

* `loadbalancer.requests.success`: A timer that measures the time of execution of any load-balanced requests that have ended in passing a response on to the underlying client;

* `loadbalancer.requests.failed`: A timer that measures the time of execution of any load-balanced requests that have ended with an exception;

* `loadbalancer.requests.discard`: A counter that measures the number of discarded load-balanced requests, i.e. requests where a service instance to run the request on has not been retrieved by the LoadBalancer.

Additional information regarding the service instances, request data, and response data is added to metrics via tags whenever available.

|   |For some implementations, such as `BlockingLoadBalancerClient`, request and response data might not be available, as we establish generic types from arguments and might not be able to determine the types and read the data.|
|---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

|   |The meters are registered in the registry when at least one record is added for a given meter.|
|---|----------------------------------------------------------------------------------------------|

|   |You can further configure the behavior of those metrics (for example, add [publishing percentiles and histograms](https://micrometer.io/docs/concepts#_histograms_and_percentiles)) by [adding `MeterFilters`](https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready-metrics-per-meter-properties).|
|---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
1287
### [](#configuring-individual-loadbalancerclients)[3.15. Configuring Individual LoadBalancerClients](#configuring-individual-loadbalancerclients)
M
Mao 已提交
1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319

Individual Loadbalancer clients may be configured individually with a different prefix `spring.cloud.loadbalancer.clients.<clientId>.` **where `clientId` is the name of the loadbalancer. Default configuration values may be set in the `spring.cloud.loadbalancer.`** namespace and will be merged with the client specific values taking precedence

Example 5. application.yml

```
spring:
  cloud:
    loadbalancer:
      health-check:
        initial-delay: 1s
      clients:
        myclient:
          health-check:
            interval: 30s
```

The above example will result in a merged health-check `@ConfigurationProperties` object with `initial-delay=1s` and `interval=30s`.

The per-client configuration properties work for most of the properties, apart from the following global ones:

* `spring.cloud.loadbalancer.enabled` - globally enables or disables load-balancing

* `spring.cloud.loadbalancer.retry.enabled` - globally enables or disables load-balanced retries. If you enable it globally, you can still disable retries for specific clients using the `client`-prefixed properties, but not the other way round

* `spring.cloud.loadbalancer.cache.enabled` - globally enables or disables LoadBalancer caching. If you enable it globally, you can still disable caching for specific clients by creating a [custom configuration](#custom-loadbalancer-configuration) that does not include the `CachingServiceInstanceListSupplier` in the `ServiceInstanceListSupplier` delegates hierarchy, but not the other way round.

* `spring.cloud.loadbalancer.stats.micrometer.enabled` - globally enables or disables LoadBalancer Micrometer metrics

|   |For the properties where maps where already used, where you could specify a different value per-client without using the `clients` keyword (for example, `hints`, `health-check.path`), we have kept that behaviour in order to keep the library backwards compatible. It will be modified in the next major release.|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
1320
## [](#spring-cloud-circuit-breaker)[4. Spring Cloud Circuit Breaker](#spring-cloud-circuit-breaker)
M
Mao 已提交
1321

茶陵後's avatar
茶陵後 已提交
1322
### [](#introduction)[4.1. Introduction](#introduction)
M
Mao 已提交
1323 1324 1325 1326

Spring Cloud Circuit breaker provides an abstraction across different circuit breaker implementations.
It provides a consistent API to use in your applications, letting you, the developer, choose the circuit breaker implementation that best fits your needs for your application.

茶陵後's avatar
茶陵後 已提交
1327
#### [](#supported-implementations)[4.1.1. Supported Implementations](#supported-implementations)
M
Mao 已提交
1328 1329 1330 1331 1332 1333 1334 1335 1336

Spring Cloud supports the following circuit-breaker implementations:

* [Resilience4J](https://github.com/resilience4j/resilience4j)

* [Sentinel](https://github.com/alibaba/Sentinel)

* [Spring Retry](https://github.com/spring-projects/spring-retry)

茶陵後's avatar
茶陵後 已提交
1337
### [](#core-concepts)[4.2. Core Concepts](#core-concepts)
M
Mao 已提交
1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366

To create a circuit breaker in your code, you can use the `CircuitBreakerFactory` API. When you include a Spring Cloud Circuit Breaker starter on your classpath, a bean that implements this API is automatically created for you.
The following example shows a simple example of how to use this API:

```
@Service
public static class DemoControllerService {
    private RestTemplate rest;
    private CircuitBreakerFactory cbFactory;

    public DemoControllerService(RestTemplate rest, CircuitBreakerFactory cbFactory) {
        this.rest = rest;
        this.cbFactory = cbFactory;
    }

    public String slow() {
        return cbFactory.create("slow").run(() -> rest.getForObject("/slow", String.class), throwable -> "fallback");
    }

}
```

The `CircuitBreakerFactory.create` API creates an instance of a class called `CircuitBreaker`.
The `run` method takes a `Supplier` and a `Function`.
The `Supplier` is the code that you are going to wrap in a circuit breaker.
The `Function` is the fallback that is run if the circuit breaker is tripped.
The function is passed the `Throwable` that caused the fallback to be triggered.
You can optionally exclude the fallback if you do not want to provide one.

茶陵後's avatar
茶陵後 已提交
1367
#### [](#circuit-breakers-in-reactive-code)[4.2.1. Circuit Breakers In Reactive Code](#circuit-breakers-in-reactive-code)
M
Mao 已提交
1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393

If Project Reactor is on the class path, you can also use `ReactiveCircuitBreakerFactory` for your reactive code.
The following example shows how to do so:

```
@Service
public static class DemoControllerService {
    private ReactiveCircuitBreakerFactory cbFactory;
    private WebClient webClient;

    public DemoControllerService(WebClient webClient, ReactiveCircuitBreakerFactory cbFactory) {
        this.webClient = webClient;
        this.cbFactory = cbFactory;
    }

    public Mono<String> slow() {
        return webClient.get().uri("/slow").retrieve().bodyToMono(String.class).transform(
        it -> cbFactory.create("slow").run(it, throwable -> return Mono.just("fallback")));
    }
}
```

The `ReactiveCircuitBreakerFactory.create` API creates an instance of a class called `ReactiveCircuitBreaker`.
The `run` method takes a `Mono` or a `Flux` and wraps it in a circuit breaker.
You can optionally profile a fallback `Function`, which will be called if the circuit breaker is tripped and is passed the `Throwable`that caused the failure.

茶陵後's avatar
茶陵後 已提交
1394
### [](#configuration)[4.3. Configuration](#configuration)
M
Mao 已提交
1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420

You can configure your circuit breakers by creating beans of type `Customizer`.
The `Customizer` interface has a single method (called `customize`) that takes the `Object` to customize.

For detailed information on how to customize a given implementation see
the following documentation:

* [Resilience4J](../../../../spring-cloud-circuitbreaker/current/reference/html/spring-cloud-circuitbreaker.html#configuring-resilience4j-circuit-breakers)

* [Sentinel](https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-docs/src/main/asciidoc/circuitbreaker-sentinel.adoc#circuit-breaker-spring-cloud-circuit-breaker-with-sentinel—​configuring-sentinel-circuit-breakers)

* [Spring Retry](../../../../../spring-cloud-circuitbreaker/docs/current/reference/html/spring-cloud-circuitbreaker.html#configuring-spring-retry-circuit-breakers)

Some `CircuitBreaker` implementations such as `Resilience4JCircuitBreaker` call `customize` method every time `CircuitBreaker#run` is called.
It can be inefficient. In that case, you can use `CircuitBreaker#once` method. It is useful where calling `customize` many times doesn’t make sense,
for example, in case of [consuming Resilience4j’s events](https://resilience4j.readme.io/docs/circuitbreaker#section-consume-emitted-circuitbreakerevents).

The following example shows the way for each `io.github.resilience4j.circuitbreaker.CircuitBreaker` to consume events.

```
Customizer.once(circuitBreaker -> {
  circuitBreaker.getEventPublisher()
    .onStateTransition(event -> log.info("{}: {}", event.getCircuitBreakerName(), event.getStateTransition()));
}, CircuitBreaker::getName)
```

茶陵後's avatar
茶陵後 已提交
1421
## [](#cachedrandompropertysource)[5. CachedRandomPropertySource](#cachedrandompropertysource)
M
Mao 已提交
1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432

Spring Cloud Context provides a `PropertySource` that caches random values based on a key. Outside of the caching
functionality it works the same as Spring Boot’s [`RandomValuePropertySource`](https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/env/RandomValuePropertySource.java).
This random value might be useful in the case where you want a random value that is consistent even after the Spring Application
context restarts. The property value takes the form of `cachedrandom.[yourkey].[type]` where `yourkey` is the key in the cache. The `type` value can
be any type supported by Spring Boot’s `RandomValuePropertySource`.

```
myrandom=${cachedrandom.appname.value}
```

茶陵後's avatar
茶陵後 已提交
1433
## [](#spring-cloud-security)[6. Security](#spring-cloud-security)
M
Mao 已提交
1434

茶陵後's avatar
茶陵後 已提交
1435
### [](#spring-cloud-security-single-sign-on)[6.1. Single Sign On](#spring-cloud-security-single-sign-on)
M
Mao 已提交
1436 1437 1438 1439

|   |All of the OAuth2 SSO and resource server features moved to Spring Boot<br/>in version 1.3. You can find documentation in the[Spring Boot user guide](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/).|
|---|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

茶陵後's avatar
茶陵後 已提交
1440
#### [](#spring-cloud-security-client-token-relay)[6.1.1. Client Token Relay](#spring-cloud-security-client-token-relay)
M
Mao 已提交
1441 1442 1443 1444 1445 1446 1447 1448

If your app is a user facing OAuth2 client (i.e. has declared`@EnableOAuth2Sso` or `@EnableOAuth2Client`) then it has an`OAuth2ClientContext` in request scope from Spring Boot. You can
create your own `OAuth2RestTemplate` from this context and an
autowired `OAuth2ProtectedResourceDetails`, and then the context will
always forward the access token downstream, also refreshing the access
token automatically if it expires. (These are features of Spring
Security and Spring Boot.)

茶陵後's avatar
茶陵後 已提交
1449
#### [](#spring-cloud-security-resource-server-token-relay)[6.1.2. Resource Server Token Relay](#spring-cloud-security-resource-server-token-relay)
M
Mao 已提交
1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506

If your app has `@EnableResourceServer` you might want to relay the
incoming token downstream to other services. If you use a`RestTemplate` to contact the downstream services then this is just a
matter of how to create the template with the right context.

If your service uses `UserInfoTokenServices` to authenticate incoming
tokens (i.e. it is using the `security.oauth2.user-info-uri`configuration), then you can simply create an `OAuth2RestTemplate`using an autowired `OAuth2ClientContext` (it will be populated by the
authentication process before it hits the backend code). Equivalently
(with Spring Boot 1.4), you could inject a`UserInfoRestTemplateFactory` and grab its `OAuth2RestTemplate` in
your configuration. For example:

MyConfiguration.java

```
@Bean
public OAuth2RestTemplate restTemplate(UserInfoRestTemplateFactory factory) {
    return factory.getUserInfoRestTemplate();
}
```

This rest template will then have the same `OAuth2ClientContext`(request-scoped) that is used by the authentication filter, so you can
use it to send requests with the same access token.

If your app is not using `UserInfoTokenServices` but is still a client
(i.e. it declares `@EnableOAuth2Client` or `@EnableOAuth2Sso`), then
with Spring Security Cloud any `OAuth2RestOperations` that the user
creates from an `@Autowired` `OAuth2Context` will also forward
tokens. This feature is implemented by default as an MVC handler
interceptor, so it only works in Spring MVC. If you are not using MVC
you could use a custom filter or AOP interceptor wrapping an`AccessTokenContextRelay` to provide the same feature.

Here’s a basic
example showing the use of an autowired rest template created
elsewhere ("foo.com" is a Resource Server accepting the same tokens as
the surrounding app):

MyController.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() + ")";
}
```

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`OAuth2Context` instead of autowiring the default one.

Feign clients will also pick up an interceptor that uses the`OAuth2ClientContext` if it is available, so they should also do a
token relay anywhere where a `RestTemplate` would.

茶陵後's avatar
茶陵後 已提交
1507
## [](#configuration-properties)[7. Configuration Properties](#configuration-properties)
M
Mao 已提交
1508 1509 1510

To see the list of all Spring Cloud Commons related configuration properties please check [the Appendix page](appendix.html).

茶陵後's avatar
茶陵後 已提交
1511
if (window.parent == window) {(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1\*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,'script','//www.google-analytics.com/analytics.js','ga');ga('create', 'UA-2728886-23', 'auto', {'siteSpeedSampleRate': 100});ga('send', 'pageview');}