API Gateway para serviços Kotlin: quando uma única entrada é melhor que mil
Imagine que seu zoológico de microsserviços em Kotlin cresceu para mais de 20 serviços. Cada um deles se comunica com o mundo através de sua própria porta, exige sua própria autenticação e trata os erros de forma diferente. Os clientes se confundem com os endpoints, e você reza todas as noites para que um serviço extra não caia e enterre todo o aplicativo. Familiar?
Existe uma solução — o API Gateway. É um ponto de entrada único que assume o roteamento, a segurança, o cache e o monitoramento. Hoje vamos analisar como construir esse gateway em Kotlin usando duas abordagens populares: o leve Ktor e o industrial Spring Cloud Gateway. Sem enrolação — apenas código e prática.
O que é um API Gateway e por que você precisa dele?
API Gateway é uma camada entre os clientes e seus microsserviços. Em vez de cada frontend ou aplicativo externo conhecer os endereços de todos os seus serviços, eles se comunicam apenas com o gateway. E é ele quem decide para onde encaminhar a requisição.
Principais funções do gateway:
- Roteamento — direciona requisições para os serviços corretos com base na URL ou cabeçalhos.
- Autenticação e autorização — verifica tokens antes que a requisição chegue à lógica de negócios.
- Balanceamento de carga — distribui requisições entre instâncias do mesmo serviço.
- Cache — armazena respostas para dados frequentemente solicitados.
- Monitoramento e registro de logs — coleta métricas de todas as requisições em um só lugar.
- Rate limiting — protege contra DDoS e sobrecargas.
Se você programa em Kotlin e usa arquitetura de microsserviços, o API Gateway é um must-have, não uma opção. Sem ele, você corre o risco de ter um caos de endpoints dispersos e problemas de segurança.
Abordagem 1: API Gateway com Ktor — leveza e flexibilidade
Ktor é um framework da JetBrains, criado especificamente para Kotlin. Ele é assíncrono, leve e ideal para escrever gateways quando você não quer usar o pesado Spring Boot.
Vamos escrever um API Gateway simples em Ktor que roteia requisições para dois serviços: user-service (usuários) e order-service (pedidos).
Passo 1: Configuração do projeto
Crie um novo projeto Ktor através do start.ktor.io ou adicione as dependências manualmente no build.gradle.kts:
dependencies { implementation("io.ktor:ktor-server-core:2.3.7") implementation("io.ktor:ktor-server-netty:2.3.7") implementation("io.ktor:ktor-client-core:2.3.7") implementation("io.ktor:ktor-client-cio:2.3.7") implementation("io.ktor:ktor-server-auth:2.3.7") implementation("io.ktor:ktor-server-content-negotiation:2.3.7") implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.7") implementation("ch.qos.logback:logback-classic:1.4.14")}Passo 2: Roteamento básico com proxy
Crie o arquivo principal Application.kt:
import io.ktor.client.*import io.ktor.client.request.*import io.ktor.client.statement.*import io.ktor.http.*import io.ktor.server.application.*import io.ktor.server.engine.*import io.ktor.server.netty.*import io.ktor.server.response.*import io.ktor.server.routing.*
fun main() { embeddedServer(Netty, port = 8080) { module() }.start(wait = true)}
fun Application.module() { val httpClient = HttpClient()
routing { // Proxy para user-service route("/api/users") { handle { val response = httpClient.get("http://localhost:8081${call.request.uri}") call.respondText( text