Versão: 1.0.0
Stack: Java 25 · Spring Boot 3.5.6 · Spring Cloud 2025.0.0 · WebFlux · Resilience4j · Caffeine Cache · Prometheus
O API Gateway atua como a porta de entrada única para o ecossistema de microsserviços da plataforma TapTrack Systems, centralizando:
- Roteamento inteligente com Spring Cloud Gateway (WebFlux)
- Descoberta de serviços com Eureka Client
- Configuração de CORS dinâmico por ambiente
- Filtros globais de auditoria e logging
- Circuit Breaker + Fallback via Resilience4j
- Caffeine Cache para otimizar o LoadBalancer
- Métricas Prometheus e monitoramento via Actuator
src/main/java/com/infradomain/apigateway/
├── ApiGatewayApplication.java
├── config/
│ ├── CacheConfig.java # Configuração do Caffeine Cache
│ ├── CorsConfig.java # CORS dinâmico via application.yml
│ ├── WebClientConfig.java # Bean singleton de WebClient
│ ├── GlobalFilterConfig.java # Registro de filtros globais (ex: auditoria)
│ ├── gateway/ # Rotas organizadas por domínio/serviço
│ │ ├── AuthGatewayConfig.java
│ │ ├── UserGatewayConfig.java
│ │ ├── AuditGatewayConfig.java
│ │ ├── ContainerMeasureGatewayConfig.java
│ │ └── ...
│ └── resilience/ # Resiliência e fallback centralizados
│ ├── CircuitBreakerConfig.java # Configura Resilience4j global
│ └── FallbackController.java # Endpoint para fallback
├── filter/
│ ├── AuditGlobalFilter.java # Envia eventos de auditoria
│ └── GatewayRequestLogger.java # Loga requisições e respostas
├── controller/
│ └── HealthController.java # Endpoint de health check
├── resources/
│ ├── application.yml # Configuração base (dev)
│ ├── application-prod.yml # Configuração de produção
│ └── logback-spring.xml # Configuração de logs
└── Dockerfile
Definido via application.yml, permitindo origens diferentes por ambiente.
cors:
allowed-origins:
- http://localhost:4200Em application-prod.yml:
cors:
allowed-origins:
- https://app.taptrack.com@Configuration
public class CorsConfig implements WebFluxConfigurer {
@Value("${cors.allowed-origins}")
private List<String> allowedOrigins;
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins(allowedOrigins.toArray(new String[ 0 ]))
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.exposedHeaders("*");
}
}Configuração central em /config/resilience/CircuitBreakerConfig.java.
resilience4j:
circuitbreaker:
instances:
auditService:
slidingWindowSize:10
minimumNumberOfCalls:5
failureRateThreshold:50
waitDurationInOpenState:10s
Fallback padrão:
@RestController
@RequestMapping("/fallback")
public class FallbackController {
@GetMapping("/{service}")
public Mono<ResponseEntity<String>> fallback(@PathVariable String service) {
return Mono.just(ResponseEntity
.status(HttpStatus.SERVICE_UNAVAILABLE)
.body("Serviço temporariamente indisponível: " + service));
}
}Aumenta a performance do Spring Cloud LoadBalancer, evitando sobrecarga de descoberta via Eureka.
@Configuration
public class CacheConfig {
@Bean
public Caffeine<Object, Object> caffeineConfig() {
return Caffeine.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.maximumSize(1000);
}
@Bean
public CacheManager cacheManager(Caffeine<Object, Object> caffeine) {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(caffeine);
return cacheManager;
}
}WebClient configurado como bean singleton para uso em filtros (como auditoria).
@Configuration
public class WebClientConfig {
@Bean
public WebClient.Builder webClientBuilder() {
return WebClient.builder()
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
}
}AuditGlobalFilter.java
@Bean
public GlobalFilter auditFilter(WebClient.Builder webClientBuilder) {
WebClient client = webClientBuilder.baseUrl("http://localhost:8091/api/v1/audit").build();
return (exchange, chain) -> {
var event = new AuditEvent("gateway", exchange.getRequest().getMethod().name(), exchange.getRequest().getURI().getPath());
return client.post()
.bodyValue(event)
.retrieve()
.bodyToMono(Void.class)
.doOnError(ex -> log.warn("[AUDIT] Falha ao enviar evento: {}", ex.getMessage()))
.onErrorResume(e -> chain.filter(exchange))
.then(chain.filter(exchange));
};
}GatewayRequestLogger.java
@Component
public class GatewayRequestLogger implements GlobalFilter {
private static final Logger log = LoggerFactory.getLogger(GatewayRequestLogger.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("[GATEWAY] {} -> {}", exchange.getRequest().getMethod(), exchange.getRequest().getURI());
return chain.filter(exchange)
.doOnSuccess(done -> log.info("[GATEWAY] Response: {}", exchange.getResponse().getStatusCode()))
.doOnError(ex -> log.error("[GATEWAY] Erro no fluxo: {}", ex.getMessage()));
}
}Cada módulo tem sua configuração em /config/gateway.
Exemplo: AuditGatewayConfig.java
@Configuration
public class AuditGatewayConfig {
@Bean
public RouteLocator auditRoutes(RouteLocatorBuilder builder) {
return builder.routes()
.route("audit-log-service", r -> r.path("/api/v1/audit/**")
.filters(f -> f.circuitBreaker(c -> c
.setName("auditService")
.setFallbackUri("forward:/fallback/audit")))
.uri("http://localhost:8091"))
.build();
}
}mvn clean package -DskipTests
java -jar target/api-gateway-1.0.0.jardocker build -t api-gateway .
docker run -p 8080:8080 api-gateway✅ Configuração modular (por domínio de serviço)
✅ Evita propriedades depreciadas (RouteDefinition via Java config)
✅ Beans reutilizáveis (WebClient, CacheManager)
✅ Filtros globais bem definidos e desacoplados
✅ Resiliência com fallback centralizado
✅ Cache de descoberta otimizado com Caffeine
✅ Logging estruturado (Logback com rotação diária)
✅ Documentação e padronização corporativa
/actuator/health→ Verifica integridade do gateway/actuator/metrics→ Métricas internas (via Micrometer)/actuator/prometheus→ Exporta métricas para Prometheus/actuator/gateway/routes→ Lista rotas ativas
Desenvolvido por: Juliane Maran Organização: TapTrack Systems Licença: Apache 2.0
“Um gateway bem projetado é o ponto de entrada da arquitetura e o primeiro passo para a resiliência.” 💡
- Acessar o
wsl - Build Manual:
docker build -t api-gateway . - Rodar container:
docker run -p 8080:8080 api-gateway - Logs em tempo real:
docker logs -f <container-id>
Se quiser que os serviços conversem entre si localmente
docker network create taptrack-net
docker run -d --network taptrack-net --name eureka eureka-server
docker run -d --network taptrack-net --name gateway api-gateway
docker run -d --network taptrack-net --name container-measure container-measure-service
docker run -d --network taptrack-net --name frontend -p 4200:4200 taptrack-frontendsrc/main/java/com/infradomain/apigateway/
├── ApiGatewayApplication.java
├── config/
│ ├── CacheConfig.java # Configuração do Caffeine Cache
│ ├── CorsConfig.java # CORS dinâmico via application.yml
│ ├── WebClientConfig.java # Bean singleton de WebClient
│ ├── GlobalFilterConfig.java # Registro de filtros globais (ex: auditoria)
│ ├── gateway/ # Rotas organizadas por domínio/serviço
│ │ ├── AuthGatewayConfig.java
│ │ ├── UserGatewayConfig.java
│ │ ├── AuditGatewayConfig.java
│ │ ├── ContainerMeasureGatewayConfig.java
│ │ └── ...
│ └── resilience/ # Configurações de resiliência e fallback
│ ├── CircuitBreakerConfig.java # Configura parâmetros globais do Resilience4j
│ └── FallbackController.java # Controlador de fallback dos serviços
├── filter/
│ ├── AuditGlobalFilter.java
│ ├── LoggingFilter.java
│ └── AuthenticationFilter.java
├── util/
│ └── RequestUtils.java
└── controller/
└── HealthController.java
| Diretório | Responsabilidade | Exemplos |
|---|---|---|
| config/ | Configurações globais e beans reutilizáveis | CorsConfig, WebClientConfig, CacheConfig |
| config/gateway/ | Rotas de cada microserviço com filtros específicos | UserGatewayConfig, AuditGatewayConfig |
| config/resilience/ | Resiliência e fallback centralizados | CircuitBreakerConfig, FallbackController |
| filter/ | Filtros globais e cross-cutting concerns | AuditGlobalFilter, LoggingFilter |
| controller/ | Endpoints internos do Gateway | /health, /fallback |
| util/ | Classes auxiliares, parsing, headers, logs, etc. | RequestUtils |