Implantação zero-downtime de serviços Java: como não derrubar a produção
Imagine: sexta-feira, 17:45, você está implantando uma nova versão do serviço, vai pegar um café, volta — e o site está fora do ar. Erro 500, clientes nervosos, o tech lead escrevendo no Slack "O que aconteceu?". Uma dor familiar? Se você trabalha com Java e microsserviços, sabe: parar o serviço para implantação não é apenas um contratempo técnico, é perda de dinheiro e reputação.
A boa notícia: a implantação zero-downtime (implantação sem interrupção) não é mágica, mas um conjunto de práticas comprovadas. Neste artigo, vamos analisar como organizar uma implantação perfeita de aplicações Java: desde conceitos até código real em Spring Boot. Você aprenderá a usar rolling update, blue-green e canary deployment para que seus usuários nem percebam as atualizações.
Por que os serviços Java falham durante a implantação?
O problema clássico: a aplicação inicia, mas o processo antigo ainda está processando requisições. Você mata o processo antigo — e as novas requisições caem no vazio. Ou o contrário: a nova instância ainda não está aquecida, mas o tráfego já está chegando. Em Java, isso é agravado pela inicialização lenta da JVM, inicialização do Hibernate e carregamento de caches.
Principais causas de interrupções:
- Encerramento abrupto do processo antigo — requisições são interrompidas no meio.
- Nova instância não aquecida — a primeira requisição é lenta, cache vazio.
- Quebra de sessões — o usuário perde dados do carrinho ou autenticação.
- Incompatibilidade de banco de dados — migrações quebram a versão antiga.
A implantação zero-downtime Java resolve todos esses problemas, se abordada de forma sistêmica. Vamos ver três padrões principais.
Padrão 1: Rolling Update (atualização contínua)
Esta é a abordagem mais popular no mundo do Kubernetes e plataformas em nuvem. A ideia é simples: você tem várias instâncias do serviço (réplicas). Você as atualiza uma a uma: a instância antiga é parada, a nova é iniciada — e assim por diante, até que todas as réplicas sejam novas.
Como funciona na prática com Spring Boot e Kubernetes
Suponha que você tenha um microsserviço em Spring Boot, implantado no Kubernetes. Para o rolling update, basta uma configuração correta do Deployment e a configuração do graceful shutdown (encerramento suave).
Passo 1: Configure o Spring Boot para graceful shutdown:
// application.ymlserver: shutdown: graceful
spring: lifecycle: timeout-per-shutdown-phase: 30sO que isso faz? Quando o Kubernetes envia o sinal SIGTERM, o Spring Boot para de aceitar novas requisições, mas conclui as que estão sendo processadas em até 30 segundos. Sem essa configuração, a JVM simplesmente mataria o processo, interrompendo as requisições.
Passo 2: Configure a readiness probe e a liveness probe:
@RestControllerpublic class HealthController {
@GetMapping("/actuator/health/readiness") public ResponseEntity<String> readiness() { // Verifica se o serviço está pronto para receber tráfego // Por exemplo, banco de dados conectado, cache aquecido return ResponseEntity.ok("OK"); }
@GetMapping("/actuator/health/liveness") public ResponseEntity<String> liveness() { // Verifica se a JVM está viva return ResponseEntity.ok("OK"); }}Passo 3: Configuração do Kubernetes Deployment:
apiVersion: apps/v1kind: Deploymentmetadata: name: my-java-servicespec: replicas: 3 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 # quantos novos pods podem ser criados além do normal maxUnavailable: 0 # nenhum pod deve ficar indisponível template: spec: containers: - name: app image: myregistry/my-java-service:2.0 readinessProbe: