Netflix Zuul: Setup and sample application

“Microservice” is a buzzword these days and many tech-savvy organizations are adopting microservices to create independent, highly scalable and easily maintainable services that exhibit highly single responsibility principle. Spring boot plays a major role in helping developers build microservices from scratch. To achieve this highly scalable architecture and provide ease of deployment, spring framework has created spring cloud library. This library helps developers create their microservices without worrying too much about the infrastructure required to host these microservices.

Zuul is a proxy server introduced by Netflix that provides dynamic routing, monitoring, resilience, security and more. And the best part is that Netflix has open sourced it for use by the community. Spring could have incorporated this proxy server in its spring-cloud suite and made it very easy for use in simple steps. Let us see in this post how to use Zuul proxy server with spring cloud in your microservice.

Let us say we are creating a microservice which gives you student details on the basis of student_id.  This post assumes that you have basic working knowledge of spring boot. If you are unfamiliar with spring boot read the tutorials below to get acquainted with it:

1) Getting started with spring boot

2) Getting started with spring boot – part 2 

Now let us start with our JVM based proxy server.

Step 1] Create a spring boot based microservice:

If you have your existing service with you, great! If not, use the link below to download the spring-boot based microservice created in our tutorial: Spring-boot-2

This post will use the microservice created earlier. Here is the repository URL for the same:

https://github.com/ninja-panda/spring-example/tree/master/spring-boot-simple

We have imported the above-mentioned project in our STS IDE (Yes you Rockstar! You can use eclipse too yes ) Our project in STS looks like below after being imported.

 

Let us run this project and check its output. We do this by running our program as a spring boot application and by typing in the following URL in our browser:

http://localhost:8080/students?studentId=18

We get JSON output as:

But we want to run the student microservice on some other port so that our proxy server runs on port 8080. How do we do that? We simply change the port in the application.properties file to some other port, say 8090. To get more details on how to change port for a spring boot application refer this post How to change port in spring-boot.

Our application does not have a properties file so we simply create a resources folder under main and add the file our project structure now looks something like this:

Now run the service on URL given below and you should see the output same as given above.

http://localhost:8090/students?studentId=18

[Step 2] Create a spring boot project for zuul proxy.

This is a spring bot based microservice with zuul API proxy. We will use this proxy to communicate with our student microserrvice. Go to spring initializer and fill in the values as given in below image and click on generate a project.

Unzip the project on your local machine and import it to STS or eclipse. Your project structure would look as below:

The project setup for zull is complete.

[Step 3] Zuul basics and use

By now we know that zuul provide a gateway for our microservices API. We can have multiple microservices hosted in our ecosystem and have a common gateway from zuul which will help us abstract out the common features required for each microservice. For example; let us say we have another hypothetical microservice for teachers which provides teacher details. Then we can have same base URL for students and teacher microservice as shown below but they are separated by the context. Abstract features like security and API monitoring & insights are moved out of the microservice layer and introduced in the zuul layer so that the student and teacher microservice can do their work independently without worrying about security. See image below, it demonstrates the concept explained in this paragraph diagrammatically:

Zuul filters:

Zuul offers 4 types of filters used to play with our requests, incoming or outgoing. Here is a detailed explanation of them:

Pre filters: Comes in to picture when we want to manipulate our incoming request.

Post filters: Comes in to picture when we want to manipulate our outgoing response.

Route Filters: Used to route request to microservices.

Error Filters: These are invoked while handling errors.

[Step 4] Coding and customizing the gateway proxy.

Now that we have a basic understanding of zuul, let us write code to configure it for our student microservice.

Enable Zuul proxy in Application class:

We need to let our application class know that the application is a zuul proxy application. We do this by annotating the application class with @EnableZuulProxy. Look at the code below which shows how to annotate the class:

package com.tuturself.spring.springbootzuul;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;

import com.tuturself.spring.springbootzuul.filters.StudentErrorFilter;
import com.tuturself.spring.springbootzuul.filters.StudentPostFilter;
import com.tuturself.spring.springbootzuul.filters.StudentPreFilter;
import com.tuturself.spring.springbootzuul.filters.StudentRouteFilter;

@EnableZuulProxy
@SpringBootApplication
public class SpringBootZuulApplication {

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

	@Bean
	public StudentPreFilter preFilter(){
		return new StudentPreFilter();
	}
	
	@Bean
	public StudentPostFilter postFilter(){
		return new StudentPostFilter();
	}
	
	@Bean
	public StudentRouteFilter routeFilter(){
		return new StudentRouteFilter();
	}

	@Bean
	public StudentErrorFilter errorFilter(){
		return new StudentErrorFilter();
	}
}

Next task is to create our filters. We will create a filter of each type for you so that you can experiment with them for your self-learning.

To create filters you need to extend the ZuulFiilter class and write an implementation of the methods. There are 4 methods in the ZuulFilter class that need to be overridden.

1)      run: This method will tell what to do while actually filtering.

2)      doFilter: determines whether to apply this filter or ignore it.

3)      filterOrder: the order of the filter in the chain. There can be multiple filters for a request and they are executed in the given order ascending.

4)      Filtertype: This defines the type of filter that is being used. These values need to be mandatorily from the set {“pre”, ”post”, ”route”, ”error”}. The names are self-explanatory and you can define whatever type of filter you want to use.

[Step 5] Add the filters:

We add a folder named filter in our application and add the student related filters in that folder. Here is code for each of the filter:

package com.tuturself.spring.springbootzuul.filters;

import javax.servlet.http.HttpServletRequest;

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

public class StudentPreFilter extends ZuulFilter {

	@Override
	public Object run() {
		RequestContext ctx = RequestContext.getCurrentContext();
		HttpServletRequest request = ctx.getRequest();

		System.out.println(String.format("%s request to %s", request.getMethod(), 
                    request.getRequestURL().toString()));
		return null;
	}

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

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

	@Override
	public String filterType() {
		return "pre";
	}
}
package com.tuturself.spring.springbootzuul.filters;

import com.netflix.zuul.ZuulFilter;

public class StudentPostFilter extends ZuulFilter{

	@Override
	public Object run() {
		System.out.println("Post filter");
		return null;
	}

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

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

	@Override
	public String filterType() {
		
		return "post";
	}
}
package com.tuturself.spring.springbootzuul.filters;

import com.netflix.zuul.ZuulFilter;

public class StudentRouteFilter extends ZuulFilter {

	@Override
	public Object run() {
		System.out.println("In route filter");
		return null;
	}

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

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

	@Override
	public String filterType() {
		return "route";
	}
}
package com.tuturself.spring.springbootzuul.filters;

import com.netflix.zuul.ZuulFilter;

public class StudentErrorFilter extends ZuulFilter {

	@Override
	public Object run() {
		System.out.println("Error filter");
		return null;
	}

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

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

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

[Step 6] Register the filters in the application:

We register the filters in the application by defining their beans in the application class as below:

	@Bean
	public StudentPreFilter preFilter(){
		return new StudentPreFilter();
	}
	
	@Bean
	public StudentPostFilter postFilter(){
		return new StudentPostFilter();
	}
	
	@Bean
	public StudentRouteFilter routeFilter(){
		return new StudentRouteFilter();
	}

	@Bean
	public StudentErrorFilter errorFilter(){
		return new StudentErrorFilter();
	}

[Step 7] Application properties configuration:

We now configure our application.properties file to proxy our requests for students. This is done by defining the file as below:

zuul.routes.students.url=http://localhost:8090/students
 
#Ribbon is a service provided by netflix OSS suite but we ont use it in this tutorial.
ribbon.eureka.enabled=false
 
server.port=8080

Make sure to provide the path correctly in the proxy URL mapping.

[Step 8] Testing and demo.

We now start the student service by running it as a spring boot app. Then we start the proxy service by running it as a spring boot app as well. Now we have bot service as well as the zuul proxy ready let us hit the URL below:

http://localhost:8080/students?studentId=18

This gives us output for our microservice as below:

Conclusion: So we have seen here how to use Zuul proxy for routing requests. Also, we have studied the various features offered by Zuul proxy.

Exercise: Checkout the logs generated by the proxy application. Figure out what logs are generated at which step.

To download the code of this demo application visit:

https://github.com/shreyasht/spring-boot-examples

Do let us know your suggestions/questions via comments. Happy Coding!

spring 12 Spring Boot 12

FOLLOW US ON LinkedIn



Explore Tutu'rself