Comunidade

O custo oculto do tempo real em aplicativos móveis

Equipes de desenvolvimento geralmente descobrem os custos ocultos de aplicativos móveis em tempo real através das avaliações negativas nos reviews da loja, não por meio de dashboards de perfilamento. Estes custos incluem a manutenção de sessões persistentes e a geração constante de pacotes de keepalive que podem acordar o sistema operacional e esgotar a bateria. Além disso, os padrões de desconexão em massa durante picos de uso ou mudanças de rede podem sobrecarregar servidores ao tentarem recuperar todo o estado do cliente, transformando pequenos problemas em grandes incidentes. A solução envolve classificar eventos e implementar mecanismos robustos para recuperação eficiente.

Compartilhar
Medium

O custo oculto do tempo real em aplicativos móveis

A maioria das equipes descobre os custos ocultos de aplicativos móveis em tempo real através de avaliações na loja de aplicativos queixando-se sobre o esgotamento da bateria, e não por meio de painéis de perfilagem. Por então, as suposições já estão codificadas na produção.

Vi esse padrão se repetir em várias plataformas. A camada WebSocket parece limpa na fase de teste. Ela desempenha bem em um ambiente de desenvolvimento conectado à Wi-Fi da empresa. Então, os usuários reais a atingem no metrô, em elevadores, durante transições celulares e depois que o sistema operacional (SO) suspendeu o aplicativo em segundo plano. O modelo de sessão começa a falhar.

O custo geralmente não é o próprio WebSocket. Ele vem das suposições embutidas em torno dele. Sessões estáveis. Execução em primeiro plano. Acesso contínuo à rede. Ambientes de desenvolvimento raramente reproduzem restrições de runtime móvel como transições de energia do rádio, suspensão de aplicativos em segundo plano, cobertura celular fraca ou comportamento de reconexão após o aplicativo acordar da pausa.

O móvel viola essas suposições constantemente.

Press enter ou clique para visualizar a imagem em tamanho completo
Suposições de sessões estáveis na fase de teste vs. restrições de runtime móvel em produção

Este post aborda os modos de falha que vi em produção e os padrões arquiteturais que resistem às verdadeiras restrições do móvel.

Sessões persistentes contra as restrições do SO móvel

A tendência de manter um WebSocket vivo para cada usuário ativo é compreensível. Isso reduz o atraso, simplifica a entrega do servidor ao cliente e evita novas buscas.

No móvel, esse design tem custos que não aparecem nos testes de carga. Pacotes de manutenção ativa, pings do WebSocket, sondas de reconexão e atualizações de token podem acordar a pilha de rede e empurrar o rádio celular para um estado de maior consumo.

Em redes de Long-Term Evolution (LTE), até pequenos pacotes podem acionar um período de radio tail, onde o modem permanece ativo por dez segundos ou mais após a transferência, dependendo da operadora, do chip, da geração da rede e do estado do dispositivo.

Equipes frequentemente descobrem isso por meio de avaliações em lojas de aplicativos, em vez de perfis. Os usuários não dizem: “o intervalo do keepalive é muito agressivo.” Eles dizem: “este aplicativo esgota minha bateria.”

WebSockets pings e keepalives do Transmission Control Protocol (TCP) podem gerar atividade de rede. Se ambos estiverem ativos e configurados sem coordenação, o cliente pode enviar mais tráfego de liveness do que pretendido, agravando o custo de despertar o rádio.

Cuidado: As limitações de execução em segundo plano do iOS e o Modo Doze do Android podem suspender o trabalho do aplicativo, adiar o acesso à rede ou impedir que a lógica de keepalive funcione confiavelmente após o aplicativo ser movido para segundo plano. Um aplicativo móvel em segundo plano não é uma guia de navegador em Wi-Fi estável.

O erro é tratar todos os eventos como igualmente urgentes. Um indicador de digitação e uma confirmação de pagamento não são da mesma classe de evento. Rotear ambos por um canal persistente porque ele já está disponível é um padrão não examinado.

Um melhor quadro começa com classificação de eventos.

  • Interações de plano de fundo ativas: Indicadores de digitação, sinais de presença, ponteiros de cursor ao vivo e estado multiplayer podem justificar um canal ao vivo enquanto o usuário está engajado.
  • Alterações de estado visíveis para o usuário: Novas mensagens, confirmações de transação e alterações na conta devem usar Apple Push Notification service (APNs) ou Firebase Cloud Messaging (FCM) como o caminho de notificação. O estado durável deve ainda residir no servidor, com suporte de armazenamento de mensagens, logs de eventos, reconhecimentos e reparo de instantâneo.
  • Sincronização não urgente: Atualizações de feed, alterações de preferência e trabalho de frescor geralmente podem esperar por uma busca em lote ao retomar o plano de fundo.

Conexões persistentes são úteis quando o benefício de latência justifica o custo móvel. O problema é torná-las a rota padrão para cada atualização.

Tempestades de reconexão em plataformas móveis

Os custos de sessões persistentes se acumulam gradualmente. Tempestades de reconexão chegam como picos de carga concentrada. Elas criam uma carga backend concentrada quando muitos clientes móveis recuperam no mesmo intervalo.

Os clientes móveis não desconectam aleatoriamente. Saídas de túnel, picos de horário de pico, mudanças Wi-Fi para celular, padrões de desbloqueio matinal e notificações agendadas podem empurrar grandes grupos de dispositivos online juntos.

Quando cada cliente em reconexão solicita uma busca de instantâneo completa, a recuperação se torna um problema de amplificação de leitura. Portais, serviços de autenticação, servidores de aplicativos, caches e caminhos de leitura do datastore são atingidos ao mesmo tempo. Se os tokens de acesso expiraram enquanto os dispositivos estavam offline, a onda de reconexão também pode se tornar uma onda de atualização de autenticação.

Em um caso que trabalhei, uma transição de túnel aproximadamente de 90 segundos produziu um pico de reconexão que atingiu cerca de 8x a carga de leitura normal no caminho de recuperação. A curva de carga parecia um pico externo coordenado, exceto que a fonte era nossos próprios clientes recuperando simultaneamente.

Cuidado: Exponencial backoff com jitter ajuda, mas não é suficiente. Se cada reconexão ainda disparar uma busca de instantâneo completa, espaçar os reintentos apenas adia o ponto de saturação.

O processo de defesa começa com logs de eventos limitados. Os clientes persistem o número da sequência mais recentemente reconhecido ou token de recuperação entre reinicializações do aplicativo e o enviam ao reconectar. Se esse ponto de recuperação ainda estiver dentro da janela de retenção, o servidor retornará apenas os eventos perdidos.

Caso o token seja muito antigo, o servidor cai de volta em um snapshot compacto e emite um novo ponto de recuperação. Sem essa alternativa, a recuperação móvel se torna uma série de leituras completas repetidas, amplificação de retentativas,

Pressione enter ou clique para visualizar a imagem em tamanho completo
Recuperação baseada em sequência vs. recuperação delta durante uma tempestade de reconexões

A diferença entre essas duas rotas de recuperação determina se uma onda de reconexão permanece rotineira ou se torna um incidente.

Evolução do contrato de eventos na concepção de aplicativos móveis

Tempestades de reconexões são visíveis operacionalmente. O desvio de versão é mais silencioso. Ele aparece mais tarde como estado da interface do usuário (UI) obsoleto, lógica de reconciliação quebrada ou bugs de replay após a entrega de uma mudança no esquema.

Os lançamentos móveis são implantados ao longo de dias ou semanas. Em qualquer momento, os payloads em tempo real podem ser consumidos por clientes executando diferentes versões do aplicativo, modelos de cache, bandeiras de recurso e comportamentos do sistema operacional. Um ambiente de teste com uma única versão raramente captura essa mistura.

Mudanças adicionais no esquema ajudam, mas apenas se os clientes as tolerarem. Clientes mais antigos podem ignorar um novo campo seguramente ou falhar na deserialização estrita, manipular incorretamente um novo valor de enumeração ou escrever um evento parcial sobre uma entrada local do cache mais recente.

Trate a evolução do esquema de eventos como migração do esquema do banco de dados. Prefira mudanças adicionais, mantenha os campos antigos durante o período de compatibilidade com clientes e use novos tipos de eventos quando as semânticas mudarem.

A camada de gateway também precisa negociar a capacidade do cliente. Ela deve examinar os dados da capacidade a partir da negociação de conexão ou cabeçalhos da solicitação, não apenas a versão do aplicativo. Com base nesse conjunto de capacidades, ela pode filtrar, traduzir ou transformar payloads antes da entrega.

Press enter or click to view image in full size
Entrega em tempo real de eventos com base na capacidade ao longo das versões do cliente móvel

Esse camada de compatibilidade tem um custo. Uma vez que os gateways transformam eventos, eles se tornam parte da superfície do contrato. Eles precisam de testes de contrato, observabilidade por capacidade do cliente e retestes de replay contra fixtures mais antigas do cliente.

Finalmente, teste mais que binários antigos. Uma versão atual do aplicativo ainda pode reconectar com um cache em disco velho após dias em segundo plano. A integração contínua (CI) deve simular desequilíbrios de versões, replay de cache velho e suspensão do sistema operacional para que falhas na reconciliação sejam detectadas antes que os usuários vejam uma UI obsoleta.

Arquitetura de entrega em camadas para aplicativos móveis

Depois de observar equipes que sobrealocam recursos em comunicação universal em tempo real, o padrão que eu recomendo é a entrega em camadas. Classifique cada atualização por urgência, durabilidade e impacto no usuário, então atribua-a a um caminho de entrega com o perfil de custos adequado.

Não todos os eventos merecem uma conexão persistente. Sinais efêmeros, como indicadores de digitação, presença, ponteiros em tempo real e recibos de leitura podem se deteriorar com elegância ou serem descartados quando o aplicativo está em segundo plano. Mudanças visíveis para o usuário, como novas mensagens, confirmações de transação e atualizações da conta devem usar APNs ou FCM como caminho de notificação, com estado durável armazenado no servidor.

Regra de design: Mantenha eventos efêmeros baratos, mantenha o estado visível para o usuário durável e use recuperação por meio de snapshots para reparar lacunas após períodos offline ou notificações perdidas.

A sincronização do servidor para o cliente não urgente, como atualizações de feed e preferências, geralmente pode esperar até a recuperação em primeiro plano. A telemetria cliente-para-servidor é um caminho separado. Análise e diagnóstico devem usar upload em lote com retentativa, backpressure e limites de tamanho em vez de competir com o tráfego real em tempo real visível para o usuário.

Este modelo reduz o tráfego persistente, diminui o custo da bateria e encolhe a área de reconexão. Conexões persistentes ainda são úteis. Elas apenas não devem ser o caminho padrão para cada atualização.

A lição que se acumula ao longo do tempo

Os custos ocultos dos aplicativos móveis em tempo real não são um único item de dívida técnica. Eles se acumulam na vida da bateria, estabilidade do back-end e velocidade de lançamento à medida que cada novo tipo de evento e versão do cliente suportado adiciona outra rota de compatibilidade.

Em um lançamento de produção, a mudança para entrega em camadas reduziu as ocorrências relacionadas à reconexão pela metade no trimestre seguinte. O protocolo não mudou. A melhoria veio do tratamento da entrega como uma decisão arquitetônica em vez de roteirizar cada atualização pelo mesmo canal ao vivo.

Conclusão: Comece com a classificação de eventos. Decida quais eventos podem ser descartados, quais eventos precisam de estado do servidor durável, quais eventos precisam de push e quais eventos podem esperar por uma recuperação de instantâneo em primeiro plano.

Para sistemas móveis em tempo real, a pergunta útil não é como tornar tudo instantâneo. É perguntar qual caminho de entrega atende às necessidades de custo, durabilidade e recuperação para cada classe de evento.

Fonte original

Conteúdo traduzido e adaptado pela redação do Notícias Mobile. Confira também a matéria na fonte original.

Leia a matéria completa