96 votes

Quelle est la différence entre : Les architectures asynchrones, non-bloquantes, à base d'événements ?

  1. Quelle est la différence entre :

    • Asynchrone ,
    • Non-bloquant et
    • Base d'événements architectures ?
  2. Est-ce que quelque chose peut être à la fois asynchrone y non bloquant (et basé sur les événements ) ?

  3. Qu'est-ce qui est le plus important en programmation, avoir quelque chose d'asynchrone, de non bloquant et/ou d'événementiel (ou les 3) ?

Si vous pouviez fournir des exemples, ce serait formidable.

Cette question est posée parce que j'ai lu cet excellent StackOverflow article sur un sujet similaire mais il ne répond pas à mes questions ci-dessus.

102voto

Rohit Karlupia Points 301

Asynchrone Asynchrone signifie littéralement non synchrone. Le courrier électronique est asynchrone. Vous envoyez un courrier, vous ne vous attendez pas à recevoir une réponse MAINTENANT. Mais il n'est pas non-bloquant. Il s'agit essentiellement d'une architecture dans laquelle les "composants" s'envoient des messages sans attendre de réponse immédiate. Les requêtes HTTP sont synchrones. Envoyez une demande et recevez une réponse.

Non-bloquant Ce terme est surtout utilisé avec IO. Ce que cela signifie, c'est que lorsque vous faites un appel système, il reviendra immédiatement avec le résultat qu'il a obtenu sans mettre votre thread en veille (avec une forte probabilité). Par exemple, les appels de lecture/écriture non bloquants renvoient tout ce qu'ils peuvent faire et attendent de l'appelant qu'il exécute à nouveau l'appel. try_lock, par exemple, est un appel non bloquant. Il ne verrouillera que si le verrou peut être acquis. La sémantique habituelle pour les appels systèmes est le blocage. read attendra jusqu'à ce qu'il ait des données et mettra le thread appelant en veille.

Base d'événements Ce terme vient de libevent. Les appels non-bloquants en lecture/écriture sont inutiles en eux-mêmes car ils ne vous disent pas "quand" vous devez les rappeler (réessayer). select/epoll/IOCompletionPort etc. sont différents mécanismes pour découvrir à partir du système d'exploitation "quand" ces appels sont censés retourner des données "intéressantes". libevent et d'autres bibliothèques de ce type fournissent des enveloppes sur ces facilités de surveillance d'événements fournies par divers systèmes d'exploitation et donnent une API cohérente pour travailler avec qui fonctionne à travers les systèmes d'exploitation. L'IO non-bloquante va de pair avec la base d'événements.

Je pense que ces termes se chevauchent. Par exemple, le protocole HTTP est synchrone, mais la mise en œuvre du protocole HTTP utilisant des entrées-sorties non bloquantes peut être asynchrone. De même, un appel API non bloquant comme read/write/try_lock est synchrone (il donne immédiatement une réponse) mais la "gestion des données" est asynchrone.

3 votes

Bon point sur le fait que le non-blocage nécessite une interrogation constante, alors que l'asynchrone peut être basé sur le push.

0 votes

Vous avez défini le terme "synchrone" comme le fait de recevoir une réponse immédiate, mais lorsque je cherche "synchrone" sur Google, tous les dictionnaires le définissent comme "se produisant au même moment", et non comme "réponse immédiate".

4 votes

Comment suis-je bloqué lorsque j'envoie un courriel mais que je n'attends pas de réponse ? Je peux aller m'occuper de mes affaires en attendant une réponse.

22voto

supercat Points 25534

Dans un matériel asynchrone, le code demande à une entité de faire quelque chose et est libre de faire autre chose pendant que l'action se déroule ; une fois l'action terminée, l'entité signalera généralement le code d'une manière ou d'une autre. Une architecture non bloquante prendra note des actions qui se produisent spontanément et qui pourraient intéresser le code, et permettra au code de demander quelles actions se sont produites, mais le code ne prendra connaissance de ces actions que lorsqu'il les demandera explicitement. Une architecture basée sur les événements notifiera le code de manière affirmative lorsque des événements se produisent spontanément.

Considérons un port série, à partir duquel le code voudra recevoir 1 000 octets.

Dans une architecture de lecture en bloc, le code attendra soit que 1 000 octets soient arrivés, soit qu'il décide d'abandonner.

Dans une architecture de lecture asynchrone, le code dira au pilote qu'il veut 1 000 octets, et sera notifié lorsque 1 000 octets seront arrivés.

Dans une architecture non bloquante, le code peut demander à tout moment combien d'octets sont arrivés, et peut lire tout ou partie de ces données quand il le souhaite, mais la seule façon de savoir quand toutes les données sont arrivées est de le demander ; si le code veut savoir en un quart de seconde quand le 1000ème octet est arrivé, il doit vérifier tous les quarts de seconde environ.

Dans une architecture basée sur les événements, le pilote du port série notifiera l'application chaque fois que des données arrivent. Le pilote ne sait pas combien d'octets l'application veut, donc l'application doit être capable de gérer les notifications pour des quantités inférieures ou supérieures à ce que l'application veut.

5voto

user924272 Points 98

Donc, pour répondre à votre première et deuxième question :

Le non-blocage est en fait la même chose que l'asynchrone - vous faites l'appel et vous obtiendrez un résultat plus tard, mais pendant ce temps, vous pouvez faire autre chose. Le blocage est le contraire. Vous attendez le retour de l'appel avant de poursuivre votre chemin.

Le code asynchrone et non bloquant semble absolument fantastique, et il l'est. Mais j'ai des mots d'avertissement. L'asynchronisme et le non-blocage sont excellents lorsque l'on travaille dans des environnements contraints, comme dans un téléphone portable... pensez à l'unité centrale et à la mémoire limitées. C'est également une bonne chose pour le développement frontal, lorsque votre code doit réagir à un widget de l'interface utilisateur d'une manière ou d'une autre.

L'asynchronisme est fondamental pour le fonctionnement de tous les systèmes d'exploitation - ils font tout pour vous en arrière-plan et réveillent votre code lorsqu'ils ont fait ce que vous avez demandé, et lorsque cet appel échoue, vous êtes informé qu'il n'a pas fonctionné, soit par une exception, soit par une sorte de code de retour/objet d'erreur.

Au moment où votre code demande quelque chose qui prendra un certain temps à répondre, votre système d'exploitation sait qu'il peut s'occuper d'autres choses. Votre code - un processus, un thread ou équivalent, se bloque. Votre code est totalement inconscient de ce qui se passe dans le système d'exploitation pendant qu'il attend que la connexion réseau soit établie, qu'il attende la réponse à une requête HTTP, qu'il attende la lecture/écriture d'un fichier, etc. Votre code pourrait "simplement" attendre un clic de souris. Ce qui se passe en réalité pendant ce temps, c'est que votre système d'exploitation gère, planifie et réagit de manière transparente aux "événements" - des choses que le système d'exploitation surveille, comme la gestion de la mémoire, les E/S (clavier, souris, disque, Internet), d'autres tâches, la reprise après défaillance, etc.

Les systèmes d'exploitation sont sacrément durs. Ils sont vraiment bons pour cacher toutes les choses compliquées asynchrones / non bloquantes au programmeur. Et c'est ainsi que la plupart des programmeurs en sont arrivés là où nous en sommes aujourd'hui avec les logiciels. Maintenant que nous atteignons les limites des processeurs, les gens disent que les choses peuvent être faites en parallèle pour améliorer les performances. Cela signifie qu'Async / non-blocage semble être une chose très favorable à faire, et oui, si votre logiciel l'exige, je suis d'accord.

Si vous écrivez un serveur web back-end, procédez avec prudence. N'oubliez pas que vous pouvez évoluer horizontalement pour beaucoup moins cher. Netflix / Amazon / Google / Facebook sont des exceptions évidentes à cette règle, purement parce qu'il est plus économique pour eux d'utiliser moins de matériel.

Je vais vous dire pourquoi le code asynchrone / non bloquant est un cauchemar avec les systèmes back-end.....

1) Cela devient un déni de service sur la productivité... vous devez penser BEAUCOUP plus, et vous faites beaucoup d'erreurs en cours de route.

2) Les traces de pile dans le code réactif deviennent indéchiffrables - il est difficile de savoir ce qui a appelé quoi, quand, pourquoi et comment. Bonne chance pour le débogage.

3) Vous devez réfléchir davantage à la façon dont les choses échouent, surtout lorsque de nombreux éléments reviennent dans le désordre par rapport à la façon dont vous les avez envoyés. Dans l'ancien monde, vous faisiez une chose à la fois.

4) C'est plus difficile à tester.

5) Il est plus difficile à entretenir.

6) C'est pénible. La programmation devrait être une joie et un plaisir. Seuls les masochistes aiment la douleur. Les gens qui écrivent des frameworks concurrents/réactifs sont des sadiques.

Et oui, j'ai écrit à la fois sync et async. Je préfère le synchrone car 99,99 % des applications back-end peuvent s'en sortir avec ce paradigme. Les applications frontales ont besoin de code réactif, sans aucun doute, et cela a toujours été le cas.

  1. Oui, le code peut être asynchrone, non bloquant ET basé sur des événements.

  2. La chose la plus importante en programmation est de s'assurer que votre code fonctionne et répond dans un délai acceptable. Respectez ce principe clé et vous ne pourrez pas vous tromper.

4voto

ewernli Points 23180

Pour moi, le non-blocage signifie que l'exécution d'une action dans un thread ne dépend pas de l'exécution d'autres threads, il ne nécessite notamment pas de section critique.

Asynchrone signifie que l'exécution a lieu en dehors du flux de l'appelant, et qu'elle est potentiellement différée. L'exécution se produit généralement dans un autre thread.

La lecture de données concurrentes est non bloquante (pas besoin de verrouiller), mais synchrone. Inversement, l'écriture de données concurrentes de manière synchrone est bloquante (nécessite un verrou exclusif). Une façon de rendre ce processus non bloquant du point de vue du flux principal est de rendre les écritures asynchrones et de différer leur exécution.

Le concept d'événement est différent. En gros, il signifie que vous êtes informé lorsque quelque chose se produit. Si les écritures ont été exécutées de manière asynchrone, un événement peut être déclenché pour informer les autres parties du système lorsque l'écriture a été exécutée. Les autres parties répondront à l'événement. Un système peut être construit uniquement sur des événements comme seul moyen de communication entre les composants (pensez au modèle de l'acteur), mais cela ne doit pas nécessairement être le cas.

Les trois termes sont liés, mais sont pour moi des concepts différents. Il se peut cependant que les gens les utilisent de manière quelque peu interchangeable.

2voto

arootbeer Points 2973

En général, une architecture non bloquante est basée sur des appels de méthode qui, bien qu'ils puissent s'exécuter pendant un long moment sur le serveur de l travailleur ne bloque pas le en appelant fil. Si le thread appelant a besoin d'acquérir des informations sur ou à partir de la tâche que le worker thread est en train d'exécuter, c'est au thread appelant de le faire.

Une architecture basée sur les événements repose sur le concept de l'exécution du code en réponse à des événements qui sont déclenchés. Le moment de l'exécution du code n'est généralement pas déterministe, mais les événements peuvent invoquer des méthodes bloquantes ; ce n'est pas parce qu'un système est basé sur des événements que tout ce qu'il fait n'est pas bloquant.

En général, une architecture asynchrone est une architecture non bloquante basée sur des événements.

Lorsqu'un appel asynchrone est effectué, des gestionnaires d'événements sont enregistrés auprès de l'API fournissant des services de synchronisation, afin d'informer l'appelant que l'événement qui l'intéresse s'est produit. L'appel revient alors immédiatement (comportement non bloquant), et l'appelant est libre de poursuivre l'exécution. Lorsque des événements sont renvoyés vers le processus appelant, ils sont traités sur un thread de ce processus.

Il est important de comprendre si les événements seront gérés sur le même thread ou non, car cela affectera la nature non bloquante de l'exécution, mais je ne connais personnellement aucune bibliothèque qui gère l'exécution asynchrone sur un seul thread.

J'ai supprimé le paragraphe ci-dessus car il n'est pas strictement correct tel qu'il est énoncé. Mon intention était de dire que même si le opérations La nature de l'exécution monofilaire signifie que lorsque des événements sont déclenchés, ils sont en concurrence avec d'autres tâches de traitement pour le temps de calcul sur le fil.

0 votes

Votre dernier paragraphe ne contredit-il pas votre déclaration selon laquelle "l'architecture asynchrone est ... non bloquante" ?

0 votes

Je suppose que je n'ai pas très bien répondu à la partie "définitions" de votre question ; je publierai une mise à jour. Mais non, la nature de l'exécution monofil est que chaque opération est intrinsèquement bloquante. pendant qu'il fonctionne ce qui rend l'asynchronie encore plus utile.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X