Split files
This commit is contained in:
@@ -6,630 +6,3 @@ include::intro.adoc[]
|
||||
|
||||
include::_attributes.adoc[]
|
||||
|
||||
[[quick-start]]
|
||||
== Quick Start
|
||||
|
||||
include::quickstart.adoc[]
|
||||
|
||||
[[spring-cloud-zookeeper-install]]
|
||||
== Install Zookeeper
|
||||
See the https://zookeeper.apache.org/doc/current/zookeeperStarted.html[installation
|
||||
documentation] for instructions on how to install Zookeeper.
|
||||
|
||||
Spring Cloud Zookeeper uses Apache Curator behind the scenes.
|
||||
While Zookeeper 3.5.x is still considered "beta" by the Zookeeper development team,
|
||||
the reality is that it is used in production by many users.
|
||||
However, Zookeeper 3.4.x is also used in production.
|
||||
Prior to Apache Curator 4.0, both versions of Zookeeper were supported via two versions of Apache Curator.
|
||||
Starting with Curator 4.0 both versions of Zookeeper are supported via the same Curator libraries.
|
||||
|
||||
In case you are integrating with version 3.4 you need to change the Zookeeper dependency
|
||||
that comes shipped with `curator`, and thus `spring-cloud-zookeeper`.
|
||||
To do so simply exclude that dependency and add the 3.4.x version like shown below.
|
||||
|
||||
.maven
|
||||
[source,xml,indent=0]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-zookeeper-all</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.zookeeper</groupId>
|
||||
<artifactId>zookeeper</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.zookeeper</groupId>
|
||||
<artifactId>zookeeper</artifactId>
|
||||
<version>3.4.12</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
.gradle
|
||||
[source,groovy,indent=0]
|
||||
----
|
||||
compile('org.springframework.cloud:spring-cloud-starter-zookeeper-all') {
|
||||
exclude group: 'org.apache.zookeeper', module: 'zookeeper'
|
||||
}
|
||||
compile('org.apache.zookeeper:zookeeper:3.4.12') {
|
||||
exclude group: 'org.slf4j', module: 'slf4j-log4j12'
|
||||
}
|
||||
----
|
||||
|
||||
[[spring-cloud-zookeeper-discovery]]
|
||||
== Service Discovery with Zookeeper
|
||||
|
||||
Service Discovery is one of the key tenets of a microservice based architecture. Trying to
|
||||
hand-configure each client or some form of convention can be difficult to do and can be
|
||||
brittle. https://curator.apache.org[Curator](A Java library for Zookeeper) provides Service
|
||||
Discovery through a https://curator.apache.org/curator-x-discovery/[Service Discovery
|
||||
Extension]. Spring Cloud Zookeeper uses this extension for service registration and
|
||||
discovery.
|
||||
|
||||
[[activating]]
|
||||
=== Activating
|
||||
|
||||
Including a dependency on
|
||||
`org.springframework.cloud:spring-cloud-starter-zookeeper-discovery` enables
|
||||
autoconfiguration that sets up Spring Cloud Zookeeper Discovery.
|
||||
|
||||
NOTE: For web functionality, you still need to include
|
||||
`org.springframework.boot:spring-boot-starter-web`.
|
||||
|
||||
CAUTION: When working with version 3.4 of Zookeeper you need to change
|
||||
the way you include the dependency as described <<spring-cloud-zookeeper-install,here>>.
|
||||
|
||||
[[registering-with-zookeeper]]
|
||||
=== Registering with Zookeeper
|
||||
|
||||
When a client registers with Zookeeper, it provides metadata (such as host and port, ID,
|
||||
and name) about itself.
|
||||
|
||||
The following example shows a Zookeeper client:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@SpringBootApplication
|
||||
@RestController
|
||||
public class Application {
|
||||
|
||||
@RequestMapping("/")
|
||||
public String home() {
|
||||
return "Hello world";
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(Application.class).web(true).run(args);
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
NOTE: The preceding example is a normal Spring Boot application.
|
||||
|
||||
If Zookeeper is located somewhere other than `localhost:2181`, the configuration must
|
||||
provide the location of the server, as shown in the following example:
|
||||
|
||||
[source,yml,indent=0]
|
||||
.application.yml
|
||||
----
|
||||
spring:
|
||||
cloud:
|
||||
zookeeper:
|
||||
connect-string: localhost:2181
|
||||
----
|
||||
|
||||
CAUTION: If you use <<spring-cloud-zookeeper-config,Spring Cloud Zookeeper Config>>, the
|
||||
values shown in the preceding example need to be in `bootstrap.yml` instead of
|
||||
`application.yml`.
|
||||
|
||||
The default service name, instance ID, and port (taken from the `Environment`) are
|
||||
`${spring.application.name}`, the Spring Context ID, and `${server.port}`, respectively.
|
||||
|
||||
Having `spring-cloud-starter-zookeeper-discovery` on the classpath makes the app into both
|
||||
a Zookeeper "`service`" (that is, it registers itself) and a "`client`" (that is, it can
|
||||
query Zookeeper to locate other services).
|
||||
|
||||
If you would like to disable the Zookeeper Discovery Client, you can set
|
||||
`spring.cloud.zookeeper.discovery.enabled` to `false`.
|
||||
|
||||
[[using-the-discoveryclient]]
|
||||
=== Using the DiscoveryClient
|
||||
|
||||
Spring Cloud has support for
|
||||
https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-feign[Feign]
|
||||
(a REST client builder),
|
||||
https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/ascii[Spring
|
||||
`RestTemplate`] and
|
||||
https://cloud.spring.io/spring-cloud-commons/reference/html/#loadbalanced-webclient[Spring WebFlux], using logical service names instead of physical URLs.
|
||||
|
||||
You can also use the `org.springframework.cloud.client.discovery.DiscoveryClient`, which
|
||||
provides a simple API for discovery clients that is not specific to Netflix, as shown in
|
||||
the following example:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@Autowired
|
||||
private DiscoveryClient discoveryClient;
|
||||
|
||||
public String serviceUrl() {
|
||||
List<ServiceInstance> list = discoveryClient.getInstances("STORES");
|
||||
if (list != null && list.size() > 0 ) {
|
||||
return list.get(0).getUri().toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
----
|
||||
|
||||
[[spring-cloud-zookeeper-other-componentes]]
|
||||
== Using Spring Cloud Zookeeper with Spring Cloud Components
|
||||
|
||||
Feign, Spring Cloud Gateway and Spring Cloud LoadBalancer all work with Spring Cloud Zookeeper.
|
||||
|
||||
[[spring-cloud-loadbalancer-with-zookeeper]]
|
||||
=== Spring Cloud LoadBalancer with Zookeeper
|
||||
|
||||
Spring Cloud Zookeeper provides an implementation of Spring Cloud LoadBalancer `ServiceInstanceListSupplier`.
|
||||
When you use the `spring-cloud-starter-zookeeper-discovery`, Spring Cloud LoadBalancer is autoconfigured to use the
|
||||
`ZookeeperServiceInstanceListSupplier` by default.
|
||||
|
||||
TIP: If you were previously using the StickyRule in Zookeeper, its replacement in the current stack
|
||||
is the `SameInstancePreferenceServiceInstanceListSupplier` in SC LoadBalancer. You can read on how to set it up in the https://docs.spring.io/spring-cloud-commons/docs/current/reference/html/#spring-cloud-loadbalancer[Spring Cloud Commons documentation].
|
||||
|
||||
[[spring-cloud-zookeeper-service-registry]]
|
||||
== Spring Cloud Zookeeper and Service Registry
|
||||
|
||||
Spring Cloud Zookeeper implements the `ServiceRegistry` interface, letting developers
|
||||
register arbitrary services in a programmatic way.
|
||||
|
||||
The `ServiceInstanceRegistration` class offers a `builder()` method to create a
|
||||
`Registration` object that can be used by the `ServiceRegistry`, as shown in the following
|
||||
example:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@Autowired
|
||||
private ZookeeperServiceRegistry serviceRegistry;
|
||||
|
||||
public void registerThings() {
|
||||
ZookeeperRegistration registration = ServiceInstanceRegistration.builder()
|
||||
.defaultUriSpec()
|
||||
.address("anyUrl")
|
||||
.port(10)
|
||||
.name("/a/b/c/d/anotherservice")
|
||||
.build();
|
||||
this.serviceRegistry.register(registration);
|
||||
}
|
||||
----
|
||||
|
||||
[[instance-status]]
|
||||
=== Instance Status
|
||||
|
||||
Netflix Eureka supports having instances that are `OUT_OF_SERVICE` registered with the server.
|
||||
These instances are not returned as active service instances.
|
||||
This is useful for behaviors such as blue/green deployments.
|
||||
(Note that the Curator Service Discovery recipe does not support this behavior.) Taking advantage of the flexible payload has let Spring Cloud Zookeeper implement `OUT_OF_SERVICE` by updating some specific metadata and then filtering on that metadata in the Spring Cloud LoadBalancer `ZookeeperServiceInstanceListSupplier`.
|
||||
The `ZookeeperServiceInstanceListSupplier` filters out all non-null instance statuses that do not equal `UP`.
|
||||
If the instance status field is empty, it is considered to be `UP` for backwards compatibility.
|
||||
To change the status of an instance, make a `POST` with `OUT_OF_SERVICE` to the `ServiceRegistry`
|
||||
instance status actuator endpoint, as shown in the following example:
|
||||
|
||||
[source,sh,indent=0]
|
||||
----
|
||||
$ http POST http://localhost:8081/service-registry status=OUT_OF_SERVICE
|
||||
----
|
||||
|
||||
NOTE: The preceding example uses the `http` command from https://httpie.org.
|
||||
|
||||
[[spring-cloud-zookeeper-dependencies]]
|
||||
== Zookeeper Dependencies
|
||||
|
||||
The following topics cover how to work with Spring Cloud Zookeeper dependencies:
|
||||
|
||||
* <<spring-cloud-zookeeper-dependencies-using>>
|
||||
* <<spring-cloud-zookeeper-dependencies-activating>>
|
||||
* <<spring-cloud-zookeeper-dependencies-setting-up>>
|
||||
* <<spring-cloud-zookeeper-dependencies-configuring>>
|
||||
|
||||
[[spring-cloud-zookeeper-dependencies-using]]
|
||||
=== Using the Zookeeper Dependencies
|
||||
|
||||
Spring Cloud Zookeeper gives you a possibility to provide dependencies of your application
|
||||
as properties. As dependencies, you can understand other applications that are registered
|
||||
in Zookeeper and which you would like to call through
|
||||
https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-feign[Feign]
|
||||
(a REST client builder),
|
||||
https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/ascii[Spring
|
||||
`RestTemplate`] and
|
||||
https://cloud.spring.io/spring-cloud-commons/reference/html/#loadbalanced-webclient[Spring WebFlux].
|
||||
|
||||
You can also use the Zookeeper Dependency Watchers functionality to control and monitor
|
||||
the state of your dependencies.
|
||||
|
||||
[[spring-cloud-zookeeper-dependencies-activating]]
|
||||
=== Activating Zookeeper Dependencies
|
||||
|
||||
Including a dependency on
|
||||
`org.springframework.cloud:spring-cloud-starter-zookeeper-discovery` enables
|
||||
autoconfiguration that sets up Spring Cloud Zookeeper Dependencies. Even if you provide
|
||||
the dependencies in your properties, you can turn off the dependencies. To do so, set the
|
||||
`spring.cloud.zookeeper.dependency.enabled` property to false (it defaults to `true`).
|
||||
|
||||
[[spring-cloud-zookeeper-dependencies-setting-up]]
|
||||
=== Setting up Zookeeper Dependencies
|
||||
|
||||
Consider the following example of dependency representation:
|
||||
|
||||
[source,yml,indent=0]
|
||||
.application.yml
|
||||
----
|
||||
spring.application.name: yourServiceName
|
||||
spring.cloud.zookeeper:
|
||||
dependencies:
|
||||
newsletter:
|
||||
path: /path/where/newsletter/has/registered/in/zookeeper
|
||||
loadBalancerType: ROUND_ROBIN
|
||||
contentTypeTemplate: application/vnd.newsletter.$version+json
|
||||
version: v1
|
||||
headers:
|
||||
header1:
|
||||
- value1
|
||||
header2:
|
||||
- value2
|
||||
required: false
|
||||
stubs: org.springframework:foo:stubs
|
||||
mailing:
|
||||
path: /path/where/mailing/has/registered/in/zookeeper
|
||||
loadBalancerType: ROUND_ROBIN
|
||||
contentTypeTemplate: application/vnd.mailing.$version+json
|
||||
version: v1
|
||||
required: true
|
||||
----
|
||||
|
||||
The next few sections go through each part of the dependency one by one. The root property
|
||||
name is `spring.cloud.zookeeper.dependencies`.
|
||||
|
||||
[[spring-cloud-zookeeper-dependencies-setting-up-aliases]]
|
||||
==== Aliases
|
||||
|
||||
Below the root property you have to represent each dependency as an alias.
|
||||
This is due to the constraints of Spring Cloud LoadBalancer, which requires that the application ID be placed in the URL.
|
||||
Consequently, you cannot pass any complex path, suchas `/myApp/myRoute/name`).
|
||||
The alias is the name you use instead of the `serviceId` for `DiscoveryClient`, `Feign`, or
|
||||
`RestTemplate`.
|
||||
|
||||
In the previous examples, the aliases are `newsletter` and `mailing`.
|
||||
The following example shows Feign usage with a `newsletter` alias:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@FeignClient("newsletter")
|
||||
public interface NewsletterService {
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/newsletter")
|
||||
String getNewsletters();
|
||||
}
|
||||
----
|
||||
|
||||
[[path]]
|
||||
==== Path
|
||||
|
||||
The path is represented by the `path` YAML property and is the path under which the dependency is registered under Zookeeper.
|
||||
As described in the
|
||||
<<spring-cloud-zookeeper-dependencies-setting-up-aliases,previous section>>, Spring Cloud LoadBalancer operates on URLs.
|
||||
As a result, this path is not compliant with its requirement.
|
||||
That is why Spring Cloud Zookeeper maps the alias to the proper path.
|
||||
|
||||
[[load-balancer-type]]
|
||||
==== Load Balancer Type
|
||||
|
||||
The load balancer type is represented by `loadBalancerType` YAML property.
|
||||
|
||||
If you know what kind of load-balancing strategy has to be applied when calling this particular dependency, you can provide it in the YAML file, and it is automatically applied.
|
||||
You can choose one of the following load balancing strategies:
|
||||
|
||||
* STICKY: Once chosen, the instance is always called.
|
||||
* RANDOM: Picks an instance randomly.
|
||||
* ROUND_ROBIN: Iterates over instances over and over again.
|
||||
|
||||
[[content-type-template-and-version]]
|
||||
==== `Content-Type` Template and Version
|
||||
|
||||
The `Content-Type` template and version are represented by the `contentTypeTemplate` and
|
||||
`version` YAML properties.
|
||||
|
||||
If you version your API in the `Content-Type` header, you do not want to add this header
|
||||
to each of your requests. Also, if you want to call a new version of the API, you do not
|
||||
want to roam around your code to bump up the API version. That is why you can provide a
|
||||
`contentTypeTemplate` with a special `$version` placeholder. That placeholder will be filled by the value of the
|
||||
`version` YAML property. Consider the following example of a `contentTypeTemplate`:
|
||||
|
||||
----
|
||||
application/vnd.newsletter.$version+json
|
||||
----
|
||||
|
||||
Further consider the following `version`:
|
||||
|
||||
----
|
||||
v1
|
||||
----
|
||||
|
||||
The combination of `contentTypeTemplate` and version results in the creation of a
|
||||
`Content-Type` header for each request, as follows:
|
||||
|
||||
----
|
||||
application/vnd.newsletter.v1+json
|
||||
----
|
||||
|
||||
[[default-headers]]
|
||||
==== Default Headers
|
||||
|
||||
Default headers are represented by the `headers` map in YAML.
|
||||
|
||||
Sometimes, each call to a dependency requires setting up of some default headers. To not
|
||||
do that in code, you can set them up in the YAML file, as shown in the following example
|
||||
`headers` section:
|
||||
|
||||
[source,yml,indent=0]
|
||||
----
|
||||
headers:
|
||||
Accept:
|
||||
- text/html
|
||||
- application/xhtml+xml
|
||||
Cache-Control:
|
||||
- no-cache
|
||||
----
|
||||
|
||||
That `headers` section results in adding the `Accept` and `Cache-Control` headers with
|
||||
appropriate list of values in your HTTP request.
|
||||
|
||||
[[required-dependencies]]
|
||||
==== Required Dependencies
|
||||
|
||||
Required dependencies are represented by `required` property in YAML.
|
||||
|
||||
If one of your dependencies is required to be up when your application boots, you can set
|
||||
the `required: true` property in the YAML file.
|
||||
|
||||
If your application cannot localize the required dependency during boot time, it throws an
|
||||
exception, and the Spring Context fails to set up. In other words, your application cannot
|
||||
start if the required dependency is not registered in Zookeeper.
|
||||
|
||||
You can read more about Spring Cloud Zookeeper Presence Checker
|
||||
<<spring-cloud-zookeeper-dependency-watcher-presence-checker,later in this document>>.
|
||||
|
||||
[[stubs]]
|
||||
==== Stubs
|
||||
|
||||
You can provide a colon-separated path to the JAR containing stubs of the dependency, as
|
||||
shown in the following example:
|
||||
|
||||
`stubs: org.springframework:myApp:stubs`
|
||||
|
||||
where:
|
||||
|
||||
* `org.springframework` is the `groupId`.
|
||||
* `myApp` is the `artifactId`.
|
||||
* `stubs` is the classifier. (Note that `stubs` is the default value.)
|
||||
|
||||
Because `stubs` is the default classifier, the preceding example is equal to the following
|
||||
example:
|
||||
|
||||
`stubs: org.springframework:myApp`
|
||||
|
||||
[[spring-cloud-zookeeper-dependencies-configuring]]
|
||||
=== Configuring Spring Cloud Zookeeper Dependencies
|
||||
|
||||
You can set the following properties to enable or disable parts of Zookeeper Dependencies functionalities:
|
||||
|
||||
* `spring.cloud.zookeeper.dependencies`: If you do not set this property, you cannot use Zookeeper Dependencies.
|
||||
* `spring.cloud.zookeeper.dependency.loadbalancer.enabled` (enabled by default): Turns on Zookeeper-specific custom load-balancing strategies, including `ZookeeperServiceInstanceListSupplier` and dependency-based load-balanced `RestTemplate` setup.
|
||||
* `spring.cloud.zookeeper.dependency.headers.enabled` (enabled by default): This property registers a `FeignBlockingLoadBalancerClient` that automatically appends appropriate headers and content types with their versions, as presented in the Dependency configuration.
|
||||
Without this setting, those two parameters do not work.
|
||||
* `spring.cloud.zookeeper.dependency.resttemplate.enabled` (enabled by default): When enabled, this property modifies the request headers of a `@LoadBalanced`-annotated
|
||||
`RestTemplate` such that it passes headers and content type with the version set in dependency configuration.
|
||||
Without this setting, those two parameters do not work.
|
||||
|
||||
[[spring-cloud-zookeeper-dependency-watcher]]
|
||||
== Spring Cloud Zookeeper Dependency Watcher
|
||||
|
||||
The Dependency Watcher mechanism lets you register listeners to your dependencies. The
|
||||
functionality is, in fact, an implementation of the `Observator` pattern. When a
|
||||
dependency changes, its state (to either UP or DOWN), some custom logic can be applied.
|
||||
|
||||
[[activating]]
|
||||
=== Activating
|
||||
|
||||
Spring Cloud Zookeeper Dependencies functionality needs to be enabled for you to use the
|
||||
Dependency Watcher mechanism.
|
||||
// TODO: How can the reader do that?
|
||||
|
||||
[[registering-a-listener]]
|
||||
=== Registering a Listener
|
||||
|
||||
To register a listener, you must implement an interface called
|
||||
`org.springframework.cloud.zookeeper.discovery.watcher.DependencyWatcherListener` and
|
||||
register it as a bean. The interface gives you one method:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
void stateChanged(String dependencyName, DependencyState newState);
|
||||
----
|
||||
|
||||
If you want to register a listener for a particular dependency, the `dependencyName` would
|
||||
be the discriminator for your concrete implementation. `newState` provides you with
|
||||
information about whether your dependency has changed to `CONNECTED` or `DISCONNECTED`.
|
||||
|
||||
[[spring-cloud-zookeeper-dependency-watcher-presence-checker]]
|
||||
=== Using the Presence Checker
|
||||
|
||||
Bound with the Dependency Watcher is the functionality called Presence Checker. It lets
|
||||
you provide custom behavior when your application boots, to react according to the state
|
||||
of your dependencies.
|
||||
|
||||
The default implementation of the abstract
|
||||
`org.springframework.cloud.zookeeper.discovery.watcher.presence.DependencyPresenceOnStartupVerifier`
|
||||
class is the
|
||||
`org.springframework.cloud.zookeeper.discovery.watcher.presence.DefaultDependencyPresenceOnStartupVerifier`,
|
||||
which works in the following way.
|
||||
|
||||
. If the dependency is marked us `required` and is not in Zookeeper, when your application
|
||||
boots, it throws an exception and shuts down.
|
||||
. If the dependency is not `required`, the
|
||||
`org.springframework.cloud.zookeeper.discovery.watcher.presence.LogMissingDependencyChecker`
|
||||
logs that the dependency is missing at the `WARN` level.
|
||||
|
||||
Because the `DefaultDependencyPresenceOnStartupVerifier` is registered only when there is
|
||||
no bean of type `DependencyPresenceOnStartupVerifier`, this functionality can be
|
||||
overridden.
|
||||
|
||||
[[spring-cloud-zookeeper-config]]
|
||||
== Distributed Configuration with Zookeeper
|
||||
|
||||
Zookeeper provides a
|
||||
https://zookeeper.apache.org/doc/current/zookeeperOver.html#sc_dataModelNameSpace[hierarchical namespace]
|
||||
that lets clients store arbitrary data, such as configuration data. Spring Cloud Zookeeper
|
||||
Config is an alternative to the
|
||||
https://github.com/spring-cloud/spring-cloud-config[Config Server and Client].
|
||||
Configuration is loaded into the Spring Environment during the special "`bootstrap`"
|
||||
phase. Configuration is stored in the `/config` namespace by default. Multiple
|
||||
`PropertySource` instances are created, based on the application's name and the active
|
||||
profiles, to mimic the Spring Cloud Config order of resolving properties. For example, an
|
||||
application with a name of `testApp` and with the `dev` profile has the following property
|
||||
sources created for it:
|
||||
|
||||
* `config/testApp,dev`
|
||||
* `config/testApp`
|
||||
* `config/application,dev`
|
||||
* `config/application`
|
||||
|
||||
The most specific property source is at the top, with the least specific at the bottom.
|
||||
Properties in the `config/application` namespace apply to all applications that use
|
||||
zookeeper for configuration. Properties in the `config/testApp` namespace are available
|
||||
only to the instances of the service named `testApp`.
|
||||
|
||||
Configuration is currently read on startup of the application. Sending a HTTP `POST`
|
||||
request to `/refresh` causes the configuration to be reloaded. Watching the configuration
|
||||
namespace (which Zookeeper supports) is not currently implemented.
|
||||
|
||||
[[activating]]
|
||||
=== Activating
|
||||
|
||||
Including a dependency on
|
||||
`org.springframework.cloud:spring-cloud-starter-zookeeper-config` enables
|
||||
autoconfiguration that sets up Spring Cloud Zookeeper Config.
|
||||
|
||||
CAUTION: When working with version 3.4 of Zookeeper you need to change
|
||||
the way you include the dependency as described <<spring-cloud-zookeeper-install,here>>.
|
||||
|
||||
[[config-data-import]]
|
||||
=== Spring Boot Config Data Import
|
||||
|
||||
Spring Boot 2.4 introduced a new way to import configuration data via the `spring.config.import` property. This is now the default way to get configuration from Zookeeper.
|
||||
|
||||
To optionally connect to Zookeeper for configuration set the following in application.properties:
|
||||
|
||||
.application.properties
|
||||
[source,properties]
|
||||
----
|
||||
spring.config.import=optional:zookeeper:
|
||||
----
|
||||
|
||||
This will connect to Zookeeper at the default location of "localhost:2181". Removing the `optional:` prefix will cause Zookeeper Config to fail if it is unable to connect to Zookeeper. To change the connection properties of Zookeeper Config either set `spring.cloud.zookeeper.connect-string` or add the connect string to the `spring.config.import` statement such as, `spring.config.import=optional:zookeeper:myhost:2818`. The location in the import property has precedence over the `connect-string` property.
|
||||
|
||||
Zookeeper Config will try to load values from four automatic contexts based on `spring.cloud.zookeeper.config.name` (which defaults to the value of the `spring.application.name` property) and `spring.cloud.zookeeper.config.default-context` (which defaults to `application`). If you want to specify the contexts rather than using the computed ones, you can add that information to the `spring.config.import` statement.
|
||||
|
||||
.application.properties
|
||||
[source,properties]
|
||||
----
|
||||
spring.config.import=optional:zookeeper:myhost:2181/contextone;/context/two
|
||||
----
|
||||
|
||||
This will optionally load configuration only from `/contextone` and `/context/two`.
|
||||
|
||||
NOTE: A `bootstrap` file (properties or yaml) is *not* needed for the Spring Boot Config Data method of import via `spring.config.import`.
|
||||
|
||||
[[customizing]]
|
||||
=== Customizing
|
||||
|
||||
Zookeeper Config may be customized by setting the following properties:
|
||||
|
||||
[source,yml,indent=0]
|
||||
----
|
||||
spring:
|
||||
cloud:
|
||||
zookeeper:
|
||||
config:
|
||||
enabled: true
|
||||
root: configuration
|
||||
defaultContext: apps
|
||||
profileSeparator: '::'
|
||||
----
|
||||
|
||||
* `enabled`: Setting this value to `false` disables Zookeeper Config.
|
||||
* `root`: Sets the base namespace for configuration values.
|
||||
* `defaultContext`: Sets the name used by all applications.
|
||||
* `profileSeparator`: Sets the value of the separator used to separate the profile name in
|
||||
property sources with profiles.
|
||||
|
||||
CAUTION: If you have set `spring.cloud.bootstrap.enabled=true` or `spring.config.use-legacy-processing=true`, or included `spring-cloud-starter-bootstrap`, then the above values will need to be placed in `bootstrap.yml` instead of `application.yml`.
|
||||
|
||||
[[access-control-lists-acls]]
|
||||
=== Access Control Lists (ACLs)
|
||||
|
||||
You can add authentication information for Zookeeper ACLs by calling the `addAuthInfo`
|
||||
method of a `CuratorFramework` bean. One way to accomplish this is to provide your own
|
||||
`CuratorFramework` bean, as shown in the following example:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@BoostrapConfiguration
|
||||
public class CustomCuratorFrameworkConfig {
|
||||
|
||||
@Bean
|
||||
public CuratorFramework curatorFramework() {
|
||||
CuratorFramework curator = new CuratorFramework();
|
||||
curator.addAuthInfo("digest", "user:password".getBytes());
|
||||
return curator;
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
Consult
|
||||
https://github.com/spring-cloud/spring-cloud-zookeeper/blob/master/spring-cloud-zookeeper-core/src/main/java/org/springframework/cloud/zookeeper/ZookeeperAutoConfiguration.java[the ZookeeperAutoConfiguration class]
|
||||
to see how the `CuratorFramework` bean's default configuration.
|
||||
|
||||
Alternatively, you can add your credentials from a class that depends on the existing
|
||||
`CuratorFramework` bean, as shown in the following example:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@BoostrapConfiguration
|
||||
public class DefaultCuratorFrameworkConfig {
|
||||
|
||||
public ZookeeperConfig(CuratorFramework curator) {
|
||||
curator.addAuthInfo("digest", "user:password".getBytes());
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
The creation of this bean must occur during the boostrapping phase. You can register
|
||||
configuration classes to run during this phase by annotating them with
|
||||
`@BootstrapConfiguration` and including them in a comma-separated list that you set as the
|
||||
value of the `org.springframework.cloud.bootstrap.BootstrapConfiguration` property in the
|
||||
`resources/META-INF/spring.factories` file, as shown in the following example:
|
||||
|
||||
.resources/META-INF/spring.factories
|
||||
----
|
||||
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
|
||||
my.project.CustomCuratorFrameworkConfig,\
|
||||
my.project.DefaultCuratorFrameworkConfig
|
||||
----
|
||||
|
||||
143
docs/modules/ROOT/pages/spring-cloud-zookeeper/config.adoc
Normal file
143
docs/modules/ROOT/pages/spring-cloud-zookeeper/config.adoc
Normal file
@@ -0,0 +1,143 @@
|
||||
[[spring-cloud-zookeeper-config]]
|
||||
= Distributed Configuration with Zookeeper
|
||||
|
||||
Zookeeper provides a
|
||||
https://zookeeper.apache.org/doc/current/zookeeperOver.html#sc_dataModelNameSpace[hierarchical namespace]
|
||||
that lets clients store arbitrary data, such as configuration data. Spring Cloud Zookeeper
|
||||
Config is an alternative to the
|
||||
https://github.com/spring-cloud/spring-cloud-config[Config Server and Client].
|
||||
Configuration is loaded into the Spring Environment during the special "`bootstrap`"
|
||||
phase. Configuration is stored in the `/config` namespace by default. Multiple
|
||||
`PropertySource` instances are created, based on the application's name and the active
|
||||
profiles, to mimic the Spring Cloud Config order of resolving properties. For example, an
|
||||
application with a name of `testApp` and with the `dev` profile has the following property
|
||||
sources created for it:
|
||||
|
||||
* `config/testApp,dev`
|
||||
* `config/testApp`
|
||||
* `config/application,dev`
|
||||
* `config/application`
|
||||
|
||||
The most specific property source is at the top, with the least specific at the bottom.
|
||||
Properties in the `config/application` namespace apply to all applications that use
|
||||
zookeeper for configuration. Properties in the `config/testApp` namespace are available
|
||||
only to the instances of the service named `testApp`.
|
||||
|
||||
Configuration is currently read on startup of the application. Sending a HTTP `POST`
|
||||
request to `/refresh` causes the configuration to be reloaded. Watching the configuration
|
||||
namespace (which Zookeeper supports) is not currently implemented.
|
||||
|
||||
[[activating]]
|
||||
== Activating
|
||||
|
||||
Including a dependency on
|
||||
`org.springframework.cloud:spring-cloud-starter-zookeeper-config` enables
|
||||
autoconfiguration that sets up Spring Cloud Zookeeper Config.
|
||||
|
||||
CAUTION: When working with version 3.4 of Zookeeper you need to change
|
||||
the way you include the dependency as described <<spring-cloud-zookeeper-install,here>>.
|
||||
|
||||
[[config-data-import]]
|
||||
== Spring Boot Config Data Import
|
||||
|
||||
Spring Boot 2.4 introduced a new way to import configuration data via the `spring.config.import` property. This is now the default way to get configuration from Zookeeper.
|
||||
|
||||
To optionally connect to Zookeeper for configuration set the following in application.properties:
|
||||
|
||||
.application.properties
|
||||
[source,properties]
|
||||
----
|
||||
spring.config.import=optional:zookeeper:
|
||||
----
|
||||
|
||||
This will connect to Zookeeper at the default location of "localhost:2181". Removing the `optional:` prefix will cause Zookeeper Config to fail if it is unable to connect to Zookeeper. To change the connection properties of Zookeeper Config either set `spring.cloud.zookeeper.connect-string` or add the connect string to the `spring.config.import` statement such as, `spring.config.import=optional:zookeeper:myhost:2818`. The location in the import property has precedence over the `connect-string` property.
|
||||
|
||||
Zookeeper Config will try to load values from four automatic contexts based on `spring.cloud.zookeeper.config.name` (which defaults to the value of the `spring.application.name` property) and `spring.cloud.zookeeper.config.default-context` (which defaults to `application`). If you want to specify the contexts rather than using the computed ones, you can add that information to the `spring.config.import` statement.
|
||||
|
||||
.application.properties
|
||||
[source,properties]
|
||||
----
|
||||
spring.config.import=optional:zookeeper:myhost:2181/contextone;/context/two
|
||||
----
|
||||
|
||||
This will optionally load configuration only from `/contextone` and `/context/two`.
|
||||
|
||||
NOTE: A `bootstrap` file (properties or yaml) is *not* needed for the Spring Boot Config Data method of import via `spring.config.import`.
|
||||
|
||||
[[customizing]]
|
||||
== Customizing
|
||||
|
||||
Zookeeper Config may be customized by setting the following properties:
|
||||
|
||||
[source,yml,indent=0]
|
||||
----
|
||||
spring:
|
||||
cloud:
|
||||
zookeeper:
|
||||
config:
|
||||
enabled: true
|
||||
root: configuration
|
||||
defaultContext: apps
|
||||
profileSeparator: '::'
|
||||
----
|
||||
|
||||
* `enabled`: Setting this value to `false` disables Zookeeper Config.
|
||||
* `root`: Sets the base namespace for configuration values.
|
||||
* `defaultContext`: Sets the name used by all applications.
|
||||
* `profileSeparator`: Sets the value of the separator used to separate the profile name in
|
||||
property sources with profiles.
|
||||
|
||||
CAUTION: If you have set `spring.cloud.bootstrap.enabled=true` or `spring.config.use-legacy-processing=true`, or included `spring-cloud-starter-bootstrap`, then the above values will need to be placed in `bootstrap.yml` instead of `application.yml`.
|
||||
|
||||
[[access-control-lists-acls]]
|
||||
== Access Control Lists (ACLs)
|
||||
|
||||
You can add authentication information for Zookeeper ACLs by calling the `addAuthInfo`
|
||||
method of a `CuratorFramework` bean. One way to accomplish this is to provide your own
|
||||
`CuratorFramework` bean, as shown in the following example:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@BoostrapConfiguration
|
||||
public class CustomCuratorFrameworkConfig {
|
||||
|
||||
@Bean
|
||||
public CuratorFramework curatorFramework() {
|
||||
CuratorFramework curator = new CuratorFramework();
|
||||
curator.addAuthInfo("digest", "user:password".getBytes());
|
||||
return curator;
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
Consult
|
||||
https://github.com/spring-cloud/spring-cloud-zookeeper/blob/master/spring-cloud-zookeeper-core/src/main/java/org/springframework/cloud/zookeeper/ZookeeperAutoConfiguration.java[the ZookeeperAutoConfiguration class]
|
||||
to see how the `CuratorFramework` bean's default configuration.
|
||||
|
||||
Alternatively, you can add your credentials from a class that depends on the existing
|
||||
`CuratorFramework` bean, as shown in the following example:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@BoostrapConfiguration
|
||||
public class DefaultCuratorFrameworkConfig {
|
||||
|
||||
public ZookeeperConfig(CuratorFramework curator) {
|
||||
curator.addAuthInfo("digest", "user:password".getBytes());
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
The creation of this bean must occur during the boostrapping phase. You can register
|
||||
configuration classes to run during this phase by annotating them with
|
||||
`@BootstrapConfiguration` and including them in a comma-separated list that you set as the
|
||||
value of the `org.springframework.cloud.bootstrap.BootstrapConfiguration` property in the
|
||||
`resources/META-INF/spring.factories` file, as shown in the following example:
|
||||
|
||||
.resources/META-INF/spring.factories
|
||||
----
|
||||
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
|
||||
my.project.CustomCuratorFrameworkConfig,\
|
||||
my.project.DefaultCuratorFrameworkConfig
|
||||
----
|
||||
208
docs/modules/ROOT/pages/spring-cloud-zookeeper/dependencies.adoc
Normal file
208
docs/modules/ROOT/pages/spring-cloud-zookeeper/dependencies.adoc
Normal file
@@ -0,0 +1,208 @@
|
||||
[[spring-cloud-zookeeper-dependencies]]
|
||||
= Zookeeper Dependencies
|
||||
|
||||
The following topics cover how to work with Spring Cloud Zookeeper dependencies:
|
||||
|
||||
* <<spring-cloud-zookeeper-dependencies-using>>
|
||||
* <<spring-cloud-zookeeper-dependencies-activating>>
|
||||
* <<spring-cloud-zookeeper-dependencies-setting-up>>
|
||||
* <<spring-cloud-zookeeper-dependencies-configuring>>
|
||||
|
||||
[[spring-cloud-zookeeper-dependencies-using]]
|
||||
== Using the Zookeeper Dependencies
|
||||
|
||||
Spring Cloud Zookeeper gives you a possibility to provide dependencies of your application
|
||||
as properties. As dependencies, you can understand other applications that are registered
|
||||
in Zookeeper and which you would like to call through
|
||||
https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-feign[Feign]
|
||||
(a REST client builder),
|
||||
https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/ascii[Spring
|
||||
`RestTemplate`] and
|
||||
https://cloud.spring.io/spring-cloud-commons/reference/html/#loadbalanced-webclient[Spring WebFlux].
|
||||
|
||||
You can also use the Zookeeper Dependency Watchers functionality to control and monitor
|
||||
the state of your dependencies.
|
||||
|
||||
[[spring-cloud-zookeeper-dependencies-activating]]
|
||||
== Activating Zookeeper Dependencies
|
||||
|
||||
Including a dependency on
|
||||
`org.springframework.cloud:spring-cloud-starter-zookeeper-discovery` enables
|
||||
autoconfiguration that sets up Spring Cloud Zookeeper Dependencies. Even if you provide
|
||||
the dependencies in your properties, you can turn off the dependencies. To do so, set the
|
||||
`spring.cloud.zookeeper.dependency.enabled` property to false (it defaults to `true`).
|
||||
|
||||
[[spring-cloud-zookeeper-dependencies-setting-up]]
|
||||
== Setting up Zookeeper Dependencies
|
||||
|
||||
Consider the following example of dependency representation:
|
||||
|
||||
[source,yml,indent=0]
|
||||
.application.yml
|
||||
----
|
||||
spring.application.name: yourServiceName
|
||||
spring.cloud.zookeeper:
|
||||
dependencies:
|
||||
newsletter:
|
||||
path: /path/where/newsletter/has/registered/in/zookeeper
|
||||
loadBalancerType: ROUND_ROBIN
|
||||
contentTypeTemplate: application/vnd.newsletter.$version+json
|
||||
version: v1
|
||||
headers:
|
||||
header1:
|
||||
- value1
|
||||
header2:
|
||||
- value2
|
||||
required: false
|
||||
stubs: org.springframework:foo:stubs
|
||||
mailing:
|
||||
path: /path/where/mailing/has/registered/in/zookeeper
|
||||
loadBalancerType: ROUND_ROBIN
|
||||
contentTypeTemplate: application/vnd.mailing.$version+json
|
||||
version: v1
|
||||
required: true
|
||||
----
|
||||
|
||||
The next few sections go through each part of the dependency one by one. The root property
|
||||
name is `spring.cloud.zookeeper.dependencies`.
|
||||
|
||||
[[spring-cloud-zookeeper-dependencies-setting-up-aliases]]
|
||||
=== Aliases
|
||||
|
||||
Below the root property you have to represent each dependency as an alias.
|
||||
This is due to the constraints of Spring Cloud LoadBalancer, which requires that the application ID be placed in the URL.
|
||||
Consequently, you cannot pass any complex path, suchas `/myApp/myRoute/name`).
|
||||
The alias is the name you use instead of the `serviceId` for `DiscoveryClient`, `Feign`, or
|
||||
`RestTemplate`.
|
||||
|
||||
In the previous examples, the aliases are `newsletter` and `mailing`.
|
||||
The following example shows Feign usage with a `newsletter` alias:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@FeignClient("newsletter")
|
||||
public interface NewsletterService {
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/newsletter")
|
||||
String getNewsletters();
|
||||
}
|
||||
----
|
||||
|
||||
[[path]]
|
||||
=== Path
|
||||
|
||||
The path is represented by the `path` YAML property and is the path under which the dependency is registered under Zookeeper.
|
||||
As described in the
|
||||
<<spring-cloud-zookeeper-dependencies-setting-up-aliases,previous section>>, Spring Cloud LoadBalancer operates on URLs.
|
||||
As a result, this path is not compliant with its requirement.
|
||||
That is why Spring Cloud Zookeeper maps the alias to the proper path.
|
||||
|
||||
[[load-balancer-type]]
|
||||
=== Load Balancer Type
|
||||
|
||||
The load balancer type is represented by `loadBalancerType` YAML property.
|
||||
|
||||
If you know what kind of load-balancing strategy has to be applied when calling this particular dependency, you can provide it in the YAML file, and it is automatically applied.
|
||||
You can choose one of the following load balancing strategies:
|
||||
|
||||
* STICKY: Once chosen, the instance is always called.
|
||||
* RANDOM: Picks an instance randomly.
|
||||
* ROUND_ROBIN: Iterates over instances over and over again.
|
||||
|
||||
[[content-type-template-and-version]]
|
||||
=== `Content-Type` Template and Version
|
||||
|
||||
The `Content-Type` template and version are represented by the `contentTypeTemplate` and
|
||||
`version` YAML properties.
|
||||
|
||||
If you version your API in the `Content-Type` header, you do not want to add this header
|
||||
to each of your requests. Also, if you want to call a new version of the API, you do not
|
||||
want to roam around your code to bump up the API version. That is why you can provide a
|
||||
`contentTypeTemplate` with a special `$version` placeholder. That placeholder will be filled by the value of the
|
||||
`version` YAML property. Consider the following example of a `contentTypeTemplate`:
|
||||
|
||||
----
|
||||
application/vnd.newsletter.$version+json
|
||||
----
|
||||
|
||||
Further consider the following `version`:
|
||||
|
||||
----
|
||||
v1
|
||||
----
|
||||
|
||||
The combination of `contentTypeTemplate` and version results in the creation of a
|
||||
`Content-Type` header for each request, as follows:
|
||||
|
||||
----
|
||||
application/vnd.newsletter.v1+json
|
||||
----
|
||||
|
||||
[[default-headers]]
|
||||
=== Default Headers
|
||||
|
||||
Default headers are represented by the `headers` map in YAML.
|
||||
|
||||
Sometimes, each call to a dependency requires setting up of some default headers. To not
|
||||
do that in code, you can set them up in the YAML file, as shown in the following example
|
||||
`headers` section:
|
||||
|
||||
[source,yml,indent=0]
|
||||
----
|
||||
headers:
|
||||
Accept:
|
||||
- text/html
|
||||
- application/xhtml+xml
|
||||
Cache-Control:
|
||||
- no-cache
|
||||
----
|
||||
|
||||
That `headers` section results in adding the `Accept` and `Cache-Control` headers with
|
||||
appropriate list of values in your HTTP request.
|
||||
|
||||
[[required-dependencies]]
|
||||
=== Required Dependencies
|
||||
|
||||
Required dependencies are represented by `required` property in YAML.
|
||||
|
||||
If one of your dependencies is required to be up when your application boots, you can set
|
||||
the `required: true` property in the YAML file.
|
||||
|
||||
If your application cannot localize the required dependency during boot time, it throws an
|
||||
exception, and the Spring Context fails to set up. In other words, your application cannot
|
||||
start if the required dependency is not registered in Zookeeper.
|
||||
|
||||
You can read more about Spring Cloud Zookeeper Presence Checker
|
||||
<<spring-cloud-zookeeper-dependency-watcher-presence-checker,later in this document>>.
|
||||
|
||||
[[stubs]]
|
||||
=== Stubs
|
||||
|
||||
You can provide a colon-separated path to the JAR containing stubs of the dependency, as
|
||||
shown in the following example:
|
||||
|
||||
`stubs: org.springframework:myApp:stubs`
|
||||
|
||||
where:
|
||||
|
||||
* `org.springframework` is the `groupId`.
|
||||
* `myApp` is the `artifactId`.
|
||||
* `stubs` is the classifier. (Note that `stubs` is the default value.)
|
||||
|
||||
Because `stubs` is the default classifier, the preceding example is equal to the following
|
||||
example:
|
||||
|
||||
`stubs: org.springframework:myApp`
|
||||
|
||||
[[spring-cloud-zookeeper-dependencies-configuring]]
|
||||
== Configuring Spring Cloud Zookeeper Dependencies
|
||||
|
||||
You can set the following properties to enable or disable parts of Zookeeper Dependencies functionalities:
|
||||
|
||||
* `spring.cloud.zookeeper.dependencies`: If you do not set this property, you cannot use Zookeeper Dependencies.
|
||||
* `spring.cloud.zookeeper.dependency.loadbalancer.enabled` (enabled by default): Turns on Zookeeper-specific custom load-balancing strategies, including `ZookeeperServiceInstanceListSupplier` and dependency-based load-balanced `RestTemplate` setup.
|
||||
* `spring.cloud.zookeeper.dependency.headers.enabled` (enabled by default): This property registers a `FeignBlockingLoadBalancerClient` that automatically appends appropriate headers and content types with their versions, as presented in the Dependency configuration.
|
||||
Without this setting, those two parameters do not work.
|
||||
* `spring.cloud.zookeeper.dependency.resttemplate.enabled` (enabled by default): When enabled, this property modifies the request headers of a `@LoadBalanced`-annotated
|
||||
`RestTemplate` such that it passes headers and content type with the version set in dependency configuration.
|
||||
Without this setting, those two parameters do not work.
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
[[spring-cloud-zookeeper-dependency-watcher]]
|
||||
= Spring Cloud Zookeeper Dependency Watcher
|
||||
|
||||
The Dependency Watcher mechanism lets you register listeners to your dependencies. The
|
||||
functionality is, in fact, an implementation of the `Observator` pattern. When a
|
||||
dependency changes, its state (to either UP or DOWN), some custom logic can be applied.
|
||||
|
||||
[[activating]]
|
||||
== Activating
|
||||
|
||||
Spring Cloud Zookeeper Dependencies functionality needs to be enabled for you to use the
|
||||
Dependency Watcher mechanism.
|
||||
// TODO: How can the reader do that?
|
||||
|
||||
[[registering-a-listener]]
|
||||
== Registering a Listener
|
||||
|
||||
To register a listener, you must implement an interface called
|
||||
`org.springframework.cloud.zookeeper.discovery.watcher.DependencyWatcherListener` and
|
||||
register it as a bean. The interface gives you one method:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
void stateChanged(String dependencyName, DependencyState newState);
|
||||
----
|
||||
|
||||
If you want to register a listener for a particular dependency, the `dependencyName` would
|
||||
be the discriminator for your concrete implementation. `newState` provides you with
|
||||
information about whether your dependency has changed to `CONNECTED` or `DISCONNECTED`.
|
||||
|
||||
[[spring-cloud-zookeeper-dependency-watcher-presence-checker]]
|
||||
== Using the Presence Checker
|
||||
|
||||
Bound with the Dependency Watcher is the functionality called Presence Checker. It lets
|
||||
you provide custom behavior when your application boots, to react according to the state
|
||||
of your dependencies.
|
||||
|
||||
The default implementation of the abstract
|
||||
`org.springframework.cloud.zookeeper.discovery.watcher.presence.DependencyPresenceOnStartupVerifier`
|
||||
class is the
|
||||
`org.springframework.cloud.zookeeper.discovery.watcher.presence.DefaultDependencyPresenceOnStartupVerifier`,
|
||||
which works in the following way.
|
||||
|
||||
. If the dependency is marked us `required` and is not in Zookeeper, when your application
|
||||
boots, it throws an exception and shuts down.
|
||||
. If the dependency is not `required`, the
|
||||
`org.springframework.cloud.zookeeper.discovery.watcher.presence.LogMissingDependencyChecker`
|
||||
logs that the dependency is missing at the `WARN` level.
|
||||
|
||||
Because the `DefaultDependencyPresenceOnStartupVerifier` is registered only when there is
|
||||
no bean of type `DependencyPresenceOnStartupVerifier`, this functionality can be
|
||||
overridden.
|
||||
|
||||
105
docs/modules/ROOT/pages/spring-cloud-zookeeper/discovery.adoc
Normal file
105
docs/modules/ROOT/pages/spring-cloud-zookeeper/discovery.adoc
Normal file
@@ -0,0 +1,105 @@
|
||||
[[spring-cloud-zookeeper-discovery]]
|
||||
= Service Discovery with Zookeeper
|
||||
|
||||
Service Discovery is one of the key tenets of a microservice based architecture. Trying to
|
||||
hand-configure each client or some form of convention can be difficult to do and can be
|
||||
brittle. https://curator.apache.org[Curator](A Java library for Zookeeper) provides Service
|
||||
Discovery through a https://curator.apache.org/curator-x-discovery/[Service Discovery
|
||||
Extension]. Spring Cloud Zookeeper uses this extension for service registration and
|
||||
discovery.
|
||||
|
||||
[[activating]]
|
||||
== Activating
|
||||
|
||||
Including a dependency on
|
||||
`org.springframework.cloud:spring-cloud-starter-zookeeper-discovery` enables
|
||||
autoconfiguration that sets up Spring Cloud Zookeeper Discovery.
|
||||
|
||||
NOTE: For web functionality, you still need to include
|
||||
`org.springframework.boot:spring-boot-starter-web`.
|
||||
|
||||
CAUTION: When working with version 3.4 of Zookeeper you need to change
|
||||
the way you include the dependency as described <<spring-cloud-zookeeper-install,here>>.
|
||||
|
||||
[[registering-with-zookeeper]]
|
||||
== Registering with Zookeeper
|
||||
|
||||
When a client registers with Zookeeper, it provides metadata (such as host and port, ID,
|
||||
and name) about itself.
|
||||
|
||||
The following example shows a Zookeeper client:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@SpringBootApplication
|
||||
@RestController
|
||||
public class Application {
|
||||
|
||||
@RequestMapping("/")
|
||||
public String home() {
|
||||
return "Hello world";
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(Application.class).web(true).run(args);
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
NOTE: The preceding example is a normal Spring Boot application.
|
||||
|
||||
If Zookeeper is located somewhere other than `localhost:2181`, the configuration must
|
||||
provide the location of the server, as shown in the following example:
|
||||
|
||||
[source,yml,indent=0]
|
||||
.application.yml
|
||||
----
|
||||
spring:
|
||||
cloud:
|
||||
zookeeper:
|
||||
connect-string: localhost:2181
|
||||
----
|
||||
|
||||
CAUTION: If you use <<spring-cloud-zookeeper-config,Spring Cloud Zookeeper Config>>, the
|
||||
values shown in the preceding example need to be in `bootstrap.yml` instead of
|
||||
`application.yml`.
|
||||
|
||||
The default service name, instance ID, and port (taken from the `Environment`) are
|
||||
`${spring.application.name}`, the Spring Context ID, and `${server.port}`, respectively.
|
||||
|
||||
Having `spring-cloud-starter-zookeeper-discovery` on the classpath makes the app into both
|
||||
a Zookeeper "`service`" (that is, it registers itself) and a "`client`" (that is, it can
|
||||
query Zookeeper to locate other services).
|
||||
|
||||
If you would like to disable the Zookeeper Discovery Client, you can set
|
||||
`spring.cloud.zookeeper.discovery.enabled` to `false`.
|
||||
|
||||
[[using-the-discoveryclient]]
|
||||
== Using the DiscoveryClient
|
||||
|
||||
Spring Cloud has support for
|
||||
https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc#spring-cloud-feign[Feign]
|
||||
(a REST client builder),
|
||||
https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/ascii[Spring
|
||||
`RestTemplate`] and
|
||||
https://cloud.spring.io/spring-cloud-commons/reference/html/#loadbalanced-webclient[Spring WebFlux], using logical service names instead of physical URLs.
|
||||
|
||||
You can also use the `org.springframework.cloud.client.discovery.DiscoveryClient`, which
|
||||
provides a simple API for discovery clients that is not specific to Netflix, as shown in
|
||||
the following example:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@Autowired
|
||||
private DiscoveryClient discoveryClient;
|
||||
|
||||
public String serviceUrl() {
|
||||
List<ServiceInstance> list = discoveryClient.getInstances("STORES");
|
||||
if (list != null && list.size() > 0 ) {
|
||||
return list.get(0).getUri().toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
----
|
||||
|
||||
54
docs/modules/ROOT/pages/spring-cloud-zookeeper/install.adoc
Normal file
54
docs/modules/ROOT/pages/spring-cloud-zookeeper/install.adoc
Normal file
@@ -0,0 +1,54 @@
|
||||
[[spring-cloud-zookeeper-install]]
|
||||
= Install Zookeeper
|
||||
|
||||
See the https://zookeeper.apache.org/doc/current/zookeeperStarted.html[installation
|
||||
documentation] for instructions on how to install Zookeeper.
|
||||
|
||||
Spring Cloud Zookeeper uses Apache Curator behind the scenes.
|
||||
While Zookeeper 3.5.x is still considered "beta" by the Zookeeper development team,
|
||||
the reality is that it is used in production by many users.
|
||||
However, Zookeeper 3.4.x is also used in production.
|
||||
Prior to Apache Curator 4.0, both versions of Zookeeper were supported via two versions of Apache Curator.
|
||||
Starting with Curator 4.0 both versions of Zookeeper are supported via the same Curator libraries.
|
||||
|
||||
In case you are integrating with version 3.4 you need to change the Zookeeper dependency
|
||||
that comes shipped with `curator`, and thus `spring-cloud-zookeeper`.
|
||||
To do so simply exclude that dependency and add the 3.4.x version like shown below.
|
||||
|
||||
.maven
|
||||
[source,xml,indent=0]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-zookeeper-all</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.zookeeper</groupId>
|
||||
<artifactId>zookeeper</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.zookeeper</groupId>
|
||||
<artifactId>zookeeper</artifactId>
|
||||
<version>3.4.12</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
.gradle
|
||||
[source,groovy,indent=0]
|
||||
----
|
||||
compile('org.springframework.cloud:spring-cloud-starter-zookeeper-all') {
|
||||
exclude group: 'org.apache.zookeeper', module: 'zookeeper'
|
||||
}
|
||||
compile('org.apache.zookeeper:zookeeper:3.4.12') {
|
||||
exclude group: 'org.slf4j', module: 'slf4j-log4j12'
|
||||
}
|
||||
----
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
[[spring-cloud-zookeeper-other-componentes]]
|
||||
= Using Spring Cloud Zookeeper with Spring Cloud Components
|
||||
|
||||
Feign, Spring Cloud Gateway and Spring Cloud LoadBalancer all work with Spring Cloud Zookeeper.
|
||||
|
||||
[[spring-cloud-loadbalancer-with-zookeeper]]
|
||||
== Spring Cloud LoadBalancer with Zookeeper
|
||||
|
||||
Spring Cloud Zookeeper provides an implementation of Spring Cloud LoadBalancer `ServiceInstanceListSupplier`.
|
||||
When you use the `spring-cloud-starter-zookeeper-discovery`, Spring Cloud LoadBalancer is autoconfigured to use the
|
||||
`ZookeeperServiceInstanceListSupplier` by default.
|
||||
|
||||
TIP: If you were previously using the StickyRule in Zookeeper, its replacement in the current stack
|
||||
is the `SameInstancePreferenceServiceInstanceListSupplier` in SC LoadBalancer. You can read on how to set it up in the https://docs.spring.io/spring-cloud-commons/docs/current/reference/html/#spring-cloud-loadbalancer[Spring Cloud Commons documentation].
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
[[quick-start]]
|
||||
= Quick Start
|
||||
|
||||
include:../:quickstart.adoc[]
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
[[spring-cloud-zookeeper-service-registry]]
|
||||
= Spring Cloud Zookeeper and Service Registry
|
||||
|
||||
Spring Cloud Zookeeper implements the `ServiceRegistry` interface, letting developers
|
||||
register arbitrary services in a programmatic way.
|
||||
|
||||
The `ServiceInstanceRegistration` class offers a `builder()` method to create a
|
||||
`Registration` object that can be used by the `ServiceRegistry`, as shown in the following
|
||||
example:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@Autowired
|
||||
private ZookeeperServiceRegistry serviceRegistry;
|
||||
|
||||
public void registerThings() {
|
||||
ZookeeperRegistration registration = ServiceInstanceRegistration.builder()
|
||||
.defaultUriSpec()
|
||||
.address("anyUrl")
|
||||
.port(10)
|
||||
.name("/a/b/c/d/anotherservice")
|
||||
.build();
|
||||
this.serviceRegistry.register(registration);
|
||||
}
|
||||
----
|
||||
|
||||
[[instance-status]]
|
||||
== Instance Status
|
||||
|
||||
Netflix Eureka supports having instances that are `OUT_OF_SERVICE` registered with the server.
|
||||
These instances are not returned as active service instances.
|
||||
This is useful for behaviors such as blue/green deployments.
|
||||
(Note that the Curator Service Discovery recipe does not support this behavior.) Taking advantage of the flexible payload has let Spring Cloud Zookeeper implement `OUT_OF_SERVICE` by updating some specific metadata and then filtering on that metadata in the Spring Cloud LoadBalancer `ZookeeperServiceInstanceListSupplier`.
|
||||
The `ZookeeperServiceInstanceListSupplier` filters out all non-null instance statuses that do not equal `UP`.
|
||||
If the instance status field is empty, it is considered to be `UP` for backwards compatibility.
|
||||
To change the status of an instance, make a `POST` with `OUT_OF_SERVICE` to the `ServiceRegistry`
|
||||
instance status actuator endpoint, as shown in the following example:
|
||||
|
||||
[source,sh,indent=0]
|
||||
----
|
||||
$ http POST http://localhost:8081/service-registry status=OUT_OF_SERVICE
|
||||
----
|
||||
|
||||
NOTE: The preceding example uses the `http` command from https://httpie.org.
|
||||
|
||||
Reference in New Issue
Block a user