125 lines
27 KiB
HTML
125 lines
27 KiB
HTML
<html><head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
|
<title>16. Client Side Load Balancer: Ribbon</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.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_netflix.html" title="Part III. Spring Cloud Netflix"><link rel="prev" href="multi__hystrix_timeouts_and_ribbon_clients.html" title="15. Hystrix Timeouts And Ribbon Clients"><link rel="next" href="multi__external_configuration_archaius.html" title="17. 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">16. Client Side Load Balancer: Ribbon</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__hystrix_timeouts_and_ribbon_clients.html">Prev</a> </td><th width="60%" align="center">Part III. Spring Cloud Netflix</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><h2 class="title"><a name="spring-cloud-ribbon" href="#spring-cloud-ribbon"></a>16. Client Side Load Balancer: Ribbon</h2></div></div></div><p>Ribbon is a client-side load balancer that gives you a lot of control over the behavior of HTTP and TCP clients.
|
|
Feign already uses Ribbon, so, if you use <code class="literal">@FeignClient</code>, this section also applies.</p><p>A central concept in Ribbon is that of the named client.
|
|
Each load balancer 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 (for example, by using the <code class="literal">@FeignClient</code> annotation).
|
|
On demand, Spring Cloud creates a new ensemble as an <code class="literal">ApplicationContext</code> for each named client by using
|
|
<code class="literal">RibbonClientConfiguration</code>.
|
|
This contains (amongst other things) an <code class="literal">ILoadBalancer</code>, a <code class="literal">RestClient</code>, and a <code class="literal">ServerListFilter</code>.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="netflix-ribbon-starter" href="#netflix-ribbon-starter"></a>16.1 How to Include Ribbon</h2></div></div></div><p>To include Ribbon in your project, use the starter with a group ID of <code class="literal">org.springframework.cloud</code> and an artifact ID of <code class="literal">spring-cloud-starter-netflix-ribbon</code>.
|
|
See the <a class="link" href="http://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="_customizing_the_ribbon_client" href="#_customizing_the_ribbon_client"></a>16.2 Customizing the Ribbon Client</h2></div></div></div><p>You can configure some bits of a Ribbon client by using external properties in <code class="literal"><client>.ribbon.*</code>, which is similar to using the Netflix APIs natively, except that you can use Spring Boot 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>, as shown in the following 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 = "custom", configuration = CustomConfiguration.class)</span></em>
|
|
<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">CustomConfiguration</code> (where the latter generally overrides the former).</p><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>The <code class="literal">CustomConfiguration</code> clas must be a <code class="literal">@Configuration</code> class, but take care that it is not in a <code class="literal">@ComponentScan</code> for the main application context.
|
|
Otherwise, it is shared by all the <code class="literal">@RibbonClients</code>. If you use <code class="literal">@ComponentScan</code> (or <code class="literal">@SpringBootApplication</code>), you need to take steps to avoid it being included (for instance, you can put it in a separate, non-overlapping package or specify the packages to scan explicitly in the <code class="literal">@ComponentScan</code>).</p></td></tr></table></div><p>The following table shows the beans that Spring Cloud Netflix provides by default for Ribbon:</p><div class="informaltable"><table style="border-collapse: collapse;border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; " width="60%"><colgroup><col class="col_1"><col class="col_2"><col class="col_3"></colgroup><thead><tr><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center" valign="top">Bean Type</th><th style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="center" valign="top">Bean Name</th><th style="border-bottom: 0.5pt solid ; " align="center" valign="top">Class Name</th></tr></thead><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">IClientConfig</code></p></td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">ribbonClientConfig</code></p></td><td style="border-bottom: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">DefaultClientConfigImpl</code></p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">IRule</code></p></td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">ribbonRule</code></p></td><td style="border-bottom: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">ZoneAvoidanceRule</code></p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">IPing</code></p></td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">ribbonPing</code></p></td><td style="border-bottom: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">DummyPing</code></p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">ServerList<Server></code></p></td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">ribbonServerList</code></p></td><td style="border-bottom: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">ConfigurationBasedServerList</code></p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">ServerListFilter<Server></code></p></td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">ribbonServerListFilter</code></p></td><td style="border-bottom: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">ZonePreferenceServerListFilter</code></p></td></tr><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">ILoadBalancer</code></p></td><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">ribbonLoadBalancer</code></p></td><td style="border-bottom: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">ZoneAwareLoadBalancer</code></p></td></tr><tr><td style="border-right: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">ServerListUpdater</code></p></td><td style="border-right: 0.5pt solid ; " align="left" valign="top"><p><code class="literal">ribbonServerListUpdater</code></p></td><td style="" align="left" valign="top"><p><code class="literal">PollingServerListUpdater</code></p></td></tr></tbody></table></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) lets you override each one of the beans described, as shown in the following example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
|
<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>
|
|
<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>
|
|
<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>The include statement in the preceding example replaces <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_the_default_for_all_ribbon_clients" href="#_customizing_the_default_for_all_ribbon_clients"></a>16.3 Customizing the Default for All Ribbon Clients</h2></div></div></div><p>A default configuration can be provided for all Ribbon Clients by 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>
|
|
<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 {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> BazServiceList(IClientConfig config) {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">super</span>.initWithNiwsConfig(config);
|
|
}
|
|
}
|
|
}
|
|
|
|
<em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
|
<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>
|
|
<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>
|
|
<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>
|
|
<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>
|
|
<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;
|
|
}
|
|
|
|
}</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_customizing_the_ribbon_client_by_setting_properties" href="#_customizing_the_ribbon_client_by_setting_properties"></a>16.4 Customizing the Ribbon Client by Setting Properties</h2></div></div></div><p>Starting with version 1.2.0, Spring Cloud Netflix now supports customizing Ribbon clients by setting properties to be compatible with the <a class="link" href="https://github.com/Netflix/ribbon/wiki/Working-with-load-balancers#components-of-load-balancer" target="_top">Ribbon documentation</a>.</p><p>This lets you change behavior at start up time in different environments.</p><p>The following list shows the supported properties>:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal"><clientName>.ribbon.NFLoadBalancerClassName</code>: Should implement <code class="literal">ILoadBalancer</code></li><li class="listitem"><code class="literal"><clientName>.ribbon.NFLoadBalancerRuleClassName</code>: Should implement <code class="literal">IRule</code></li><li class="listitem"><code class="literal"><clientName>.ribbon.NFLoadBalancerPingClassName</code>: Should implement <code class="literal">IPing</code></li><li class="listitem"><code class="literal"><clientName>.ribbon.NIWSServerListClassName</code>: Should implement <code class="literal">ServerList</code></li><li class="listitem"><code class="literal"><clientName>.ribbon.NIWSServerListFilterClassName</code>: Should implement <code class="literal">ServerListFilter</code></li></ul></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>Classes defined in these properties have precedence over beans defined by using <code class="literal">@RibbonClient(configuration=MyRibbonConfig.class)</code> and the defaults provided by Spring Cloud Netflix.</p></td></tr></table></div><p>To set the <code class="literal">IRule</code> for a service name called <code class="literal">users</code>, you could set the following properties:</p><p><b>application.yml. </b>
|
|
</p><pre class="screen">users:
|
|
ribbon:
|
|
NIWSServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList
|
|
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule</pre><p>
|
|
</p><p>See the <a class="link" href="https://github.com/Netflix/ribbon/wiki/Working-with-load-balancers" target="_top">Ribbon documentation</a> for implementations provided by Ribbon.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_using_ribbon_with_eureka" href="#_using_ribbon_with_eureka"></a>16.5 Using Ribbon with Eureka</h2></div></div></div><p>When Eureka is used in conjunction with Ribbon (that is, both are on the classpath), the <code class="literal">ribbonServerList</code> is overridden with an extension of <code class="literal">DiscoveryEnabledNIWSServerList</code>, which populates the list of servers from Eureka.
|
|
It also replaces the <code class="literal">IPing</code> interface with <code class="literal">NIWSDiscoveryPing</code>, which delegates to Eureka to determine if a server is up.
|
|
The <code class="literal">ServerList</code> that is installed by default is a <code class="literal">DomainExtractingServerList</code>. Its purpose is to make metadata available to the load balancer without using AWS AMI metadata (which is what Netflix relies on).
|
|
By default, the server list is constructed with “zone” information, as provided in the instance metadata (so, on the remote clients, set <code class="literal">eureka.instance.metadataMap.zone</code>).
|
|
If that is missing and if the <code class="literal">approximateZoneFromHostname</code> flag is set, it can use the domain name from the server hostname as a proxy for the zone.
|
|
Once the zone information is available, it can be used in a <code class="literal">ServerListFilter</code>.
|
|
By default, it is used to locate a server in the same zone as the client, because the default is a <code class="literal">ZonePreferenceServerListFilter</code>.
|
|
By default, the zone of the client is determined in the same way as the remote instances (that is, through <code class="literal">eureka.instance.metadataMap.zone</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>The orthodox “archaius” way to set the client zone is through a configuration property called "@zone".
|
|
If it is available, Spring Cloud uses that in preference to all other settings (note that the key must be quoted in YAML configuration).</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>If there is no other source of zone data, then a guess is made, based on the client configuration (as opposed to the instance configuration).
|
|
We take <code class="literal">eureka.client.availabilityZones</code>, which is a map from region name to a list of zones, and pull out the first zone for the instance’s own region (that is, the <code class="literal">eureka.client.region</code>, which defaults to "us-east-1", for compatibility with native Netflix).</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-cloud-ribbon-without-eureka" href="#spring-cloud-ribbon-without-eureka"></a>16.6 Example: How to Use Ribbon Without Eureka</h2></div></div></div><p>Eureka is a convenient way to abstract the discovery of remote servers so that you do not have to hard code their URLs in clients.
|
|
However, if you prefer not to use Eureka, Ribbon and Feign also work.
|
|
Suppose you have declared a <code class="literal">@RibbonClient</code> for "stores", and Eureka is not in use (and not even on the classpath).
|
|
The Ribbon client defaults to a configured server list.
|
|
You can supply the configuration as follows:</p><p><b>application.yml. </b>
|
|
</p><pre class="screen">stores:
|
|
ribbon:
|
|
listOfServers: example.com,google.com</pre><p>
|
|
</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_example_disable_eureka_use_in_ribbon" href="#_example_disable_eureka_use_in_ribbon"></a>16.7 Example: Disable Eureka Use in Ribbon</h2></div></div></div><p>Setting the <code class="literal">ribbon.eureka.enabled</code> property to <code class="literal">false</code> explicitly disables the use of Eureka in Ribbon, as shown in the following example:</p><p><b>application.yml. </b>
|
|
</p><pre class="screen">ribbon:
|
|
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>16.8 Using the Ribbon API Directly</h2></div></div></div><p>You can also use the <code class="literal">LoadBalancerClient</code> directly, as shown in the following 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>
|
|
<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() {
|
|
ServiceInstance instance = loadBalancer.choose(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"stores"</span>);
|
|
URI storesUri = URI.create(String.format(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://%s:%s"</span>, instance.getHost(), instance.getPort()));
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// ... do something with the URI</span>
|
|
}
|
|
}</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ribbon-child-context-eager-load" href="#ribbon-child-context-eager-load"></a>16.9 Caching of Ribbon Configuration</h2></div></div></div><p>Each Ribbon named client has a corresponding child application Context that Spring Cloud maintains.
|
|
This application context is lazily loaded on the first request to the named client.
|
|
This lazy loading behavior can be changed to instead eagerly load these child application contexts at startup, by specifying the names of the Ribbon clients, as shown in the following example:</p><p><b>application.yml. </b>
|
|
</p><pre class="screen">ribbon:
|
|
eager-load:
|
|
enabled: true
|
|
clients: client1, client2, client3</pre><p>
|
|
</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="how-to-configure-hystrix-thread-pools" href="#how-to-configure-hystrix-thread-pools"></a>16.10 How to Configure Hystrix Thread Pools</h2></div></div></div><p>If you change <code class="literal">zuul.ribbonIsolationStrategy</code> to <code class="literal">THREAD</code>, the thread isolation strategy for Hystrix is used for all routes.
|
|
In that case, the <code class="literal">HystrixThreadPoolKey</code> is set to <code class="literal">RibbonCommand</code> as the default.
|
|
It means that HystrixCommands for all routes are executed in the same Hystrix thread pool.
|
|
This behavior can be changed with the following configuration:</p><p><b>application.yml. </b>
|
|
</p><pre class="screen">zuul:
|
|
threadPool:
|
|
useSeparateThreadPools: true</pre><p>
|
|
</p><p>The preceding example results in HystrixCommands being executed in the Hystrix thread pool for each route.</p><p>In this case, the default <code class="literal">HystrixThreadPoolKey</code> is the same as the service ID for each route.
|
|
To add a prefix to <code class="literal">HystrixThreadPoolKey</code>, set <code class="literal">zuul.threadPool.threadPoolKeyPrefix</code> to the value that you want to add, as shown in the following example:</p><p><b>application.yml. </b>
|
|
</p><pre class="screen">zuul:
|
|
threadPool:
|
|
useSeparateThreadPools: true
|
|
threadPoolKeyPrefix: zuulgw</pre><p>
|
|
</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="how-to-provdie-a-key-to-ribbon" href="#how-to-provdie-a-key-to-ribbon"></a>16.11 How to Provide a Key to Ribbon’s <code class="literal">IRule</code></h2></div></div></div><p>If you need to provide your own <code class="literal">IRule</code> implementation to handle a special routing requirement like a “canary” test, pass some information to the <code class="literal">choose</code> method of <code class="literal">IRule</code>.</p><p><b>com.netflix.loadbalancer.IRule.java. </b>
|
|
</p><pre class="screen">public interface IRule{
|
|
public Server choose(Object key);
|
|
:</pre><p>
|
|
</p><p>You can provide some information that is used by your <code class="literal">IRule</code> implementation to choose a target server, as shown in the following example:</p><pre class="screen">RequestContext.getCurrentContext()
|
|
.set(FilterConstants.LOAD_BALANCER_KEY, "canary-test");</pre><p>If you put any object into the <code class="literal">RequestContext</code> with a key of <code class="literal">FilterConstants.LOAD_BALANCER_KEY</code>, it is passed to the <code class="literal">choose</code> method of the <code class="literal">IRule</code> implementation.
|
|
The code shown in the preceding example must be executed before <code class="literal">RibbonRoutingFilter</code> is executed.
|
|
Zuul’s pre filter is the best place to do that.
|
|
You can access HTTP headers and query parameters through the <code class="literal">RequestContext</code> in pre filter, so it can be used to determine the <code class="literal">LOAD_BALANCER_KEY</code> that is passed to Ribbon.
|
|
If you do not put any value with <code class="literal">LOAD_BALANCER_KEY</code> in <code class="literal">RequestContext</code>, null is passed as a parameter of the <code class="literal">choose</code> method.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__hystrix_timeouts_and_ribbon_clients.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_netflix.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="multi__external_configuration_archaius.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">15. Hystrix Timeouts And Ribbon Clients </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top"> 17. External Configuration: Archaius</td></tr></table></div></body></html> |