Choisissez le bon style de communication pour votre application

Dans notre application Air Business, la communication entre les couches est simple et directe : nous utilisons des appels de fonction Java internes.

Cela dit, si nous Ă©tendons cette application pour qu’elle soit exĂ©cutĂ©e sur plusieurs serveurs (par exemple, si la partie base de donnĂ©es Ă©tait exĂ©cutĂ©e sur un ou des serveurs dĂ©diĂ©s), quelles options de communication s’offriraient Ă  nous ?

L’envoi de messages d’une couche à l’autre peut prendre plusieurs formes. Voici quelques options de communication populaires :

  • Synchrone

  • Asynchrone

  • Polling (sondage)

  • Callback (rappel)

  • Publish-subscribe / Message queuing (publication-souscription/file d’attente de messages)

Voyons quels sont les avantages et les inconvénients de chacune de ces options, et comment les utiliser.

Mais avant de nous lancer, voici deux termes que vous aurez besoin de connaßtre :

  • Consumer/Consommateur : C’est ce qui formule la requĂȘte. Si vous allez au restaurant et que vous passez votre commande, vous ĂȘtes le consommateur.

  • Producer ou supplier/producteur ou fournisseur : C’est ce qui rĂ©pond Ă  la requĂȘte du consommateur. Dans notre exemple du restaurant, c’est la personne chargĂ©e du service.

Un fournisseur dans une situation donnĂ©e peut ĂȘtre un consommateur dans une autre situation. Par exemple, une fois que la personne chargĂ©e du service a pris notre commande, cette derniĂšre est envoyĂ©e en cuisine pour ĂȘtre prĂ©parĂ©e. L’envoi de ce message Ă  la cuisine transforme notre serveur ou serveuse en consommateur pour cette partie du processus du repas.

Tout est clair ? Alors, lançons-nous !

Comprenez le principe de l'approche synchrone

Commençons avec un exemple simple et direct : l’appel et la rĂ©ponse.

  1. Le consommateur formule une requĂȘte : "Puis-je avoir un verre d’eau ?".

  2. Le fournisseur accomplit ce qui est demandĂ© : "Voici votre verre d’eau".

Le consommateur ne peut rien faire jusqu’à ce que le fournisseur rĂ©ponde Ă  sa requĂȘte : il ne peut pas boire d’eau jusqu’à ce que l’eau soit amenĂ©e Ă  table.

C’est ainsi qu’Air Business est implĂ©mentĂ© actuellement. Tous les appels de fonctions internes fonctionnent de cette façon. Et tous nos endpoints externes Ă©galement.

Cette approche a l'avantage d'ĂȘtre trĂšs simple :

  1. la requĂȘte est formulĂ©e,

  2. et le consommateur attend la réponse.

Mais que se passe-t-il si la requĂȘte est mal formulĂ©e ? qu'elle comporte des erreurs ? Le consommateur pourrait attendre longtemps si nous n’envoyons pas de rĂ©ponse d’erreur


Cette latence reprĂ©sente le plus gros inconvĂ©nient de cette approche : le consommateur ne peut rien faire d’autre tant que la requĂȘte est en cours de traitement.

Découvrez les options asynchrones

L'approche asynchrone permet de ne pas subir cette latence justement !

Le consommateur peut :

  1. formuler une requĂȘte,

  2. puis continuer Ă  faire autre chose en attendant.

Pour se faire, en Java, nous pouvons lancer des requĂȘtes dans des threads diffĂ©rents.

Pour notre petite application, cela ne reprĂ©sente peut-ĂȘtre pas d'intĂ©rĂȘt aujourd'hui car notre thread client "n’a rien d’autre Ă  faire" en attendant la rĂ©ponse Ă  une requĂȘte. Mais que se passera-t-il quand nous dĂ©ploierons l'application sur un serveur web et que nous recevrons des multitudes de requĂȘtes simultanĂ©es ?

À ce moment-lĂ , l’exploration d’une approche multi-threads pour gĂ©rer toutes les requĂȘtes entrantes sera justifiĂ©e. Spring Boot effectue cela en coulisses. Chaque requĂȘte se voit attribuer son propre thread. C'est donc en fait du synchrone, mais par requĂȘte. 😄

Optez pour la technique du "polling"

NĂ©anmoins, si le consommateur fait d’autres choses au lieu d’attendre, nous avons un problĂšme.

Comment le fournisseur indique-t-il que le rĂ©sultat est maintenant prĂȘt pour le consommateur ? Nous devons introduire davantage de coordination entre le consommateur et le fournisseur.

Dans cette situation, le consommateur continue Ă  demander au fournisseur si la rĂ©ponse est prĂȘte. Un appel sĂ©parĂ© est passĂ© Ă  l’API pour voir comment ça se passe.

Si vous avez dĂ©jĂ  Ă©tĂ© en voiture avec un enfant, vous connaissez la chanson : « Quand est-ce qu'on arrive ? ». Une question rĂ©pĂ©tĂ©e inlassablement. 😅

C’est une option facile Ă  implĂ©menter. La plus grande partie de la coordination est du cĂŽtĂ© du consommateur. Il continue simplement Ă  demander si le fournisseur a terminĂ©. LĂ  oĂč ça se complique, c’est si plusieurs consommateurs formulent des requĂȘtes similaires. Le fournisseur doit donner un identifiant ou un token au consommateur. Le consommateur renvoie ensuite ce token au fournisseur, afin qu’il voie si la requĂȘte est achevĂ©e.

Ce fonctionnement ressemble un peu Ă  celui d’un vestiaire dans un théùtre : vous donnez votre manteau et recevez en Ă©change une carte portant un numĂ©ro. À la fin du spectacle, lorsque vous rendez la carte, elle permet Ă  la personne du vestiaire de savoir quel manteau vous voulez.

L'inconvĂ©nient de cette approche, ce sont les ressources. On peut avoir beaucoup de demandes pour savoir si la rĂ©ponse est prĂȘte, avant que la rĂ©ponse ne le soit vraiment. Chaque question (et rĂ©ponse) nĂ©cessite de la bande passante (rĂ©seau, processeur, etc.) des deux cĂŽtĂ©s de l’interaction. Alors, comment limiter le nombre d’interactions ? Avec la mĂ©thode du "callback".

Optez pour la technique du "callback"

Le plus efficace dans ce cas-lĂ  c'est de stopper les questions du consommateur.

Lorsque le fournisseur a terminĂ©, le consommateur est rappelĂ©. Seuls deux messages sont envoyĂ©s (la requĂȘte, la rĂ©ponse), ce qui rĂ©duit considĂ©rablement la bande passante.

Dans notre approche d’endpoint, l’endpoint du consommateur peut ĂȘtre envoyĂ© dans le message JSON. Le fournisseur doit sauvegarder ce endpoint, afin de savoir oĂč appeler lorsque la rĂ©ponse est prĂȘte.

De plus, le consommateur n’a aucune idĂ©e de quand le fournisseur enverra le rĂ©sultat. Le consommateur devra dĂ©dier une ressource (un thread, par exemple) pour attendre et guetter la rĂ©ponse.

De nombreuses requĂȘtes peuvent avoir Ă©tĂ© envoyĂ©es au fournisseur par le consommateur. Lorsque le rĂ©sultat arrive, le consommateur doit savoir Ă  quelle requĂȘte le rĂ©sultat correspond. Dans ce cas aussi, on utilise une approche avec un identifiant ou un token.

SI vous intégrez un jour une solution de paiement en ligne, vous utiliserez trÚs probablement le callback :

  1. via un back-office de la solution, vous indiquerez une URL de rappel

  2. lorsque vous requĂȘterez la solution, vous transmettrez un identifiant de paiement

  3. quand le paiement sera traitĂ© par la banque, la solution rappellera votre application Ă  l’URL fournie, en vous renvoyant aussi l'identifiant de paiement

Un seul appel en requĂȘte, un seul appel en rĂ©ponse !

Optez pour la technique du "publish/subscribe" ou "message queuing"

Et si de nombreux consommateurs s’intĂ©ressent au rĂ©sultat de la rĂ©ponse d’un fournisseur Ă  un autre consommateur ? Ou vice versa ?

Un consommateur soumet une requĂȘte, mais ne s’intĂ©resse pas Ă  l’identitĂ© du fournisseur qui y rĂ©pond, pourvu qu’elle soit gĂ©rĂ©e facilement. Peu m’importe quel est le cuisinier qui prĂ©pare mon repas, par exemple. C’est celui qui est libre qui devrait s’en occuper.

Avec cette approche, il y a une file d’attente ou un porteur central de toutes les requĂȘtes. Et de la mĂȘme façon : il y a une file d’attente ou un porteur de toutes les rĂ©ponses. Un contrĂŽleur s’assure que tous les messages (requĂȘtes et rĂ©ponses) vont lĂ  oĂč ils doivent aller.

Le grand avantage de cette approche, c’est l’efficacitĂ©. Les messages ne sont envoyĂ©s qu’en cas de besoin. Et ils sont seulement stockĂ©s le temps nĂ©cessaire.

Dans l’entreprise de donnĂ©es mĂ©dicales pour laquelle je travaillais, nous avions plusieurs files de publications/souscriptions. Certaines Ă©taient configurĂ©es pour traiter les choses en quelques minutes, et supprimer les messages envoyĂ©s immĂ©diatement. D’autres Ă©taient configurĂ©es pour sauvegarder les messages pendant un mois.

Pour l’application Air Business, ces mĂ©canismes vont au-delĂ  de notre besoin. En revanche, si les demandes de rĂ©servations "s’envolaient" rĂ©ellement, nous pourrions utiliser cette approche pour aider Ă  rĂ©partir la charge sur plusieurs serveurs.

En résumé

  • Il existe de nombreuses options pour communiquer entre les couches, dont la plupart utilisent des consommateurs et des fournisseurs.

  • Les appels en synchrone Ă  un fournisseur peuvent ĂȘtre implĂ©mentĂ©s avec REST.

  • Les mĂ©canismes asynchrones doivent ĂȘtre utilisĂ©s si le temps de traitement par le fournisseur est long.

  • Le polling est facile Ă  implĂ©menter, mais peut ĂȘtre lent.

  • Les callbacks sont efficaces.

  • Les files d’attente de messages, ou publications/souscriptions, sont trĂšs efficaces, mais nĂ©cessitent gĂ©nĂ©ralement une implĂ©mentation tierce pour gĂ©rer tous les dĂ©tails.

Maintenant que vous maütrisez la communication, concluons ce cours  !

Et si vous obteniez un diplĂŽme OpenClassrooms ?
  • Formations jusqu’à 100 % financĂ©es
  • Date de dĂ©but flexible
  • Projets professionnalisants
  • Mentorat individuel
Trouvez la formation et le financement faits pour vous