spring:
+ cloud:
+ config:
+ server:
+ git:
+ uri: https://github.com/myorg/{application}
+diff --git a/images/RequestLatency.png b/images/RequestLatency.png new file mode 100644 index 0000000..6c7e93b Binary files /dev/null and b/images/RequestLatency.png differ diff --git a/spring-cloud.html b/spring-cloud.html index 7a7be39..7860570 100644 --- a/spring-cloud.html +++ b/spring-cloud.html @@ -520,6 +520,7 @@ body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-b
Spring Cloud Config Server supports a single or multiple git
-repositories with pattern matching on the application and profile
-name. The pattern format is a comma-separated list of
-{application}/{profile} names with wildcards (where a pattern
-beginning with a wildcard may need to be quoted). Example:
Spring Cloud Config Server supports a git repository URL with
+placeholders for the {application} and {profile} (and {label} if
+you need it, but remember that the label is applied as a git label
+anyway). So you can easily support a "one repo per application" policy
+using (for example):
spring:
+ cloud:
+ config:
+ server:
+ git:
+ uri: https://github.com/myorg/{application}
+or a "one repo per profile" policy using a similar pattern but with
+{profile}.
There is also support for more complex requirements with pattern
+matching on the application and profile name. The pattern format is a
+comma-separated list of {application}/{profile} names with wildcards
+(where a pattern beginning with a wildcard may need to be
+quoted). Example:
~/.ssh)
and the uri points to an SSH location,
e.g. "git@github.com:configuration/cloud-configuration". The
repository is accessed using JGit, so any documentation you find on
-that should be applicable.
+that should be applicable. HTTPS proxy settings can be set in
+~/.git/config or in the same way as for any other JVM process via
+system properties (-Dhttps.proxyHost and -Dhttps.proxyPort).
+searchLocations is identical to a
-local Spring Boot application (so
-[classpath:/, classpath:/config, file:./, file:./config]) which will
-expose the application.properties from the server to all clients.
+local Spring Boot application (so [classpath:/, classpath:/config,
+file:./, file:./config]). This does not expose the
+application.properties from the server to all clients because any
+property sources present in the server are removed before being sent
+to the client.
This repository implementation maps the {label} parameter of the
-HTTP resource to a suffix on the search path, so properties files are
-loaded from each search location and a subdirectory with the same
-name as the label (the labelled properties take precedence in the
-Spring Environment).
The search locations can contain placeholders for {application},
+{profile} and {label}. In this way you can segregate the
+directories in the path, and choose a strategy that makes sense for
+you (e.g. sub-directory per application, or sub-directory per
+profile).
If you don’t use placeholders in the search locations, this repository
+also appends the {label} parameter of the HTTP resource to a suffix
+on the search path, so properties files are loaded from each search
+location and a subdirectory with the same name as the label (the
+labelled properties take precedence in the Spring Environment). Thus
+the default behaviour with no placeholders is the same as adding a
+search location ending with /{label}/. For example `file:/tmp/config
+is the same as file:/tmp/config,file:/tmp/config/{label}
With file-based (i.e. git, svn and native) repositories, resources
+with file names in application* are shared between all client
+applications (so application.properties, application.yml,
+application-*.properties etc.). You can use resources with these
+file names to configure global defaults and have them overridden by
+application-specific files as necessary.
The #_property_overrides[property overrides] feature can also be used +for setting global defaults, and with placeholders applications are +allowed to override them locally.
+|
+ Tip
+ |
+
+With the "native" profile (local file system backend) it is
+recommended that you use an explicit search location that isn’t part
+of the server’s own configuration. Otherwise the application*
+resources in the default search locations are removed because they are
+part of the server.
+ |
+
The Config Server has an "overrides" feature that allows the operator
+to provide configuration properties to all applications that cannot be
+accidentally changed by the application using the normal Spring Boot
+hooks. To declare overrides just add a map of name-value pairs to
+spring.cloud.config.server.overrides. For example
spring: + cloud: + config: + server: + foo: bar+
will cause all applications that are config clients to read foo=bar
+independent of their own configuration. (Of course an application can
+use the data in the Config Server in any way it likes, so overrides
+are not enforceable, but they do provide useful default behaviour if
+they are Spring Cloud Config clients.)
|
+ Tip
+ |
+
+Normal, Spring environment placeholders with "${}" can be escaped
+(and resolved on the client) by using backslash ("\") to escape the
+"$", e.g. \${app.foo:bar} resolves to "bar" unless the app provides
+its own "app.foo". Note that in YAML you don’t need to escape the
+backslash itself, but in properties files you do, when you configure
+the overrides on the server.
+ |
+
You can change the priority of all overrides in the client to be more +like default values, allowing applications to supply their own values +in environment variables or System properties, by setting the flag `
Contract feignContract: SpringMvcContract
Feign.Builder feignBuilder: HystrixFeign.Builder
If Hystrix is on the classpath, by default Feign will wrap all methods with a circuit breaker. Returning a com.netflix.hystrix.HystrixCommand is also available. This lets you use reactive patterns (with a call to .toObservable() or .observe() or asynchronous use (with a call to .queue()).
To disable Hystrix support for Feign, set feign.hystrix.enabled=false.
To disable Hystrix support on a per-client basis create a vanilla Feign.Builder with the "prototype" scope, e.g.:
@Configuration
+public class FooConfiguration {
+ @Bean
+ @Scope("prototype")
+ public Feign.Builder feignBuilder() {
+ return Feign.builder();
+ }
+}
+Feign supports boilerplate apis via single-inheritance interfaces. @@ -3724,6 +3882,28 @@ users:
You can provide convention between serviceId and routes using regexmapper. +It uses regular expression named group to extract variables from serviceId and inject them +into a route pattern.
+ zuul:
+ regexMapper:
+ enabled: true
+ servicePattern: "(?<name>^.+)-(?<version>v.+$)"
+ routePattern: "${version}/${name}"
+This means that a serviceId "myusers-v1" will be mapped to route "/v1/myusers/". +Any regular expression is accepted but all named group must be present in both servicePattern and routePattern. +If servicePattern do not match a serviceId, the default behavior is used. In exemple above, +a serviceId "myusers" will be mapped to route "/myusers/" (no version detected) +These feature is disable by default and is only applied to discovered services.
+To add a prefix to all mappings, set zuul.prefix to a value, such as
/api. The proxy prefix is stripped from the request before the
request is forwarded by default (switch this behaviour off with
@@ -4018,6 +4198,325 @@ info:
When used together, Spectator/Servo and Atlas provide a near real-time operational insight platform.
+Spectator and Servo are Netflix’s metrics collection libraries. Atlas is a Netflix metrics backend to manage dimensional time series data.
+Servo served Netflix for several years and is still usable, but is gradually being phased out in favor of Spectator, which is only designed to work with Java 8. Spring Cloud Netflix provides support for both, but Java 8 based applications are encouraged to use Spectator.
+Spring Boot Actuator metrics are hierarchical and metrics are separated only by name. These names often follow a naming convention that embeds key/value attribute pairs (dimensions) into the name separated by periods. Consider the following metrics for two endpoints, root and star-star:
+{
+ "counter.status.200.root": 20,
+ "counter.status.400.root": 3,
+ "counter.status.200.star-star": 5,
+}
+The first metric gives us a normalized count of successful requests against the root endpoint per unit of time. But what if the system had 20 endpoints and you want to get a count of successful requests against all the endpoints? Some hierarchical metrics backends would allow you to specify a wild card such as counter.status.200. that would read all 20 metrics and aggregate the results. Alternatively, you could provide a HandlerInterceptorAdapter that intercepts and records a metric like counter.status.200.all for all successful requests irrespective of the endpoint, but now you must write 20+1 different metrics. Similarly if you want to know the total number of successful requests for all endpoints in the service, you could specify a wild card such as counter.status.2.*.
Even in the presence of wildcarding support on a hierarchical metrics backend, naming consistency can be difficult. Specifically the position of these tags in the name string can slip with time, breaking queries. For example, suppose we add an additional dimension to the hierarchical metrics above for HTTP method. Then counter.status.200.root becomes counter.status.200.method.get.root, etc. Our counter.status.200.* suddenly no longer has the same semantic meaning. Furthermore, if the new dimension is not applied uniformly across the codebase, certain queries may become impossible. This can quickly get out of hand.
Netflix metrics are tagged (a.k.a. dimensional). Each metric has a name, but this single named metric can contain multiple statistics and 'tag' key/value pairs that allows more querying flexibility. In fact, the statistics themselves are recorded in a special tag.
+Recorded with Netflix Servo or Spectator, a timer for the root endpoint described above contains 4 statistics per status code, where the count statistic is identical to Spring Boot Actuator’s counter. In the event that we have encountered an HTTP 200 and 400 thus far, there will be 8 available data points:
+{
+ "root(status=200,stastic=count)": 20,
+ "root(status=200,stastic=max)": 0.7265630630000001,
+ "root(status=200,stastic=totalOfSquares)": 0.04759702862580789,
+ "root(status=200,stastic=totalTime)": 0.2093076914666667,
+ "root(status=400,stastic=count)": 1,
+ "root(status=400,stastic=max)": 0,
+ "root(status=400,stastic=totalOfSquares)": 0,
+ "root(status=400,stastic=totalTime)": 0,
+}
+Without any additional dependencies or configuration, a Spring Cloud based service will autoconfigure a Servo MonitorRegistry and begin collecting metrics on every Spring MVC request. By default, a Servo timer with the name rest will be recorded for each MVC request which is tagged with:
HTTP method
+HTTP status (e.g. 200, 400, 500)
+URI (or "root" if the URI is empty), sanitized for Atlas
+The exception class name, if the request handler threw an exception
+The caller, if a request header with a key matching netflix.metrics.rest.callerHeader is set on the request. There is no default key for netflix.metrics.rest.callerHeader. You must add it to your application properties if you wish to collect caller information.
Set the netflix.metrics.rest.metricName property to change the name of the metric from rest to a name you provide.
If Spring AOP is enabled and org.aspectj:aspectjweaver is present on your runtime classpath, Spring Cloud will also collect metrics on every client call made with RestTemplate. A Servo timer with the name of restclient will be recorded for each MVC request which is tagged with:
HTTP method
+HTTP status (e.g. 200, 400, 500), "CLIENT_ERROR" if the response returned null, or "IO_ERROR" if an IOException occurred during the execution of the RestTemplate method
URI, sanitized for Atlas
+Client name
+To enable Spectator metrics, include a dependency on spring-boot-starter-spectator:
<dependency>
+ <groupId>org.springframework.cloud</groupId>
+ <artifactId>spring-cloud-starter-spectator</artifactId>
+ </dependency>
+In Spectator parlance, a meter is a named, typed, and tagged configuration and a metric represents the value of a given meter at a point in time. Spectator meters are created and controlled by a registry, which currently has several different implementations. Spectator provides 4 meter types: counter, timer, gauge, and distribution summary.
+Spring Cloud Spectator integration configures an injectable com.netflix.spectator.api.Registry instance for you. Specifically, it configures a ServoRegistry instance in order to unify the collection of REST metrics and the exporting of metrics to the Atlas backend under a single Servo API. Practically, this means that your code may use a mixture of Servo monitors and Spectator meters and both will be scooped up by Spring Boot Actuator MetricReader instances and both will be shipped to the Atlas backend.
A counter is used to measure the rate at which some event is occurring.
+// create a counter with a name and a set of tags
+Counter counter = registry.counter("counterName", "tagKey1", "tagValue1", ...);
+counter.increment(); // increment when an event occurs
+counter.increment(10); // increment by a discrete amount
+The counter records a single time-normalized statistic.
+A timer is used to measure how long some event is taking. Spring Cloud automatically records timers for Spring MVC requests and conditionally RestTemplate requests, which can later be used to create dashboards for request related metrics like latency:
image::RequestLatency.png []
+// create a timer with a name and a set of tags
+Timer timer = registry.timer("timerName", "tagKey1", "tagValue1", ...);
+
+// execute an operation and time it at the same time
+T result = timer.record(() -> fooReturnsT());
+
+// alternatively, if you must manually record the time
+Long start = System.nanoTime();
+T result = fooReturnsT();
+timer.record(System.nanoTime() - start, TimeUnit.NANOSECONDS);
+The timer simultaneously records 4 statistics: count, max, totalOfSquares, and totalTime. The count statistic will always match the single normalized value provided by a counter if you had called increment() once on the counter for each time you recorded a timing, so it is rarely necessary to count and time separately for a single operation.
For long running operations, Spectator provides a special LongTaskTimer.
Gauges are used to determine some current value like the size of a queue or number of threads in a running state. Since gauges are sampled, they provide no information about how these values fluctuate between samples.
+The normal use of a gauge involves registering the gauge once in initialization with an id, a reference to the object to be sampled, and a function to get or compute a numeric value based on the object. The reference to the object is passed in separately and the Spectator registry will keep a weak reference to the object. If the object is garbage collected, then Spectator will automatically drop the registration. See the note in Spectator’s documentation about potential memory leaks if this API is misused.
+// the registry will automatically sample this gauge periodically
+registry.gauge("gaugeName", pool, Pool::numberOfRunningThreads);
+
+// manually sample a value in code at periodic intervals -- last resort!
+registry.gauge("gaugeName", Arrays.asList("tagKey1", "tagValue1", ...), 1000);
+A distribution summary is used to track the distribution of events. It is similar to a timer, but more general in that the size does not have to be a period of time. For example, a distribution summary could be used to measure the payload sizes of requests hitting a server.
+// the registry will automatically sample this gauge periodically
+DistributionSummary ds = registry.distributionSummary("dsName", "tagKey1", "tagValue1", ...);
+ds.record(request.sizeInBytes());
+|
+ Warning
+ |
++If your code is compiled on Java 8, please use Spectator instead of Servo as Spectator is destined to replace Servo entirely in the long term. + | +
In Servo parlance, a monitor is a named, typed, and tagged configuration and a metric represents the value of a given monitor at a point in time. Servo monitors are logically equivalent to Spectator meters. Servo monitors are created and controlled by a MonitorRegistry. In spite of the above warning, Servo does have a wider array of monitor options than Spectator has meters.
Spring Cloud integration configures an injectable com.netflix.servo.MonitorRegistry instance for you. Once you have created the appropriate Monitor type in Servo, the process of recording data is wholly similar to Spectator.
If you are using the Servo MonitorRegistry instance provided by Spring Cloud (specifically, an instance of DefaultMonitorRegistry), Servo provides convenience classes for retrieving counters and timers. These convenience classes ensure that only one Monitor is registered for each unique combination of name and tags.
To manually create a Monitor type in Servo, especially for the more exotic monitor types for which convenience methods are not provided, instantiate the appropriate type by providing a MonitorConfig instance:
MonitorConfig config = MonitorConfig.builder("timerName").withTag("tagKey1", "tagValue1").build();
+
+// somewhere we should cache this Monitor by MonitorConfig
+Timer timer = new BasicTimer(config);
+monitorRegistry.register(timer);
+Atlas was developed by Netflix to manage dimensional time series data for near real-time operational insight. Atlas features in-memory data storage, allowing it to gather and report very large numbers of metrics, very quickly.
+Atlas captures operational intelligence. Whereas business intelligence is data gathered for analyzing trends over time, operational intelligence provides a picture of what is currently happening within a system.
+Spring Cloud provides a spring-cloud-starter-atlas that has all the dependencies you need. Then just annotate your Spring Boot application with @EnableAtlas and provide a location for your running Atlas server with the netflix.atlas.uri property.
Spring Cloud enables you to add tags to every metric sent to the Atlas backend. Global tags can be used to separate metrics by application name, environment, region, etc.
+Each bean implementing AtlasTagProvider will contribute to the global tag list:
@Bean
+AtlasTagProvider atlasCommonTags(
+ @Value("${spring.application.name}") String appName) {
+ return () -> Collections.singletonMap("app", appName);
+}
+To bootstrap a in-memory standalone Atlas instance:
+$ curl -LO https://github.com/Netflix/atlas/releases/download/v1.4.2/atlas-1.4.2-standalone.jar
+$ java -jar atlas-1.4.2-standalone.jar
+|
+ Tip
+ |
++An Atlas standalone node running on an r3.2xlarge (61GB RAM) can handle roughly 2 million metrics per minute for a given 6 hour window. + | +
Once running and you have collected a handful of metrics, verify that your setup is correct by listing tags on the Atlas server:
+$ curl http://ATLAS/api/v1/tags
+|
+ Tip
+ |
+
+After executing several requests against your service, you can gather some very basic information on the request latency of every request by pasting the following url in your browser: http://ATLAS/api/v1/graph?q=name,rest,:eq,:avg
+ |
+
The Atlas wiki contains a compilation of sample queries for various scenarios.
+Make sure to check out the alerting philosophy and docs on using double exponential smoothing to generate dynamic alert thresholds.
+