mirror of
https://github.com/spring-cloud/spring-cloud-netflix.git
synced 2026-10-08 05:29:03 +00:00
Sync docs from 1.4.x to gh-pages
This commit is contained in:
@@ -32,11 +32,11 @@ circuit, and what to do in case of a failure.</p><p>To configure the <code class
|
||||
attribute with a list of <code class="literal">@HystrixProperty</code> annotations. See
|
||||
<a class="link" href="https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica#configuration" target="_top">here</a>
|
||||
for more details. See the <a class="link" href="https://github.com/Netflix/Hystrix/wiki/Configuration" target="_top">Hystrix wiki</a>
|
||||
for details on the properties available.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_propagating_the_security_context_or_using_spring_scopes" href="#_propagating_the_security_context_or_using_spring_scopes"></a>3.2 Propagating the Security Context or using Spring Scopes</h2></div></div></div><p>If you want some thread local context to propagate into a <code class="literal">@HystrixCommand</code> the default declaration will not work because it executes the command in a thread pool (in case of timeouts). You can switch Hystrix to use the same thread as the caller using some configuration, or directly in the annotation, by asking it to use a different "Isolation Strategy". For example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@HystrixCommand(fallbackMethod = "stubMyService",
|
||||
for details on the properties available.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_propagating_the_security_context_or_using_spring_scopes" href="#_propagating_the_security_context_or_using_spring_scopes"></a>3.2 Propagating the Security Context or using Spring Scopes</h2></div></div></div><p>If you want some thread local context to propagate into a <code class="literal">@HystrixCommand</code> the default declaration will not work because it executes the command in a thread pool (in case of timeouts). You can switch Hystrix to use the same thread as the caller using some configuration, or directly in the annotation, by asking it to use a different "Isolation Strategy". For example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@HystrixCommand(fallbackMethod = "stubMyService",
|
||||
commandProperties = {
|
||||
@HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE")
|
||||
}
|
||||
)</span></em>
|
||||
)</xslthl:annotation>
|
||||
...</pre><p>The same thing applies if you are using <code class="literal">@SessionScope</code> or <code class="literal">@RequestScope</code>. You will know when you need to do this because of a runtime exception that says it can’t find the scoped context.</p><p>You also have the option to set the <code class="literal">hystrix.shareSecurityContext</code> property to <code class="literal">true</code>. Doing so will auto configure an Hystrix concurrency strategy plugin hook who will transfer the <code class="literal">SecurityContext</code> from your main thread to the one used by the Hystrix command. Hystrix does not allow multiple hystrix concurrency strategy to be registered so an extension mechanism is available by declaring your own <code class="literal">HystrixConcurrencyStrategy</code> as a Spring bean. Spring Cloud will lookup for your implementation within the Spring context and wrap it inside its own plugin.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_health_indicator" href="#_health_indicator"></a>3.3 Health Indicator</h2></div></div></div><p>The state of the connected circuit breakers are also exposed in the
|
||||
<code class="literal">/health</code> endpoint of the calling application.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"hystrix"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
|
||||
@@ -21,14 +21,14 @@ indicator. It should return a json document like the following:</p><p><b>health
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre><p>
|
||||
</p><p>Here is an example application.yml for a Sidecar application:</p><p><b>application.yml. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">server</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> port</span>: <span class="hl-number">5678</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> port</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">5678</xslthl:number>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spring</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> application</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> name</span>: sidecar
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">sidecar</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> port</span>: <span class="hl-number">8000</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> health-uri</span>: http://localhost:<span class="hl-number">8000</span>/health.json</pre><p>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> port</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">8000</xslthl:number>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> health-uri</span>: http://localhost:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">8000</xslthl:number>/health.json</pre><p>
|
||||
</p><p>The api for the <code class="literal">DiscoveryClient.getInstances()</code> method is <code class="literal">/hosts/{serviceId}</code>.
|
||||
Here is an example response for <code class="literal">/hosts/customers</code> that returns two instances on
|
||||
different hosts. This api is accessible to the non-jvm app (if the sidecar is
|
||||
@@ -36,14 +36,14 @@ on port 5678) at <code class="literal"><a class="link" href="http://localhost:56
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">[</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"host"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"myhost"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"port"</span>: <span class="hl-number">9000</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"port"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">9000</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"uri"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://myhost:9000"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"serviceId"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"CUSTOMERS"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"secure"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">false</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">},</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"host"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"myhost2"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"port"</span>: <span class="hl-number">9000</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"port"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">9000</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"uri"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://myhost2:9000"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"serviceId"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"CUSTOMERS"</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"secure"</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">false</span>
|
||||
@@ -60,7 +60,7 @@ documents. For example, a call to <a class="link" href="https://sidecar.local.s
|
||||
might result in a YAML document like the following</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">eureka</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> client</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> serviceUrl</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> defaultZone</span>: http://localhost:<span class="hl-number">8761</span>/eureka/
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> defaultZone</span>: http://localhost:<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">8761</xslthl:number>/eureka/
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> password</span>: password
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">info</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> description</span>: Spring Cloud Samples
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -6,13 +6,13 @@ for details on setting up your build system with the current Spring Cloud Releas
|
||||
such as host and port, health indicator URL, home page etc. Eureka
|
||||
receives heartbeat messages from each instance belonging to a service.
|
||||
If the heartbeat fails over a configurable timetable, the instance is
|
||||
normally removed from the registry.</p><p>Example eureka client:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@ComponentScan</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableAutoConfiguration</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@RestController</span></em>
|
||||
normally removed from the registry.</p><p>Example eureka client:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ComponentScan</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableAutoConfiguration</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RestController</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@RequestMapping("/")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping("/")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String home() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Hello world"</span>;
|
||||
}
|
||||
@@ -104,8 +104,8 @@ implementing your own <code class="literal">com.netflix.appinfo.HealthCheckHandl
|
||||
instance:
|
||||
hostname: ${vcap.application.uris[0]}
|
||||
nonSecurePort: 80</pre><p>
|
||||
</p><p>Depending on the way the security rules are set up in your Cloud Foundry instance, you might be able to register and use the IP address of the host VM for direct service-to-service calls. This feature is not (yet) available on Pivotal Web Services (<a class="link" href="https://run.pivotal.io" target="_top">PWS</a>).</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_using_eureka_on_aws" href="#_using_eureka_on_aws"></a>1.7.2 Using Eureka on AWS</h3></div></div></div><p>If the application is planned to be deployed to an AWS cloud, then the Eureka instance will have to be configured to be AWS aware and this can be done by customizing the <a class="link" href="https://github.com/spring-cloud/spring-cloud-netflix/tree/master/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java" target="_top">EurekaInstanceConfigBean</a> the following way:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@Profile("!default")</span></em>
|
||||
</p><p>Depending on the way the security rules are set up in your Cloud Foundry instance, you might be able to register and use the IP address of the host VM for direct service-to-service calls. This feature is not (yet) available on Pivotal Web Services (<a class="link" href="https://run.pivotal.io" target="_top">PWS</a>).</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_using_eureka_on_aws" href="#_using_eureka_on_aws"></a>1.7.2 Using Eureka on AWS</h3></div></div></div><p>If the application is planned to be deployed to an AWS cloud, then the Eureka instance will have to be configured to be AWS aware and this can be done by customizing the <a class="link" href="https://github.com/spring-cloud/spring-cloud-netflix/tree/master/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java" target="_top">EurekaInstanceConfigBean</a> the following way:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Profile("!default")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> EurekaInstanceConfigBean eurekaInstanceConfig(InetUtils inetUtils) {
|
||||
EurekaInstanceConfigBean b = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> EurekaInstanceConfigBean(inetUtils);
|
||||
AmazonInfo info = AmazonInfo.Builder.newBuilder().autoBuild(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"eureka"</span>);
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>12. Metrics: Spectator, Servo, and Atlas</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-netflix.html" title="Spring Cloud Netflix"><link rel="up" href="multi_spring-cloud-netflix.html" title="Spring Cloud Netflix"><link rel="prev" href="multi_netflix-rxjava-springmvc.html" title="11. RxJava with Spring MVC"><link rel="next" href="multi__http_clients.html" title="13. HTTP Clients"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">12. Metrics: Spectator, Servo, and Atlas</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_netflix-rxjava-springmvc.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__http_clients.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="netflix-metrics" href="#netflix-metrics"></a>12. Metrics: Spectator, Servo, and Atlas</h1></div></div></div><p>When used together, Spectator/Servo and Atlas provide a near real-time operational insight platform.</p><p>Spectator and Servo are Netflix’s metrics collection libraries. Atlas is a Netflix metrics backend to manage dimensional time series data.</p><p>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.</p><p>To enable Servo you must set <code class="literal">spring.metrics.servo.enabled</code> to <code class="literal">true</code>.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_dimensional_vs_hierarchical_metrics" href="#_dimensional_vs_hierarchical_metrics"></a>12.1 Dimensional vs. Hierarchical Metrics</h2></div></div></div><p>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:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"counter.status.200.root"</span>: <span class="hl-number">20</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"counter.status.400.root"</span>: <span class="hl-number">3</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"counter.status.200.star-star"</span>: <span class="hl-number">5</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"counter.status.200.root"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">20</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"counter.status.400.root"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">3</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"counter.status.200.star-star"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">5</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre><p>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 <code class="literal">counter.status.200.*</code> that would read all 20 metrics and aggregate the results. Alternatively, you could provide a <code class="literal">HandlerInterceptorAdapter</code> that intercepts and records a metric like <code class="literal">counter.status.200.all</code> 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 <code class="literal">counter.status.2*.*</code>.</p><p>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 <code class="literal">counter.status.200.root</code> becomes <code class="literal">counter.status.200.method.get.root</code>, etc. Our <code class="literal">counter.status.200.*</code> 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.</p><p>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.</p><p>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:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"root(status=200,stastic=count)"</span>: <span class="hl-number">20</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"root(status=200,stastic=max)"</span>: <span class="hl-number">0.7265630630000001</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"root(status=200,stastic=totalOfSquares)"</span>: <span class="hl-number">0.04759702862580789</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"root(status=200,stastic=totalTime)"</span>: <span class="hl-number">0.2093076914666667</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"root(status=400,stastic=count)"</span>: <span class="hl-number">1</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"root(status=400,stastic=max)"</span>: <span class="hl-number">0</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"root(status=400,stastic=totalOfSquares)"</span>: <span class="hl-number">0</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"root(status=400,stastic=totalTime)"</span>: <span class="hl-number">0</span><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"root(status=200,stastic=count)"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">20</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"root(status=200,stastic=max)"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.7265630630000001</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"root(status=200,stastic=totalOfSquares)"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.04759702862580789</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"root(status=200,stastic=totalTime)"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0.2093076914666667</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"root(status=400,stastic=count)"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"root(status=400,stastic=max)"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"root(status=400,stastic=totalOfSquares)"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"root(status=400,stastic=totalTime)"</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">0</xslthl:number><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_default_metrics_collection" href="#_default_metrics_collection"></a>12.2 Default Metrics Collection</h2></div></div></div><p>Without any additional dependencies or configuration, a Spring Cloud based service will autoconfigure a Servo <code class="literal">MonitorRegistry</code> and begin collecting metrics on every Spring MVC request. By default, a Servo timer with the name <code class="literal">rest</code> will be recorded for each MVC request which is tagged with:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">HTTP method</li><li class="listitem">HTTP status (e.g. 200, 400, 500)</li><li class="listitem">URI (or "root" if the URI is empty), sanitized for Atlas</li><li class="listitem">The exception class name, if the request handler threw an exception</li><li class="listitem">The caller, if a request header with a key matching <code class="literal">netflix.metrics.rest.callerHeader</code> is set on the request. There is no default key for <code class="literal">netflix.metrics.rest.callerHeader</code>. You must add it to your application properties if you wish to collect caller information.</li></ol></div><p>Set the <code class="literal">netflix.metrics.rest.metricName</code> property to change the name of the metric from <code class="literal">rest</code> to a name you provide.</p><p>If Spring AOP is enabled and <code class="literal">org.aspectj:aspectjweaver</code> is present on your runtime classpath, Spring Cloud will also collect metrics on every client call made with <code class="literal">RestTemplate</code>. A Servo timer with the name of <code class="literal">restclient</code> will be recorded for each MVC request which is tagged with:</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">HTTP method</li><li class="listitem">HTTP status (e.g. 200, 400, 500), "CLIENT_ERROR" if the response returned null, or "IO_ERROR" if an <code class="literal">IOException</code> occurred during the execution of the <code class="literal">RestTemplate</code> method</li><li class="listitem">URI, sanitized for Atlas</li><li class="listitem">Client name</li></ol></div><div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Warning"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="images/warning.png"></td><th align="left">Warning</th></tr><tr><td align="left" valign="top"><p>Avoid using hardcoded url parameters within <code class="literal">RestTemplate</code>. When targeting dynamic endpoints use URL variables. This will avoid potential "GC Overhead Limit Reached" issues where <code class="literal">ServoMonitorCache</code> treats each url as a unique key.</p></td></tr></table></div><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// recommended</span>
|
||||
String orderid = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"1"</span>;
|
||||
restTemplate.getForObject(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://testclient/orders/{orderid}"</span>, String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>, orderid)
|
||||
@@ -24,7 +24,7 @@ restTemplate.getForObject(<span xmlns:d="http://docbook.org/ns/docbook" class="h
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre><p>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.</p><p>Spring Cloud Spectator integration configures an injectable <code class="literal">com.netflix.spectator.api.Registry</code> instance for you. Specifically, it configures a <code class="literal">ServoRegistry</code> 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 <code class="literal">MetricReader</code> instances and both will be shipped to the Atlas backend.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_spectator_counter" href="#_spectator_counter"></a>12.3.1 Spectator Counter</h3></div></div></div><p>A counter is used to measure the rate at which some event is occurring.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// create a counter with a name and a set of tags</span>
|
||||
Counter counter = registry.counter(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"counterName"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"tagKey1"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"tagValue1"</span>, ...);
|
||||
counter.increment(); <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// increment when an event occurs</span>
|
||||
counter.increment(<span class="hl-number">10</span>); <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// increment by a discrete amount</span></pre><p>The counter records a single time-normalized statistic.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_spectator_timer" href="#_spectator_timer"></a>12.3.2 Spectator Timer</h3></div></div></div><p>A timer is used to measure how long some event is taking. Spring Cloud automatically records timers for Spring MVC requests and conditionally <code class="literal">RestTemplate</code> requests, which can later be used to create dashboards for request related metrics like latency:</p><div class="figure"><a name="d0e3406" href="#d0e3406"></a><p class="title"><b>Figure 12.1. Request Latency</b></p><div class="figure-contents"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-netflix/1.4.x/docs/src/main/asciidoc/images/RequestLatency.png" alt="RequestLatency"></div></div></div><br class="figure-break"><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// create a timer with a name and a set of tags</span>
|
||||
counter.increment(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">10</xslthl:number>); <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// increment by a discrete amount</span></pre><p>The counter records a single time-normalized statistic.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_spectator_timer" href="#_spectator_timer"></a>12.3.2 Spectator Timer</h3></div></div></div><p>A timer is used to measure how long some event is taking. Spring Cloud automatically records timers for Spring MVC requests and conditionally <code class="literal">RestTemplate</code> requests, which can later be used to create dashboards for request related metrics like latency:</p><div class="figure"><a name="d0e3406" href="#d0e3406"></a><p class="title"><b>Figure 12.1. Request Latency</b></p><div class="figure-contents"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-netflix/1.4.x/docs/src/main/asciidoc/images/RequestLatency.png" alt="RequestLatency"></div></div></div><br class="figure-break"><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// create a timer with a name and a set of tags</span>
|
||||
Timer timer = registry.timer(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"timerName"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"tagKey1"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"tagValue1"</span>, ...);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// execute an operation and time it at the same time</span>
|
||||
@@ -37,18 +37,18 @@ timer.record(System.nanoTime() - start, TimeUnit.NANOSECONDS);</pre><p>The timer
|
||||
registry.gauge(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"gaugeName"</span>, pool, Pool::numberOfRunningThreads);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// manually sample a value in code at periodic intervals -- last resort!</span>
|
||||
registry.gauge(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"gaugeName"</span>, Arrays.asList(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"tagKey1"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"tagValue1"</span>, ...), <span class="hl-number">1000</span>);</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_spectator_distribution_summaries" href="#_spectator_distribution_summaries"></a>12.3.4 Spectator Distribution Summaries</h3></div></div></div><p>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.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// the registry will automatically sample this gauge periodically</span>
|
||||
registry.gauge(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"gaugeName"</span>, Arrays.asList(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"tagKey1"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"tagValue1"</span>, ...), <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1000</xslthl:number>);</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_spectator_distribution_summaries" href="#_spectator_distribution_summaries"></a>12.3.4 Spectator Distribution Summaries</h3></div></div></div><p>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.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// the registry will automatically sample this gauge periodically</span>
|
||||
DistributionSummary ds = registry.distributionSummary(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"dsName"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"tagKey1"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"tagValue1"</span>, ...);
|
||||
ds.record(request.sizeInBytes());</pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="netflix-metrics-servo" href="#netflix-metrics-servo"></a>12.4 Metrics Collection: Servo</h2></div></div></div><div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Warning"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="images/warning.png"></td><th align="left">Warning</th></tr><tr><td align="left" valign="top"><p>If 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.</p></td></tr></table></div><p>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 <code class="literal">MonitorRegistry</code>. In spite of the above warning, Servo does have a <a class="link" href="https://github.com/Netflix/servo/wiki/Getting-Started" target="_top">wider array</a> of monitor options than Spectator has meters.</p><p>Spring Cloud integration configures an injectable <code class="literal">com.netflix.servo.MonitorRegistry</code> instance for you. Once you have created the appropriate <code class="literal">Monitor</code> type in Servo, the process of recording data is wholly similar to Spectator.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_creating_servo_monitors" href="#_creating_servo_monitors"></a>12.4.1 Creating Servo Monitors</h3></div></div></div><p>If you are using the Servo <code class="literal">MonitorRegistry</code> instance provided by Spring Cloud (specifically, an instance of <code class="literal">DefaultMonitorRegistry</code>), Servo provides convenience classes for retrieving <a class="link" href="https://github.com/Netflix/spectator/wiki/Servo-Comparison#dynamiccounter" target="_top">counters</a> and <a class="link" href="https://github.com/Netflix/spectator/wiki/Servo-Comparison#dynamictimer" target="_top">timers</a>. These convenience classes ensure that only one <code class="literal">Monitor</code> is registered for each unique combination of name and tags.</p><p>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 <code class="literal">MonitorConfig</code> instance:</p><pre class="programlisting">MonitorConfig config = MonitorConfig.builder(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"timerName"</span>).withTag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"tagKey1"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"tagValue1"</span>).build();
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// somewhere we should cache this Monitor by MonitorConfig</span>
|
||||
Timer timer = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> BasicTimer(config);
|
||||
monitorRegistry.register(timer);</pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="netflix-metrics-atlas" href="#netflix-metrics-atlas"></a>12.5 Metrics Backend: Atlas</h2></div></div></div><p>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.</p><p>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.</p><p>Spring Cloud provides a <code class="literal">spring-cloud-starter-netflix-atlas</code> that has all the dependencies you need. Then just annotate your Spring Boot application with <code class="literal">@EnableAtlas</code> and provide a location for your running Atlas server with the <code class="literal">netflix.atlas.uri</code> property.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_global_tags" href="#_global_tags"></a>12.5.1 Global tags</h3></div></div></div><p>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.</p><p>Each bean implementing <code class="literal">AtlasTagProvider</code> will contribute to the global tag list:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
monitorRegistry.register(timer);</pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="netflix-metrics-atlas" href="#netflix-metrics-atlas"></a>12.5 Metrics Backend: Atlas</h2></div></div></div><p>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.</p><p>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.</p><p>Spring Cloud provides a <code class="literal">spring-cloud-starter-netflix-atlas</code> that has all the dependencies you need. Then just annotate your Spring Boot application with <code class="literal">@EnableAtlas</code> and provide a location for your running Atlas server with the <code class="literal">netflix.atlas.uri</code> property.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_global_tags" href="#_global_tags"></a>12.5.1 Global tags</h3></div></div></div><p>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.</p><p>Each bean implementing <code class="literal">AtlasTagProvider</code> will contribute to the global tag list:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
||||
AtlasTagProvider atlasCommonTags(
|
||||
<em><span class="hl-annotation" style="color: gray">@Value("${spring.application.name}")</span></em> String appName) {
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Value("${spring.application.name}")</xslthl:annotation> String appName) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> () -> Collections.singletonMap(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"app"</span>, appName);
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_using_atlas" href="#_using_atlas"></a>12.5.2 Using Atlas</h3></div></div></div><p>To bootstrap a in-memory standalone Atlas instance:</p><pre class="programlisting">$ curl -LO https://github.com/Netflix/atlas/releases/download/v1.<span class="hl-number">4.2</span>/atlas-<span class="hl-number">1.4</span>.<span class="hl-number">2</span>-standalone.jar
|
||||
$ java -jar atlas-<span class="hl-number">1.4</span>.<span class="hl-number">2</span>-standalone.jar</pre><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>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.</p></td></tr></table></div><p>Once running and you have collected a handful of metrics, verify that your setup is correct by listing tags on the Atlas server:</p><pre class="programlisting">$ curl http://ATLAS/api/v1/tags</pre><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>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: <code class="literal"><a class="link" href="http://ATLAS/api/v1/graph?q=name,rest,:eq,:avg" target="_top">http://ATLAS/api/v1/graph?q=name,rest,:eq,:avg</a></code></p></td></tr></table></div><p>The Atlas wiki contains a <a class="link" href="https://github.com/Netflix/atlas/wiki/Single-Line" target="_top">compilation of sample queries</a> for various scenarios.</p><p>Make sure to check out the <a class="link" href="https://github.com/Netflix/atlas/wiki/Alerting-Philosophy" target="_top">alerting philosophy</a> and docs on using <a class="link" href="https://github.com/Netflix/atlas/wiki/DES" target="_top">double exponential smoothing</a> to generate dynamic alert thresholds.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="retrying-failed-requests" href="#retrying-failed-requests"></a>12.6 Retrying Failed Requests</h2></div></div></div><p>Spring Cloud Netflix offers a variety of ways to make HTTP requests. You can use a load balanced
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_using_atlas" href="#_using_atlas"></a>12.5.2 Using Atlas</h3></div></div></div><p>To bootstrap a in-memory standalone Atlas instance:</p><pre class="programlisting">$ curl -LO https://github.com/Netflix/atlas/releases/download/v1.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">4.2</xslthl:number>/atlas-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.4</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2</xslthl:number>-standalone.jar
|
||||
$ java -jar atlas-<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1.4</xslthl:number>.<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2</xslthl:number>-standalone.jar</pre><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>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.</p></td></tr></table></div><p>Once running and you have collected a handful of metrics, verify that your setup is correct by listing tags on the Atlas server:</p><pre class="programlisting">$ curl http://ATLAS/api/v1/tags</pre><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>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: <code class="literal"><a class="link" href="http://ATLAS/api/v1/graph?q=name,rest,:eq,:avg" target="_top">http://ATLAS/api/v1/graph?q=name,rest,:eq,:avg</a></code></p></td></tr></table></div><p>The Atlas wiki contains a <a class="link" href="https://github.com/Netflix/atlas/wiki/Single-Line" target="_top">compilation of sample queries</a> for various scenarios.</p><p>Make sure to check out the <a class="link" href="https://github.com/Netflix/atlas/wiki/Alerting-Philosophy" target="_top">alerting philosophy</a> and docs on using <a class="link" href="https://github.com/Netflix/atlas/wiki/DES" target="_top">double exponential smoothing</a> to generate dynamic alert thresholds.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="retrying-failed-requests" href="#retrying-failed-requests"></a>12.6 Retrying Failed Requests</h2></div></div></div><p>Spring Cloud Netflix offers a variety of ways to make HTTP requests. You can use a load balanced
|
||||
<code class="literal">RestTemplate</code>, Ribbon, or Feign. No matter how you choose to your HTTP requests, there is always
|
||||
a chance the request may fail. When a request fails you may want to have the request retried
|
||||
automatically. To accomplish this when using Sping Cloud Netflix you need to include
|
||||
@@ -56,12 +56,12 @@ automatically. To accomplish this when using Sping Cloud Netflix you need to in
|
||||
When Spring Retry is present load balanced <code class="literal">RestTemplates</code>, Feign, and Zuul will automatically
|
||||
retry any failed requests (assuming you configuration allows it to).</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_backoff_policies" href="#_backoff_policies"></a>12.6.1 BackOff Policies</h3></div></div></div><p>By default no backoff policy is used when retrying requests. If you would like to configure
|
||||
a backoff policy you will need to create a bean of type <code class="literal">LoadBalancedBackOffPolicyFactory</code>
|
||||
which will be used to create a <code class="literal">BackOffPolicy</code> for a given service.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||
which will be used to create a <code class="literal">BackOffPolicy</code> for a given service.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyConfiguration {
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
||||
LoadBalancedBackOffPolicyFactory backOffPolciyFactory() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> LoadBalancedBackOffPolicyFactory() {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> BackOffPolicy createBackOffPolicy(String service) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ExponentialBackOffPolicy();
|
||||
}
|
||||
@@ -76,7 +76,7 @@ on the server’s resources due to the buffering of the request’s body
|
||||
response. You can list the response codes you would like the Ribbon client to retry using the
|
||||
property <code class="literal">clientName.ribbon.retryableStatusCodes</code>. For example</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">clientName</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> ribbon</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> retryableStatusCodes</span>: <span class="hl-number">404</span>,<span class="hl-number">502</span></pre><p>You can also create a bean of type <code class="literal">LoadBalancedRetryPolicy</code> and implement the <code class="literal">retryableStatusCode</code>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> retryableStatusCodes</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">404</xslthl:number>,<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">502</xslthl:number></pre><p>You can also create a bean of type <code class="literal">LoadBalancedRetryPolicy</code> and implement the <code class="literal">retryableStatusCode</code>
|
||||
method to determine whether you want to retry a request given the status code.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_zuul" href="#_zuul"></a>12.6.3 Zuul</h3></div></div></div><p>You can turn off Zuul’s retry functionality by setting <code class="literal">zuul.retryable</code> to <code class="literal">false</code>. You
|
||||
can also disable retry functionality on route by route basis by setting
|
||||
<code class="literal">zuul.routes.routename.retryable</code> to <code class="literal">false</code>.</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_netflix-rxjava-springmvc.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__http_clients.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">11. RxJava with Spring MVC </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-netflix.html">Home</a></td><td width="40%" align="right" valign="top"> 13. HTTP Clients</td></tr></table></div></body></html>
|
||||
@@ -1,35 +1,35 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>11. RxJava with Spring MVC</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-netflix.html" title="Spring Cloud Netflix"><link rel="up" href="multi_spring-cloud-netflix.html" title="Spring Cloud Netflix"><link rel="prev" href="multi__polyglot_support_with_sidecar.html" title="10. Polyglot support with Sidecar"><link rel="next" href="multi_netflix-metrics.html" title="12. Metrics: Spectator, Servo, and Atlas"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">11. RxJava with Spring MVC</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__polyglot_support_with_sidecar.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi_netflix-metrics.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="netflix-rxjava-springmvc" href="#netflix-rxjava-springmvc"></a>11. RxJava with Spring MVC</h1></div></div></div><p>Spring Cloud Netflix includes <a class="link" href="https://github.com/ReactiveX/RxJava" target="_top">RxJava</a>.</p><div class="blockquote"><blockquote class="blockquote"><p>RxJava is a Java VM implementation of <a class="link" href="http://reactivex.io/" target="_top">Reactive Extensions</a>: a library for composing asynchronous and event-based programs by using observable sequences.</p></blockquote></div><p>Spring Cloud Netflix provides support for returning <code class="literal">rx.Single</code> objects from Spring MVC Controllers. It also supports using <code class="literal">rx.Observable</code> objects for <a class="link" href="https://en.wikipedia.org/wiki/Server-sent_events" target="_top">Server-sent events (SSE)</a>. This can be very convenient if your internal APIs are already built using RxJava (see <a class="xref" href="multi_spring-cloud-feign.html#spring-cloud-feign-hystrix" title="7.4 Feign Hystrix Support">Section 7.4, “Feign Hystrix Support”</a> for examples).</p><p>Here are some examples of using <code class="literal">rx.Single</code>:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RequestMapping(method = RequestMethod.GET, value = "/single")</span></em>
|
||||
<title>11. RxJava with Spring MVC</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-netflix.html" title="Spring Cloud Netflix"><link rel="up" href="multi_spring-cloud-netflix.html" title="Spring Cloud Netflix"><link rel="prev" href="multi__polyglot_support_with_sidecar.html" title="10. Polyglot support with Sidecar"><link rel="next" href="multi_netflix-metrics.html" title="12. Metrics: Spectator, Servo, and Atlas"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">11. RxJava with Spring MVC</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__polyglot_support_with_sidecar.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi_netflix-metrics.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="netflix-rxjava-springmvc" href="#netflix-rxjava-springmvc"></a>11. RxJava with Spring MVC</h1></div></div></div><p>Spring Cloud Netflix includes <a class="link" href="https://github.com/ReactiveX/RxJava" target="_top">RxJava</a>.</p><div class="blockquote"><blockquote class="blockquote"><p>RxJava is a Java VM implementation of <a class="link" href="http://reactivex.io/" target="_top">Reactive Extensions</a>: a library for composing asynchronous and event-based programs by using observable sequences.</p></blockquote></div><p>Spring Cloud Netflix provides support for returning <code class="literal">rx.Single</code> objects from Spring MVC Controllers. It also supports using <code class="literal">rx.Observable</code> objects for <a class="link" href="https://en.wikipedia.org/wiki/Server-sent_events" target="_top">Server-sent events (SSE)</a>. This can be very convenient if your internal APIs are already built using RxJava (see <a class="xref" href="multi_spring-cloud-feign.html#spring-cloud-feign-hystrix" title="7.4 Feign Hystrix Support">Section 7.4, “Feign Hystrix Support”</a> for examples).</p><p>Here are some examples of using <code class="literal">rx.Single</code>:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(method = RequestMethod.GET, value = "/single")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Single<String> single() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> Single.just(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"single value"</span>);
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@RequestMapping(method = RequestMethod.GET, value = "/singleWithResponse")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(method = RequestMethod.GET, value = "/singleWithResponse")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> ResponseEntity<Single<String>> singleWithResponse() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ResponseEntity<>(Single.just(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"single value"</span>),
|
||||
HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@RequestMapping(method = RequestMethod.GET, value = "/singleCreatedWithResponse")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(method = RequestMethod.GET, value = "/singleCreatedWithResponse")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Single<ResponseEntity<String>> singleOuterWithResponse() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> Single.just(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ResponseEntity<>(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"single value"</span>, HttpStatus.CREATED));
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@RequestMapping(method = RequestMethod.GET, value = "/throw")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(method = RequestMethod.GET, value = "/throw")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Single<Object> error() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> Single.error(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RuntimeException(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Unexpected"</span>));
|
||||
}</pre><p>If you have an <code class="literal">Observable</code>, rather than a single, you can use <code class="literal">.toSingle()</code> or <code class="literal">.toList().toSingle()</code>. Here are some examples:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RequestMapping(method = RequestMethod.GET, value = "/single")</span></em>
|
||||
}</pre><p>If you have an <code class="literal">Observable</code>, rather than a single, you can use <code class="literal">.toSingle()</code> or <code class="literal">.toList().toSingle()</code>. Here are some examples:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(method = RequestMethod.GET, value = "/single")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Single<String> single() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> Observable.just(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"single value"</span>).toSingle();
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@RequestMapping(method = RequestMethod.GET, value = "/multiple")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(method = RequestMethod.GET, value = "/multiple")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Single<List<String>> multiple() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> Observable.just(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"multiple"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"values"</span>).toList().toSingle();
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@RequestMapping(method = RequestMethod.GET, value = "/responseWithObservable")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(method = RequestMethod.GET, value = "/responseWithObservable")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> ResponseEntity<Single<String>> responseWithObservable() {
|
||||
|
||||
Observable<String> observable = Observable.just(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"single value"</span>);
|
||||
@@ -38,27 +38,27 @@
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ResponseEntity<>(observable.toSingle(), headers, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@RequestMapping(method = RequestMethod.GET, value = "/timeout")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(method = RequestMethod.GET, value = "/timeout")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Observable<String> timeout() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> Observable.timer(<span class="hl-number">1</span>, TimeUnit.MINUTES).map(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Func1<Long, String>() {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> Observable.timer(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>, TimeUnit.MINUTES).map(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Func1<Long, String>() {
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String call(Long aLong) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"single value"</span>;
|
||||
}
|
||||
});
|
||||
}</pre><p>If you have a streaming endpoint and client, SSE could be an option. To convert <code class="literal">rx.Observable</code> to a Spring <code class="literal">SseEmitter</code> use <code class="literal">RxResponse.sse()</code>. Here are some examples:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RequestMapping(method = RequestMethod.GET, value = "/sse")</span></em>
|
||||
}</pre><p>If you have a streaming endpoint and client, SSE could be an option. To convert <code class="literal">rx.Observable</code> to a Spring <code class="literal">SseEmitter</code> use <code class="literal">RxResponse.sse()</code>. Here are some examples:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(method = RequestMethod.GET, value = "/sse")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> SseEmitter single() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> RxResponse.sse(Observable.just(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"single value"</span>));
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@RequestMapping(method = RequestMethod.GET, value = "/messages")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(method = RequestMethod.GET, value = "/messages")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> SseEmitter messages() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> RxResponse.sse(Observable.just(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"message 1"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"message 2"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"message 3"</span>));
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@RequestMapping(method = RequestMethod.GET, value = "/events")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(method = RequestMethod.GET, value = "/events")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> SseEmitter event() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> RxResponse.sse(APPLICATION_JSON_UTF8,
|
||||
Observable.just(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> EventDto(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Spring io"</span>, getDate(<span class="hl-number">2016</span>, <span class="hl-number">5</span>, <span class="hl-number">19</span>)),
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> EventDto(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"SpringOnePlatform"</span>, getDate(<span class="hl-number">2016</span>, <span class="hl-number">8</span>, <span class="hl-number">1</span>))));
|
||||
Observable.just(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> EventDto(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Spring io"</span>, getDate(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>, <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">5</xslthl:number>, <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">19</xslthl:number>)),
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> EventDto(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"SpringOnePlatform"</span>, getDate(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2016</xslthl:number>, <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">8</xslthl:number>, <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>))));
|
||||
}</pre></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__polyglot_support_with_sidecar.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi_netflix-metrics.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">10. Polyglot support with Sidecar </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-netflix.html">Home</a></td><td width="40%" align="right" valign="top"> 12. Metrics: Spectator, Servo, and Atlas</td></tr></table></div></body></html>
|
||||
@@ -2,8 +2,8 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>2. Service Discovery: Eureka Server</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-netflix.html" title="Spring Cloud Netflix"><link rel="up" href="multi_spring-cloud-netflix.html" title="Spring Cloud Netflix"><link rel="prev" href="multi__service_discovery_eureka_clients.html" title="1. Service Discovery: Eureka Clients"><link rel="next" href="multi__circuit_breaker_hystrix_clients.html" title="3. Circuit Breaker: Hystrix Clients"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">2. Service Discovery: Eureka Server</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__service_discovery_eureka_clients.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__circuit_breaker_hystrix_clients.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="spring-cloud-eureka-server" href="#spring-cloud-eureka-server"></a>2. Service Discovery: Eureka Server</h1></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="netflix-eureka-server-starter" href="#netflix-eureka-server-starter"></a>2.1 How to Include Eureka Server</h2></div></div></div><p>To include Eureka Server in your project use the starter with group <code class="literal">org.springframework.cloud</code>
|
||||
and artifact id <code class="literal">spring-cloud-starter-netflix-eureka-server</code>. See the <a class="link" href="https://projects.spring.io/spring-cloud/" target="_top">Spring Cloud Project page</a>
|
||||
for details on setting up your build system with the current Spring Cloud Release Train.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-cloud-running-eureka-server" href="#spring-cloud-running-eureka-server"></a>2.2 How to Run a Eureka Server</h2></div></div></div><p>Example eureka server;</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@SpringBootApplication</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableEurekaServer</span></em>
|
||||
for details on setting up your build system with the current Spring Cloud Release Train.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-cloud-running-eureka-server" href="#spring-cloud-running-eureka-server"></a>2.2 How to Run a Eureka Server</h2></div></div></div><p>Example eureka server;</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@SpringBootApplication</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableEurekaServer</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> main(String[] args) {
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>7. Declarative REST Client: Feign</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-netflix.html" title="Spring Cloud Netflix"><link rel="up" href="multi_spring-cloud-netflix.html" title="Spring Cloud Netflix"><link rel="prev" href="multi_spring-cloud-ribbon.html" title="6. Client Side Load Balancer: Ribbon"><link rel="next" href="multi__external_configuration_archaius.html" title="8. External Configuration: Archaius"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">7. Declarative REST Client: Feign</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_spring-cloud-ribbon.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__external_configuration_archaius.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="spring-cloud-feign" href="#spring-cloud-feign"></a>7. Declarative REST Client: Feign</h1></div></div></div><p><a class="link" href="https://github.com/Netflix/feign" target="_top">Feign</a> is a declarative web service client. It makes writing web service clients easier. To use Feign create an interface and annotate it. It has pluggable annotation support including Feign annotations and JAX-RS annotations. Feign also supports pluggable encoders and decoders. Spring Cloud adds support for Spring MVC annotations and for using the same <code class="literal">HttpMessageConverters</code> used by default in Spring Web. Spring Cloud integrates Ribbon and Eureka to provide a load balanced http client when using Feign.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="netflix-feign-starter" href="#netflix-feign-starter"></a>7.1 How to Include Feign</h2></div></div></div><p>To include Feign in your project use the starter with group <code class="literal">org.springframework.cloud</code>
|
||||
and artifact id <code class="literal">spring-cloud-starter-openfeign</code>. See the <a class="link" href="https://projects.spring.io/spring-cloud/" target="_top">Spring Cloud Project page</a>
|
||||
for details on setting up your build system with the current Spring Cloud Release Train.</p><p>Example spring boot app</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@ComponentScan</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableAutoConfiguration</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableFeignClients</span></em>
|
||||
for details on setting up your build system with the current Spring Cloud Release Train.</p><p>Example spring boot app</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@ComponentScan</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableAutoConfiguration</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableFeignClients</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> main(String[] args) {
|
||||
@@ -13,13 +13,13 @@ for details on setting up your build system with the current Spring Cloud Releas
|
||||
}
|
||||
|
||||
}</pre><p><b>StoreClient.java. </b>
|
||||
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@FeignClient("stores")</span></em>
|
||||
</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@FeignClient("stores")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> StoreClient {
|
||||
<em><span class="hl-annotation" style="color: gray">@RequestMapping(method = RequestMethod.GET, value = "/stores")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(method = RequestMethod.GET, value = "/stores")</xslthl:annotation>
|
||||
List<Store> getStores();
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")</span></em>
|
||||
Store update(<em><span class="hl-annotation" style="color: gray">@PathVariable("storeId")</span></em> Long storeId, Store store);
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")</xslthl:annotation>
|
||||
Store update(<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@PathVariable("storeId")</xslthl:annotation> Long storeId, Store store);
|
||||
}</pre><p>
|
||||
</p><p>In the <code class="literal">@FeignClient</code> annotation the String value ("stores" above) is
|
||||
an arbitrary client name, which is used to create a Ribbon load
|
||||
@@ -34,21 +34,21 @@ it will resolve the service in the Eureka service registry. If you
|
||||
don’t want to use Eureka, you can simply configure a list of servers
|
||||
in your external configuration (see
|
||||
<a class="link" href="multi_spring-cloud-ribbon.html#spring-cloud-ribbon-without-eureka" title="6.6 Example: How to Use Ribbon Without Eureka">above for example</a>).</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-cloud-feign-overriding-defaults" href="#spring-cloud-feign-overriding-defaults"></a>7.2 Overriding Feign Defaults</h2></div></div></div><p>A central concept in Spring Cloud’s Feign support is that of the named client. Each feign client is part of an ensemble of components that work together to contact a remote server on demand, and the ensemble has a name that you give it as an application developer using the <code class="literal">@FeignClient</code> annotation. Spring Cloud creates a new ensemble as an
|
||||
<code class="literal">ApplicationContext</code> on demand for each named client using <code class="literal">FeignClientsConfiguration</code>. This contains (amongst other things) an <code class="literal">feign.Decoder</code>, a <code class="literal">feign.Encoder</code>, and a <code class="literal">feign.Contract</code>.</p><p>Spring Cloud lets you take full control of the feign client by declaring additional configuration (on top of the <code class="literal">FeignClientsConfiguration</code>) using <code class="literal">@FeignClient</code>. Example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@FeignClient(name = "stores", configuration = FooConfiguration.class)</span></em>
|
||||
<code class="literal">ApplicationContext</code> on demand for each named client using <code class="literal">FeignClientsConfiguration</code>. This contains (amongst other things) an <code class="literal">feign.Decoder</code>, a <code class="literal">feign.Encoder</code>, and a <code class="literal">feign.Contract</code>.</p><p>Spring Cloud lets you take full control of the feign client by declaring additional configuration (on top of the <code class="literal">FeignClientsConfiguration</code>) using <code class="literal">@FeignClient</code>. Example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@FeignClient(name = "stores", configuration = FooConfiguration.class)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> StoreClient {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//..</span>
|
||||
}</pre><p>In this case the client is composed from the components already in <code class="literal">FeignClientsConfiguration</code> together with any in <code class="literal">FooConfiguration</code> (where the latter will override the former).</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p><code class="literal">FooConfiguration</code> does not need to be annotated with <code class="literal">@Configuration</code>. However, if it is, then take care to exclude it from any <code class="literal">@ComponentScan</code> that would otherwise include this configuration as it will become the default source for <code class="literal">feign.Decoder</code>, <code class="literal">feign.Encoder</code>, <code class="literal">feign.Contract</code>, etc., when specified. This can be avoided by putting it in a separate, non-overlapping package from any <code class="literal">@ComponentScan</code> or <code class="literal">@SpringBootApplication</code>, or it can be explicitly excluded in <code class="literal">@ComponentScan</code>.</p></td></tr></table></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The <code class="literal">serviceId</code> attribute is now deprecated in favor of the <code class="literal">name</code> attribute.</p></td></tr></table></div><div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Warning"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="images/warning.png"></td><th align="left">Warning</th></tr><tr><td align="left" valign="top"><p>Previously, using the <code class="literal">url</code> attribute, did not require the <code class="literal">name</code> attribute. Using <code class="literal">name</code> is now required.</p></td></tr></table></div><p>Placeholders are supported in the <code class="literal">name</code> and <code class="literal">url</code> attributes.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@FeignClient(name = "${feign.name}", url = "${feign.url}")</span></em>
|
||||
}</pre><p>In this case the client is composed from the components already in <code class="literal">FeignClientsConfiguration</code> together with any in <code class="literal">FooConfiguration</code> (where the latter will override the former).</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p><code class="literal">FooConfiguration</code> does not need to be annotated with <code class="literal">@Configuration</code>. However, if it is, then take care to exclude it from any <code class="literal">@ComponentScan</code> that would otherwise include this configuration as it will become the default source for <code class="literal">feign.Decoder</code>, <code class="literal">feign.Encoder</code>, <code class="literal">feign.Contract</code>, etc., when specified. This can be avoided by putting it in a separate, non-overlapping package from any <code class="literal">@ComponentScan</code> or <code class="literal">@SpringBootApplication</code>, or it can be explicitly excluded in <code class="literal">@ComponentScan</code>.</p></td></tr></table></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The <code class="literal">serviceId</code> attribute is now deprecated in favor of the <code class="literal">name</code> attribute.</p></td></tr></table></div><div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Warning"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="images/warning.png"></td><th align="left">Warning</th></tr><tr><td align="left" valign="top"><p>Previously, using the <code class="literal">url</code> attribute, did not require the <code class="literal">name</code> attribute. Using <code class="literal">name</code> is now required.</p></td></tr></table></div><p>Placeholders are supported in the <code class="literal">name</code> and <code class="literal">url</code> attributes.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@FeignClient(name = "${feign.name}", url = "${feign.url}")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> StoreClient {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//..</span>
|
||||
}</pre><p>Spring Cloud Netflix provides the following beans by default for feign (<code class="literal">BeanType</code> beanName: <code class="literal">ClassName</code>):</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">Decoder</code> feignDecoder: <code class="literal">ResponseEntityDecoder</code> (which wraps a <code class="literal">SpringDecoder</code>)</li><li class="listitem"><code class="literal">Encoder</code> feignEncoder: <code class="literal">SpringEncoder</code></li><li class="listitem"><code class="literal">Logger</code> feignLogger: <code class="literal">Slf4jLogger</code></li><li class="listitem"><code class="literal">Contract</code> feignContract: <code class="literal">SpringMvcContract</code></li><li class="listitem"><code class="literal">Feign.Builder</code> feignBuilder: <code class="literal">HystrixFeign.Builder</code></li><li class="listitem"><code class="literal">Client</code> feignClient: if Ribbon is enabled it is a <code class="literal">LoadBalancerFeignClient</code>, otherwise the default feign client is used.</li></ul></div><p>The OkHttpClient and ApacheHttpClient feign clients can be used by setting <code class="literal">feign.okhttp.enabled</code> or <code class="literal">feign.httpclient.enabled</code> to <code class="literal">true</code>, respectively, and having them on the classpath.
|
||||
You can customize the HTTP client used by providing a bean of either <code class="literal">ClosableHttpClient</code> when using Apache or <code class="literal">OkHttpClient</code> whe using OK HTTP.</p><p>Spring Cloud Netflix <span class="emphasis"><em>does not</em></span> provide the following beans by default for feign, but still looks up beans of these types from the application context to create the feign client:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">Logger.Level</code></li><li class="listitem"><code class="literal">Retryer</code></li><li class="listitem"><code class="literal">ErrorDecoder</code></li><li class="listitem"><code class="literal">Request.Options</code></li><li class="listitem"><code class="literal">Collection<RequestInterceptor></code></li><li class="listitem"><code class="literal">SetterFactory</code></li></ul></div><p>Creating a bean of one of those type and placing it in a <code class="literal">@FeignClient</code> configuration (such as <code class="literal">FooConfiguration</code> above) allows you to override each one of the beans described. Example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||
You can customize the HTTP client used by providing a bean of either <code class="literal">ClosableHttpClient</code> when using Apache or <code class="literal">OkHttpClient</code> whe using OK HTTP.</p><p>Spring Cloud Netflix <span class="emphasis"><em>does not</em></span> provide the following beans by default for feign, but still looks up beans of these types from the application context to create the feign client:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">Logger.Level</code></li><li class="listitem"><code class="literal">Retryer</code></li><li class="listitem"><code class="literal">ErrorDecoder</code></li><li class="listitem"><code class="literal">Request.Options</code></li><li class="listitem"><code class="literal">Collection<RequestInterceptor></code></li><li class="listitem"><code class="literal">SetterFactory</code></li></ul></div><p>Creating a bean of one of those type and placing it in a <code class="literal">@FeignClient</code> configuration (such as <code class="literal">FooConfiguration</code> above) allows you to override each one of the beans described. Example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> FooConfiguration {
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Contract feignContract() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> feign.Contract.Default();
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> BasicAuthRequestInterceptor(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"user"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"password"</span>);
|
||||
}
|
||||
@@ -56,8 +56,8 @@ You can customize the HTTP client used by providing a bean of either <code class
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> client</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> config</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> feignName</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> connectTimeout</span>: <span class="hl-number">5000</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> readTimeout</span>: <span class="hl-number">5000</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> connectTimeout</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">5000</xslthl:number>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> readTimeout</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">5000</xslthl:number>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> loggerLevel</span>: full
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> errorDecoder</span>: com.example.SimpleErrorDecoder
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> retryer</span>: com.example.SimpleRetryer
|
||||
@@ -68,8 +68,8 @@ You can customize the HTTP client used by providing a bean of either <code class
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> client</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> config</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> default</span>:
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> connectTimeout</span>: <span class="hl-number">5000</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> readTimeout</span>: <span class="hl-number">5000</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> connectTimeout</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">5000</xslthl:number>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> readTimeout</span>: <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">5000</xslthl:number>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> loggerLevel</span>: basic</pre><p>If we create both <code class="literal">@Configuration</code> bean and configuration properties, configuration properties will win.
|
||||
It will override <code class="literal">@Configuration</code> values. But if you want to change the priority to <code class="literal">@Configuration</code>,
|
||||
you can change <code class="literal">feign.client.default-to-properties</code> to <code class="literal">false</code>.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>If you need to use <code class="literal">ThreadLocal</code> bound variables in your <code class="literal">RequestInterceptor`s you will need to either set the
|
||||
@@ -88,14 +88,14 @@ thread isolation strategy for Hystrix to `SEMAPHORE</code> or disable Hystrix in
|
||||
possible using the methods above. In this case you can create Clients using the
|
||||
<a class="link" href="https://github.com/OpenFeign/feign/#basics" target="_top">Feign Builder API</a>. Below is an example
|
||||
which creates two Feign Clients with the same interface but configures each one with
|
||||
a separate request interceptor.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Import(FeignClientsConfiguration.class)</span></em>
|
||||
a separate request interceptor.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Import(FeignClientsConfiguration.class)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> FooController {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> FooClient fooClient;
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> FooClient adminClient;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> FooController(
|
||||
Decoder decoder, Encoder encoder, Client client) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.fooClient = Feign.builder().client(client)
|
||||
@@ -110,62 +110,62 @@ a separate request interceptor.</p><pre class="programlisting"><em><span class="
|
||||
.target(FooClient.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://PROD-SVC"</span>);
|
||||
}
|
||||
}</pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>In the above example <code class="literal">FeignClientsConfiguration.class</code> is the default configuration
|
||||
provided by Spring Cloud Netflix.</p></td></tr></table></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p><code class="literal">PROD-SVC</code> is the name of the service the Clients will be making requests to.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-cloud-feign-hystrix" href="#spring-cloud-feign-hystrix"></a>7.4 Feign Hystrix Support</h2></div></div></div><p>If Hystrix is on the classpath and <code class="literal">feign.hystrix.enabled=true</code>, Feign will wrap all methods with a circuit breaker. Returning a <code class="literal">com.netflix.hystrix.HystrixCommand</code> is also available. This lets you use reactive patterns (with a call to <code class="literal">.toObservable()</code> or <code class="literal">.observe()</code> or asynchronous use (with a call to <code class="literal">.queue()</code>).</p><p>To disable Hystrix support on a per-client basis create a vanilla <code class="literal">Feign.Builder</code> with the "prototype" scope, e.g.:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||
provided by Spring Cloud Netflix.</p></td></tr></table></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p><code class="literal">PROD-SVC</code> is the name of the service the Clients will be making requests to.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-cloud-feign-hystrix" href="#spring-cloud-feign-hystrix"></a>7.4 Feign Hystrix Support</h2></div></div></div><p>If Hystrix is on the classpath and <code class="literal">feign.hystrix.enabled=true</code>, Feign will wrap all methods with a circuit breaker. Returning a <code class="literal">com.netflix.hystrix.HystrixCommand</code> is also available. This lets you use reactive patterns (with a call to <code class="literal">.toObservable()</code> or <code class="literal">.observe()</code> or asynchronous use (with a call to <code class="literal">.queue()</code>).</p><p>To disable Hystrix support on a per-client basis create a vanilla <code class="literal">Feign.Builder</code> with the "prototype" scope, e.g.:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> FooConfiguration {
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@Scope("prototype")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Scope("prototype")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Feign.Builder feignBuilder() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> Feign.builder();
|
||||
}
|
||||
}</pre><div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Warning"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="images/warning.png"></td><th align="left">Warning</th></tr><tr><td align="left" valign="top"><p>Prior to the Spring Cloud Dalston release, if Hystrix was on the classpath Feign would have wrapped
|
||||
all methods in a circuit breaker by default. This default behavior was changed in Spring Cloud Dalston in
|
||||
favor for an opt-in approach.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-cloud-feign-hystrix-fallback" href="#spring-cloud-feign-hystrix-fallback"></a>7.5 Feign Hystrix Fallbacks</h2></div></div></div><p>Hystrix supports the notion of a fallback: a default code path that is executed when they circuit is open or there is an error. To enable fallbacks for a given <code class="literal">@FeignClient</code> set the <code class="literal">fallback</code> attribute to the class name that implements the fallback. You also need to declare your implementation as a Spring bean.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@FeignClient(name = "hello", fallback = HystrixClientFallback.class)</span></em>
|
||||
favor for an opt-in approach.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-cloud-feign-hystrix-fallback" href="#spring-cloud-feign-hystrix-fallback"></a>7.5 Feign Hystrix Fallbacks</h2></div></div></div><p>Hystrix supports the notion of a fallback: a default code path that is executed when they circuit is open or there is an error. To enable fallbacks for a given <code class="literal">@FeignClient</code> set the <code class="literal">fallback</code> attribute to the class name that implements the fallback. You also need to declare your implementation as a Spring bean.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@FeignClient(name = "hello", fallback = HystrixClientFallback.class)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">protected</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> HystrixClient {
|
||||
<em><span class="hl-annotation" style="color: gray">@RequestMapping(method = RequestMethod.GET, value = "/hello")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(method = RequestMethod.GET, value = "/hello")</xslthl:annotation>
|
||||
Hello iFailSometimes();
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> HystrixClientFallback <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">implements</span> HystrixClient {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Hello iFailSometimes() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Hello(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fallback"</span>);
|
||||
}
|
||||
}</pre><p>If one needs access to the cause that made the fallback trigger, one can use the <code class="literal">fallbackFactory</code> attribute inside <code class="literal">@FeignClient</code>.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@FeignClient(name = "hello", fallbackFactory = HystrixClientFallbackFactory.class)</span></em>
|
||||
}</pre><p>If one needs access to the cause that made the fallback trigger, one can use the <code class="literal">fallbackFactory</code> attribute inside <code class="literal">@FeignClient</code>.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@FeignClient(name = "hello", fallbackFactory = HystrixClientFallbackFactory.class)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">protected</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> HystrixClient {
|
||||
<em><span class="hl-annotation" style="color: gray">@RequestMapping(method = RequestMethod.GET, value = "/hello")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(method = RequestMethod.GET, value = "/hello")</xslthl:annotation>
|
||||
Hello iFailSometimes();
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Component</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Component</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> HystrixClientFallbackFactory <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">implements</span> FallbackFactory<HystrixClient> {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> HystrixClient create(Throwable cause) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> HystrixClient() {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Hello iFailSometimes() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Hello(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"fallback; reason was: "</span> + cause.getMessage());
|
||||
}
|
||||
};
|
||||
}
|
||||
}</pre><div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Warning"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="images/warning.png"></td><th align="left">Warning</th></tr><tr><td align="left" valign="top"><p>There is a limitation with the implementation of fallbacks in Feign and how Hystrix fallbacks work. Fallbacks are currently not supported for methods that return <code class="literal">com.netflix.hystrix.HystrixCommand</code> and <code class="literal">rx.Observable</code>.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_feign_and_literal_primary_literal" href="#_feign_and_literal_primary_literal"></a>7.6 Feign and <code class="literal">@Primary</code></h2></div></div></div><p>When using Feign with Hystrix fallbacks, there are multiple beans in the <code class="literal">ApplicationContext</code> of the same type. This will cause <code class="literal">@Autowired</code> to not work because there isn’t exactly one bean, or one marked as primary. To work around this, Spring Cloud Netflix marks all Feign instances as <code class="literal">@Primary</code>, so Spring Framework will know which bean to inject. In some cases, this may not be desirable. To turn off this behavior set the <code class="literal">primary</code> attribute of <code class="literal">@FeignClient</code> to false.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@FeignClient(name = "hello", primary = false)</span></em>
|
||||
}</pre><div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Warning"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="images/warning.png"></td><th align="left">Warning</th></tr><tr><td align="left" valign="top"><p>There is a limitation with the implementation of fallbacks in Feign and how Hystrix fallbacks work. Fallbacks are currently not supported for methods that return <code class="literal">com.netflix.hystrix.HystrixCommand</code> and <code class="literal">rx.Observable</code>.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_feign_and_literal_primary_literal" href="#_feign_and_literal_primary_literal"></a>7.6 Feign and <code class="literal">@Primary</code></h2></div></div></div><p>When using Feign with Hystrix fallbacks, there are multiple beans in the <code class="literal">ApplicationContext</code> of the same type. This will cause <code class="literal">@Autowired</code> to not work because there isn’t exactly one bean, or one marked as primary. To work around this, Spring Cloud Netflix marks all Feign instances as <code class="literal">@Primary</code>, so Spring Framework will know which bean to inject. In some cases, this may not be desirable. To turn off this behavior set the <code class="literal">primary</code> attribute of <code class="literal">@FeignClient</code> to false.</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@FeignClient(name = "hello", primary = false)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> HelloClient {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// methods here</span>
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-cloud-feign-inheritance" href="#spring-cloud-feign-inheritance"></a>7.7 Feign Inheritance Support</h2></div></div></div><p>Feign supports boilerplate apis via single-inheritance interfaces.
|
||||
This allows grouping common operations into convenient base interfaces.</p><p><b>UserService.java. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> UserService {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@RequestMapping(method = RequestMethod.GET, value ="/users/{id}")</span></em>
|
||||
User getUser(<em><span class="hl-annotation" style="color: gray">@PathVariable("id")</span></em> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">long</span> id);
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RequestMapping(method = RequestMethod.GET, value ="/users/{id}")</xslthl:annotation>
|
||||
User getUser(<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@PathVariable("id")</xslthl:annotation> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">long</span> id);
|
||||
}</pre><p>
|
||||
</p><p><b>UserResource.java. </b>
|
||||
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RestController</span></em>
|
||||
</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RestController</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> UserResource <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">implements</span> UserService {
|
||||
|
||||
}</pre><p>
|
||||
</p><p><b>UserClient.java. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">package</span> project.user;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@FeignClient("users")</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@FeignClient("users")</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> UserClient <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> UserService {
|
||||
|
||||
}</pre><p>
|
||||
@@ -176,11 +176,11 @@ mapping is not inherited).</p></td></tr></table></div></div><div class="section"
|
||||
Feign requests. You can do this by enabling one of the properties:</p><pre class="programlisting">feign.compression.request.enabled=true
|
||||
feign.compression.response.enabled=true</pre><p>Feign request compression gives you settings similar to what you may set for your web server:</p><pre class="programlisting">feign.compression.request.enabled=true
|
||||
feign.compression.request.mime-types=text/xml,application/xml,application/json
|
||||
feign.compression.request.min-request-size=<span class="hl-number">2048</span></pre><p>These properties allow you to be selective about the compressed media types and minimum request threshold length.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_feign_logging" href="#_feign_logging"></a>7.9 Feign logging</h2></div></div></div><p>A logger is created for each Feign client created. By default the name of the logger is the full class name of the interface used to create the Feign client. Feign logging only responds to the <code class="literal">DEBUG</code> level.</p><p><b>application.yml. </b>
|
||||
feign.compression.request.min-request-size=<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">2048</xslthl:number></pre><p>These properties allow you to be selective about the compressed media types and minimum request threshold length.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_feign_logging" href="#_feign_logging"></a>7.9 Feign logging</h2></div></div></div><p>A logger is created for each Feign client created. By default the name of the logger is the full class name of the interface used to create the Feign client. Feign logging only responds to the <code class="literal">DEBUG</code> level.</p><p><b>application.yml. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">logging.level.project.user.UserClient</span>: DEBUG</pre><p>
|
||||
</p><p>The <code class="literal">Logger.Level</code> object that you may configure per client, tells Feign how much to log. Choices are:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">NONE</code>, No logging (<span class="strong"><strong>DEFAULT</strong></span>).</li><li class="listitem"><code class="literal">BASIC</code>, Log only the request method and URL and the response status code and execution time.</li><li class="listitem"><code class="literal">HEADERS</code>, Log the basic information along with request and response headers.</li><li class="listitem"><code class="literal">FULL</code>, Log the headers, body, and metadata for both requests and responses.</li></ul></div><p>For example, the following would set the <code class="literal">Logger.Level</code> to <code class="literal">FULL</code>:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||
</p><p>The <code class="literal">Logger.Level</code> object that you may configure per client, tells Feign how much to log. Choices are:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">NONE</code>, No logging (<span class="strong"><strong>DEFAULT</strong></span>).</li><li class="listitem"><code class="literal">BASIC</code>, Log only the request method and URL and the response status code and execution time.</li><li class="listitem"><code class="literal">HEADERS</code>, Log the basic information along with request and response headers.</li><li class="listitem"><code class="literal">FULL</code>, Log the headers, body, and metadata for both requests and responses.</li></ul></div><p>For example, the following would set the <code class="literal">Logger.Level</code> to <code class="literal">FULL</code>:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> FooConfiguration {
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
||||
Logger.Level feignLoggerLevel() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> Logger.Level.FULL;
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ configuration files. The native options can
|
||||
be inspected as static fields in <a class="link" href="https://github.com/Netflix/ribbon/blob/master/ribbon-core/src/main/java/com/netflix/client/config/CommonClientConfigKey.java" target="_top"><code class="literal">CommonClientConfigKey</code></a> (part of
|
||||
ribbon-core).</p><p>Spring Cloud also lets you take full control of the client by
|
||||
declaring additional configuration (on top of the
|
||||
<code class="literal">RibbonClientConfiguration</code>) using <code class="literal">@RibbonClient</code>. Example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@RibbonClient(name = "foo", configuration = FooConfiguration.class)</span></em>
|
||||
<code class="literal">RibbonClientConfiguration</code>) using <code class="literal">@RibbonClient</code>. Example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RibbonClient(name = "foo", configuration = FooConfiguration.class)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> TestConfiguration {
|
||||
}</pre><p>In this case the client is composed from the components already in
|
||||
<code class="literal">RibbonClientConfiguration</code> together with any in <code class="literal">FooConfiguration</code>
|
||||
@@ -32,20 +32,20 @@ separate, non-overlapping package, or specify the packages to scan
|
||||
explicitly in the <code class="literal">@ComponentScan</code>).</p></td></tr></table></div><p>Spring Cloud Netflix provides the following beans by default for ribbon
|
||||
(<code class="literal">BeanType</code> beanName: <code class="literal">ClassName</code>):</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">IClientConfig</code> ribbonClientConfig: <code class="literal">DefaultClientConfigImpl</code></li><li class="listitem"><code class="literal">IRule</code> ribbonRule: <code class="literal">ZoneAvoidanceRule</code></li><li class="listitem"><code class="literal">IPing</code> ribbonPing: <code class="literal">DummyPing</code></li><li class="listitem"><code class="literal">ServerList<Server></code> ribbonServerList: <code class="literal">ConfigurationBasedServerList</code></li><li class="listitem"><code class="literal">ServerListFilter<Server></code> ribbonServerListFilter: <code class="literal">ZonePreferenceServerListFilter</code></li><li class="listitem"><code class="literal">ILoadBalancer</code> ribbonLoadBalancer: <code class="literal">ZoneAwareLoadBalancer</code></li><li class="listitem"><code class="literal">ServerListUpdater</code> ribbonServerListUpdater: <code class="literal">PollingServerListUpdater</code></li></ul></div><p>Creating a bean of one of those type and placing it in a <code class="literal">@RibbonClient</code>
|
||||
configuration (such as <code class="literal">FooConfiguration</code> above) allows you to override each
|
||||
one of the beans described. Example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||
one of the beans described. Example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">protected</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> FooConfiguration {
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> ZonePreferenceServerListFilter serverListFilter() {
|
||||
ZonePreferenceServerListFilter filter = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ZonePreferenceServerListFilter();
|
||||
filter.setZone(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"myTestZone"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> filter;
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> IPing ribbonPing() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> PingUrl();
|
||||
}
|
||||
}</pre><p>This replaces the <code class="literal">NoOpPing</code> with <code class="literal">PingUrl</code> and provides a custom <code class="literal">serverListFilter</code></p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_customizing_default_for_all_ribbon_clients" href="#_customizing_default_for_all_ribbon_clients"></a>6.3 Customizing default for all Ribbon Clients</h2></div></div></div><p>A default configuration can be provided for all Ribbon Clients using the <code class="literal">@RibbonClients</code> annotation and registering a default configuration as shown in the following example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@RibbonClients(defaultConfiguration = DefaultRibbonConfig.class)</span></em>
|
||||
}</pre><p>This replaces the <code class="literal">NoOpPing</code> with <code class="literal">PingUrl</code> and provides a custom <code class="literal">serverListFilter</code></p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_customizing_default_for_all_ribbon_clients" href="#_customizing_default_for_all_ribbon_clients"></a>6.3 Customizing default for all Ribbon Clients</h2></div></div></div><p>A default configuration can be provided for all Ribbon Clients using the <code class="literal">@RibbonClients</code> annotation and registering a default configuration as shown in the following example:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@RibbonClients(defaultConfiguration = DefaultRibbonConfig.class)</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> RibbonClientDefaultConfigurationTestsConfig {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> BazServiceList <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> ConfigurationBasedServerList {
|
||||
@@ -55,25 +55,25 @@ one of the beans described. Example:</p><pre class="programlisting"><em><span c
|
||||
}
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> DefaultRibbonConfig {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> IRule ribbonRule() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> BestAvailableRule();
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> IPing ribbonPing() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> PingUrl();
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> ServerList<Server> ribbonServerList(IClientConfig config) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> RibbonClientDefaultConfigurationTestsConfig.BazServiceList(config);
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> ServerListSubsetFilter serverListFilter() {
|
||||
ServerListSubsetFilter filter = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ServerListSubsetFilter();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> filter;
|
||||
@@ -125,7 +125,7 @@ disable the use of Eureka in Ribbon.</p><p><b>application.yml. </b>
|
||||
eureka:
|
||||
enabled: false</pre><p>
|
||||
</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_using_the_ribbon_api_directly" href="#_using_the_ribbon_api_directly"></a>6.8 Using the Ribbon API Directly</h2></div></div></div><p>You can also use the <code class="literal">LoadBalancerClient</code> directly. Example:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyClass {
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
|
||||
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> LoadBalancerClient loadBalancer;
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> doStuff() {
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user