Spring Netflix Zuul

By Dhiraj Ray, 02 March,2018   1K

In this tutorial, we will be discussing about how to route in cloud native apps to different services using spring netflix zuul proxy.We will have multiple micro services running and an API gateway that does intelligent routing through proxy based on the requested resource. We will be also discussing about setting up Zuul Filter to intercept all the request and perform some operations to all the requests that pass through the API gateway.

API Gateway means a single entry point for all clients.So, we have a single interface exposed on behalf of all the microservices running. This gateway at the run-time will identify the correct service to be invoked. To achieve this routing we have Netflix zuul proxy. Zuul is an edge service that provides dynamic routing, monitoring, resiliency, security, and more.

In this example, we will be creating two different services as first-service and second-service first and enable discovery server to auto discover these services. Till this point we have already discussed in my last article - Spring cloud netflix eureka.On top of this, we will be creating an API gateway using netflix zuul for intelligent routing.

Netflix Discovery Server

We will be using our existing discovery server implementation on github. Following is the application.properties file and DiscoveryServerApplication.javathat we used while implementing discovery server in our last example.

application.properties
spring.application.name=discovery-server
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
server.port=8761
DiscoveryServerApplication.java
@EnableEurekaServer
@SpringBootApplication
public class DiscoveryServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(DiscoveryServerApplication.class, args);
	}
}

API Gateway Service

By default, zuul routes request by service name which is resolved by discovery server.For example, if the request url is like /first-service/first then zuul discovers service with name first-service and routes the request to it for url mapping first. So, basically zuul strips the prefix and route it to the corresponding service.

Spring Cloud Netflix includes an embedded Zuul proxy, which we can enable with the @EnableZuulProxy annotation in our main application class. Since, we want our service to be auto discoverable, we also have annotated it with @EnableDiscoveryClient

spring-cloud-netflix-zuul GatewayServiceApplication.java
package com.devglan.gatewayservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringBootApplication
@EnableZuulProxy
@EnableDiscoveryClient
public class GatewayServiceApplication {

	public static void main(String[] args) {
		SpringApplication.run(GatewayServiceApplication.class, args);
	}
}

For auto discovery, we also require to tell the spring about our eureka discovery server url. Following are the requird entries in application.properties for this.

application.properties
spring.application.name=gateway-service
eureka.client.service-url.default-zone=http://localhost:8761/eureka

This is it for configuring a simple API gateway service. Now, this app will be running on port 8080 and it will intercept all the request and based on the service id, it will discover the dervice from discovery server and route the request to the corresponding service.

Implementing Cloud Service

In this section, we will implementing our micro services. We will have 2 different services with application name as first-service running on 9090 and second-service running on 9095 respectively.Following is the implementation of the respective controller class.

netflix-zuul-service FirstController.java
@RestController
public class FirstController {

    @RequestMapping("/")
    public String demo(){
        return "First service ";
    }
}

SecondController.java
@RestController
public class SecondController {

    @RequestMapping("/")
    public String demo(){
        return "Second service";
    }
}

Testing Zuul Proxy

Now, we will test the application. For that first start discovery server then the gateway service and then the two micro service and hit the url http://localhost:8080/first-service. Here, our gateway service is running on port 8080 and first-service is the service name. You can see that the request is proxied to first service by zuul.

netflix-zuul-test

Zuul Filter Implementation

Sometimes, it is required to intercept the request and response that is passed through the gateway.Doing so, we can add some validations or modify headers of requet and response. For this, zuul provides filter implementation and this filter implementation provides full control about how how to proceed with the request and response. There are 4 types of filter provided by zuul. We have pre filter that is executed before the request is routed.Similarly, we have route filter to direct the request and post filter that is executed after the the request is routed.We also have error filter that is executed when any error is occurred during routing.

Fllowing is a sample pre filter implementation that modifies the request header and adds X-source in the header.And the same header can be extracted in the service implementation. This is a very useful feature in a real time app.

AddRequestHeaderFilter.java
package com.devglan.gatewayservice.config;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;

public class AddRequestHeaderFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext context = RequestContext.getCurrentContext();
        context.addZuulRequestHeader("X-source", "Zuul");
        return null;
    }
}

Before this filter can be used we need to define it as a bean.

@Bean
public AddRequestHeaderFilter addRequestHeaderFilter(){
	return new AddRequestHeaderFilter();
}

Now, we can have access to this header in our controller as below:

@RequestMapping("/")
public String demo(@RequestHeader("X-source") String source){
	return "First service with " + source;
}

Conclusion

In this article, we discussed about implementing API gateway using spring cloud netflix zuul proxy for intelligent routing.In next article, we will be discussing about spring cloud netflix hystrix.The source can be downloaded from here.If you have anything that you want to add or share then please share it below in the comment section

1. Spring Cloud Config

2. Spring Cloud Netflix Eureka

3. Introduction To Microservices

4. Refresh Property Config Runtime

If You Appreciate What We Do Here On Devglan, You Should Consider: