工作中最常用的6种API网关
苏三说技术
2026年02月13日 14:42

大家好,我是苏三,又跟大家见面了。

前言

API网关在项目中非常重要。

今天这篇文章跟大家一起聊聊工作最常用的6种网关,希望对你会有所帮助。

一、为什么需要API网关?

有些小伙伴在工作中可能会问:我们的系统直接调用微服务不是更简单吗?

为什么非要引入API网关这个"中间商"呢?

让我们先来看一个实际的例子。

没有网关的微服务困境

代码块
PlainText
自动换行
复制代码
// 前端直接调用多个微服务 - 问题重重
@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 ");
    }
}
复制成功

引入网关后的优雅架构

代码块
PlainText
自动换行
复制代码
// 网关统一处理所有横切关注点
@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大核心问题:

  1. 统一入口:所有请求都通过网关进入系统

  2. 认证授权:集中处理身份验证和权限控制

  3. 流量控制:限流、熔断、降级等 resiliency 模式

  4. 监控统计:统一的日志、指标收集

  5. 协议转换:HTTP/1.1、HTTP/2、gRPC 等协议适配

  6. 缓存加速:响应缓存降低后端压力

  7. 安全防护:WAF、防爬虫、防重放攻击

  8. 服务治理:服务发现、负载均衡、路由转发

下面我们一起看看工作中最常见的6种API网关有哪些。

二、Spring Cloud Gateway

有些小伙伴在Spring技术栈中开发微服务,Spring Cloud Gateway 无疑是最自然的选择。

作为Spring官方推出的第二代网关,它基于WebFlux响应式编程模型,性能卓越。

核心架构深度解析

代码块
PlainText
自动换行
复制代码
@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技术栈

更多项目实战在我的技术网站:http://susan.net.cn/project

三、Kong:企业级API网关标杆

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

Kong 配置实战

代码块
PlainText
自动换行
复制代码
# 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插件开发

代码块
PlainText
自动换行
复制代码
-- 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"]
ifnot api_key then
    kong.response.exit(401, { message = "Missing API Key" })
end

-- 验证API Key格式
ifnotstring.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
    ifnot body or body == ""then
      kong.response.exit(400, { message = "Request body is required" })
    end
    
    local ok, json_body = pcall(cjson.decode, body)
    ifnot ok then
      kong.response.exit(400, { message = "Invalid JSON format" })
    end
    
    -- 业务规则验证
    if json_body.amount andtonumber(json_body.amount) <= 0then
      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 集群架构

优点:

  • 基于Nginx,性能极高

  • 插件生态丰富

  • 支持集群部署

  • 成熟的监控和管理界面

缺点:

  • 依赖数据库(PostgreSQL/Cassandra)

  • 插件开发需要Lua知识

  • 配置相对复杂

使用场景:

  • 高并发企业级应用

  • 需要丰富插件功能的场景

  • 已有Kong技术栈的团队

四、Nginx:经典反向代理网关

有些小伙伴在传统架构或简单场景中,Nginx仍然是最可靠的选择。它虽然功能相对简单,但性能卓越且稳定。

Nginx 配置详解

代码块
PlainText
自动换行
复制代码
# 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;
        }
    }
}
复制成功

Nginx 请求处理流程

优点:

  • 性能极高,C语言编写

  • 配置相对简单

  • 资源消耗低

  • 社区成熟,资料丰富

缺点:

  • 动态配置能力弱

  • 功能相对基础

  • 需要reload生效配置变更

使用场景:

  • 高性能要求的简单路由

  • 静态资源服务

  • 传统架构升级

更多项目实战在我的技术网站:http://susan.net.cn/project

五、APISIX:云原生API网关新星

有些小伙伴在云原生环境中需要动态配置和高性能,APISIX就是这样一个基于etcd的云原生API网关。

APISIX 路由配置

代码块
PlainText
自动换行
复制代码
# apisix-config.yaml
routes:
-uri:/api/users/*
    name:user-service
    methods:[GET,POST,PUT,DELETE]
    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
复制成功

APISIX 插件开发

代码块
PlainText
自动换行
复制代码
-- apisix/plugins/rate-limit-advanced/init.lua
local core = require("apisix.core")
local plugin_name = "rate-limit-advanced"

local schema = {
    type = "object",
    properties = {
        rate = {type = "integer", minimum = 1},
        burst = {type = "integer", minimum = 0},
        key = {type = "string"},
        window = {type = "integer", minimum = 1},
        rejected_code = {type = "integer", default = 429},
        rejected_msg = {type = "string", default = "rate limit exceeded"}
    },
    required = {"rate", "key"}
}

local _M = {
    version = 1.0,
    priority = 1000,
    name = plugin_name,
    schema = schema,
}

function _M.check_schema(conf)
    return core.schema.check(schema, conf)
end

function _M.access(conf, ctx)
    local key = conf.key
    if key == "remote_addr"then
        key = ctx.var.remote_addr
    elseif key == "server_addr"then
        key = ctx.var.server_addr
    end
    
    local rate = conf.rate
    local burst = conf.burst or0
    local window = conf.window or60
    
    -- 使用redis进行分布式限流
    local redis = require("resty.redis")
    local red = redis:new()
    
    local ok, err = red:connect("127.0.0.1", 6379)
    ifnot ok then
        core.log.error("failed to connect to redis: ", err)
        return500
    end
    
    local current_time = ngx.now()
    local key_name = "rate_limit:" .. key
    
    -- 使用令牌桶算法
    local tokens = red:get(key_name)
    if tokens then
        tokens = tonumber(tokens)
    else
        tokens = burst
    end
    
    local last_update = red:get(key_name .. ":time")
    if last_update then
        last_update = tonumber(last_update)
        local elapsed = current_time - last_update
        local new_tokens = elapsed * rate / window
        
        if new_tokens > 0then
            tokens = math.min(tokens + new_tokens, burst)
        end
    end
    
    if tokens < 1then
        red:setex(key_name .. ":time", window, current_time)
        return conf.rejected_code, conf.rejected_msg
    end
    
    tokens = tokens - 1
    red:setex(key_name, window, tokens)
    red:setex(key_name .. ":time", window, current_time)
end

return _M
复制成功

优点:

  • 配置热更新,无需重启

  • 性能卓越

  • 插件生态丰富

  • 云原生友好

缺点:

  • 相对较新,生态不如Kong成熟

  • 依赖etcd

  • 学习成本较高

使用场景:

  • 云原生环境

  • 需要动态配置的场景

  • 高性能要求的微服务架构

六、Zuul:Netflix经典网关

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

Zuul 过滤器实战

代码块
PlainText
自动换行
复制代码
// Zuul前置过滤器 - 认证和限流
@Component
public class AuthPreFilter extends ZuulFilter {
    
    @Autowired
    private RateLimiterService rateLimiter;
    
    @Autowired
    private JwtTokenProvider tokenProvider;
    
    @Override
    public String filterType() {
        return "pre";
    }
    
    @Override
    public int filterOrder() {
        return 1;
    }
    
    @Override
    public boolean shouldFilter() {
        return true;
    }
    
    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        
        // 1. 限流检查
        String clientId = getClientId(request);
        if (!rateLimiter.tryAcquire(clientId)) {
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(429);
            ctx.setResponseBody("{\"error\": \"Rate limit exceeded\"}");
            return null;
        }
        
        // 2. JWT认证
        String token = extractToken(request);
        if (token == null && requiresAuth(request)) {
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            ctx.setResponseBody("{\"error\": \"Authentication required\"}");
            return null;
        }
        
        if (token != null) {
            try {
                Claims claims = tokenProvider.parseToken(token);
                ctx.addZuulRequestHeader("X-User-Id", claims.getSubject());
                ctx.addZuulRequestHeader("X-User-Roles", 
                    String.join(",", claims.get("roles", List.class)));
            } catch (Exception e) {
                ctx.setSendZuulResponse(false);
                ctx.setResponseStatusCode(401);
                ctx.setResponseBody("{\"error\": \"Invalid token\"}");
                return null;
            }
        }
        
        // 3. 添加追踪信息
        ctx.addZuulRequestHeader("X-Request-ID", UUID.randomUUID().toString());
        ctx.addZuulRequestHeader("X-Forwarded-For", request.getRemoteAddr());
        
        return null;
    }
    
    private String getClientId(HttpServletRequest request) {
        String apiKey = request.getHeader("X-API-Key");
        return apiKey != null ? apiKey : request.getRemoteAddr();
    }
    
    private String extractToken(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
    
    private boolean requiresAuth(HttpServletRequest request) {
        String path = request.getRequestURI();
        return !path.startsWith("/api/public/") && 
               !path.equals("/health") && 
               !path.startsWith("/actuator/");
    }
}

// Zuul后置过滤器 - 响应处理
@Component
public class ResponsePostFilter extends ZuulFilter {
    
    private static final Logger logger = LoggerFactory.getLogger(ResponsePostFilter.class);
    
    @Override
    public String filterType() {
        return "post";
    }
    
    @Override
    public int filterOrder() {
        return 1000;
    }
    
    @Override
    public boolean shouldFilter() {
        return true;
    }
    
    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        HttpServletResponse response = ctx.getResponse();
        
        long startTime = (Long) ctx.get("startTime");
        long duration = System.currentTimeMillis() - startTime;
        
        // 记录访问日志
        logger.info("{} {} {} {} {}ms", 
            request.getRemoteAddr(),
            request.getMethod(),
            request.getRequestURI(),
            response.getStatus(),
            duration);
        
        // 添加响应头
        response.setHeader("X-Response-Time", duration + "ms");
        response.setHeader("X-API-Version", "1.0");
        
        // 统一响应格式
        if (ctx.getResponseBody() != null && 
            response.getContentType() != null && 
            response.getContentType().contains("application/json")) {
            
            String originalBody = ctx.getResponseBody();
            String wrappedBody = "{\"code\": 0, \"data\": " + originalBody + ", \"timestamp\": " + 
                System.currentTimeMillis() + "}";
            ctx.setResponseBody(wrappedBody);
        }
        
        return null;
    }
}
复制成功

优点:

  • 与Netflix集成良好

  • 过滤器机制灵活

  • 文档资料丰富

缺点:

  • 性能较差(阻塞IO)

  • 已被Spring Cloud Gateway取代

  • 社区活跃度下降

使用场景:

  • 遗留Spring Cloud项目

  • Netflix技术栈

  • 非性能敏感场景

更多项目实战在我的技术网站:http://susan.net.cn/project

七、Traefik:云原生动态网关

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

Traefik 配置示例

代码块
PlainText
自动换行
复制代码
# traefik.yaml
api:
dashboard:true
insecure:true

entryPoints:
web:
    address:":80"
    http:
      redirections:
        entryPoint:
          to:websecure
          scheme:https
          
websecure:
    address:":443"

certificatesResolvers:
myresolver:
    acme:
      email:admin@example.com
      storage:/etc/traefik/acme.json
      httpChallenge:
        entryPoint:web

providers:
docker:
    endpoint:"unix:///var/run/docker.sock"
    exposedByDefault:false
    
file:
    filename:/etc/traefik/dynamic.yaml
    watch:true

log:
level:INFO

accessLog:
filePath:"/var/log/traefik/access.log"
bufferingSize:100

metrics:
prometheus:
    entryPoint:websecure

# 动态配置
# dynamic.yaml
http:
middlewares:
    # 认证中间件
    auth-middleware:
      basicAuth:
        users:
          -"admin:$2y$05$YOUR_HASHED_PASSWORD"
          
    # 限流中间件  
    rate-limit-middleware:
      rateLimit:
        burst:100
        period:1m
        
    # 重试中间件
    retry-middleware:
      retry:
        attempts:3
        
    # 熔断中间件
    circuit-breaker-middleware:
      circuitBreaker:
        expression:"NetworkErrorRatio() > 0.5"
        
    # 压缩中间件
    compress-middleware:
      compress:{}

routers:
    # 用户服务路由
    user-service:
      rule:"PathPrefix(`/api/users`)"
      entryPoints:
        -websecure
      middlewares:
        -rate-limit-middleware
        -compress-middleware
      service:user-service
      tls:
        certResolver:myresolver
        
    # 订单服务路由  
    order-service:
      rule:"PathPrefix(`/api/orders`)"
      entryPoints:
        -websecure
      middlewares:
        -auth-middleware
        -rate-limit-middleware
        -circuit-breaker-middleware
      service:order-service
      tls:
        certResolver:myresolver

services:
    user-service:
      loadBalancer:
        servers:
          -url:"http://user-service-1:8080"
          -url:"http://user-service-2:8080"
        healthCheck:
          path:/health
          interval:10s
          timeout:5s
          
    order-service:
      loadBalancer:
        servers:
          -url:"http://order-service-1:8080"
          -url:"http://order-service-2:8080"
复制成功

优点:

  • 自动服务发现

  • 配置简单

  • 云原生友好

  • 内置监控和Dashboard

缺点:

  • 功能相对简单

  • 性能不如Nginx系网关

  • 高级功能需要企业版

使用场景:

  • 容器化环境

  • 需要自动服务发现的场景

  • 快速原型开发

八、6大网关对比

通过前面的分析,我们现在对这六种API网关有了深入的了解。

让我们通过一个全面的对比来帮助大家做出正确的技术选型。

详细对比表格

选型决策指南

选择Spring Cloud Gateway当:

  • 技术栈以Spring为主

  • 需要深度定制网关逻辑

  • 已经使用Spring Cloud组件

  • 团队熟悉响应式编程

选择Kong当:

  • 企业级高并发场景

  • 需要丰富插件生态

  • 有专业运维团队

  • 需要成熟的管理界面

选择Nginx当:

  • 性能要求极高

  • 场景相对简单

  • 团队熟悉Nginx

  • 资源受限环境

选择APISIX当:

  • 云原生环境

  • 需要动态配置

  • 追求最新技术

  • 高性能要求

选择Zuul当:

  • 维护遗留Spring Cloud项目

  • Netflix技术栈

  • 非性能敏感场景

选择Traefik当:

  • 容器化部署

  • 需要自动服务发现

  • 快速开发部署

  • 配置简单要求

总结

通过本文的介绍,我们对6种主流API网关有了全面的认识。

在选择网关时需要考虑以下关键因素:

  1. 技术栈匹配:选择与团队技术栈最匹配的方案

  2. 性能要求:根据业务并发量选择性能合适的网关

  3. 功能需求:评估需要的功能特性,如限流、认证、监控等

  4. 运维成本:考虑部署、监控、维护的复杂度

  5. 团队能力:评估团队对网关技术的掌握程度

核心建议

  1. 新项目优先考虑:Spring Cloud Gateway(Spring技术栈)或 APISIX(云原生)

  2. 高并发场景:Kong 或 Nginx

  3. 快速原型:Traefik

  4. 遗留系统:根据现有技术栈选择

记住,没有最好的网关,只有最合适的网关。

合理的网关选型可以大大提升系统的可维护性、可扩展性和性能表现。

更多项目实战在我的技术网站:http://susan.net.cn/project