856 lines
33 KiB
HTML
856 lines
33 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta name="generator" content="Asciidoctor 1.5.1">
|
|
<title>Spring Cloud</title>
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic|Noto+Serif:400,400italic,700,700italic|Droid+Sans+Mono:400">
|
|
<link rel="stylesheet" href="./asciidoctor.css">
|
|
</head>
|
|
<body class="book toc2 toc-left">
|
|
<div id="header">
|
|
<h1>Spring Cloud</h1>
|
|
<div id="toc" class="toc2">
|
|
<div id="toctitle">Table of Contents</div>
|
|
<ul class="sectlevel1">
|
|
<li><a href="#_features">Features</a></li>
|
|
<li><a href="#_spring_cloud_config">Spring Cloud Config</a>
|
|
<ul class="sectlevel1">
|
|
<li><a href="#_quick_start">Quick Start</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#_client_side_usage">Client Side Usage</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#_spring_cloud_config_server">Spring Cloud Config Server</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#_encryption_and_decryption">Encryption and Decryption</a></li>
|
|
<li><a href="#_key_management">Key Management</a></li>
|
|
<li><a href="#_creating_a_key_store_for_testing">Creating a Key Store for Testing</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#_spring_cloud_config_client">Spring Cloud Config Client</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#_environment_changes">Environment Changes</a></li>
|
|
<li><a href="#_refresh_scope">Refresh Scope</a></li>
|
|
<li><a href="#_encryption_and_decryption_2">Encryption and Decryption</a></li>
|
|
<li><a href="#_endpoints">Endpoints</a></li>
|
|
<li><a href="#_the_bootstrap_application_context">The Bootstrap Application Context</a></li>
|
|
<li><a href="#_customizing_the_bootstrap">Customizing the Bootstrap</a></li>
|
|
<li><a href="#_customizing_the_property_sources">Customizing the Property Sources</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#_spring_cloud_netflix">Spring Cloud Netflix</a>
|
|
<ul class="sectlevel1">
|
|
<li><a href="#_service_discovery_eureka_clients">Service Discovery: Eureka Clients</a></li>
|
|
<li><a href="#_service_discovery_eureka_server">Service Discovery: Eureka Server</a></li>
|
|
<li><a href="#_circuit_breaker_hystrix_clients">Circuit Breaker: Hystrix Clients</a></li>
|
|
<li><a href="#_circuit_breaker_hystrix_dashboard">Circuit Breaker: Hystrix Dashboard</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#_turbine">Turbine</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#_declarative_rest_client_feign">Declarative REST Client: Feign</a></li>
|
|
<li><a href="#_client_side_load_balancer_ribbon">Client Side Load Balancer: Ribbon</a></li>
|
|
<li><a href="#_external_configuration_archaius">External Configuration: Archaius</a></li>
|
|
<li><a href="#_router_and_filter_zuul">Router and Filter: Zuul</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#_spring_cloud_cluster">Spring Cloud Cluster</a></li>
|
|
<li><a href="#_spring_platform_bus">Spring Platform Bus</a>
|
|
<ul class="sectlevel1">
|
|
<li><a href="#_quick_start_2">Quick Start</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#_spring_cloud_for_cloud_foundry">Spring Cloud for Cloud Foundry</a>
|
|
<ul class="sectlevel1">
|
|
<li><a href="#_service_broker_example">Service Broker Example</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div id="content">
|
|
<div id="preamble">
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>Spring Cloud provides tools for developers to quickly build some of
|
|
the common patterns in distributed systems (e.g. configuration
|
|
management, service discovery, circuit breakers, intelligent routing,
|
|
micro-proxy, control bus, one-time tokens, global locks, leadership
|
|
election, distributed sessions, cluster state). Coordination of
|
|
distributed systems leads to boiler plate patterns, and using Spring
|
|
Cloud developers can quickly stand up services and applications that
|
|
implement those patterns. They will work well in any distributed
|
|
environment, including the developer’s own laptop, bare metal data
|
|
centres, and managed platforms such as Cloud Foundry.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_features">Features</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>Spring Cloud focuses on providing good out of box experience for typical use cases and extensibility mechanism to cover others.</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Distributed/versioned configuration</p>
|
|
</li>
|
|
<li>
|
|
<p>Service registration and discovery</p>
|
|
</li>
|
|
<li>
|
|
<p>Routing</p>
|
|
</li>
|
|
<li>
|
|
<p>Service-to-service calls</p>
|
|
</li>
|
|
<li>
|
|
<p>Load balancing</p>
|
|
</li>
|
|
<li>
|
|
<p>Circuit Breakers</p>
|
|
</li>
|
|
<li>
|
|
<p>Global locks</p>
|
|
</li>
|
|
<li>
|
|
<p>Leadership election and cluster state</p>
|
|
</li>
|
|
<li>
|
|
<p>Distributed messaging</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<h1 id="_spring_cloud_config" class="sect0">Spring Cloud Config</h1>
|
|
<div class="openblock partintro">
|
|
<div class="content">
|
|
Spring Cloud Config provides server and client-side support for externalized configuration in a distributed system. With the Config Server you have a central place to manage external properties for applications across all environments. The concepts on both client and server map identically to the Spring <code>Environment</code> and <code>PropertySource</code> abstractions, so they fit very well with Spring applications, but can be used with any application running in any language. As an application moves through the deployment pipeline from dev to test and into production you can manage the configuration between those environments and be certain that applications have everything they need to run when they migrate. The default implementation of the server storage backend uses git so it easily supports labelled versions of configuration environments, as well as being accessible to a wide range of tooling for managing the content. It is easy to add alternative implementations and plug them in with Spring configuration.
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_quick_start">Quick Start</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>Start the server:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>$ cd spring-cloud-config-server
|
|
$ mvn spring-boot:run</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The server is a Spring Boot application so you can build the jar file
|
|
and run that (<code>java -jar …​</code>) or pull it down from a Maven
|
|
repository. Then try it out as a client:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>$ curl localhost:8888/foo/development
|
|
{"name":"development","label":"master","propertySources":[
|
|
{"name":"https://github.com/scratches/config-repo/foo-development.properties","source":{"bar":"spam"}},
|
|
{"name":"https://github.com/scratches/config-repo/foo.properties","source":{"foo":"bar"}}
|
|
]}</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The default strategy for locating property sources is to clone a git
|
|
repository (at "spring.platform.config.server.uri") and use it to
|
|
initialize a mini <code>SpringApplication</code>. The mini-application’s
|
|
<code>Environment</code> is used to enumerate property sources and publish them
|
|
via a JSON endpoint. The service has resources in the form:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>/{application}/{profile}[/{label}]</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>where the "application" is injected as the "spring.config.name" in the
|
|
<code>SpringApplication</code> (i.e. what is normally "application" in a regular
|
|
Spring Boot app), "profile" is an active profile (or comma-separated
|
|
list of properties), and "label" is an optional git label (defaults to
|
|
"master").</p>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="_client_side_usage">Client Side Usage</h3>
|
|
<div class="paragraph">
|
|
<p>To use these features in an application, just build it as a Spring
|
|
Boot application that depends on spring-cloud-config-client (e.g. see
|
|
the test cases for the config-client, or the sample app). The most
|
|
convenient way to add the dependency is via a Spring Boot starter
|
|
<code>org.springframework.cloud:spring-cloud-starter</code>. There is also a
|
|
parent pom and BOM (<code>spring-cloud-starters</code>) for Maven users and a
|
|
Spring IO version management properties file for Gradle and Spring CLI
|
|
users. Example Maven configuration:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="title">pom.xml</div>
|
|
<div class="content">
|
|
<pre class="highlight"><code class="language-xml" data-lang="xml"><parent>
|
|
<groupId>org.springframework.boot</groupId>
|
|
<artifactId>spring-boot-starter-parent</artifactId>
|
|
<version>1.1.7.RELEASE</version>
|
|
<relativePath /> <!-- lookup parent from repository -->
|
|
</parent>
|
|
|
|
<dependencyManagement>
|
|
<dependencies>
|
|
<dependency>
|
|
<groupId>org.springframework.cloud</groupId>
|
|
<artifactId>spring-cloud-starters</artifactId>
|
|
<version>1.0.0.BUILD-SNAPSHOT</version>
|
|
<type>pom</type>
|
|
<scope>import</scope>
|
|
</dependency>
|
|
</dependencies>
|
|
</dependencyManagement>
|
|
|
|
<dependencies>
|
|
<dependency>
|
|
<groupId>org.springframework.cloud</groupId>
|
|
<artifactId>spring-cloud-starter</artifactId>
|
|
</dependency>
|
|
<dependency>
|
|
<groupId>org.springframework.boot</groupId>
|
|
<artifactId>spring-boot-starter-test</artifactId>
|
|
<scope>test</scope>
|
|
</dependency>
|
|
</dependencies>
|
|
|
|
<build>
|
|
<plugins>
|
|
<plugin>
|
|
<groupId>org.springframework.boot</groupId>
|
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
|
</plugin>
|
|
</plugins>
|
|
</build>
|
|
|
|
<!-- repositories also needed for snapshots and milestones --></code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Then you can create a standard Spring Boot application, like this simple HTTP server:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>@Configuration
|
|
@EnableAutoConfiguration
|
|
@RestController
|
|
public class Application {
|
|
|
|
@RequestMapping("/")
|
|
public String home() {
|
|
return "Hello World!";
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
SpringApplication.run(Application.class, args);
|
|
}
|
|
|
|
}</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When it runs it will pick up the external configuration from the
|
|
default local config server on port 8888 if it is running. To modify
|
|
the startup behaviour you can change the location of the config server
|
|
using <code>bootstrap.properties</code> (like <code>application.properties</code> but for
|
|
the bootstrap phase of an application context), e.g.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>spring.cloud.config.uri: http://myconfigserver.com</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The bootstrap properties will show up in the <code>/env</code> endpoint as a
|
|
high-priority property source, e.g.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>$ curl localhost:8080/env
|
|
{
|
|
"profiles":[],
|
|
"configService:https://github.com/scratches/config-repo/bar.properties":{"foo":"bar"},
|
|
"servletContextInitParams":{},
|
|
"systemProperties":{...},
|
|
...
|
|
}</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>(a property source called "configService:<URL of remote
|
|
repository>/<file name>" contains the property "foo" with value
|
|
"bar" and is highest priority).</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_spring_cloud_config_server">Spring Cloud Config Server</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>The Server provides an HTTP, resource-based API for external
|
|
configuration (name-value pairs, or equivalent YAML content). The
|
|
server is easily embeddable in a Spring Boot application using the
|
|
<code>@EnableConfigServer</code> annotation.</p>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="_encryption_and_decryption">Encryption and Decryption</h3>
|
|
<div class="paragraph">
|
|
<p>The server exposes <code>/encrypt</code> and <code>/decrypt</code> endpoints (on the
|
|
assumption that these will be secured and only accessed by authorized
|
|
agents). If the remote property sources contain encryted content
|
|
(values starting with <code>{cipher}</code>) they will be decrypted before
|
|
sending to clients over HTTP. The main advantage of this set up is
|
|
that the property values don’t have to be in plain text when they are
|
|
"at rest" (e.g. in a git repository).</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you are setting up a remote config repository for config client
|
|
applications it might contain an <code>application.yml</code> like this, for
|
|
instance:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="title">application.yml</div>
|
|
<div class="content">
|
|
<pre>spring:
|
|
datasource:
|
|
username: dbuser
|
|
password: {cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You can safely push this plain text to a shared git repository and the
|
|
secret password is protected.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you are editing a remote config file you can use the Config Server
|
|
to encrypt values by POSTing to the <code>/encrypt</code> endpoint, e.g.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>$ curl localhost:8888/encrypt -d mysecret
|
|
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The inverse operation is also available via <code>/decrypt</code> (provided the server is
|
|
configured with a symmetric key or a full key pair):</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>$ curl localhost:8888/edecrypt -d 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
|
|
mysecret</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Take the encypted value and add the <code>{cipher}</code> prefix before you put
|
|
it in the YAML or properties file, and before you commit and push it
|
|
to a remote, potentially insecure store.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The <code>spring</code> command line client (with Spring Cloud CLI extensions
|
|
installed) can also be used to encrypt and decrypt, e.g.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>$ spring encrypt mysecret --key foo
|
|
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
|
|
$ spring decrypt --key foo 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
|
|
mysecret</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To use a key in a file (e.g. an RSA public key for encyption) prepend
|
|
the key value with "@" and provide the file path, e.g.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>$ spring encrypt mysecret --key @${HOME}/.ssh/id_rsa.pub
|
|
AQAjPgt3eFZQXwt8tsHAVv/QHiY5sI2dRcR+...</pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="_key_management">Key Management</h3>
|
|
<div class="paragraph">
|
|
<p>The Config Server can use a symmetric (shared) key or an asymmetric
|
|
one (RSA key pair). The asymmetric choice is superior in terms of
|
|
security, but it is often more convenient to use a symmetric key since
|
|
it is just a single property value to configure.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To configure a symmetric key you just need to set <code>encrypt.key</code> to a
|
|
secret String (or use an enviroment variable <code>ENCRYPT_KEY</code> to keep it
|
|
out of plain text configuration files). You can also POST a key value
|
|
to the <code>/key</code> endpoint (but that won’t change any existing encrypted
|
|
values in remote repositories).</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To configure an asymmetric key you can either set the key as a
|
|
PEM-encoded text value (in <code>encrypt.key</code>), or via a keystore (e.g. as
|
|
created by the <code>keytool</code> utility that comes with the JDK). The
|
|
keystore properties are <code>encrypt.keyStore.<strong></code> with <code></strong></code> equals to
|
|
<code>location</code> (a <code>Resource</code> location), <code>password</code> (to unlock the
|
|
keystore) and <code>alias</code> (to identify which key in the store is to be
|
|
used).</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The encryption is done with the public key, and a private key is
|
|
needed for decryption. Thus in principle you can configure only the
|
|
public key in the server if you only want to do encryption (and are
|
|
prepared to decrypt the values yourself locally with the private
|
|
key). In practice you might not want to do that because it spreads the
|
|
key management process around all the clients, instead of
|
|
concentrating it in the server. On the other hand it’s a useful option
|
|
if your config server really is relatively insecure and only a
|
|
handful of clients need the encrypted properties.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="_creating_a_key_store_for_testing">Creating a Key Store for Testing</h3>
|
|
<div class="paragraph">
|
|
<p>To create a keystore for testing you can do something like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>$ keytool -genkeypair -alias mytestkey -keyalg RSA \
|
|
-dname "CN=Web Server,OU=Unit,O=Organization,L=City,S=State,C=US" \
|
|
-keypass changeme -keystore server.jks -storepass letmein</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Put the <code>server.jks</code> file in the classpath (for instance) and then in
|
|
your <code>application.yml</code> for the Config Server:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>encrypt:
|
|
keyStore:
|
|
location: classpath:/server.jks
|
|
alias: mytestkey
|
|
password: letmein</pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_spring_cloud_config_client">Spring Cloud Config Client</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>A Spring Boot application can take immediate advantage of the Spring
|
|
Config Server (or other external property sources provided by the
|
|
application developer), and it will also pick up some additional
|
|
useful features related to <code>Environment</code> change events. When a config
|
|
client starts up it binds to the Config Server (via the bootstrap
|
|
configuration property <code>spring.cloud.config.uri</code>) and initializes
|
|
Spring <code>Environment</code> with remote property sources</p>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="_environment_changes">Environment Changes</h3>
|
|
<div class="paragraph">
|
|
<p>The application will listen for an <code>EnvironmentChangedEvent</code> and react
|
|
to the change in a couple of standard ways (additional
|
|
<code>ApplicationListeners</code> can be added as <code>@Beans</code> by the user in the
|
|
normal way). When an <code>EnvironmentChangedEvent</code> is observed it will
|
|
have a list of key values that have changed, and the application will
|
|
use those to:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Re-bind any <code>@ConfigurationProperties</code> beans in the context</p>
|
|
</li>
|
|
<li>
|
|
<p>Set the logger levels for any properties in <code>logging.level.*</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This covers a large class of refresh use cases, and you can verify the
|
|
changes by visiting the <code>/configprops</code> endpoint (normal Spring Boot
|
|
Actuator feature). For instance a <code>DataSource</code> can have its
|
|
<code>maxPoolSize</code> changed at runtime (the default <code>DataSource</code> created by
|
|
Spring Boot is an <code>@ConfigurationProperties</code> bean) and grow capacity
|
|
dynamically. It does not cover another large class of use cases, where
|
|
you need more control over the refresh, and where you need a
|
|
configuration change to be atomic over the whole
|
|
<code>ApplicationContext</code>. To address those concerns we have
|
|
<code>@RefreshScope</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="_refresh_scope">Refresh Scope</h3>
|
|
<div class="paragraph">
|
|
<p>A Spring <code>@Bean</code> that is marked as <code>@RefreshScope</code> will get special
|
|
treatment when there is a configuration change. This addresses the
|
|
problem of stateful beans that only get their configuration injected
|
|
when they are initialized. For instance if a <code>DataSource</code> has open
|
|
connections when the database URL is changed via the <code>Environment</code>, we
|
|
probably want the holders of those connections to be able to complete
|
|
what they are doing. Then the next time someone borrows a connection
|
|
from the pool he gets one with the new URL.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Refresh scope beans are lazy proxies that initialize when they are
|
|
used (i.e. 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 just need to invalidate its cache entry.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The <code>RefreshScope</code> is a bean in the context and it has a public method
|
|
<code>refreshAll()</code> to refresh all beans in the scope by clearing the
|
|
target cache. There is also a <code>refresh(String)</code> method to refresh an
|
|
individual bean by name. This functionality is exposed in the
|
|
<code>/refresh</code> endpoint (over HTTP or JMX).</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="_encryption_and_decryption_2">Encryption and Decryption</h3>
|
|
<div class="paragraph">
|
|
<p>The Config Client has an <code>Environment</code> pre-processor for decrypting
|
|
property values locally. It follows the same rules as the Config
|
|
Server, and has the same external configuration via <code>encrypt.<strong></code>. Thus
|
|
you can use encrypted values in the form <code>{cipher}</strong></code> and as long as
|
|
there is a valid key then they will be decrypted before the main
|
|
application context gets the <code>Environment</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="_endpoints">Endpoints</h3>
|
|
<div class="paragraph">
|
|
<p>For a Spring Boot Actuator application there are some additional management endpoints:
|
|
* POST to <code>/env</code> to update the <code>Environment</code> and rebind <code>@ConfigurationProperties</code> and log levels
|
|
* <code>/refresh</code> for re-loading the boot strap context and refreshing the <code>@RefreshScope</code> beans
|
|
* <code>/restart</code> for closing the <code>ApplicationContext</code> and restarting it (disabled by default)
|
|
* <code>/pause</code> and <code>/resume</code> for calling the <code>Lifecycle</code> methods (<code>stop()</code> and <code>start()</code> on the <code>ApplicationContext</code>)</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="_the_bootstrap_application_context">The Bootstrap Application Context</h3>
|
|
<div class="paragraph">
|
|
<p>The Config Client operates by creating a "bootstrap" application
|
|
context, which is a parent context for the main application. Out of
|
|
the box it is responsible for loading configuration properties from
|
|
the Config Server, and also decrypting properties in the local
|
|
external configuration files. The two contexts share an <code>Environment</code>
|
|
which is the source of external properties for any Spring
|
|
application. Bootstrap properties are added with hight precedence, so
|
|
they cannot be overridden by local configuration.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The bootstrap context uses a different convention for locating
|
|
external configuration than the main application context, so instead
|
|
of <code>application.yml</code> (or <code>.properties</code>) you use <code>bootstrap.yml</code>,
|
|
keeping the external configuration for bootstrap and main context
|
|
nicely separate. Example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="title">bootstrap.yml</div>
|
|
<div class="content">
|
|
<pre>spring:
|
|
application:
|
|
name: foo
|
|
cloud:
|
|
config:
|
|
uri: ${SPRING_CONFIG_URI:http://localhost:8888}</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>It is a good idea to set the <code>spring.application.name</code> in
|
|
<code>bootstrap.yml</code> if your application needs any application-specific
|
|
configuration from the server.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You can disable the bootstrap process completely by setting
|
|
<code>spring.platform.bootstrap.enabled=false</code> (e.g. in System properties).</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="_customizing_the_bootstrap">Customizing the Bootstrap</h3>
|
|
<div class="paragraph">
|
|
<p>The bootstrap context can be trained to do anything you like by adding
|
|
entries to <code>/META-INF/spring.factories</code> under the key
|
|
<code>org.springframework.cloud.bootstrap.BootstrapConfiguration</code>. This is
|
|
a comma-separated list of Spring <code>@Configuration</code> classes which will
|
|
be used to create the context. Any beans that you want to be available
|
|
to the main application context for autowiring can be created here,
|
|
and also there is a special contract for <code>@Beans</code> of type
|
|
<code>ApplicationContextInitializer</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The bootstrap process ends by injecting initializers into the main
|
|
<code>SpringApplication</code> instance (i.e. the normal Spring Boot startup
|
|
sequence, whether it is running as a standalone app or deployed in an
|
|
application server). First a bootstrap context is created from the
|
|
classes found in <code>spring.factories</code> and then all <code>@Beans</code> of type
|
|
<code>ApplicationContextInitializer</code> are added to the main
|
|
<code>SpringApplication</code> before it is started.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="_customizing_the_property_sources">Customizing the Property Sources</h3>
|
|
<div class="paragraph">
|
|
<p>The default property source for external configuration added by the
|
|
bootstrap process is the Config Server, but you can add additional
|
|
sources by adding beans of type <code>PropertySourceLocator</code> to the
|
|
bootstrap context (via <code>spring.factories</code>). You could use this to
|
|
insert additional properties from a different server, or from a
|
|
database, for instance.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<h1 id="_spring_cloud_netflix" class="sect0">Spring Cloud Netflix</h1>
|
|
<div class="openblock partintro">
|
|
<div class="content">
|
|
This project provides Netflix OSS integrations for Spring Boot apps through autoconfiguration
|
|
and binding to the Spring Environment and other Spring programming model idioms. With a few
|
|
simple annotations you can quickly enable and configure the common patterns inside your
|
|
application and build large distributed systems with battle-tested Netflix components. The
|
|
patterns provided include Service Discovery (Eureka), Circuit Breaker (Hystrix),
|
|
Intelligent Routing (Zuul) and Client Side Load Balancing (Ribbon).
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_service_discovery_eureka_clients">Service Discovery: Eureka Clients</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>Example eureka client:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>@Configuration
|
|
@ComponentScan
|
|
@EnableAutoConfiguration
|
|
@EnableEurekaClient
|
|
@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);
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>(i.e. utterly normal Spring Boot app). Configuration is required to locate the Eureka server. Example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>eureka:
|
|
client:
|
|
serviceUrl:
|
|
defaultZone: http://localhost:8080/v2/
|
|
default.defaultZone: http://localhost:8080/v2/</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The default application name, virtual host and non-secure port are taken from the <code>Environment</code> is
|
|
<code>${spring.application.name}</code>, <code>${spring.application.name}.mydomain.net</code> and <code>${server.port}</code> respectively.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_service_discovery_eureka_server">Service Discovery: Eureka Server</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>Example eureka server:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>@Configuration
|
|
@EnableAutoConfiguration
|
|
@EnableEurekaServer
|
|
public class Application {
|
|
|
|
public static void main(String[] args) {
|
|
new SpringApplicationBuilder(Application.class).web(true).run(args);
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The server has a home page with a UI, and HTTP API endpoints per the
|
|
normal Eureka functionality under <code>/v2/*</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Eureka (apache → tomcat) see <a href="https://github.com/cfregly/fluxcapacitor/wiki/NetflixOSS-FAQ#eureka-service-discovery-load-balancer">flux capacitor</a> and <a href="https://groups.google.com/forum/?fromgroups#!topic/eureka_netflix/g3p2r7gHnN0">google group discussion</a>.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_circuit_breaker_hystrix_clients">Circuit Breaker: Hystrix Clients</h2>
|
|
<div class="sectionbody">
|
|
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_circuit_breaker_hystrix_dashboard">Circuit Breaker: Hystrix Dashboard</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="_turbine">Turbine</h3>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_declarative_rest_client_feign">Declarative REST Client: Feign</h2>
|
|
<div class="sectionbody">
|
|
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_client_side_load_balancer_ribbon">Client Side Load Balancer: Ribbon</h2>
|
|
<div class="sectionbody">
|
|
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_external_configuration_archaius">External Configuration: Archaius</h2>
|
|
<div class="sectionbody">
|
|
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_router_and_filter_zuul">Router and Filter: Zuul</h2>
|
|
<div class="sectionbody">
|
|
|
|
</div>
|
|
</div>
|
|
<h1 id="_spring_cloud_cluster" class="sect0">Spring Cloud Cluster</h1>
|
|
<div class="openblock partintro">
|
|
<div class="content">
|
|
Spring Cloud Cluster offers a set of primitives for building "cluster"
|
|
features into a distributed system. Example are leadership election,
|
|
consistent storage of cluster state, global locks and one-time tokens.
|
|
</div>
|
|
</div>
|
|
<h1 id="_spring_platform_bus" class="sect0">Spring Platform Bus</h1>
|
|
<div class="openblock partintro">
|
|
<div class="content">
|
|
Spring Cloud Bus links nodes of a distributed system with a lightweight message broker. This can then be used to broadcast state changes (e.g. configuration changes) or other management instructions. The only implementation currently is with an AMQP broker as the transport, but the same basic feature set (and some more depending on the transport) is on the roadmap for other transports.
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_quick_start_2">Quick Start</h2>
|
|
<div class="sectionbody">
|
|
|
|
</div>
|
|
</div>
|
|
<h1 id="_spring_cloud_for_cloud_foundry" class="sect0">Spring Cloud for Cloud Foundry</h1>
|
|
<div class="openblock partintro">
|
|
<div class="content">
|
|
Integration between <a href="https://github.com/cloudfoundry">Cloud Foundry</a>
|
|
and <a href="https://github.com/spring-cloud">Spring Cloud</a>.
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_service_broker_example">Service Broker Example</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>Example script to deploy and regis#ter a broker:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>DOMAIN=mydomain.net
|
|
cf push app -p target/*.jar --no-start
|
|
cf env app | grep SPRING_PROFILES_ACTIVE || cf set-env app SPRING_PROFILES_ACTIVE cloud
|
|
cf env app | grep APPLICATION_DOMAIN || cf set-env app APPLICATION_DOMAIN ${DOMAIN}
|
|
|
|
cf services | grep configserver && cf bind app configserver
|
|
|
|
cf restart app
|
|
cf create-service-broker app user secure http://app.${DOMAIN}
|
|
|
|
for f in `cf curl /v2/service_plans | grep '\"guid' | sed -e 's/.*: "//' -e 's/".*//'`; do
|
|
cf curl v2/service_plans/$f -X PUT -d '{"public":true}'
|
|
done
|
|
|
|
cf create-service app free appi</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>At which point you have a service called "app" and a service instance called "appi":</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>$ cf marketplace
|
|
OK
|
|
|
|
service plans description
|
|
app free Singleton service app
|
|
$ cf services
|
|
Getting services in org default / space development as admin...
|
|
OK
|
|
|
|
name service plan bound apps
|
|
appi app free</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Your application can define a configuration property
|
|
<code>application.domain</code> (defaults to "cfapps.io") which will be used to
|
|
construct the credentials for any app that binds to your service. Or
|
|
it can define the URI directly using
|
|
<code>cloudfoundry.service.definition.metadata.uri</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You can change some other basic metadata by setting config properties:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>cloudfoundry.service.definition.*</code> is bound to a
|
|
<code>ServiceDefinition</code> (defined in spring-boot-cf-service-broker) which
|
|
has optional setters for plans and metadata.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>cloudfoundry.service.broker.*</code> is bound to an internal bean. It has
|
|
optional setters for "name" (the service name), "description" (user
|
|
friendly description) and "prefix" (used to create a unique id from
|
|
the name).</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>An app which binds to your service will get credentials that contain a
|
|
"uri" property linking to your service. A Spring Boot app can bind to
|
|
that through the <code>vcap.services.[service].credentials.uri</code> environment
|
|
property.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If your service also has a
|
|
<a href="https://github.com/Netflix/eureka">Eureka core</a> dependency, and you
|
|
can expose it as a Eureka service, then any service which registers
|
|
with Eureka will also become a Cloud Foundry service.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="footer">
|
|
<div id="footer-text">
|
|
Last updated 2014-10-01 15:12:43 BST
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html> |