Skip to content

Core Features

Arthur Gonigberg edited this page Apr 12, 2018 · 17 revisions

Service Discovery

Zuul is built to work seamlessly with Eureka but can also be configured to work with static server lists or a discovery service of your choice.

The standard approach with a Eureka server would look like this:

### Load balancing backends with Eureka

eureka.shouldUseDns=true
eureka.eurekaServer.context=discovery/v2
eureka.eurekaServer.domainName=discovery${environment}.netflix.net
eureka.eurekaServer.gzipContent=true

eureka.serviceUrl.default=http://${region}.${eureka.eurekaServer.domainName}:7001/${eureka.eurekaServer.context}

api.ribbon.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList
api.ribbon.DeploymentContextBasedVipAddresses=api-test.netflix.net:7001

In this configuration you have to specify your Eureka context and location. Given that, Zuul will automatically select the server list from Eureka with the given VIP for the api Ribbon client. You can find more info about Ribbon configuration here.

To configure Zuul with a static server list or a different discovery provider, you'll have to keep the the listOfServers property up to date:

### Load balancing backends without Eureka

eureka.shouldFetchRegistry=false

api.ribbon.listOfServers=100.66.23.88:7001,100.65.155.22:7001
api.ribbon.client.NIWSServerListClassName=com.netflix.loadbalancer.ConfigurationBasedServerList
api.ribbon.DeploymentContextBasedVipAddresses=api-test.netflix.net:7001

Notice in this configuration the server list class name is ConfigurationBasedServerList instead of DiscoveryEnabledNIWSServerList.

Load Balancing

By default Zuul load balances using the ZoneAwareLoadBalancer from Ribbon. The algorithm is a round robin of the instances available in discovery, with availability zone success tracking for resiliency. The load balancer will keep stats for each zone and will drop a zone if the failure rates are above a configurable threshold.

If you want to use your own custom load balancer you can set the NFLoadBalancerClassName property for that Ribbon client namespace or override the getLoadBalancerClass() method in the DefaultClientChannelManager. Note that your class should extend DynamicServerListLoadBalancer.

Ribbon also allows you to configure the load balancing rule. For example, you can swap the RoundRobinRule for the WeightedResponseTimeRule, AvailabilityFilteringRule, or your own rule.

You can find more details here.

Connection Pooling

Zuul does not use Ribbon for making outgoing connections and instead uses its own connection pool, using a Netty client. Zuul creates a connection pool per host, per event loop. It does this in order to reduce context switching between threads and to ensure sanity for both the inbound event loops and outbound event loops. The result is that the entire request is run on the same thread, regardless of which event loop is running it.

One of the side-effects of this strategy is that the minumum amount of connections made to each back-end server can be quite high if you have a lot of Zuul instances running, with a lot of event loops in each. This is important to keep in mind when configuring the connection pool.

Some useful settings, and their default values, for tweaking the connection pool are:

Ribbon Client Config Properties

<originName>.ribbon.ConnectionTimeout                // default: 500 (ms)
<originName>.ribbon.MaxConnectionsPerHost            // default: 50
<originName>.ribbon.ConnIdleEvictTimeMilliSeconds    // default: 60000 (ms)
<originName>.ribbon.ReceiveBufferSize                // default: 32 * 1024
<originName>.ribbon.SendBufferSize                   // default: 32 * 1024
<originName>.ribbon.UseIPAddrForServer               // default: true

Zuul Properties

# Max amount of requests any given connection will have before forcing a close
<originName>.netty.client.maxRequestsPerConnection    // default: 1000

# Max amount of connection per server, per event loop
<originName>.netty.client.perServerWaterline          // default: 4

# Netty configuration connection
<originName>.netty.client.TcpKeepAlive                // default: false
<originName>.netty.client.TcpNoDelay                  // default: false
<originName>.netty.client.WriteBufferHighWaterMark    // default: 32 * 1024
<originName>.netty.client.WriteBufferLowWaterMark     // default: 8 * 1024
<originName>.netty.client.AutoRead                    // default: false

The connection pool also outputs a lot of metrics, so take a look at the Spectator registry if you want to collect them.

Retries

Request Passport

HTTP/2

Mutual TLS

Proxy Protocol

GZip