/gs-routing-and-filtering

Routing and Filtering :: Learn how to route and filter requests to a microservice using Netflix Zuul

Primary LanguageJava

tags projects
spring cloud
zuul
spring-cloud
spring-cloud-netflix

This guide walks you through the process of routing and filtering requests to a microservice application using the Netflix Zuul edge service library.

What you’ll build

You’ll write a simple microservice application and then build a reverse proxy application that uses Netflix Zuul to forward requests to the service application. You’ll also see how to use Zuul to filter requests made through the proxy service.

What you’ll need

Build with Gradle

Build with Gradle

book/build.gradle

link:https://raw.githubusercontent.com/spring-guides/gs-routing-and-filtering/master/initial/book/build.gradle[role=include]

gateway/build.gradle

link:https://raw.githubusercontent.com/spring-guides/gs-routing-and-filtering/master/initial/gateway/build.gradle[role=include]

Build with Maven

Build with Maven

book/pom.xml

link:https://raw.githubusercontent.com/spring-guides/gs-routing-and-filtering/master/initial/book/pom.xml[role=include]

gateway/pom.xml

link:https://raw.githubusercontent.com/spring-guides/gs-routing-and-filtering/master/initial/gateway/pom.xml[role=include]

Set up a microservice

The Book service will be super-simple. Edit BookApplication.java to look like this:

book/src/main/java/hello/BookApplication.java

link:complete/book/src/main/java/hello/BookApplication.java[role=include]

The BookApplication class is now a REST controller. @RestController marks the class as a controller class, and also ensures that return values from @RequestMapping methods in this class will be automatically converted appropriately and written directly to the HTTP response.

Speaking of @RequestMapping methods, we’ve added two: available() and checkedOut(). They handle requests to the paths /available and /checked-out, each simply returning the String name of a book.

Set the application name (book) in src/main/resources/application.properties.

book/src/main/resources/application.properties

link:complete/book/src/main/resources/application.properties[role=include]

We’re also setting server.port here so that it won’t conflict with our edge service when we get both services up and running locally.

Create an edge service

Spring Cloud Netflix includes an embedded Zuul proxy, which we can enable with the @EnableZuulProxy annotation. This will turn the Gateway application into a reverse proxy that forwards relevant calls to other services---such as our Book service.

Open the Gateway application’s GatewayApplication class and add the annotation, like so:

gateway/src/main/java/hello/GatewayApplication.java

package hello;

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

@EnableZuulProxy
@SpringBootApplication
public class GatewayApplication {

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

}

To forward requests from the Gateway application, we need to tell Zuul the routes that it should watch and the services to which to forward requests to those routes. We specify routes using properties under zuul.routes. Each of our microservices can have an entry under zuul.routes.NAME, where NAME is the application name (as stored in the spring.application.name property).

Add the application.properties file to a new directory, src/main/resources, in the Gateway application. It should look like this:

gateway/src/main/resources/application.properties

link:complete/gateway/src/main/resources/application.properties[role=include]

Spring Cloud Zuul will automatically set the path to the application name. In this sample because we set zuul.routes.books.url, so Zuul will proxy requests to /books to this URL.

Notice the second-to-last property in our file: Spring Cloud Netflix Zuul uses Netflix’s Ribbon to perform client-side load balancing, and by default, Ribbon would use Netflix Eureka for service discovery. For this simple example, we’re skipping service discovery, so we’ve set ribbon.eureka.enabled to false. Since Ribbon now can’t use Eureka to look up services, we must specify a url for the Book service.

Add a filter

Now let’s see how we can filter requests through our proxy service. Zuul has four standard filter types:

  • pre filters are executed before the request is routed,

  • route filters can handle the actual routing of the request,

  • post filters are executed after the request has been routed, and

  • error filters execute if an error occurs in the course of handling the request.

We’re going to write a pre filter. Spring Cloud Netflix picks up, as a filter, any @Bean which extends com.netflix.zuul.ZuulFilter and is available in the application context. Create a new directory, src/main/java/hello/filters/pre, and within it, create the filter file, SimpleFilter.java:

gateway/src/main/java/hello/filters/pre/SimpleFilter.java

link:complete/gateway/src/main/java/hello/filters/pre/SimpleFilter.java[role=include]

Filter classes implement four methods:

  • filterType() returns a String that stands for the type of the filter---in this case, pre, or it could be route for a routing filter.

  • filterOrder() gives the order in which this filter will be executed, relative to other filters.

  • shouldFilter() contains the logic that determines when to execute this filter (this particular filter will always be executed).

  • run() contains the functionality of the filter.

Zuul filters store request and state information in (and share it by means of) the RequestContext. We’re using that to get at the HttpServletRequest, and then we log the HTTP method and URL of the request before it is sent on its way.

The GatewayApplication class is annotated with @SpringBootApplication, which is equivalent to (among others) the @Configuration annotation that tells Spring to look in a given class for @Bean definitions. Add one for our SimpleFilter here:

gateway/src/main/java/hello/GatewayApplication.java

link:complete/gateway/src/main/java/hello/GatewayApplication.java[role=include]

Trying it out

Make sure that both applications are running. In a browser, visit one of the Book application’s endpoints via the Gateway application. If you’ve used the configuration shown in this guide, you can access the Book service directly at localhost:8090 and via the Gateway service at localhost:8080/books.

Visit one of the Book service endpoints, as localhost:8080/books/available, and you should see your request’s method logged by the Gateway application before it’s handed on to the Book application:

2016-01-19 16:51:14.672  INFO 58807 --- [nio-8080-exec-6] hello.filters.pre.SimpleFilter           : GET request to http://localhost:8080/books/available
2016-01-19 16:51:14.672  INFO 58807 --- [nio-8080-exec-6] o.s.c.n.zuul.filters.ProxyRouteLocator   : Finding route for path: /books/available

Summary

Congratulations! You’ve just used Spring to develop an edge service application that can proxy and filter requests for your microservices.

See Also

The following guides may also be helpful: