支季雅 发表于 2025-11-18 10:55:02

工作中最常用的6种API网关

前言

API网关在项目中非常重要。
今天这篇文章跟大家一起聊聊工作最常用的6种网关,希望对你会有所帮助。
一、为什么需要API网关?

有些小伙伴在工作中可能会问:我们的系统直接调用微服务不是更简单吗?
为什么非要引入API网关这个"中间商"呢?
让我们先来看一个实际的例子。
没有网关的微服务困境

// 前端直接调用多个微服务 - 问题重重
@RestController
public class FrontendController {
   
    // 问题1:服务地址硬编码
    @Value("${user.service.url:http://localhost:8081}")
    private String userServiceUrl;
   
    @Value("${order.service.url:http://localhost:8082}")
    private String orderServiceUrl;
   
    @Autowired
    private RestTemplate restTemplate;
   
    @GetMapping("/user-dashboard")
    public UserDashboard getUserDashboard(@RequestHeader("Authorization") String token) {
      // 问题2:每个服务都要重复认证逻辑
      if (!validateToken(token)) {
            throw new UnauthorizedException("Token invalid");
      }
      
      // 问题3:需要手动处理服务间调用顺序
      User user = restTemplate.getForObject(userServiceUrl + "/users/current", User.class);
      List<Order> orders = restTemplate.getForObject(orderServiceUrl + "/orders?userId=" + user.getId(), List.class);
      
      // 问题4:错误处理复杂
      if (user == null || orders == null) {
            throw new ServiceUnavailableException("Backend service unavailable");
      }
      
      return new UserDashboard(user, orders);
    }
   
    // 问题5:重复的认证代码
    private boolean validateToken(String token) {
      // 每个接口都要实现的认证逻辑
      return token != null && token.startsWith("Bearer ");
    }
}引入网关后的优雅架构

// 网关统一处理所有横切关注点
@Configuration
public class GatewayConfig {
   
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
      return builder.routes()
            .route("user_service", r -> r.path("/api/users/**")
                .uri("lb://user-service"))
            .route("order_service", r -> r.path("/api/orders/**")
                .uri("lb://order-service"))
            .route("product_service", r -> r.path("/api/products/**")
                .uri("lb://product-service"))
            .build();
    }
}

// 前端只需调用网关
@RestController
public class FrontendController {
   
    @Autowired
    private RestTemplate restTemplate;
   
    @GetMapping("/api/user-dashboard")
    public UserDashboard getUserDashboard() {
      // 网关已经处理了认证、路由、负载均衡等问题
      return restTemplate.getForObject("http://gateway/api/users/current/dashboard", UserDashboard.class);
    }
}API网关的核心价值

让我们通过架构图来理解网关在微服务架构中的关键作用:

网关解决的8大核心问题:

[*]统一入口:所有请求都通过网关进入系统
[*]认证授权:集中处理身份验证和权限控制
[*]流量控制:限流、熔断、降级等 resiliency 模式
[*]监控统计:统一的日志、指标收集
[*]协议转换:HTTP/1.1、HTTP/2、gRPC 等协议适配
[*]缓存加速:响应缓存降低后端压力
[*]安全防护:WAF、防爬虫、防重放攻击
[*]服务治理:服务发现、负载均衡、路由转发
下面我们一起看看工作中最常见的6种API网关有哪些。
二、Spring Cloud Gateway

有些小伙伴在Spring技术栈中开发微服务,Spring Cloud Gateway 无疑是最自然的选择。
作为Spring官方推出的第二代网关,它基于WebFlux响应式编程模型,性能卓越。
核心架构深度解析

@Configuration
public class AdvancedGatewayConfig {
   
    @Bean
    @Order(-1)
    public GlobalFilter customGlobalFilter() {
      return (exchange, chain) -> {
            // 前置处理
            long startTime = System.currentTimeMillis();
            ServerHttpRequest request = exchange.getRequest();
            
            // 添加追踪ID
            String traceId = UUID.randomUUID().toString();
            ServerHttpRequest mutatedRequest = request.mutate()
                .header("X-Trace-Id", traceId)
                .build();
               
            return chain.filter(exchange.mutate().request(mutatedRequest).build())
                .then(Mono.fromRunnable(() -> {
                  // 后置处理
                  long duration = System.currentTimeMillis() - startTime;
                  log.info("Request {} completed in {}ms", traceId, duration);
                }));
      };
    }
   
    @Bean
    public RouteLocator advancedRoutes(RouteLocatorBuilder builder) {
      return builder.routes()
            // 用户服务 - 带熔断和重试
            .route("user_service", r -> r.path("/api/users/**")
                .filters(f -> f
                  .circuitBreaker(config -> config
                        .setName("userServiceCB")
                        .setFallbackUri("forward:/fallback/user-service"))
                  .retry(config -> config
                        .setRetries(3)
                        .setMethods(HttpMethod.GET, HttpMethod.POST)
                        .setBackoff(100L, 1000L, 2, true))
                  .requestRateLimiter(config -> config
                        .setRateLimiter(redisRateLimiter())
                        .setKeyResolver(apiKeyResolver()))
                  .modifyRequestBody(String.class, String.class,
                        (exchange, s) -> Mono.just(validateAndTransform(s))))
                .uri("lb://user-service"))
            
            // 订单服务 - 带JWT认证
            .route("order_service", r -> r.path("/api/orders/**")
                .filters(f -> f
                  .filter(jwtAuthenticationFilter())
                  .prefixPath("/v1")
                  .addResponseHeader("X-API-Version", "1.0"))
                .uri("lb://order-service"))
            
            // 商品服务 - 静态资源缓存
            .route("product_service", r -> r.path("/api/products/**")
                .filters(f -> f
                  .dedupeResponseHeader("Cache-Control", "RETAIN_FIRST")
                  .setResponseHeader("Cache-Control", "public, max-age=3600"))
                .uri("lb://product-service"))
            .build();
    }
   
    @Bean
    public JwtAuthenticationFilter jwtAuthenticationFilter() {
      return new JwtAuthenticationFilter();
    }
   
    @Bean
    public RedisRateLimiter redisRateLimiter() {
      return new RedisRateLimiter(10, 20);
    }
   
    @Bean
    public KeyResolver apiKeyResolver() {
      return exchange -> {
            String apiKey = exchange.getRequest().getHeaders().getFirst("X-API-Key");
            return Mono.just(Optional.ofNullable(apiKey).orElse("anonymous"));
      };
    }
}

// JWT认证过滤器
@Component
class JwtAuthenticationFilter implements GatewayFilter {
   
    @Autowired
    private JwtUtil jwtUtil;
   
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
      String token = extractToken(exchange.getRequest());
      
      if (token == null) {
            return onError(exchange, "Missing authentication token", HttpStatus.UNAUTHORIZED);
      }
      
      try {
            Claims claims = jwtUtil.parseToken(token);
            String username = claims.getSubject();
            
            // 将用户信息添加到header
            ServerHttpRequest mutatedRequest = exchange.getRequest().mutate()
                .header("X-User-Name", username)
                .header("X-User-Roles", String.join(",", claims.get("roles", List.class)))
                .build();
               
            return chain.filter(exchange.mutate().request(mutatedRequest).build());
      } catch (Exception e) {
            return onError(exchange, "Invalid token: " + e.getMessage(), HttpStatus.UNAUTHORIZED);
      }
    }
   
    private String extractToken(ServerHttpRequest request) {
      String bearerToken = request.getHeaders().getFirst("Authorization");
      if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
      }
      return null;
    }
   
    private Mono<Void> onError(ServerWebExchange exchange, String err, HttpStatus status) {
      exchange.getResponse().setStatusCode(status);
      DataBuffer buffer = exchange.getResponse().bufferFactory()
            .wrap(("{\"error\":\"" + err + "\"}").getBytes());
      return exchange.getResponse().writeWith(Mono.just(buffer));
    }
}Spring Cloud Gateway 执行流程


优点:

[*]与Spring Cloud生态完美集成
[*]基于WebFlux,性能优秀
[*]功能丰富,支持过滤器和断言
[*]配置灵活,支持代码和配置文件两种方式
缺点:

[*]对非Spring技术栈不友好
[*]学习曲线相对陡峭
[*]依赖Spring Cloud组件
使用场景:

[*]Spring Cloud微服务架构
[*]需要深度定制网关逻辑
[*]团队熟悉Spring技术栈
三、Kong:企业级API网关标杆

有些小伙伴在企业级场景中需要更高的性能和更丰富的功能,Kong就是这样一个基于Nginx和OpenResty的高性能API网关。
Kong 配置实战

# kong.yml - 声明式配置
_format_version: "2.1"
_transform: true

services:
- name: user-service
    url: http://user-service:8080
    routes:
      - name: user-route
      paths: ["/api/users"]
      strip_path: true
    plugins:
      - name: key-auth
      config:
          key_names: ["apikey"]
          hide_credentials: true
      - name: rate-limiting
      config:
          minute: 10
          policy: redis
      - name: prometheus
      enabled: true

- name: order-service
    url: http://order-service:8080
    routes:
      - name: order-route
      paths: ["/api/orders"]
      methods: ["GET", "POST", "PUT"]
    plugins:
      - name: cors
      config:
          origins: ["https://example.com"]
          methods: ["GET", "POST", "PUT"]
          headers: ["Accept", "Authorization", "Content-Type"]
      - name: request-transformer
      config:
          add:
            headers: ["X-From-Kong: true"]
          remove:
            headers: ["User-Agent"]

consumers:
- username: mobile-app
    keyauth_credentials:
      - key: mobile-key-123
- username: web-app
    keyauth_credentials:
      - key: web-key-456

plugins:
- name: ip-restriction
    config:
      allow: ["192.168.0.0/16", "10.0.0.0/8"]
- name: correlation-id
    config:
      header_name: "X-Request-ID"
      generator: "uuid"自定义Kong插件开发

-- kong/plugins/request-validator/handler.lua
local BasePlugin = require "kong.plugins.base_plugin"
local cjson = require "cjson"

local RequestValidator = BasePlugin:extend()

function RequestValidator:new()
RequestValidator.super.new(self, "request-validator")
end

function RequestValidator:access(conf)
RequestValidator.super.access(self)

local headers = kong.request.get_headers()
local method = kong.request.get_method()
local body = kong.request.get_raw_body()

-- API Key验证
local api_key = headers["X-API-Key"]
if not api_key then
    kong.response.exit(401, { message = "Missing API Key" })
end

-- 验证API Key格式
if not string.match(api_key, "^%x%x%x%-%x%x%x%-%x%x%x$") then
    kong.response.exit(401, { message = "Invalid API Key format" })
end

-- 请求体验证
if method == "POST" or method == "PUT" then
    if not body or body == "" then
      kong.response.exit(400, { message = "Request body is required" })
    end
   
    local ok, json_body = pcall(cjson.decode, body)
    if not ok then
      kong.response.exit(400, { message = "Invalid JSON format" })
    end
   
    -- 业务规则验证
    if json_body.amount and tonumber(json_body.amount) <= 0 then
      kong.response.exit(400, { message = "Amount must be greater than 0" })
    end
end

-- 添加验证通过标记
kong.service.request.set_header("X-Request-Validated", "true")
kong.service.request.set_header("X-API-Key", api_key)

-- 记录审计日志
kong.log.info("Request validated for API Key: ", api_key)
end

return RequestValidator优点:

[*]配置热更新,无需重启
[*]性能卓越
[*]插件生态丰富
[*]云原生友好
缺点:

[*]相对较新,生态不如Kong成熟
[*]依赖etcd
[*]学习成本较高
使用场景:

[*]云原生环境
[*]需要动态配置的场景
[*]高性能要求的微服务架构
六、Zuul:Netflix经典网关

有些小伙伴在传统Spring Cloud项目中可能还在使用Zuul,虽然它已被Spring Cloud Gateway取代,但了解其原理仍有价值。
Zuul 过滤器实战

# nginx.conf - 生产环境配置
http {
    # 基础配置
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
   
    # 日志格式
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for" '
                  'rt=$request_time uct="$upstream_connect_time" '
                  'uht="$upstream_header_time" urt="$upstream_response_time"';
   
    # 上游服务配置
    upstream user_service {
      server user-service-1:8080 weight=3;
      server user-service-2:8080 weight=2;
      server user-service-3:8080 weight=1;
      
      # 健康检查
      check interval=3000 rise=2 fall=3 timeout=1000;
    }
   
    upstream order_service {
      server order-service-1:8080;
      server order-service-2:8080;
      
      # 会话保持
      hash $cookie_jsessionid;
      hash_again 1;
    }
   
    upstream product_service {
      server product-service:8080;
      
      # 备份服务器
      server backup-product-service:8080 backup;
    }
   
    # API网关配置
    server {
      listen 80;
      server_name api.example.com;
      
      # 全局限流
      limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
      
      # 用户服务路由
      location /api/users/ {
            limit_req zone=api burst=20 nodelay;
            
            # 反向代理配置
            proxy_pass http://user_service;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            
            # 超时配置
            proxy_connect_timeout 5s;
            proxy_read_timeout 10s;
            proxy_send_timeout 10s;
            
            # 重试机制
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
            proxy_next_upstream_tries 3;
            proxy_next_upstream_timeout 10s;
            
            # 缓存配置
            proxy_cache api_cache;
            proxy_cache_key "$scheme$request_method$host$request_uri";
            proxy_cache_valid 200 302 5m;
            proxy_cache_valid 404 1m;
            
            # 添加安全头
            add_header X-Frame-Options DENY;
            add_header X-Content-Type-Options nosniff;
            add_header X-XSS-Protection "1; mode=block";
      }
      
      # 订单服务路由
      location /api/orders/ {
            # JWT验证
            auth_request /auth;
            auth_request_set $user $upstream_http_x_user;
            proxy_set_header X-User $user;
            
            proxy_pass http://order_service;
            
            # CORS配置
            if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type';
                add_header 'Access-Control-Max-Age' 86400;
                return 204;
            }
      }
      
      # 认证端点
      location = /auth {
            internal;
            proxy_pass http://auth_service/validate;
            proxy_pass_request_body off;
            proxy_set_header Content-Length "";
            proxy_set_header X-Original-URI $request_uri;
      }
      
      # 健康检查端点
      location /health {
            access_log off;
            return 200 "healthy\n";
            add_header Content-Type text/plain;
      }
      
      # 监控端点
      location /nginx-status {
            stub_status on;
            access_log off;
            allow 192.168.0.0/16;
            deny all;
      }
    }
}优点:

[*]与Netflix集成良好
[*]过滤器机制灵活
[*]文档资料丰富
缺点:

[*]性能较差(阻塞IO)
[*]已被Spring Cloud Gateway取代
[*]社区活跃度下降
使用场景:

[*]遗留Spring Cloud项目
[*]Netflix技术栈
[*]非性能敏感场景
七、Traefik:云原生动态网关

有些小伙伴在容器化环境中需要自动服务发现,Traefik就是为云原生而生的动态网关。
Traefik 配置示例

# apisix-config.yaml
routes:
- uri: /api/users/*
    name: user-service
    methods:
    upstream:
      type: roundrobin
      nodes:
      user-service-1:8080: 1
      user-service-2:8080: 2
      user-service-3:8080: 1
    plugins:
      proxy-rewrite:
      uri: "/users$1"
      limit-count:
      count: 100
      time_window: 60
      key: remote_addr
      rejected_code: 503
      jwt-auth:
      key: user-service
      secret: my-secret-key
      exp: 86400

- uri: /api/orders/*
    name: order-service
    upstream:
      type: chash
      key: arg_user_id
      nodes:
      order-service-1:8080: 1
      order-service-2:8080: 1
    plugins:
      cors:
      allow_origins: "https://example.com"
      allow_methods: "GET,POST,PUT,DELETE"
      allow_headers: "*"
      response-rewrite:
      body: '{"code": 0, "message": "success", "data": $body}'
      fault-injection:
      abort:
          http_status: 500
          body: "service unavailable"
          percentage: 5

- uri: /api/products/*
    name: product-service
    upstream:
      type: roundrobin
      nodes:
      product-service:8080: 1
    plugins:
      proxy-cache:
      cache_key: ["$uri", "$args"]
      cache_zone: disk_cache_one
      cache_ttl: 300
      uri-blocker:
      block_rules: ["^/admin/", ".php$"]
      rejected_code: 403

# 全局插件
plugins:
- name: prometheus
    enable: true
- name: zipkin
    enable: true
    config:
      endpoint: http://zipkin:9411/api/v2/spans
      sample_ratio: 0.001优点:

[*]自动服务发现
[*]配置简单
[*]云原生友好
[*]内置监控和Dashboard
缺点:

[*]功能相对简单
[*]性能不如Nginx系网关
[*]高级功能需要企业版
使用场景:

[*]容器化环境
[*]需要自动服务发现的场景
[*]快速原型开发
八、6大网关对比

通过前面的分析,我们现在对这六种API网关有了深入的了解。
让我们通过一个全面的对比来帮助大家做出正确的技术选型。
详细对比表格

特性维度Spring Cloud GatewayKongNginxAPISIXZuulTraefik性能高(WebFlux)极高(Nginx)极高(C)极高(Nginx)中(阻塞IO)中配置方式代码/配置声明式YAML配置文件动态配置代码/配置动态配置服务发现Spring Cloud插件支持需手动配置支持Spring Cloud自动发现K8s支持良好良好需Ingress优秀一般优秀监控MicrometerPrometheus基础监控PrometheusHystrix内置学习曲线中中高低中高中低适用场景Spring Cloud企业级传统架构云原生传统Spring容器化选型决策指南

选择Spring Cloud Gateway当:

[*]技术栈以Spring为主
[*]需要深度定制网关逻辑
[*]已经使用Spring Cloud组件
[*]团队熟悉响应式编程
选择Kong当:

[*]企业级高并发场景
[*]需要丰富插件生态
[*]有专业运维团队
[*]需要成熟的管理界面
选择Nginx当:

[*]性能要求极高
[*]场景相对简单
[*]团队熟悉Nginx
[*]资源受限环境
选择APISIX当:

[*]云原生环境
[*]需要动态配置
[*]追求最新技术
[*]高性能要求
选择Zuul当:

[*]维护遗留Spring Cloud项目
[*]Netflix技术栈
[*]非性能敏感场景
选择Traefik当:

[*]容器化部署
[*]需要自动服务发现
[*]快速开发部署
[*]配置简单要求
总结

通过本文的介绍,我们对6种主流API网关有了全面的认识。
在选择网关时需要考虑以下关键因素:

[*]技术栈匹配:选择与团队技术栈最匹配的方案
[*]性能要求:根据业务并发量选择性能合适的网关
[*]功能需求:评估需要的功能特性,如限流、认证、监控等
[*]运维成本:考虑部署、监控、维护的复杂度
[*]团队能力:评估团队对网关技术的掌握程度
核心建议


[*]新项目优先考虑:Spring Cloud Gateway(Spring技术栈)或 APISIX(云原生)
[*]高并发场景:Kong 或 Nginx
[*]快速原型:Traefik
[*]遗留系统:根据现有技术栈选择
记住,没有最好的网关,只有最合适的网关。
合理的网关选型可以大大提升系统的可维护性、可扩展性和性能表现。
最后说一句(求关注,别白嫖我)

如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下我的同名公众号:苏三说技术,您的支持是我坚持写作最大的动力。
求一键三连:点赞、转发、在看。
关注公众号:【苏三说技术】,在公众号中回复:进大厂,可以免费获取我最近整理的10万字的面试宝典,好多小伙伴靠这个宝典拿到了多家大厂的offer。
更多项目实战在我的技术网站:http://www.susan.net.cn/project

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

习和璧 发表于 2025-11-26 15:34:22

很好很强大我过来先占个楼 待编辑

蛟当罟 发表于 昨天 16:31

感谢,下载保存了
页: [1]
查看完整版本: 工作中最常用的6种API网关