web-dev-qa-db-fra.com

Beaucoup de petites demandes vs peu de grandes demandes (conception API)

Je travaille actuellement sur un projet avec une organisation comme suit:

  • Client - Obtient les données du serveur principal via REST api.
  • Serveur - Demande des données à divers autres serveurs via des API tierces
  • API tierces - Services hors de mon contrôle qui fournissent des données au serveur (Reddit, Hackernews, Quora, etc.)

Par souci d'argument, supposons que le client ait d'abord besoin d'une liste d'éléments de chacune des API tierces. À partir de cette liste, un élément sera choisi à quel point le client doit voir le contenu complet de l'élément ainsi que les réponses (c'est-à-dire les commentaires) à l'élément. J'essaie de décider entre trois options:

À la carte

Dans cette approche, j'aurais 3 points de terminaison distincts sur mon serveur: un pour obtenir la liste des éléments, un pour obtenir le contenu principal d'un élément et un pour obtenir les réponses de l'élément.

  • Avantages: Je ne fais jamais plus de demandes que je n'en ai besoin, les demandes doivent être petites, donc généralement elles doivent être plus rapides.
  • Inconvénients: je dois faire beaucoup de demandes. Après avoir choisi un élément dans la liste, l'utilisateur peut devoir attendre avant de voir le contenu principal, puis attendre encore plus longtemps pour voir les réponses

Cache côté serveur

Dans cette demande, je ferais un seul appel à mon serveur pour "récupérer" toutes les données pour toutes les sources. Les données seraient ensuite mises en cache sur le serveur. Le client aurait alors les mêmes points de terminaison REST qu'avant, sauf qu'il n'y aurait pas beaucoup d'attente entre les appels car mon serveur a déjà les données et n'a qu'à les transmettre au client.

  • Avantages: toujours facile à mettre en œuvre côté client, mais sans les problèmes de latence
  • Inconvénients: Un peu plus impliqué côté serveur, et le premier appel pourrait prendre vraiment très longtemps.

Cache côté client

Ce scénario est similaire au précédent, sauf que le client ne fait qu'une seule demande au serveur: donnez-moi toutes les données. À partir de là, il incombe au client de sauvegarder les données et de les utiliser de manière appropriée.

  • Avantages: mise en œuvre facile du serveur, très rapide après le premier appel
  • Inconvénients: le premier appel sera une implémentation côté client très lente et plus compliquée

Je ne sais pas quelle est la meilleure approche, ou si je manque peut-être la solution évidente. Tout avis serait grandement apprécié!

57
williamg

Une chose à garder à l'esprit est la latence du réseau attendue (c'est-à-dire le temps de ping) entre vos clients et votre serveur. Dans une situation de latence élevée avec une bande passante par ailleurs bonne, de nombreuses petites demandes effectueront de manière significative pire qu'une grande.

J'ai récemment collaboré à un projet d'application Web multi-équipes soutenu par une base de données dans lequel l'une des équipes est en Inde (les autres sont aux États-Unis). Nous avons une seule instance de base de données hébergée dans notre bureau américain à laquelle les développeurs connectent nos instances de serveur Web local. Mon bureau est peut-être à cinquante pieds et deux LAN Hops loin de l'instance de base de données, et les performances sont bonnes.

Lorsque nous avons commencé pour la première fois avec les développeurs en Inde, ils connaissaient des temps d'attente énormes pour démarrer l'application et naviguer page à page. Nous parlons ici de temps d'attente de dix minutes. Il s'avère que c'était parce que le temps de ping ~ 200 ms de leurs bureaux à notre serveur de base de données dev devenait multiplié par de très nombreuses requêtes brèves vers la base de données. Mon ping local de 0,5 ms était si trivial que la conversation entre le serveur Web et le serveur de base de données n'avait jamais d'importance. C'était la première fois que nous avions une séparation géographique entre le serveur Web et le serveur de base de données.

La solution dans notre cas était de cloner le serveur de base de données et de conserver la copie en Inde, mais le point ici est de garder à l'esprit que si votre client et votre serveur sont éloignés, la latence du réseau sera multipliée par le nombre de communications à travers le câble. La bande passante une fois la connexion établie est généralement beaucoup moins préoccupante.

32
JakeRobb

Ces trois options ne s'excluent pas mutuellement, vous pouvez utiliser une combinaison de caches côté client et côté serveur. Cependant, certaines données, comme les commentaires, peuvent devenir périmées si elles sont conservées trop longtemps en cache. Étant donné que vous ne pouvez pas vérifier si tel est le cas, vous devriez probablement vous abstenir de tout stocker. D'un autre côté, le contenu ne change généralement pas radicalement, il n'y aurait donc aucun mal à le mettre en cache côté serveur, puis à en pré-extraire une partie du côté client pour réduire la latence.

2
wfdctrl

Sur la base des informations que vous avez fournies, option 1, car

  • avec une seule demande du client, vous mélangeriez des pommes et des oranges et la corbeille de fruits pourrait être très grande.

  • la mise en cache est un compromis où vous gagnez en performances mais potentiellement perdez la cohérence (données périmées). Si vous n'avez aucun problème de performances identifié, les problèmes de synchronisation ne valent généralement pas la peine d'être risqués.

1
guillaume31

J'ai toujours trouvé que quelques grosses demandes étaient plus performantes et plus évolutives. Mais il y a des compromis dans toutes les approches, cela dépend donc des besoins du serveur et du client. Vous souhaiterez peut-être utiliser une autre option, qui consiste à demander au client de spécifier une plage entière ou un ensemble de données à récupérer - pas nécessairement toutes les données, mais une certaine plage, qui est réglée au fil du temps pour correspondre à la bande passante disponible.

0
Frank Hileman

Je voudrais (presque) escompter l'option 3. Choisir entre 1 et 2 dépend de deux choses:

  • (A) quelle est la taille du résultat d'une seule extraction totale
  • (B) quelle partie du détail du résultat le client/utilisateur utilisera généralement dans cette session.

Il est facile de prendre une décision si A et B sont extrêmes:

  • Si A est grand et B est petit, optez certainement pour l'option 1 (à la carte).
  • Si A est petit et B est grand, optez pour 2 (cache côté serveur) ou même 3 (cache côté client).

Pour toute autre variation A/B (grande/petite), vous devrez faire preuve de discrétion. Je fournis souvent les deux points de terminaison grossiers et fins pour répondre aux différents cas d'utilisation de différents clients.

0
Cornel Masson

Comme toujours en programmation, cela dépend.

Donc, la vraie question est: que devez-vous considérer lorsque vous décidez pour A/B/C ou une combinaison des trois?

Je dirais que les vrais facteurs discriminants sont les détails de mise en œuvre des API tierces que vous consommez. À titre d'exemple, vous devriez considérer: sont-ils rapides ou lents? Les données changent-elles fréquemment et de manière inattendue? Sont-ils "bavards" ou repos?

En cas de services rapides et faciles à appeler, avec des données changeant si fréquemment que votre cache côté serveur va créer des problèmes de cache périmé, optez pour l'option 1: plus de demandes, pas de cache, uniquement en cas de besoin.

Si vos données externes vont changer de manière prévisible, ou si vous êtes limité dans l'utilisation, ou simplement vous pouvez obtenir une meilleure expérience utilisateur de mise en cache des données sur votre serveur, allez avec 2. Mais gardez à l'esprit que le cache n'est pas gratuit: cela a des coûts en termes de débogage et parfois les utilisateurs se plaignent de ne pas voir les mises à jour.

Option 3, je n'envisagerais que si les données ne sont pas beaucoup, mais dans ce cas, même les options 1 ou 2 peuvent fonctionner, et vous gardez plus de logique sur le serveur, donc je resterais pour 1 ou 2.

Juste mon 2c.

0
A. Chiesa