Implementing an API Gateway with Spring Cloud Zuul

Spring Cloud Zuul Overview

Zuul serves as an edge service providing load balancing, reverse proxying, authentication, dynamic routing, monitoring, and security. It acts as a protective layer for microservice architectures by handling non-business logic concerns at the routing level.

Routing Gateway Patterns

Consider three architectural approaches:

  1. Direct Service Access: Clients connect directly to individual services
  2. Gateway Routing: All requests pass through a single gateway before reaching services
  3. Registry-Integrated Gateway: Gateway integrates with service discovery for dynamic routing

Development Environment

  • Java Development Kit: 1.8+
  • Spring Boot: 2.0.6.RELEASE
  • Spring Cloud: Finchley.SR2

Service Implementation

Service Registry Configuration

Create a Eureka registry service with the following configuration:

Maven Dependencies

<dependencies>
  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
  </dependency>
</dependencies>

Application Properties

application.name=service-registry
server.port=8006
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.service-url.default-zone=http://localhost:${server.port}/eureka/

Registry Main Class

@EnableEurekaServer
@SpringBootApplication
public class RegistryMain {
  public static void main(String[] args) {
    SpringApplication.run(RegistryMain.class, args);
  }
}

Gateway Configuration

Gateway Dependencies

<dependencies>
  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  </dependency>
</dependencies>

Gateway Properties

application.name=api-gateway
server.port=9009
eureka.client.service-url.default-zone=http://localhost:8006/eureka/

zuul.routes.service-a.path=/greeting/**
zuul.routes.service-a.url=http://localhost:9010/greeting
zuul.routes.service-b.path=/salutation/**
zuul.routes.service-b.url=http://localhost:9011/salutation

Gateway Main Class

@EnableZuulProxy
@EnableDiscoveryClient
@SpringBootApplication
public class GatewayMain {
  public static void main(String[] args) {
    SpringApplication.run(GatewayMain.class, args);
  }
}

Service Implementations

Service A Configuration

application.name=service-a
server.port=9010
eureka.client.service-url.default-zone=http://localhost:8006/eureka/

Service A Controller

@RestController
public class GreetingController {
  @GetMapping("/greeting/{user}")
  public String greetUser(@PathVariable String user) {
    return user + ", welcome!";
  }
}

Service B Configuraton

application.name=service-b
server.port=9011
eureka.client.service-url.default-zone=http://localhost:8006/eureka/

Service B Controller

@RestController
public class SalutationController {
  @GetMapping("/salutation")
  public String saluteUser(@RequestParam String name) {
    return name + ", greetings!";
  }
}

Verification Process

Start all services in sequence: registry, gateway, service A, and service B. Validate routing functionality through these endpoints:

Endpoint Expected Response
http://localhost:9010/greeting/John John, welcome!
http://localhost:9011/salutation?name=Jane Jane, greetings!
http://localhost:9009/greeting/John John, welcome!
http://localhost:9009/salutation?name=Jane Jane, greetings!

Tags: spring-cloud Zuul api-gateway Eureka microservices

Posted on Sun, 01 Nov 2026 16:47:24 +0000 by lnt