Organising the interactions between different services in a modern microservices architecture can be challenging. The Zuul proxy, a gateway service that manages every request and performs dynamic routing for a microservice based applications.
What is Zuul and how it came ?
Zuul is an edge service that offers security, resilience, monitoring, and dynamic routing. It is made to manage all of the routing and filtering required in a microservices architecture and is a component of the Netflix OSS (Open Source Software) stack.
Benefits of Using Zuul
- Dynamic Routing: Zuul can dynamically route requests to different backend services.
- Monitoring and Insights: It offers monitoring capabilities to gain insights into traffic and performance.
- Resiliency: Zuul can handle failover and retry mechanisms.
- Security: It provides features for authentication and authorization.
Using Zuul with Spring Boot
We start by initializing a spring boot project along with the spring-cloud-starter-netflix-zuul dependency. The dependency in the pom.xml should be like the below:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
Next we enable the Zuul proxy with the help of @EnableZuulProxy annotation in the main class.
@SpringBootApplication
@EnableZuulProxy
public class ZuulProxyApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulProxyApplication.class, args);
}
}
Finally, we configure the zuul routes in our application.properties file.
zuul.routes.service1.path=/service1/**
zuul.routes.service1.url=http://localhost:8081
zuul.routes.service2.path=/service2/**
zuul.routes.service2.url=http://localhost:8082
Requests from /service1/** and /service2/** are routed to http://localhost:8081 and 8082, respectively, with this configuration.
Assuming we have two microservices running on different ports:
- Service 1 running on
localhost:8081
with an endpoint/hello
- Service 2 running on
localhost:8082
with an endpoint/world
With Zuul configured as above, you can access these services through the Zuul proxy:
http://localhost:8080/service1/hello
will be routed tohttp://localhost:8081/hello
http://localhost:8080/service2/world
will be routed tohttp://localhost:8082/world
Filters in Zuul
Zuul supports filters that can be used for various purposes like authentication, logging, etc. Here’s how we can add a filter:
@Component
public class SimpleFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
System.out.println(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
return null;
}
}
With the above filter implemented, let’s assume a client makes a GET request to http://localhost:8080/service1/hello, then we would get an output like the below:
GET request to http://localhost:8080/service1/hello