Set up an API Gateway using Spring Cloud Gateway to route requests to UserService
, ProductService
, and OrderService
. This setup centralizes request handling and paves the way for future enhancements like security and rate limiting.
- Inside the MicroservicesProject workspace, create a folder named
ApiGateway
.
- Open the Command Palette (View > Command Palette or
Ctrl+Shift+P
). - Select Spring Initializr: Generate a Maven Project.
- Configure the options:
- Group Id:
com.microservices
- Artifact Id:
api-gateway
- Name:
ApiGateway
- Dependencies: Spring Cloud Gateway, Spring Cloud Eureka Client
- Group Id:
- Save the project in the
ApiGateway
folder.
- In
ApiGateway/src/main/resources
, openapplication.properties
and add:server.port=8080 spring.application.name=api-gateway eureka.client.service-url.defaultZone=http://localhost:8761/eureka
Add the following dependencies to enable Spring Cloud Gateway and Eureka Client:
<properties>
<java.version>17</java.version>
<spring-cloud.version>2023.0.3</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2023.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Spring Cloud Gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- Reactive WebFlux -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- Eureka Client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
- For each service (
UserService
,ProductService
, andOrderService
,), open thepom.xml
file. - Add the Ribbon dependency:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
-
In
application.properties
, add the routes for each microservice:spring.cloud.gateway.routes[0].id=user-service spring.cloud.gateway.routes[0].uri=lb://user-service spring.cloud.gateway.routes[0].predicates[0]=Path=/api/users/** spring.cloud.gateway.routes[1].id=product-service spring.cloud.gateway.routes[1].uri=lb://product-service spring.cloud.gateway.routes[1].predicates[0]=Path=/api/products/** spring.cloud.gateway.routes[2].id=order-service spring.cloud.gateway.routes[2].uri=lb://order-service spring.cloud.gateway.routes[2].predicates[0]=Path=/api/orders/**
-
In
application.properties
, add filters to rewrite the request paths:spring.cloud.gateway.routes[0].filters[0]=RewritePath=/api/users/(?<segment>.*), /${segment} spring.cloud.gateway.routes[1].filters[0]=RewritePath=/api/products/(?<segment>.*), /${segment} spring.cloud.gateway.routes[2].filters[0]=RewritePath=/api/orders/(?<segment>.*), /${segment}
- Ensure that EurekaServer, UserService, ProductService, and OrderService are all running.
-
In the
ApiGateway
directory, create aDockerfile
:FROM openjdk:17 EXPOSE 8080 ADD target/api-gateway-0.0.1-SNAPSHOT.jar api-gateway.jar ENTRYPOINT ["java", "-jar", "api-gateway.jar"]
-
Build the Docker image for API Gateway:
docker build -t api-gateway .
-
Open
docker-compose.yml
and add the following configuration for the API Gateway:api-gateway: build: ./APIGateway/api-gateway environment: EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE: http://eureka-server:8761/eureka SPRING_APPLICATION_NAME: api-gateway ports: - "8080:8080" depends_on: - eureka-server - user-service - product-service - order-service command: ["sh", "-c", "sleep 25 && java -jar api-gateway.jar"]
-
Start all services, including the API Gateway, with Docker Compose:
docker-compose up --build
- In Postman or a browser, test the endpoints routed through the API Gateway:
- UserService:
http://localhost:8080/api/users
- ProductService:
http://localhost:8080/api/products
- OrderService:
http://localhost:8080/api/orders
- UserService:
-
In
application.properties
, add the following CORS configuration to allow cross-origin requests:spring.web.cors.allowed-origin-patterns=* spring.web.cors.allowed-methods=GET,POST,PUT,DELETE spring.web.cors.allowed-headers=* spring.web.cors.exposed-headers=*
-
This ensures that the API Gateway allows requests from any origin and supports the specified HTTP methods and headers.
- Open the Eureka dashboard at
http://localhost:8761
in your browser. - Confirm that
user-service
,product-service
,order-service
, andapi-gateway
are registered.
-
In the
ApiGateway
project, create a new file namedGlobalLoggingFilter.java
in thecom.microservices.api_gateway.filter
package. -
Add the following code to log incoming requests and outgoing responses:
package com.microservices.api_gateway.filter; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import org.springframework.core.Ordered; @Component public class GlobalLoggingFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // Log the incoming request details System.out.println("Incoming request: " + exchange.getRequest().getPath()); System.out.println("Request method: " + exchange.getRequest().getMethod()); System.out.println("Request headers: " + exchange.getRequest().getHeaders()); // Filter and log the response after processing the request return chain.filter(exchange) .doOnSuccess(aVoid -> { System.out.println("Response status code: " + exchange.getResponse().getStatusCode()); System.out.println("Response headers: " + exchange.getResponse().getHeaders()); }); } @Override public int getOrder() { // This ensures that this filter runs early in the filter chain return -1; } }
- Review what was covered:
- Set up an API Gateway with Spring Cloud Gateway.
- Configured routing and service discovery with Eureka.
- Verified service communication through Postman.
- Added request path rewriting and logging filters.
-
Add a New Static Route:
- Add a route in
application.properties
to direct requests to a static HTML or JSON file hosted on the API Gateway. - Example:
spring.cloud.gateway.routes[3].id=static-content spring.cloud.gateway.routes[3].uri=file:///static spring.cloud.gateway.routes[3].predicates[0]=Path=/static/**
- Test it in Postman by hitting
http://localhost:8080/static/
.
- Add a route in
-
Add Custom Response Headers:
- Modify the
GlobalLoggingFilter
to add a custom header to every response:exchange.getResponse().getHeaders().add("X-Gateway", "ApiGateway");
- Verify in Postman that the custom header appears in the responses.
- Modify the
-
Implement Rate Limiting:
- Explore using Spring Cloud Gateway’s built-in rate-limiting filter to restrict requests per user or IP address.
- Add a rate-limiting filter in
application.properties
:spring.cloud.gateway.routes[0].filters[1]=RequestRateLimiter=redis-rate-limiter[1,2]
- This example uses Redis for rate limiting, which requires additional setup.
-
Experiment with Priority Routing:
- Add overlapping routes in
application.properties
and use theorder
property to control which route takes precedence. - Example:
spring.cloud.gateway.routes[4].id=high-priority-route spring.cloud.gateway.routes[4].uri=lb://user-service spring.cloud.gateway.routes[4].predicates[0]=Path=/api/users/** spring.cloud.gateway.routes[4].order=1
- Test by sending requests to
http://localhost:8080/api/users/
and observing the results.
- Add overlapping routes in