【架构实战】API网关Kong落地:从选型到生产避坑全记录
【架构实战】API网关Kong落地从选型到生产避坑全记录一、为什么我们需要API网关2022年我们团队有30多个微服务。每次产品提需求“给XX系统开放一个接口”开发就开始头疼这接口该谁来提供订单服务用户服务要认证吗要限流吗文档谁来写谁来维护更崩溃的是每个服务的认证逻辑都不一样订单服务用JWT支付服务用签名用户服务用Session通知服务……什么都没用直接裸奔2022年Q3一次安全审计发现了8个未授权访问漏洞全是内部接口被外部调用的。那个月技术负责人拉了我进一个小群说“做个网关把所有对外接口收敛到一处统一认证、限流、监控。”这就是我接下这个任务的背景。二、选型为什么是Kong2.1 市面主流网关对比选型前我们调研了4个方案方案优点缺点适合场景Kong插件丰富、性能强、文档好学习曲线、DB依赖可选中大型微服务APISIX动态配置、无DB、高性能生态稍弱云原生场景Nginx性能极高、成熟稳定配置复杂、插件开发成本高简单反向代理Spring Cloud GatewayJava生态、集成方便性能一般、运维成本高Java技术栈最终选Kong理由三个插件体系最成熟认证、限流、日志、监控开箱即用Admin API Deck配置GitOps友好公司有工程师之前用过上手快2.2 Kong架构概览【客户端请求】 │ ▼ ┌───────────────────────┐ │ Kong Gateway │ │ ┌─────────────────┐ │ │ │ Admin API │ │ │ │ (配置管理) │ │ │ └─────────────────┘ │ │ ┌─────────────────┐ │ │ │ Data Plane │ │ │ │ (请求代理) │ │ │ │ Plugin Chain │ │ │ │ (认证/限流/日志) │ │ │ └─────────────────┘ │ └───────────┬───────────┘ │ ┌──────────────┼──────────────┐ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ 订单服务 │ │ 用户服务 │ │ 支付服务 │ └──────────┘ └──────────┘ └──────────┘ 【Kong组件说明】 - Kong Gateway核心代理Lua/Nginx - Kong Admin API配置网关RESTful - Kong ManagerWeb UI可选 - DatabasePostgreSQL/Cassandra存储路由/服务/插件配置三、安装部署从零到跑通3.1 Docker Compose快速部署# docker-compose.ymlversion:3.8services:kong-database:image:postgres:13environment:POSTGRES_DB:kongPOSTGRES_USER:kongPOSTGRES_PASSWORD:kongvolumes:-kong-data:/var/lib/postgresql/datanetworks:-kong-netkong:image:kong:3.4environment:KONG_DATABASE:postgresKONG_PG_HOST:kong-databaseKONG_PG_USER:kongKONG_PG_PASSWORD:kongKONG_ADMIN_LISTEN:0.0.0.0:8001KONG_PROXY_LISTEN:0.0.0.0:8000KONG_PROXY_LISTEN_SSL:0.0.0.0:8443depends_on:-kong-databaseports:-8000:8000# HTTP代理-8443:8443# HTTPS代理-8001:8001# Admin APInetworks:-kong-netcommand:kong migrations bootstrapkong-manager:image:kong/kong-manager:3.4environment:KONG_ADMIN_API_URL:http://kong:8001depends_on:-kongports:-8002:8002networks:-kong-netvolumes:kong-data:networks:kong-net:driver:bridge启动命令docker-composeup-ddocker-composeps# 确认所有服务运行中3.2 DB-less模式无数据库生产环境推荐DB-less配置通过Deck管理GitOps友好# docker-compose-dbless.ymlversion:3.8services:kong:image:kong:3.4environment:KONG_DATABASE:offKONG_DECLARATIVE_CONFIG:/usr/local/kong/declarative.ymlKONG_PROXY_LISTEN:0.0.0.0:8000KONG_ADMIN_LISTEN:0.0.0.0:8001KONG_LOG_LEVEL:infovolumes:-./kong-declarative.yml:/usr/local/kong/declarative.yml:roports:-8000:8000-8001:8001# kong-declarative.ymlDeck配置_format_version:3.0services:-name:user-serviceurl:http://user-service:8080routes:-name:user-routepaths:-/api/usersstrip_path:falseplugins:-name:rate-limitingconfig:minute:100policy:local-name:jwtconfig:uri_param_names:-jwtcookie_names:[]header_names:-Authorization四、核心配置Route、Service、Plugin4.1 基础概念Kong三要素Service上游服务目标地址Route路由规则匹配条件Plugin插件认证、限流等Service服务 上游真实服务 Route路由 请求匹配规则path、host、method等 Plugin插件 中间件请求处理链4.2 添加一个服务通过Admin API添加# 添加上游服务curl-i-XPOST http://localhost:8001/services\-HContent-Type: application/json\-d{ name: product-service, url: http://product-service:8080, retries: 3, timeout: 60000 }# 添加路由curl-i-XPOST http://localhost:8001/services/product-service/routes\-HContent-Type: application/json\-d{ name: product-route, paths: [/api/products], methods: [GET, POST], strip_path: false, preserve_host: true }# 测试curlhttp://localhost:8000/api/products验证配置# 查看所有服务curlhttp://localhost:8001/services# 查看所有路由curlhttp://localhost:8001/routes# 测试路由是否生效curl-vhttp://localhost:8000/api/products4.3 路由优先级Kong路由匹配优先级1. Serverless FunctionsServerless插件 2. Dependencies基于IP的访问控制 3. MethodsHTTP方法过滤 4. Hosts域名匹配 5. Paths路径匹配 ← 最常用 6. Headers请求头匹配 7. Query Strings查询参数匹配路径匹配示例# 精确匹配/api/products# 前缀匹配/api/products/.*# 正则匹配~ ^/api/v[0-9]/products$# 按优先级配置多个路由curl-XPOST http://localhost:8001/services/product-service/routes\-d{name:product-v2,paths:[/api/v2/products],strip_path: true}curl-XPOST http://localhost:8001/services/product-service/routes\-d{name:product-v1,paths:[/api/v1/products],strip_path: true}五、插件实战认证、限流、日志5.1 JWT认证插件场景所有接口需要JWT Token认证。# 为服务启用JWT插件curl-XPOST http://localhost:8001/services/product-service/plugins\-HContent-Type: application/json\-d{ name: jwt, config: { uri_param_names: [jwt], header_names: [Authorization], claims_to_verify: [exp], maximum_expiration: 3600 } }创建消费者和JWT凭证# 创建消费者curl-XPOST http://localhost:8001/consumers\-dusernameapp-client-001# 生成JWT凭证curl-XPOST http://localhost:8001/consumers/app-client-001/jwt\-HContent-Type: application/json\-d{ key: app-client-001, algorithm: RS256, rsa_public_key: -----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY----- }JWT Token生成Python示例importjwtimportdatetime payload{iss:app-client-001,sub:app-client-001,iat:datetime.datetime.utcnow(),exp:datetime.datetime.utcnow()datetime.timedelta(hours2),kong_jwt_claim_name:user_id,user_id:12345}# 使用RS256私钥签名tokenjwt.encode(payload,private_key,algorithmRS256)print(fBearer{token})测试# 无Token访问 → 401curlhttp://localhost:8000/api/products# HTTP/1.1 401 Unauthorized# 带Token访问 → 200curl-HAuthorization: Bearer eyJ...http://localhost:8000/api/products# HTTP/1.1 200 OK5.2 限流插件场景防止接口被刷每个消费者每分钟最多100次请求。# 启用限流插件curl-XPOST http://localhost:8001/services/product-service/plugins\-HContent-Type: application/json\-d{ name: rate-limiting, config: { minute: 100, hour: 1000, policy: redis, redis_host: redis, redis_port: 6379, hide_client_headers: false, fault_tolerant: true } }多维度限流# 按IP限流curl-XPOST http://localhost:8001/routes/product-route/plugins\-HContent-Type: application/json\-d{ name: rate-limiting, config: { minute: 60, policy: local, fault_tolerant: true } }限流响应头X-RateLimit-Limit-Minute: 100 X-RateLimit-Remaining-Minute: 95 X-RateLimit-Limit-Hour: 1000 X-RateLimit-Remaining-Hour: 980 Retry-After: 58 ← 被限流时返回被限流后的响应{message:API rate limit exceeded,retry_after:58}5.3 请求日志插件ELK集成场景所有请求日志发送到ELK。# 启用HTTP Log插件curl-XPOST http://localhost:8001/services/product-service/plugins\-HContent-Type: application/json\-d{ name: http-log, config: { http_endpoint: http://logstash:5044/logs, method: POST, content_type: application/json, timeout: 10000, keepalive: 10000, flush_timeout: 2 } }自定义日志格式# 启用File Log方便调试curl-XPOST http://localhost:8001/services/product-service/plugins\-HContent-Type: application/json\-d{ name: file-log, config: { path: /var/log/kong/logs.log, reopen: false, custom_fields_by_lua: { trace_id: ngx.var.request_id, upstream_addr: ngx.var.upstream_addr, latency_ms: ngx.var.request_time } } }六、生产避坑实录坑1Path路径匹配不生效现象配置了Route路径/api/users但请求/api/users/123返回404。原因Kong默认严格匹配如果strip_pathfalse请求路径必须完全匹配。解法# 方案1开启前缀匹配curl-XPUT http://localhost:8001/routes/product-route\-dpaths[]/api/products# 方案2开启正则匹配curl-XPUT http://localhost:8001/routes/product-route\-dpaths[]~^/api/products/.*$# 方案3strip_pathtrue去掉前缀curl-XPUT http://localhost:8001/routes/product-route\-d{ paths: [/api/products], strip_path: true }# 请求 /api/products/123 → 转发到 upstream /products/123坑2限流计数不准Redis并发问题现象配置了每分钟100次限流但实际20个并发请求全部通过了。根因Redis INCR操作在高并发下存在竞争条件。解法使用Redis Lua原子操作或者改用local策略基于Nginx共享字典# nginx.conf 中配置共享字典nginx_http_templates:-name:kong_http_filterstemplate:|lua_shared_dict kong_rate_limit 10m; # 限流计数存储 lua_shared_dict kong_process_events 1m;最终方案# 生产环境使用Redis但开启滑动窗口curl-XPOST http://localhost:8001/plugins\-dnamerate-limiting\-dconfig.minute100\-dconfig.policyredis\-dconfig.redis_hostredis-prod\-dconfig.redis_port6379\-dconfig.redis_passwordxxx\-dconfig.limit_byconsumer# 按消费者维度限流坑3上游服务故障导致网关雪崩现象上游Java服务GC停顿所有请求超时网关线程池打满。解法配置主动健康检查和熔断。# 添加主动健康检查curl-XPOST http://localhost:8001/services/product-service/plugins\-HContent-Type: application/json\-d{ name: active-healthcheck, config: { https_path: /health, http_path: /health, timeout: 2, interval: 5, concurrency: 10, healthy: { interval: 5, http_statuses: [200, 302], successes: 3 }, unhealthy: { interval: 5, http_failures: 3, tcps_failures: 3, timeouts: 3 } } }坑4Kong日志丢失现象File Log插件日志写不进去权限报错。解法Docker环境下确保目录挂载# docker-compose.yml 中添加services:kong:volumes:-./logs/kong:/var/log/kong-./kong-declarative.yml:/usr/local/kong/declarative.yml:ro同时设置日志轮转否则磁盘满# /etc/logrotate.d/kong/var/log/kong/*.log{daily rotate7compress delaycompress notifempty create 0644 root root sharedscripts postrotate kong quit2/dev/null||truesleep1kong start2/dev/null||trueendscript}七、配置管理Deck与GitOps7.1 为什么用Deck问题通过Admin API手动配置生产环境操作容易出错无法版本控制。Deck方案声明式配置Git管理一键同步。# 安装Deckbrewinstallkong/deck/deck# 导出当前配置deckfiledump --output-file kong-config.yml# 验证配置语法deckfilevalidate-skong-config.yml# 对比当前Kong配置与YAML差异deckdiff-skong-config.yml# 同步配置到Kongdecksync-skong-config.yml7.2 完整Deck配置文件# kong-config.yml_format_version:3.0_transform:true# 全局插件plugins:-name:corsconfig:origins:-https://app.example.commethods:-GET-POST-PUT-DELETEheaders:-Authorization-Content-Typeexposed_headers:-X-Request-Idcredentials:truemax_age:3600# 服务定义services:-name:user-serviceurl:http://user-service:8080routes:-name:user-routepaths:-/api/usersmethods:-GET-POSTstrip_path:falseplugins:-name:rate-limitingconfig:minute:100hour:1000policy:redisredis_host:redisredis_port:6379-name:order-serviceurl:http://order-service:8080routes:-name:order-routepaths:-/api/ordersmethods:-GET-POST-DELETEplugins:-name:jwtconfig:claims_to_verify:-exp-name:rate-limitingconfig:minute:50policy:redis# 消费者consumers:-username:mobile-appplugins:-name:key-authconfig:key_names:-X-API-Key-username:web-adminplugins:-name:jwtconfig:rsa_public_key:-----BEGIN PUBLIC KEY-----\n...7.3 CI/CD自动化GitHub Actions自动同步# .github/workflows/kong-sync.ymlname:Sync Kong Configon:push:branches:-mainpaths:-kong-config.ymljobs:sync:runs-on:ubuntu-lateststeps:-uses:actions/checkoutv3-name:Setup Deckrun:|curl -Ls https://github.com/Kong/deck/releases/download/v1.24.0/deck_1.24.0_linux_amd64.tar.gz | tar xz chmod x deck-name:Validate Configrun:./deck file validate-s kong-config.yml-name:Sync to Kongenv:KONG_ADMIN_TOKEN:${{secrets.KONG_ADMIN_TOKEN}}KONG_ADMIN_URL:https://kong.internal/adminrun:|./deck sync \ -s kong-config.yml \ --kong-addr$KONG_ADMIN_URL \ --headersAuthorization:Bearer $KONG_ADMIN_TOKEN八、性能数据8.1 我们生产环境的性能指标数据日处理请求量5000万峰值QPS8万P99延迟8ms网关本身CPU使用率30%4核机器内存占用2GB含Redis插件计数可用性99.99%8.2 性能优化建议# 1. Nginx worker数 CPU核数KONG_NGINX_WORKER_PROCESSES: auto# 2. 开启HTTP/2KONG_HTTP2:on# 3. 合理buffer配置KONG_PROXY_BUFFERING:off# 流式响应KONG_ADMIN_BUFFERING:on# 4. 连接池配置KONG_UPSTREAM_KEEPALIVE:60KONG_UPSTREAM_KEEPALIVE_TIMEOUT:60KONG_UPSTREAM_KEEPALIVE_POOL_SIZE:100九、总结Kong网关落地关键点从DB-less开始Deck管理配置GitOps版本控制这是生产环境的正确姿势。认证插件放在Route层而不是Service层避免影响健康检查。限流用Redis 滑动窗口本地策略在分布式环境下不准。健康检查必开防止把请求打到已故障的上游。日志轮转必配Kong日志量大磁盘满会导致写入失败。Deck CI/CD是标配手工Admin API操作生产环境等于裸奔。监控指标接入Prometheus监控kong_http_requests_total、kong_http_request_latency_ms、kong_datastore_reachable。Kong不是银弹它解决的是入口统一的问题。但把认证、限流、日志收敛到网关后我们团队的接口管理效率提升了一大截——新增一个接口只需要在Deck配置里加一个Service和Route5分钟搞定还不用动业务代码。作者架构实战团队日期2026-07-25标签#API网关 #Kong #微服务 #架构实战 #网关