Zuul API Gateway example
A service API gateway
acts as an intermediary between the service client and a service being invoked. The service client
talks only to a single URL managed by the service gateway. The service API gateway
sits as the gatekeeper for all inbound
traffic to microservice calls within your application.
With a service gateway in place, your service clients never directly call the URL of an individual service, but instead place all calls to the service gateway.
You can implement API gateway
using Netflix
open source project Zuul
. Zuul
is a services gateway that's extremely easy to set up. Below example shows how to configure service registgry,
write a simple microservice application (Book Service) and then build a reverse proxy application that uses Netflix Zuul
to forward requests to the book service application.
Step 1) Add below dependencies in pom.xml file as below to create Eureka Service registry
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.3</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2021.0.3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
Step 2) Create EurekaServiceApplication class to launch Eureka Service registry
package com.example.hello; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer @SpringBootApplication public class EurekaServiceApplication { public static void main(String[] args) { SpringApplication.run(EurekaServiceApplication.class, args); } }
Step 3) Create application.yml file under src/main/resources
server: port: 8761 spring: application: name: discovery-service eureka: client: register-with-eureka: false fetch-registry: false
Step 4) Launch EurekaServiceApplication and open http://localhost:8761/ in the browser.
Step 5) Add below dependencies in pom.xml file as mentioned below for BookService application
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.3</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2021.0.3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
Step 6) Create Book, BookApplication & BookRestController classes
package com.example.demo; public class Book { private String title; private String author; private String genre; //removed getters, setters for brevity }
package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @EnableEurekaClient @SpringBootApplication public class BookApplication { public static void main(String[] args) { SpringApplication.run(BookApplication.class, args); } }
package com.example.demo; import java.util.ArrayList; import java.util.List; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class BookRestController { List<Book> books = new ArrayList<>(); public BookRestController() { books.add(new Book("The Fountainhead", "Ayn Rand", "Philosophical")); books.add(new Book("Murder on the Orient Express", "Agatha Christie", "Thriller")); books.add(new Book("The Silence of the Lambs", "Thomas Harris", "Thriller")); } @GetMapping("/{id}") public Book get(@PathVariable("id") int id) { return books.get(id); } }
Step 7) Create application.properties file under src/main/resources
spring.application.name=book-service eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
Step 8) Add below dependencies in pom.xml file as below to create ZuulProxy application.
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.1.RELEASE</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
Step 9) Create ZuulApplication & SimpleFilter classes
package com.example.demo; 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; import org.springframework.context.annotation.Bean; @SpringBootApplication @EnableDiscoveryClient @EnableZuulProxy public class ZuulApplication { public static void main(String[] args) { SpringApplication.run(ZuulApplication.class, args); } @Bean public SimpleFilter simpleFilter() { return new SimpleFilter(); } }
package com.example.demo; 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; } }
Step 10) Create application.yml file under src/main/resources
spring: application: name: zuul-gateway server: port: 9999 eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka
Step 11) Launch BookApplication & ZuulApplication and open http://localhost:9999/book-service/1 in the browser.
Note that browser will send call to Zuul Proxy Gateway which internaly forwards the call to Book Service and returns result.
Step 12) Also refresh http://localhost:8761/ in the browser.
References :
Spring Docs Routing and Filtering