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
ApiGatewayfolder.
- In
ApiGateway/src/main/resources, openapplication.propertiesand 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.xmlfile. - 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
ApiGatewaydirectory, 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.ymland 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:8761in your browser. - Confirm that
user-service,product-service,order-service, andapi-gatewayare registered.
-
In the
ApiGatewayproject, create a new file namedGlobalLoggingFilter.javain thecom.microservices.api_gateway.filterpackage. -
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.propertiesto 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
GlobalLoggingFilterto 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.propertiesand use theorderproperty 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