<

I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE COURSE

1. Overview

In this article, we’ll look at how load balancing works with Zuul and Eureka.

We’ll route requests to a REST Service discovered by Spring Cloud Eureka through Zuul Proxy.

2. Initial Setup

We need to set up Eureka server/client as shown in the article Spring Cloud Netflix-Eureka

3. Configuring Zuul

Zuul, among many other things, fetches from Eureka service locations and does server-side load balancing.

3.1. Maven Configuration

First, we’ll add Zuul Server and Eureka dependency to our pom.xml:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

3.2. Communication with Eureka

Secondly, we’ll add necessary properties in Zuul’s application.properties file:

server.port=8762
spring.application.name=zuul-server
eureka.instance.preferIpAddress=true
eureka.client.registerWithEureka=true
eureka.client.fetchRegistry=true
eureka.serviceurl.defaultzone=http://localhost:8761/eureka/

Here we’re telling Zuul to register itself as a service in Eureka and to run on port 8762.

Next, we’ll implement the main class with @EnableZuulProxy and @EnableDiscoveryClient. @EnableZuulProxy indicates this as Zuul Server and @EnableDiscoveryClient indicates this as Eureka Client:

@SpringBootApplication
@EnableZuulProxy
@EnableDiscoveryClient
public class ZuulConfig {
    public static void main(String[] args) {
        SpringApplication.run(ZuulConfig.class, args);
    }
}

We’ll point our browser to http://localhost:8762/routes. This should show up all the routes available for Zuul that are discovered by Eureka:

{"/spring-cloud-eureka-client/**":"spring-cloud-eureka-client"}

Now, we’ll communicate with Eureka client using Zuul Proxy route obtained. Pointing our browser to http://localhost:8762/spring-cloud-eureka-client/greeting should generate the response something like:

Hello from 'SPRING-CLOUD-EUREKA-CLIENT with Port Number 8081'!

4. Load Balancing with Zuul

When Zuul receives a request, it picks up one of the physical locations available and forwards requests to the actual service instance. The whole process of caching the location of the service instances and forwarding the request to the actual location is provided out of the box with no additional configurations needed.

Here, we can see how Zuul is encapsulating three different instances of the same service:

Internally, Zuul uses Netflix Ribbon to look up for all instances of the service from the service discovery (Eureka Server).

Let’s observe this behavior when multiple instances are brought up.

4.1. Registering Multiple Instances

We’ll start by running two instances (8081 and 8082 ports).

Once all the instances are up, we can observe in logs that physical locations of the instances are registered in DynamicServerListLoadBalancer and the route is mapped to Zuul Controller which takes care of forwarding requests to the actual instance:

Mapped URL path [/spring-cloud-eureka-client/**] onto handler of type [class org.springframework.cloud.netflix.zuul.web.ZuulController]
Client:spring-cloud-eureka-client instantiated a LoadBalancer:
  DynamicServerListLoadBalancer:{NFLoadBalancer:name=spring-cloud-eureka-client,
  current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null
Using serverListUpdater PollingServerListUpdater
DynamicServerListLoadBalancer for client spring-cloud-eureka-client initialized: 
  DynamicServerListLoadBalancer:{NFLoadBalancer:name=spring-cloud-eureka-client,
  current list of Servers=[0.0.0.0:8081, 0.0.0.0:8082],
  Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone;	Instance count:2;	
  Active connections count: 0;	Circuit breaker tripped count: 0;	
  Active connections per server: 0.0;]},
  Server stats: 
    [[Server:0.0.0.0:8080;	Zone:defaultZone;......],
    [Server:0.0.0.0:8081;	Zone:defaultZone; ......],

Note: logs were formatted for better readability.

4.2. Load-Balancing Example

Let’s navigate our browser to http://localhost:8762/spring-cloud-eureka-client/greeting a few times.

Each time, we should see a slightly different result:

Hello from 'SPRING-CLOUD-EUREKA-CLIENT with Port Number 8081'!
Hello from 'SPRING-CLOUD-EUREKA-CLIENT with Port Number 8082'!
Hello from 'SPRING-CLOUD-EUREKA-CLIENT with Port Number 8081'!

Each request received by Zuul is forwarded to a different instance in a round robin fashion.

If we start another instance and register it in Eureka, Zuul will register it automatically and start forwarding requests to it:

Hello from 'SPRING-CLOUD-EUREKA-CLIENT with Port Number 8083'!

We can also change Zuul’s load-balancing strategy to any other Netflix Ribbon strategy – more about this can be found in our Ribbon article.

5. Conclusion

As we’ve seen, Zuul provides a single URL for all the instances of the Rest Service and does load balancing to forward the requests to one of the instances in round robin fashion.

As always, the complete code for this article can be found over on GitHub.

I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE LESSONS

  Subscribe  
newest oldest most voted
Notify of
Bhushan
Guest
Bhushan

Can you please explain how we can override default behavior (round robbin) of ZUUL for forwarding the request?

Loredana Crusoveanu
Editor

Have a look at our other article on Netflix Ribbon, which Zuul uses internally: http://www.baeldung.com/spring-cloud-rest-client-with-netflix-ribbon
Specifically, you have to change the load balancing rule. There are multiple rules defined in the Ribbon project, but you can also add a custom one.

RaouZ
Guest
RaouZ

Good article! Thanks for the good work!

You wrote, that Zuul does server-side load-balancing and uses Ribbon internally to do load-balancing. As far as I know does Ribbon client-side load balancing. So, which is correct?

We want to use Zuul (with server-side load-balancing) and now we are looking for a service registry, that uses Third-Party registration pattern. As Eureka uses Self-Registration, is there an alternative for that?

Thanks a lot in advance for your help!

Loredana Crusoveanu
Editor

Hey Raoul,

The best explanation for the first question that I found is here: https://stackoverflow.com/questions/43538030/zuul-and-ribbon-integration

As for other service registries, Consul and Lagom, for example, support third-party registration.

Hope you found a good solution for your project.
Cheers.