Muitas solicitações pequenas versus poucas solicitações grandes (Design da API)

49

Atualmente, estou trabalhando em um projeto com uma organização da seguinte maneira:

  • Cliente - Obtém dados do servidor principal via API REST.
  • Servidor - solicita dados de vários outros servidores por meio de APIs de terceiros
  • APIs de terceiros - serviços fora do meu controle que fornecem dados ao servidor (Reddit, Hackernews, Quora etc.)

Por uma questão de argumento, digamos que o cliente precise primeiro de uma lista de itens de cada uma das APIs de terceiros. A partir dessa lista, um item será escolhido no momento em que o cliente precisará ver o conteúdo completo do item, bem como as respostas (isto é, comentários) ao item. Estou tentando decidir entre três opções:

À la Carte

Nessa abordagem, eu teria três pontos de extremidade separados no meu servidor: um para obter a lista de itens, um para obter o conteúdo principal de um item e outro para obter as respostas do item.

  • Prós: nunca faço mais solicitações do que preciso, as solicitações devem ser pequenas e, geralmente, devem ser mais rápidas.
  • Contras: Eu tenho que fazer muitos pedidos. Depois de escolher um item da lista, o usuário pode ter que esperar antes de ver o conteúdo principal e esperar ainda mais para ver as respostas

Cache do servidor

Nesta solicitação, eu faria uma única chamada ao meu servidor para "buscar" todos os dados de todas as fontes. Os dados seriam armazenados em cache no servidor. O cliente teria os mesmos pontos de extremidade REST de antes, exceto que não haveria muita espera entre as chamadas, pois meu servidor já possui os dados e apenas precisa alimentá-los com o cliente.

  • Prós: Ainda fácil de implementar no lado do cliente, mas sem os problemas de latência
  • Contras: um pouco mais envolvido do lado do servidor, e a primeira chamada pode demorar muito.

Cache do lado do cliente

Esse cenário é semelhante ao anterior, exceto que o cliente apenas faz uma solicitação ao servidor: forneça todos os dados. A partir daqui, é de responsabilidade do cliente salvar os dados e usá-los adequadamente.

  • Prós: Fácil implementação do servidor, muito rápido após a primeira chamada
  • Contras: a primeira chamada será muito lenta, implementação mais complicada do lado do cliente

Não tenho certeza de qual é a melhor abordagem ou se talvez eu esteja perdendo a solução óbvia. Qualquer conselho seria muito apreciado!

williamg
fonte
Parece-me uma escolha entre frescura e velocidade. O que suas partes interessadas e usuários finais preferem?
Erk

Respostas:

28

Um aspecto a ter em mente é a latência esperada da rede (ou seja, o tempo de ping) entre seus clientes e seu servidor. Em uma situação de alta latência com boa largura de banda, muitas solicitações pequenas terão desempenho significativamente pior do que uma solicitação grande.

Recentemente, colaborei em um projeto de aplicativo da Web suportado por banco de dados de várias equipes, no qual uma das equipes está na Índia (as demais estão nos EUA). Temos uma única instância de banco de dados hospedada em nosso escritório nos EUA, à qual os desenvolvedores conectam nossas instâncias de servidor da web local. Minha mesa fica a quinze metros e dois saltos de LAN da instância do banco de dados, e o desempenho é bom.

Quando começamos as atividades com os desenvolvedores na Índia, eles estavam enfrentando enormes tempos de espera para iniciar o aplicativo e navegar de página para página. Estamos falando de dez minutos de espera aqui. Acontece que isso ocorreu porque o tempo de ping de ~ 200 ms de suas mesas para o servidor de banco de dados dev estava sendo multiplicado por muitas e breves consultas ao banco de dados. Meu ping local de 0,5 ms foi tão trivial que nunca houve diferença entre o servidor da web e o servidor de banco de dados. Foi a primeira vez que fizemos uma separação geográfica entre servidor da web e servidor de banco de dados.

A solução, no nosso caso, foi clonar o servidor de banco de dados e manter a cópia na Índia, mas o ponto aqui é ter em mente que, se o cliente e o servidor estiverem afastados, a latência da rede será multiplicada pelo número de comunicações no fio. A largura de banda depois que a conexão é estabelecida geralmente é muito menos preocupante.

JakeRobb
fonte
2

Essas três opções não são mutuamente exclusivas, você pode usar uma combinação de caches do lado do cliente e do lado do servidor. No entanto, alguns dados, como comentários, podem ficar obsoletos, se mantidos em cache por muito tempo. Considerando que você não pode verificar se esse é o caso, você provavelmente deve evitar armazená-lo. Por outro lado, o conteúdo geralmente não muda drasticamente, portanto não haveria mal em armazenar em cache no lado do servidor e, em seguida, buscar um pouco no lado do cliente para diminuir a latência.

wfdctrl
fonte
1

Com base apenas nas informações fornecidas, opção 1, porque

  • com uma única solicitação do cliente, você misturaria maçãs e laranjas e a cesta de frutas pode ser muito grande.

  • o armazenamento em cache é uma troca em que você obtém desempenho, mas potencialmente perde consistência (dados obsoletos). Se você não tiver nenhum problema de desempenho identificado, geralmente não vale a pena arriscar os problemas de sincronização.

guillaume31
fonte
0

Sempre achei algumas solicitações grandes com melhor desempenho e mais escalabilidade. Mas existem trocas em todas as abordagens, portanto, isso depende das necessidades do servidor e do cliente. Você pode usar outra opção, que é fazer com que o cliente especifique todo um intervalo ou conjunto de dados a serem recuperados - não necessariamente todos os dados, mas algum intervalo, que é ajustado ao longo do tempo para corresponder à largura de banda disponível.

Frank Hileman
fonte
0

Gostaria (quase) de desconto na opção 3. A escolha entre 1 e 2 depende de duas coisas:

  • (A) qual é o tamanho do resultado de uma única busca total
  • (B) quanto dos detalhes do resultado o cliente / usuário normalmente usará nessa sessão.

É fácil tomar uma decisão se A e B são extremos:

  • Se A for grande e B for pequeno, definitivamente escolha a opção 1 (A la Carte).
  • Se A for pequeno e B for grande, escolha 2 (cache do servidor) ou até 3 (cache do cliente).

Para quaisquer outras variações A / B (grandes / pequenas), você deverá aplicar discrição. Eu muitas vezes fornecem ambos os grossos e finos terminais para atender a diferentes casos de uso de diferentes clientes.

Cornel Masson
fonte
0

Como sempre na programação, isso depende.

Então, a verdadeira questão é: o que você deve considerar ao decidir A / B / C ou uma combinação dos três?

Eu diria que os verdadeiros fatores discriminatórios são os detalhes de implementação das APIs de terceiros que você está consumindo. Como exemplo, você deve considerar: Eles são rápidos ou lentos? Os dados são alterados com frequência e inesperadamente? Eles são "faladores" ou Descansam?

No caso de serviços rápidos e fáceis de chamar, com a alteração de dados com tanta frequência que o cache do lado do servidor criará problemas de cache obsoleto, por todos os meios, vá para a opção 1: mais solicitações, sem cache, somente quando necessário.

Se seus dados externos mudarem de maneira previsível, ou você estiver limitado ao uso, ou simplesmente conseguir uma melhor experiência do usuário para armazenar dados em cache no servidor, vá com 2. Mas lembre-se de que o cache não é gratuito: possui custos em termos de depuração e, às vezes, usuários reclamando que não veem atualizações.

Opção 3, consideraria apenas se os dados não forem muitos, mas, nesse caso, até as opções 1 ou 2 podem funcionar, e você manterá mais lógica no servidor, portanto, eu ficaria com 1 ou 2.

Apenas o meu 2c.

A. Chiesa
fonte