This guide walks you through the process of routing and filtering requests to a microservice application by using the Netflix Zuul edge service library.
What You Will Build
You will write a simple microservice application and then build a reverse proxy application that uses Netflix Zuul to forward requests to the service application. You will also see how to use Zuul to filter requests that are made through the proxy service.
What You Need
-
About 15 minutes
-
A favorite text editor or IDE
-
JDK 1.8 or later
-
You can also import the code straight into your IDE:
How to complete this guide
Like most Spring Getting Started guides, you can start from scratch and complete each step or you can bypass basic setup steps that are already familiar to you. Either way, you end up with working code.
To start from scratch, move on to Starting with Spring Initializr.
To skip the basics, do the following:
-
Download and unzip the source repository for this guide, or clone it using Git:
git clone https://github.com/spring-guides/gs-routing-and-filtering.git
-
cd into
gs-routing-and-filtering/initial
-
Jump ahead to Set up a Microservice.
When you finish, you can check your results against the code in gs-routing-and-filtering/complete
.
Starting with Spring Initializr
For all Spring applications, you should start with the Spring Initializr. The Initializr offers a fast way to pull in all the dependencies you need for an application and does a lot of the set up for you.
This guide needs two applications. The first application (the book application) needs only the Spring Web dependency.
The second application (the routing and filtering application) needs the Spring Web and Zuul dependencies.
For convenience, we have provided build files (a pom.xml file and a build.gradle file) at the top of the project (one directory above the book and gateway directories) that you can use to build both projects at once. We also added the Maven and Gradle wrappers there. |
To initialize the project, create two applications:
-
Navigate to https://start.spring.io. This service pulls in all the dependencies you need for an application and does most of the setup for you.
-
Choose either Gradle or Maven and the language you want to use. This guide assumes that you chose Java.
-
Click Dependencies and select Spring Web for the book application and Spring Web and Zuul for the routing and filtering application.
-
Click Generate.
-
Download the resulting ZIP file, which is an archive of a web application that is configured with your choices.
If your IDE has the Spring Initializr integration, you can complete this process from your IDE. |
You can also fork the project from Github and open it in your IDE or other editor. |
Set up a Microservice
The Book service will be as simple as a Spring application can be. Edit RoutingAndFilteringBookApplicationBookApplication.java
so that it matches the following listing (from book/src/main/java/com/example/routingandfilteringbook/RoutingAndFilteringBookApplication.java
):
package com.example.routingandfilteringbook;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@SpringBootApplication
public class RoutingAndFilteringBookApplication {
@RequestMapping(value = "/available")
public String available() {
return "Spring in Action";
}
@RequestMapping(value = "/checked-out")
public String checkedOut() {
return "Spring Boot in Action";
}
public static void main(String[] args) {
SpringApplication.run(RoutingAndFilteringBookApplication.class, args);
}
}
The RoutingAndFilteringBookApplicationBookApplication
class is now a REST controller. The @RestController
annotation marks the class as a controller class and ensures that return values from @RequestMapping
methods in this class are automatically and appropriately converted and written directly to the HTTP response.
Speaking of @RequestMapping
methods, we have added two: available()
and checkedOut()
. They handle requests to the /available
and /checked-out
paths, each of which returns the String
name of a book.
Set the application name (book
) in src/main/resources/application.properties
, as the following listing shows:
spring.application.name=book
server.port=8090
Set server.port
here, too, so that it does not conflict with your edge service when you get both services up and running locally.
Create an Edge Service
Spring Cloud Netflix includes an embedded Zuul proxy, which you 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 application.
Open the Gateway application’s RoutingAndFilteringGatewayApplicationGatewayApplication
class and add the @EnableZuulProxy
annotation, as the following listing (from gateway/src/main/java/com/example/routingandfilteringgateway/RoutingAndFilteringGatewayApplication.java
) shows:
package com.example.routingandfilteringgateway;
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.example.routingandfilteringgateway.filters.pre.SimpleFilter;
@EnableZuulProxy
@SpringBootApplication
public class RoutingAndFilteringGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(RoutingAndFilteringGatewayApplication.class, args);
}
@Bean
public SimpleFilter simpleFilter() {
return new SimpleFilter();
}
}
To forward requests from the Gateway application, you need to tell Zuul the routes that it should watch and the services to which to forward requests that are made to those routes. We specify routes by setting 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 match the following listing (from gateway/src/main/resources/application.properties
):
zuul.routes.books.url=http://localhost:8090
ribbon.eureka.enabled=false
server.port=8080
Spring Cloud Zuul automatically sets the path to the application name. In this sample, set zuul.routes.books.url
so that Zuul will proxy requests to /books
to this URL.
Notice the second property in the application.properties
file, Spring Cloud Netflix Zuul uses Netflix’s Ribbon to perform client-side load balancing. By default, Ribbon would use Netflix Eureka for service discovery. For this simple example, you can skip service discovery, so set ribbon.eureka.enabled
to false
. Since Ribbon now cannot use Eureka to look up services, we must specify a url
for the book service.
Add a Filter
Now you can see how to filter requests through your proxy service. Zuul has four standard filter types:
-
pre
filters run before the request is routed. -
route
filters can handle the actual routing of the request. -
post
filters run after the request has been routed. -
error
filters run if an error occurs in the course of handling the request.
You are going to write a pre
filter. Spring Cloud Netflix picks up, as a filter, any @Bean
that extends com.netflix.zuul.ZuulFilter
and is available in the application context. The following listing (from gateway/src/main/java/com/example/routingandfilteringgateway/filters/pre/SimpleFilter.java
) shows the filter you need:
package com.example.routingandfilteringgateway.filters.pre;
import javax.servlet.http.HttpServletRequest;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.ZuulFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SimpleFilter extends ZuulFilter {
private static Logger log = LoggerFactory.getLogger(SimpleFilter.class);
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
log.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
return null;
}
}
Filter classes implement four methods:
-
filterType()
: Returns aString
that stands for the type of the filter — in this case,pre
. (It would beroute
for a routing filter.) -
filterOrder()
: Gives the order in which this filter is to be run, relative to other filters. -
shouldFilter()
: Contains the logic that determines when to run this filter (this particular filter is always run). -
run()
: Contains the functionality of the filter.
Zuul filters store request and state information in (and share it by means of) the RequestContext
. You can use that to get at the HttpServletRequest
and then log the HTTP method and URL of the request before it is sent on its way.
The GatewayApplication
class is annotated with @SpringBootApplication
, which includes (among others) the @Configuration
annotation that tells Spring to look in a given class for @Bean
definitions. Put the filter in the application class, as shown in the following listing (from gateway/src/main/java/com/example/routingandfilteringgateway/RoutingAndFilteringGatewayApplication.java
):
package com.example.routingandfilteringgateway;
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.example.routingandfilteringgateway.filters.pre.SimpleFilter;
@EnableZuulProxy
@SpringBootApplication
public class RoutingAndFilteringGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(RoutingAndFilteringGatewayApplication.class, args);
}
@Bean
public SimpleFilter simpleFilter() {
return new SimpleFilter();
}
}
Testing Your Application
Make sure that both applications are running. In a browser, visit one of the book application’s endpoints through the Gateway application. If you have used the configuration shown in this guide, you can access the book application directly at localhost:8090/available
and through the Gateway service at localhost:8080/books/available
.
Visit one of the Book service endpoints (localhost:8080/books/available
or localhost:8080/books/checked-out
) and you should see your request’s method logged by the Gateway application before it is handed on to the Book application, as the following sample logging output shows:
2019-10-02 10:58:34.694 INFO 11608 --- [nio-8080-exec-4] c.e.r.filters.pre.SimpleFilter : GET request to http://localhost:8080/books/available
Summary
Congratulations! You have 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:
Want to write a new guide or contribute to an existing one? Check out our contribution guidelines.
All guides are released with an ASLv2 license for the code, and an Attribution, NoDerivatives creative commons license for the writing. |