Skip to content

Latest commit

 

History

History
282 lines (222 loc) · 9.65 KB

File metadata and controls

282 lines (222 loc) · 9.65 KB

Lab 7: API Gateway with Spring Cloud Gateway

Objective

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.


Steps

1. Create a New Folder for the API Gateway

  • Inside the MicroservicesProject workspace, create a folder named ApiGateway.

2. Generate API Gateway with Spring Initializr

  • 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
  • Save the project in the ApiGateway folder.

3. Configure API Gateway Properties

  • In ApiGateway/src/main/resources, open application.properties and add:
    server.port=8080
    spring.application.name=api-gateway
    eureka.client.service-url.defaultZone=http://localhost:8761/eureka

4. Update Dependencies in pom.xml

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>

4.1. Add Eureka Dependency to Each Microservice

  • For each service (UserService, ProductService, and OrderService,), open the pom.xml file.
  • Add the Ribbon dependency:
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    

5. Define Routing Configuration for Microservices

  • 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/**

6. Add Custom Filters in API Gateway

  • 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}

7. Run Eureka Server and Microservices

  • Ensure that EurekaServer, UserService, ProductService, and OrderService are all running.

8. Containerize API Gateway with Docker

  • In the ApiGateway directory, create a Dockerfile:

    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 .

9. Update Docker Compose for 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"]

10. Run Docker Compose

  • Start all services, including the API Gateway, with Docker Compose:

    docker-compose up --build

11. Test API Gateway Endpoints

  • 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

12. Add CORS Configuration in API Gateway (Optional)

  • 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.


13. Verify Service Discovery with Eureka

  • Open the Eureka dashboard at http://localhost:8761 in your browser.
  • Confirm that user-service, product-service, order-service, and api-gateway are registered.

14. Add Global Logging Filter for API Gateway

  • In the ApiGateway project, create a new file named GlobalLoggingFilter.java in the com.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;
        }
    }

15. Summary of Lab

  • 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.

Extra Exercises (20 minutes)

  1. 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/.
  2. 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.
  3. 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.
  4. Experiment with Priority Routing:

    • Add overlapping routes in application.properties and use the order 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.