gateway-service Architecture

duobao backend — stateless edge: JWT verify, rate-limit, route, trace injection, TG initData guard

gateway-service (stateless — no schema, port 6661) Spring Cloud Gateway / WebFlux Internet Client Browser / mobile / Telegram HTTPS :443 / :80 PUBLIC (no JWT) /auth/v1/* POST /auth/v1/tg/login POST /auth/v1/refresh POST /auth/v1/logout rate: 5 req/s per IP burst 20 AUTHENTICATED (JWT) /api/v1/* /api/v1/user/** → user-service /api/v1/game/** → game-service /api/v1/prize/** → game-service /api/v1/wallet/** → wallet-service /api/v1/messages/→ message-service /api/v1/agent/** → agent-service rate: 10-30 req/s per uid burst 30-90 injects X-User-Id + HMAC to downstream on pass v1.0 done ADMIN /admin/v1/* (internal VPN only) /admin/v1/** → admin-service admin JWT verified by admin-service gateway routes, does not auth it v1.0 done GLOBAL WEBFLUX FILTERS (ordered) TraceIdGlobalFilter injects X-Trace-Id MDC order -10 RateLimitFilter Redis sliding-window per-IP/uid order -5 · Spring RequestRateLimiter JwtAuthGlobalFilter verify HS256 · reject /api/* anon order 0 · sets X-User-Id + HMAC InternalPath BlockerFilter 404 /internal/* DOMAIN HELPERS JwtVerifier JJWT HS256 + aud/iss JwtRevocationCheck Redis jti blacklist lookup JsonResultError Handler uniform {code,msg,traceId} ROUTE PREDICATES (Spring Cloud Gateway) Route ID Path Predicate Upstream (lb://) Rate Key auth-v1 /auth/v1/** user-service ipKeyResolver api-v1-user /api/v1/user/** user-service uidKeyResolver api-v1-game /api/v1/game/** game-service uidOrIpKeyResolver api-v1-prize /api/v1/prize/** game-service uidKeyResolver api-v1-pay /api/v1/wallet/** wallet-service uidKeyResolver api-v1-messages /api/v1/messages/** message-service uidKeyResolver api-v1-agent /api/v1/agent/** agent-service uidKeyResolver admin-v1 /admin/v1/** admin-service (internal VPN) Nacos service discovery via Spring Cloud LoadBalancer (lb:// prefix) /internal/v1/** blocked at InternalPathBlockerFilter — public HTTP 404 X-User-Id injected via HMAC(uid, secret, epochSecond) — downstream validates v1.0 done — 8 routes wired configs: JwtProperties GatewayProperties (spring.cloud.gateway.routes in application.yml) error format: { code, msg, data:null, traceId } via JsonResultErrorHandler Redis 7 namespace: gateway: • ratelimit:{path}:{key}:{window} • jwt:revoked:{jti} (lookup only) Spring RequestRateLimiter uses RESP3 reactive driver v1.0 done Nacos 2.3 service registry + config • lb:// endpoint resolution • JWT secret via Nacos config v1.0 done Downstream Services (all via Nacos lb://) user-service :6671 game-service :6672 wallet-service :6673 sms-service :6675 agent-service :6676 admin-service :6677 message-service :6678 sign-service / chain-service not routed via gateway (internal Feign only) v1.0 done No Kafka gateway is stateless proxy — zero business / event logic No DB · No Mappers LEGEND Controllers / Routes Services / sibling svc Auth / rate-limit filters DB / Mappers Events / channels External services Helpers / lanes Service boundary Cache / limiter line Kafka publish v1.0 done v1.1 deferred

What gateway-service owns

  • • JWT verification (HS256) + X-User-Id HMAC injection to downstream
  • • Redis sliding-window rate limiting per-IP (public) and per-uid (API)
  • • Path-based routing to 7 backend services via Nacos lb://
  • • CORS deduplication (DedupeResponseHeader filter)
  • • trace_id injection on every request (X-Trace-Id header)
  • • /internal/v1/** hard-blocked from public internet (HTTP 404)
  • • Uniform { code, msg, data, traceId } error envelope
  • • WebFlux / reactive — no blocking code, no DB, no Kafka

Kafka events produced / consumed

  • • Produces: none
  • • Consumes: none
  • • gateway is a stateless proxy — all event logic lives downstream

External dependencies

  • • Redis 7 — rate-limit counters (Spring RequestRateLimiter) + jti blacklist lookup
  • • Nacos 2.3 — service discovery (lb:// resolution) + config (JWT secret, gateway props)
  • • Downstream services: user, game, wallet, message, agent, admin (Nacos-discovered)
  • • sign-service and chain-service are NOT routed via gateway (internal Feign only)