Spring Cloud Gateway实战,从零搭建API网关,构建高性能微服务统一入口

大家好,我是小悟。

一、API Gateway概述

什么是API Gateway?

API Gateway(API网关)是一个服务器端组件,作为客户端与后端微服务之间的单一入口点。它负责请求路由、组合、协议转换以及跨领域功能处理。

主要功能:

  1. 请求路由:将客户端请求路由到对应的后端服务
  2. 负载均衡:在多个服务实例间分发请求
  3. 身份验证和授权:统一处理安全认证
  4. 限流和熔断:防止服务过载
  5. 监控和日志:集中收集请求指标
  6. 协议转换:处理不同协议间的转换
  7. 缓存:缓存响应以提升性能

二、Spring Cloud Gateway整合步骤

环境要求

  • JDK 11+
  • Spring Boot 2.7+
  • Maven 3.6+

步骤1:创建父工程

复制代码
<!-- pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>com.example</groupId>
    <artifactId>gateway-demo</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.14</version>
        <relativePath/>
    </parent>
    
    <properties>
        <java.version>11</java.version>
        <spring-cloud.version>2021.0.8</spring-cloud.version>
    </properties>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    <modules>
        <module>api-gateway</module>
    </modules>
</project>

步骤2:创建Gateway服务

复制代码
<!-- api-gateway/pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>gateway-demo</artifactId>
        <groupId>com.example</groupId>
        <version>1.0.0</version>
    </parent>
    
    <modelVersion>4.0.0</modelVersion>
    <artifactId>api-gateway</artifactId>
    
    <dependencies>
        <!-- Spring Cloud Gateway -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        
        <!-- 服务发现 -->
        <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-config</artifactId>
        </dependency>
        
        <!-- 监控 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        
        <!-- 安全 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        
        <!-- JWT -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
    </dependencies>
</project>

步骤3:主启动类

复制代码
// ApiGatewayApplication.java
package com.example.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

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

步骤4:基础配置

复制代码
# application.yml
server:
  port: 8080

spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  # 启用服务发现
          lower-case-service-id: true
      
      routes:
        # 用户服务路由
        - id: user-service
          uri: lb://USER-SERVICE
          predicates:
            - Path=/api/users/**
          filters:
            - StripPrefix=1
            - name: CircuitBreaker
              args:
                name: userService
                fallbackUri: forward:/fallback/user
        
        # 商品服务路由
        - id: product-service
          uri: lb://PRODUCT-SERVICE
          predicates:
            - Path=/api/products/**
          filters:
            - StripPrefix=1
            - AddRequestHeader=X-Request-From, gateway
        
        # 订单服务路由
        - id: order-service
          uri: lb://ORDER-SERVICE
          predicates:
            - Path=/api/orders/**
          filters:
            - StripPrefix=1
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10  # 每秒10个请求
                redis-rate-limiter.burstCapacity: 20   # 最大突发容量20
                key-resolver: "#{@userKeyResolver}"
        
        # 直接路由示例
        - id: baidu-route
          uri: https://www.baidu.com
          predicates:
            - Path=/baidu/**

      # 全局过滤器配置
      default-filters:
        - AddResponseHeader=X-Response-Time, ${spring.application.name}

    # 负载均衡配置
    loadbalancer:
      retry:
        enabled: true

# 熔断器配置
resilience4j:
  circuitbreaker:
    instances:
      userService:
        slidingWindowSize: 10
        failureRateThreshold: 50
        waitDurationInOpenState: 10000

# 监控端点
management:
  endpoints:
    web:
      exposure:
        include: health,info,gateway
  endpoint:
    gateway:
      enabled: true

步骤5:自定义过滤器

复制代码
// JwtAuthenticationFilter.java
package com.example.gateway.filter;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

@Component
public class JwtAuthenticationFilter extends AbstractGatewayFilterFactory<JwtAuthenticationFilter.Config> {
    
    @Value("${jwt.secret}")
    private String jwtSecret;
    
    public JwtAuthenticationFilter() {
        super(Config.class);
    }
    
    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            String path = exchange.getRequest().getURI().getPath();
            
            // 跳过认证的路径
            if (config.getWhiteList().stream().anyMatch(path::startsWith)) {
                return chain.filter(exchange);
            }
            
            // 获取token
            String token = exchange.getRequest()
                    .getHeaders()
                    .getFirst(HttpHeaders.AUTHORIZATION);
            
            if (token == null || !token.startsWith("Bearer ")) {
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            }
            
            try {
                // 验证JWT
                Claims claims = Jwts.parser()
                        .setSigningKey(jwtSecret)
                        .parseClaimsJws(token.substring(7))
                        .getBody();
                
                // 添加用户信息到header
                exchange.getRequest().mutate()
                        .header("X-User-Id", claims.getSubject())
                        .header("X-User-Roles", claims.get("roles", String.class))
                        .build();
                
            } catch (Exception e) {
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            }
            
            return chain.filter(exchange);
        };
    }
    
    public static class Config {
        private java.util.List<String> whiteList = new java.util.ArrayList<>();
        
        public java.util.List<String> getWhiteList() {
            return whiteList;
        }
        
        public void setWhiteList(java.util.List<String> whiteList) {
            this.whiteList = whiteList;
        }
    }
}

步骤6:全局过滤器

复制代码
// GlobalLoggingFilter.java
package com.example.gateway.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class GlobalLoggingFilter implements GlobalFilter, Ordered {
    
    private static final Logger logger = LoggerFactory.getLogger(GlobalLoggingFilter.class);
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        long startTime = System.currentTimeMillis();
        
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            long duration = System.currentTimeMillis() - startTime;
            logger.info("Request: {} {} - Status: {} - Time: {}ms",
                    exchange.getRequest().getMethod(),
                    exchange.getRequest().getURI().getPath(),
                    exchange.getResponse().getStatusCode(),
                    duration);
        }));
    }
    
    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}

步骤7:限流配置

复制代码
// RateLimiterConfig.java
package com.example.gateway.config;

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;

@Configuration
public class RateLimiterConfig {
    
    @Bean
    public KeyResolver userKeyResolver() {
        return exchange -> {
            // 根据用户限流
            String userId = exchange.getRequest()
                    .getHeaders()
                    .getFirst("X-User-Id");
            
            if (userId != null) {
                return Mono.just(userId);
            }
            
            // 根据IP限流
            String ip = exchange.getRequest()
                    .getRemoteAddress()
                    .getAddress()
                    .getHostAddress();
            
            return Mono.just(ip);
        };
    }
    
    @Bean
    public KeyResolver apiKeyResolver() {
        return exchange -> Mono.just(
                exchange.getRequest().getURI().getPath()
        );
    }
}

步骤8:熔断降级处理

复制代码
// FallbackController.java
package com.example.gateway.controller;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;

@RestController
public class FallbackController {
    
    @GetMapping("/fallback/user")
    public Mono<ResponseEntity<Map<String, Object>>> userServiceFallback() {
        return Mono.just(ResponseEntity
                .status(HttpStatus.SERVICE_UNAVAILABLE)
                .body(createFallbackResponse("User service is temporarily unavailable")));
    }
    
    @GetMapping("/fallback/product")
    public Mono<ResponseEntity<Map<String, Object>>> productServiceFallback() {
        return Mono.just(ResponseEntity
                .status(HttpStatus.SERVICE_UNAVAILABLE)
                .body(createFallbackResponse("Product service is temporarily unavailable")));
    }
    
    private Map<String, Object> createFallbackResponse(String message) {
        Map<String, Object> response = new HashMap<>();
        response.put("success", false);
        response.put("message", message);
        response.put("timestamp", System.currentTimeMillis());
        response.put("code", 503);
        return response;
    }
}

步骤9:安全配置

复制代码
// SecurityConfig.java
package com.example.gateway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;

@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
    
    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        return http
                .csrf().disable()
                .authorizeExchange()
                .pathMatchers("/actuator/**", "/fallback/**").permitAll()
                .pathMatchers("/api/auth/**").permitAll()
                .pathMatchers("/api/public/**").permitAll()
                .anyExchange().authenticated()
                .and()
                .httpBasic().disable()
                .formLogin().disable()
                .build();
    }
}

步骤10:健康检查配置

复制代码
// HealthCheckConfig.java
package com.example.gateway.config;

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.ReactiveHealthIndicator;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

@Component
public class HealthCheckConfig implements ReactiveHealthIndicator {
    
    @Override
    public Mono<Health> health() {
        return checkDownstreamServiceHealth()
                .onErrorResume(ex -> Mono.just(
                        Health.down().withException(ex).build())
                );
    }
    
    private Mono<Health> checkDownstreamServiceHealth() {
        // 检查下游服务健康状态
        return Mono.just(Health.up().build());
    }
}

步骤11:动态路由配置(基于数据库)

复制代码
// DynamicRouteService.java
package com.example.gateway.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.List;

@Service
public class DynamicRouteService {
    
    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;
    
    @Autowired
    private ApplicationEventPublisher publisher;
    
    @PostConstruct
    public void initRoutes() {
        // 从数据库加载路由配置
        loadRoutesFromDatabase();
    }
    
    private void loadRoutesFromDatabase() {
        // 实现从数据库加载路由的逻辑
    }
    
    public void addRoute(RouteDefinition definition) {
        routeDefinitionWriter.save(Mono.just(definition)).subscribe();
        refreshRoutes();
    }
    
    public void updateRoute(RouteDefinition definition) {
        deleteRoute(definition.getId());
        addRoute(definition);
    }
    
    public void deleteRoute(String routeId) {
        routeDefinitionWriter.delete(Mono.just(routeId)).subscribe();
        refreshRoutes();
    }
    
    private void refreshRoutes() {
        publisher.publishEvent(new RefreshRoutesEvent(this));
    }
}

三、测试验证

创建测试配置

复制代码
# application-test.yml
spring:
  cloud:
    gateway:
      routes:
        - id: test-route
          uri: http://httpbin.org:80
          predicates:
            - Path=/get/**
          filters:
            - AddRequestHeader=Hello, World

logging:
  level:
    org.springframework.cloud.gateway: DEBUG
    com.example.gateway: DEBUG

编写测试用例

复制代码
// GatewayTest.java
package com.example.gateway;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
import org.springframework.test.web.reactive.server.WebTestClient;

import static com.github.tomakehurst.wiremock.client.WireMock.*;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureWireMock(port = 8081)
class GatewayTest {
    
    @Autowired
    private WebTestClient webClient;
    
    @Test
    void testRoute() {
        stubFor(get(urlEqualTo("/test"))
                .willReturn(aResponse()
                        .withBody("test")
                        .withHeader("Content-Type", "text/plain")));
        
        webClient.get()
                .uri("/test")
                .exchange()
                .expectStatus().isOk()
                .expectBody(String.class).isEqualTo("test");
    }
}

四、部署配置

Docker部署配置

复制代码
# Dockerfile
FROM openjdk:11-jre-slim
VOLUME /tmp
COPY target/api-gateway-*.jar app.jar
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar"]
EXPOSE 8080

Kubernetes配置

复制代码
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-gateway
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api-gateway
  template:
    metadata:
      labels:
        app: api-gateway
    spec:
      containers:
      - name: api-gateway
        image: api-gateway:latest
        ports:
        - containerPort: 8080
        env:
        - name: SPRING_PROFILES_ACTIVE
          value: "prod"
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 30
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 15

五、总结

优势特点:

  1. 性能优秀:基于WebFlux响应式编程,非阻塞IO,高并发能力强
  2. 功能全面:内置路由、过滤、熔断、限流等核心功能
  3. 易于扩展:支持自定义过滤器和全局过滤器
  4. 云原生友好:完美整合Spring Cloud生态
  5. 配置灵活:支持YAML配置、Java配置和动态配置

最佳实践:

  1. 路由设计:合理规划API路径,遵循RESTful规范
  2. 安全防护:统一认证授权,实施请求验证
  3. 性能监控:集成监控系统,实时收集指标
  4. 容错处理:配置熔断降级,确保系统可用性
  5. 版本管理:支持API版本控制,平滑升级

注意事项:

  1. 网关应保持轻量级,避免复杂业务逻辑
  2. 合理配置超时时间和重试机制
  3. 实施灰度发布和蓝绿部署
  4. 定期更新和维护路由规则
  5. 监控网关性能,及时扩容

通过Spring Cloud Gateway,我们可以构建一个高性能、可扩展、安全的API网关,有效管理和保护微服务架构中的API接口,提升系统的整体稳定性和可维护性。

谢谢你看我的文章,既然看到这里了,如果觉得不错,随手点个赞、转发、在看三连吧,感谢感谢。那我们,下次再见。

您的一键三连,是我更新的最大动力,谢谢

山水有相逢,来日皆可期,谢谢阅读,我们再会

我手中的金箍棒,上能通天,下能探海

相关推荐
shejizuopin2 小时前
基于JavaSSM+MySQL的实验室考勤管理系统设计与实现
java·mysql·vue·毕业设计·论文·springboot·实验室考勤管理系统设计与实现
J***51682 小时前
SpringSecurity的配置
java
面汤放盐2 小时前
软件架构指南 Software Architecture Guide
java·微服务·devops
tkevinjd2 小时前
JUC5(线程池)
java·线程池·多线程·juc
Tao____2 小时前
如何对接Modbus-tcp协议(使用Thinlinks物联网平台)
java·物联网·网络协议·tcp/ip·modbus
鱼跃鹰飞2 小时前
经典面试题:K8S的自动缩扩容和崩溃恢复
java·容器·kubernetes
Coder_Boy_2 小时前
Spring Boot 事务回滚异常 UnexpectedRollbackException 详解(常见问题集合)
java·spring boot·后端
青云交2 小时前
Java 大视界 -- 基于 Java+Redis Cluster 构建分布式缓存系统:实战与一致性保障(444)
java·redis·缓存·缓存穿透·分布式缓存·一致性保障·java+redis clus
不知疲倦的仄仄2 小时前
第五天:深度解密 Netty ByteBuf:高性能 IO 的基石
java·开源·github
xiaobaishuoAI2 小时前
后端工程化实战指南:从规范到自动化,打造高效协作体系
java·大数据·运维·人工智能·maven·devops·geo