Question

Lors de la création de services système hautement fiables, je finis souvent par écrire de nombreux mécanismes "à sécurité intégrée" dans les cas suivants: communications ayant disparu (par exemple, communication avec la base de données), que se passerait-il si le courant est perdu et le service redémarre .... comment ramasser les pièces et continuer de manière correcte (et en se rappelant que lors du ramassage des pièces, le courant peut s'éteindre à nouveau ...), etc. etc.

Je peux imaginer, pour des systèmes peu complexes, un langage qui tiendrait compte de cela serait très pratique. Donc, une langue qui se souviendrait de son état à tout moment, peu importe si le courant est coupé, et continue là où elle s’est arrêtée.

Est-ce que cela existe déjà? Si oui, où puis-je le trouver? Sinon, pourquoi cela ne peut-il pas être réalisé? Cela me semblerait très pratique pour les systèmes critiques.

p.s. Si la connexion à la base de données est perdue, cela signifierait qu'un problème est survenu et qu'une intervention manuelle est nécessaire. Dès que la connexion sera rétablie, elle continuera là où elle s’est arrêtée.

EDIT: Puisque la discussion semble s'être éteinte, permettez-moi d'ajouter quelques points (en attendant de pouvoir ajouter une prime à la question)

La réponse Erlang semble être la mieux notée pour le moment. Je connais Erlang et j'ai lu le livre pragmatique d'Armstrong (le créateur principal). Tout cela est très agréable (bien que les langages fonctionnels me font tourner la tête avec toute la récursion), mais le bit "tolérant aux pannes" ne vient pas automatiquement. Loin de là. Erlang propose à de nombreux superviseurs et méthodologies de superviser un processus et de le redémarrer si nécessaire. Cependant, pour créer correctement quelque chose qui fonctionne avec ces structures, vous devez être tout à fait le gourou erlang et adapter votre logiciel à tous ces cadres. De plus, si le courant est coupé, le programmeur doit également prendre les mesures qui s’imposent et essayer de le récupérer au prochain redémarrage du programme

Ce que je recherche est quelque chose de beaucoup plus simple:

Imaginez un langage (aussi simple que PHP par exemple), dans lequel vous pouvez faire des requêtes telles que des requêtes DB, agir dessus, manipuler des fichiers, effectuer des manipulations de dossiers, etc.

Cependant, sa caractéristique principale devrait être la suivante: si le pouvoir meurt et que la chose redémarre, il faut qu'il en reste là (il ne se souvient pas seulement de l'endroit où il était, il se souviendra également des états variables). De plus, s’il s’est arrêté au milieu d’une copie de fichier, il reprendra correctement. etc etc.

Dernier point, mais non le moindre, si la connexion à la base de données est interrompue et ne peut pas être restaurée, la langue s’arrête, et signale (syslog peut-être) une intervention humaine, puis se poursuit là où elle s’est interrompue.

Un tel langage faciliterait la programmation de nombreux services.

EDIT: Il semble (à en juger par tous les commentaires et réponses) qu'un tel système n'existe pas. Et ne le sera probablement pas dans un avenir proche et prévisible car il est (presque?) Impossible d'obtenir les résultats escomptés.

Dommage .... encore une fois, je ne cherche pas ce langage (ou cette structure) pour me rendre sur la lune, ni l’utiliser pour surveiller le rythme cardiaque de quelqu'un. Mais pour les petits services / tâches périodiques qui finissent toujours par avoir des charges de traitement de code (pannes de courant quelque part au milieu, connexions interrompues et ne revenant pas), ... où une pause ici, ... résout les problèmes, .. ..et continuer là où vous en étiez approche fonctionnerait bien.

(ou une approche au point de contrôle, comme l’a souligné l’un des commentateurs (comme dans un jeu vidéo). Définissez un point de contrôle .... et si le programme meurt, redémarrez ici la prochaine fois.)

Bounty attribué: À la dernière minute, lorsque tout le monde en arrivait à la conclusion que cela ne pouvait être fait, Stephen C est arrivé avec napier88, qui semble avoir les attributs que je cherchais. Même s’il s’agit d’un langage expérimental, cela prouve que c’est possible et c’est quelque chose qui mérite d’être approfondi.

Je créerai mon propre cadre (avec éventuellement un état persistant et des instantanés) pour ajouter les fonctionnalités que je recherche dans .Net ou un autre ordinateur virtuel.

Merci à tous pour vos commentaires et vos idées intéressantes.

Était-ce utile?

La solution

Il existe un langage expérimental appelé Napier88 qui (en théorie) présente certains attributs comme étant résistant aux catastrophes. Le langage prend en charge la persistance orthogonale et, dans certaines implémentations, cela s'étend pour inclure l’état du calcul complet. En particulier, lorsque le système d’exécution de Napier88 a pointé une application en cours sur le magasin persistant, l’état actuel du thread était inclus dans le point de contrôle. Si l'application se bloque alors et que vous la redémarrez correctement, vous pouvez reprendre le calcul à partir du point de contrôle.

Malheureusement, un certain nombre de problèmes difficiles doivent être résolus avant que ce type de technologie ne soit prêt à être utilisé par tous. Celles-ci comprennent notamment la prise en charge du multi-threading dans le contexte de la persistance orthogonale, la définition de la procédure permettant à plusieurs processus de partager un magasin persistant et le nettoyage de mémoire évolutif de ces magasins.

Et il y a le problème de la persistance orthogonale dans une langue dominante. Des tentatives d’opération en Java ont été tentées, notamment par des personnes associées à Sun (le projet Pjama), mais rien n’est en cours pour le moment. Les approches JDO / Hibernate sont plus favorisées de nos jours.

Je tiens à souligner que la persistance orthogonale n’est pas vraiment à l’épreuve des catastrophes au sens large. Par exemple, il ne peut pas traiter:

  • rétablissement des connexions, etc. avec " dehors " systèmes après un redémarrage,
  • bogues d'application provoquant la corruption de données persistantes ou
  • perte de données due à une défaillance du système entre les points de contrôle.

Pour ceux-là, je ne crois pas qu'il existe de solutions générales pratiques.

Autres conseils

La

mémoire logicielle transactionnelle (STM) associée à une RAM non volatile satisferait probablement à la question révisée du PO.

La STM est une technique permettant de mettre en oeuvre des "transactions", par exemple des ensembles d’actions qui sont effectuées efficacement en tant qu’opération atomique, ou pas du tout. STM a normalement pour but de permettre aux programmes hautement parallèles d’interagir sur des ressources partagées de manière à être plus faciles à comprendre que les programmes traditionnels "lock-that-resource", et a sans doute réduit les coûts indirects du fait de son style sans optimisme très optimiste. la programmation.

L’idée de base est simple: tout le monde lit et écrit à l’intérieur d’une "transaction". les blocs sont enregistrés (en quelque sorte!); si deux threads entrent en conflit sur ces ensembles (conflits lecture-écriture ou écriture-écriture) à la fin de l'une de leurs transactions, l'un est choisi comme gagnant et continue, et l'autre est forcé de revenir au début de son état. de la transaction et ré-exécuter.

Si l'on insistait sur le fait que tous les calculs étaient des transactions et que l'état au début (/ fin) de chaque transaction était stocké dans une mémoire RAM non volatile (NVRAM), une panne d'alimentation pourrait être traitée comme une défaillance de transaction entraînant un "rollback". ;. Les calculs ne seraient effectués que de manière fiable à partir des États ayant fait l’objet d’une transaction. La NVRAM de nos jours peut être mise en œuvre avec une mémoire flash ou avec une sauvegarde de la batterie. On peut avoir besoin de BEAUCOUP de NVRAM, car les programmes ont beaucoup d’état (voir l’histoire du mini-ordinateur à la fin). Autrement, les modifications d'état validées peuvent être écrites dans des fichiers journaux écrits sur le disque; c'est la méthode standard utilisée par la plupart des bases de données et par des systèmes de fichiers fiables.

La question qui se pose actuellement avec STM est la suivante: combien coûte-t-il de garder trace des conflits de transaction potentiels? Si la mise en œuvre de STM ralentit la machine d’un montant appréciable, les utilisateurs devront faire face aux systèmes existants légèrement peu fiables au lieu d’abandonner ces performances. Jusqu’à présent, l’histoire n’est pas bonne, mais la recherche est précoce.

Les gens n’ont généralement pas conçu de langage pour STM; à des fins de recherche, ils ont surtout Java amélioré avec STM (voir l’article de Communications of ACM de juin 2002 de cette année). J'entends MS a une version expérimentale de C #. Intel a une version expérimentale pour C et C ++. La page wikipedia a une longue liste. Et les gars de la programmation fonctionnelle comme d'habitude, prétendent que la propriété free-side effect des programmes fonctionnels rend STM relativement facile à implémenter dans des langages fonctionnels.

Si je me souviens bien, dans les années 70, les systèmes d’exploitation distribués avaient fait l’objet de beaucoup de travail, dans lequel les processus (code + état) pouvaient se déplacer de manière triviale d’une machine à l’autre. Je crois que plusieurs de ces systèmes ont explicitement autorisé la défaillance de noeud et pourraient redémarrer un processus dans un noeud défaillant à partir de l'état de sauvegarde dans un autre noeud. Les premiers travaux clés étaient sur le Système d'informatique distribuée de Dave Farber. Parce que la conception de langages dans les années 70 était populaire, je me souviens que DCS avait son propre langage de programmation, mais je ne me souviens pas de son nom. Si DCS n'autorisait pas la défaillance et le redémarrage d'un nœud, je suis à peu près sûr que les systèmes de recherche suivants l'ont fait.

EDIT: Un système de 1996 qui semble avoir les propriétés que vous désirez est documenté ici . Son concept de transaction atomique est cohérent avec les idées qui sous-tendent STM. (Va prouver qu'il n'y a pas grand chose de nouveau sous le soleil).

Une note de côté: De retour dans les années 70, Core Memory était toujours roi. Le noyau, étant magnétique, était non volatil malgré les pannes de courant et de nombreux mini-ordinateurs (et je suis sûr que les ordinateurs centraux) avaient des interruptions de courant qui signalaient au logiciel quelques millisecondes d'avance sur une perte de puissance. En utilisant cela, on pourrait facilement stocker l’état du registre de la machine et l’éteindre complètement. Lorsque le courant était rétabli, le contrôle revenait à un point de restauration de l'état et le logiciel pouvait continuer. De nombreux programmes pourraient ainsi survivre, clignoter et redémarrer de manière fiable. J'ai personnellement construit un système à temps partagé sur un mini-ordinateur Data General Nova; vous pourriez en fait faire fonctionner 16 télétypes à fond, prendre un coup puissant et revenir et redémarrer tous les télétypes comme si de rien n'était. Le passage de la cacophonie au silence et retour était stupéfiant, je sais, je devais le répéter plusieurs fois pour déboguer le code de gestion des pannes de courant, et cela a bien sûr fait une excellente démo (tirer la fiche, le silence mortel, rebranchez-la .. .) Le nom de la langue qui a fait cela était bien sûr Assembler: -}

D'après ce que je sais, Ada est souvent utilisé pour des raisons de sécurité. (sécurité intégrée).

  

Ada était à l'origine destiné à   systèmes embarqués et temps réel.

     

Les principales caractéristiques d'Ada sont les suivantes:   typage fort, mécanismes de modularité   (packages), vérification de l'exécution,   traitement parallèle (tâches), exception   manipulation, et génériques. Ada 95 ajouté   support pour orienté objet   programmation, y compris dynamique   envoi.

     

Ada prend en charge les vérifications d'exécution dans l'ordre   protéger contre l'accès à   mémoire non allouée, débordement de tampon   erreurs, erreurs off-by-one, tableau   erreurs d'accès, et autres détectables   bogues. Ces contrôles peuvent être désactivés dans   l'intérêt de l'efficacité d'exécution,   mais peut souvent être compilé efficacement.   Il comprend également des installations pour aider   vérification du programme.

     

Pour ceux-ci   raisons, Ada est largement utilisé dans   systèmes critiques, où toute anomalie   pourrait conduire à très grave   conséquences, c’est-à-dire décès accidentel   ou une blessure. Exemples de systèmes où   Ada est utilisé incluent avionique, arme   systèmes (y compris thermonucléaire   armes) et vaisseaux spatiaux.

La

programmation N-Version peut également vous donner des informations utiles à la lecture de l'arrière-plan.

& # 185; Il s’agit d’une connaissance qui écrit un logiciel essentiel pour la sécurité

Je doute que les fonctionnalités de langage que vous décrivez soient réalisables.

Et la raison en est qu’il serait très difficile de définir les modes de défaillance communs et généraux et de savoir comment les récupérer. Réfléchissez un instant à votre exemple d’application - un site Web avec une logique et un accès à une base de données. Et disons que nous avons un langage qui peut détecter une coupure de courant et un redémarrage ultérieur, et en quelque sorte le récupérer. Le problème est qu’il est impossible de savoir pour le langage comment récupérer.

Supposons que votre application est une application de blog en ligne. Dans ce cas, il serait peut-être suffisant de continuer à partir du point où nous avons échoué et que tout se passe bien. Cependant, considérons un scénario similaire pour une banque en ligne. Du coup, il n’est plus malin de continuer du même point. Par exemple, si j'essayais de retirer de l'argent de mon compte et que l'ordinateur mourut juste après les vérifications, mais avant d'effectuer le retrait, et qu'il remonte une semaine plus tard, il me donnera l'argent même si mon compte est dans le négatif maintenant.

En d’autres termes, il n’existe pas de stratégie de récupération correcte unique. Par conséquent, cela ne peut pas être mis en œuvre dans le langage. Ce que la langue peut faire est de vous dire quand quelque chose de grave se produit - mais la plupart des langues supportent déjà cela avec des mécanismes de gestion des exceptions. Le reste appartient aux concepteurs d’applications.

De nombreuses technologies permettent de concevoir des applications tolérantes aux pannes. Transactions de base de données, files d'attente de messages durables, mise en cluster, échange à chaud de matériel, etc. Mais tout dépend des exigences concrètes et du montant que l'utilisateur final est prêt à payer pour tout cela.

La majorité de ces efforts - nommés " la tolérance de panne " - concernent la matériel, pas le logiciel.

L'exemple extrême en est le Tandem , dont les machines "non-stop" ont une redondance complète.

L’implémentation de la tolérance de panne au niveau matériel est intéressante, car une pile de logiciels est généralement composée de composants provenant de différents fournisseurs. Votre application logicielle à haute disponibilité peut être installée avec certaines autres applications et services résolument fragiles au-dessus d’un système est floconneux et utilise des pilotes de périphériques matériels qui sont résolument fragiles.

Mais au niveau des langues, presque toutes les langues offrent les fonctionnalités nécessaires pour vérifier correctement les erreurs. Cependant, même avec RAII, exceptions, contraintes et transactions, ces chemins de code sont rarement testés correctement et ensemble dans des scénarios de défaillance multiples, et c’est généralement dans le code de traitement des erreurs masqué par les bogues. Il s’agit donc davantage de compréhension, de discipline et de compromis des programmeurs que de langues.

Ce qui nous ramène à la tolérance de panne au niveau matériel. Si vous pouvez éviter que votre lien de base de données ne tombe en panne, vous pouvez éviter d’exercer le code de gestion des erreurs douteuses dans les applications.

Non , une langue à l'épreuve des catastrophes n'existe pas.

Modifier:

Résister aux catastrophes implique la perfection. Cela évoque des images d'un processus qui utilise une certaine intelligence pour résoudre de manière logique des conditions inconnues, non spécifiées et inattendues. Il n'y a aucune manière par laquelle un langage de programmation peut le faire. Si, en tant que programmeur, vous ne pouvez pas savoir comment votre programme va échouer ni comment le récupérer, votre programme ne pourra pas le faire non plus.

Du point de vue des technologies de l’information, les catastrophes peuvent surgir de telle manière qu’aucun processus ne peut résoudre tous ces problèmes. L'idée que vous puissiez concevoir un langage qui traite de toutes les manières dont quelque chose pourrait mal tourner est tout simplement incorrecte. En raison de l'abstraction matérielle, de nombreux problèmes n'ont même pas beaucoup de sens à résoudre avec un langage de programmation; mais ce sont toujours des "catastrophes".

Bien sûr, dès que vous commencez à limiter la portée du problème; nous pourrons alors commencer à discuter d’une solution à ce problème. Ainsi, lorsque nous cessons de parler d’être à l’abri des catastrophes et de nous occuper de récupérer des surtensions imprévues, il devient beaucoup plus facile de développer un langage de programmation pour répondre à cette préoccupation, même lorsque, peut-être, il n’a pas beaucoup de sens de gérer ce problème à un tel niveau de la pile. Cependant, je vais me risquer à prédire qu’une fois que vous aurez défini des implémentations réalistes, il deviendra inintéressant en tant que langage, car il est devenu si spécifique. c'est-à-dire utiliser mon langage de script pour exécuter des processus de traitement par lots pendant la nuit qui permettront de récupérer des surtensions imprévues et des connexions réseau perdues (avec une assistance humaine); ce n'est pas une analyse de rentabilisation convaincante dans mon esprit.

S'il vous plaît, ne vous méprenez pas. Ce fil contient d'excellentes suggestions mais, à mon sens, elles ne répondent à rien, même à distance, à l'abri des catastrophes.

Considérons un système construit à partir de mémoire non volatile. L'état du programme est maintenu en permanence et si le processeur s'arrête pour quelque temps que ce soit, il reprendra à son point de départ lors du redémarrage. Par conséquent, votre programme est "à l'épreuve des catastrophes" dans la mesure où il peut survivre à une panne d'électricité.

Cela est tout à fait possible, comme indiqué dans d’autres publications à propos de la mémoire logicielle transactionnelle, de la "tolérance aux pannes", etc. complètement l'architecture de von Neumann aussi.

Imaginons maintenant un système construit à partir de deux tels systèmes distincts - pour une illustration simple, l’un est un serveur de base de données et l’autre, un serveur d’applications pour un site Web de services bancaires en ligne.

Si l'un marque une pause, que fait l'autre? Comment gère-t-il l'indisponibilité soudaine de son collègue?

Cela pourrait être géré au niveau de la langue, mais cela signifierait beaucoup de gestion des erreurs, etc., et c’est un code difficile à comprendre. Ce n’est guère mieux que là où nous en sommes aujourd’hui, où les machines ne sont pas contrôlées mais les langages essaient de détecter les problèmes et demandent au programmeur de les gérer.

Cela pourrait également faire une pause - au niveau du matériel, ils pourraient être liés, de sorte que, d’un point de vue énergétique, ils ne forment qu’un seul système. Mais ce n'est pas une bonne idée. une meilleure disponibilité proviendrait d’une architecture à tolérance de pannes avec des systèmes de sauvegarde, etc.

Ou nous pourrions utiliser des files de messages persistantes entre les deux machines. Cependant, à un moment donné, ces messages sont traités et ils risquent alors d'être trop vieux! Seule la logique d’application peut vraiment fonctionner, dans ce cas, et nous revenons aux langages qui délèguent de nouveau au programmeur.

Il semble donc que la protection contre les sinistres soit meilleure dans sa forme actuelle: blocs d'alimentation ininterrompus, serveurs de sauvegarde à chaud prêts à fonctionner, routes de réseau multiples entre hôtes, etc. Et il ne reste plus qu'à espérer que notre logiciel présente des erreurs. gratuit!

Réponse précise:

Ada et SPARK ont été conçus pour une tolérance de panne maximale et pour déplacer tous les bogues possibles au moment de la compilation plutôt que de l'exécution. Ada a été conçu par le département américain de la défense pour les systèmes militaires et aéronautiques, fonctionnant sur des périphériques embarqués, tels que des avions. Spark est son descendant. Un autre langage utilisé dans le premier programme spatial américain, HAL / S, était destiné à gérer les défaillances matérielles et la corruption de la mémoire dues aux rayons cosmiques.

Réponse pratique:

Je n'ai jamais rencontré quelqu'un qui puisse coder Ada / Spark. Pour la plupart des utilisateurs, la meilleure solution est d'utiliser des variantes SQL sur un SGBD avec basculement automatique et mise en cluster des serveurs. Les contrôles d'intégrité garantissent la sécurité. Quelque chose comme T-SQL ou PL / SQL a une sécurité transactionnelle complète, est complet avec Turing et tolère assez bien les problèmes.

La raison pour laquelle il n'y a pas de meilleure réponse:

Pour des raisons de performances, vous ne pouvez pas assurer la durabilité de toutes les opérations du programme . Si vous le faisiez, le traitement ralentirait à la vitesse de votre stockage non volatile le plus rapide. Au mieux, vos performances chuteront d'un millier ou d'un million de fois, en raison de la lenteur de ANYTHING par rapport aux caches de processeur ou à la RAM.

Cela équivaudrait à passer d'un processeur Core 2 Duo à l'ancien processeur 8086 - vous pouvez tout au plus effectuer quelques centaines d'opérations par seconde. Sauf que ce serait encore plus lent.

En cas de coupure de courant fréquente ou de pannes matérielles, vous utilisez un système semblable à un SGBD, qui garantit ACID pour chaque opération importante . Ou bien, vous utilisez du matériel qui dispose d’un stockage rapide et non volatile (flash, par exemple). C’est toujours beaucoup plus lent, mais si le traitement est simple, c’est OK.

Au mieux, votre langage vous donne de bonnes vérifications de sécurité au moment de la compilation pour les bogues, et émettra des exceptions plutôt que de planter. La gestion des exceptions est une caractéristique de la moitié des langues utilisées actuellement.

Il existe plusieurs frameworks disponibles dans le commerce: Veritas, HA, Sun, IBM HACMP, etc. qui surveillera automatiquement les processus et les démarrera sur un autre serveur en cas de défaillance.

Il existe également un matériel coûteux, tel que la gamme HPs Tandem Nonstop, qui peut survivre à des pannes de matériel internes.

Cependant, les logiciels sont construits par des peuples et les peuples aiment se tromper. Considérez le récit édifiant du programme IEFBR14 fourni avec IBM MVS. Il s’agit essentiellement d’un programme factice NOP qui permet aux bits déclaratifs de JCL de se produire sans exécuter réellement un programme. C'est tout le code source original: -

     IEFBR14 START
             BR    14       Return addr in R14 -- branch at it
             END

Rien ne code plus simple? Au cours de sa longue vie, ce programme a en réalité accumulé un rapport de bogue et est maintenant sur la version 4.

Thats 1 bug à trois lignes de code, la version actuelle est quatre fois la taille de l'original.

Les erreurs s'infiltrent toujours, assurez-vous de pouvoir les récupérer.

Cette question m'a obligé à poster ce texte

(Il est cité dans HGTTG ??de Douglas Adams:)

Cliquez, hum.

L’immense navire de reconnaissance gris Grebulon a traversé le vide noir en silence. Il voyageait à une vitesse fabuleuse et époustouflante, mais apparaissait pourtant sur le fond scintillant de milliards d'étoiles lointaines ne bougeant pas du tout. Ce n'était qu'une tache sombre figée dans une infinie granularité d'une nuit brillante.

À bord du navire, tout était comme depuis des millénaires, profondément sombre et silencieux.

Cliquez, hum.

Au moins, presque tout.

Cliquez, cliquez, hum.

Cliquez, bourdonnez, cliquez, bourdonnez, cliquez, bourdonnez.

Cliquez, cliquez, cliquez, cliquez, cliquez, cliquez, hum.

Hmmm.

Un programme de supervision de bas niveau a réveillé un programme de supervision de niveau légèrement supérieur situé au cœur du cyber-cerveau semi-somnolent du navire et lui a signalé que chaque fois qu’il cliquait, il produisait tout un bourdonnement.

Le programme de supervision de niveau supérieur lui a demandé ce qu’il était supposé obtenir, et le programme de supervision de niveau inférieur a dit qu’il ne pouvait pas se souvenir exactement, mais pensait que c’était probablement davantage une sorte de soupir satisfait et distant, n’est-ce pas? ? Il ne savait pas ce que c'était. Cliquez, hum, cliquez, hum. C'était tout ce que je devenais.

Le programme de supervision de niveau supérieur a envisagé cela et ne l’a pas aimé. Il a demandé au programme de supervision de bas niveau en quoi consistait exactement la supervision et le programme de supervision de bas niveau a dit qu'il ne pouvait pas s'en souvenir non plus, mais que c'était quelque chose qui était censé aller avec un clic, un soupir tous les dix ans environ, ce qui se produisait généralement sans échouer. Il avait essayé de consulter sa table de recherche d’erreurs mais ne l’avait pas trouvée, raison pour laquelle il avait alerté le programme de supervision de niveau supérieur sur le problème.

Le programme de supervision de niveau supérieur est allé consulter l’une de ses propres tables de recherche pour savoir ce que le programme de supervision de bas niveau était censé superviser.

Impossible de trouver la table de consultation.

Bizarre.

Il a regardé encore. Tout ce qu'il a eu était un message d'erreur. Il a essayé de rechercher le message d'erreur dans sa table de recherche de messages d'erreur et n'a pas pu le trouver non plus. Cela a pris quelques nanosecondes pendant que tout cela était à nouveau passé. Ensuite, il a réveillé son superviseur de fonction de secteur.

Le superviseur de la fonction sectorielle a rencontré des problèmes immédiats. Il a appelé son agent de surveillance qui a également rencontré des problèmes. Quelques millions de secondes de seconde sur des circuits virtuels en sommeil, certains depuis des années, d'autres depuis des siècles, s'embrasaient dans tout le vaisseau. Quelque chose, quelque part, s'était terriblement mal passé, mais aucun des programmes de supervision ne pouvait dire ce que c'était. À tous les niveaux, il manquait des instructions vitales et des instructions sur la procédure à suivre si on découvrait qu'il manquait des instructions vitales.

Petits modules de logiciels & # 8212; agents & # 8212; traversée par les voies logiques, regroupement, conseil, regroupement. Ils ont rapidement constaté que la mémoire du navire, jusque dans son module de mission central, était en lambeaux. Aucune quantité d'interrogatoire n'a pu déterminer ce qui s'était passé. Même le module de mission central lui-même semblait endommagé.

Cela a rendu le problème très simple à traiter. Remplacez le module de mission central. Il y en avait un autre, une sauvegarde, une copie exacte de l'original. Il a dû être remplacé physiquement car, pour des raisons de sécurité, il n'y avait aucun lien entre l'original et sa copie de sauvegarde. Une fois le module de mission central remplacé, il pourrait superviser lui-même la reconstruction du reste du système dans les moindres détails et tout irait bien.

Les robots ont reçu pour instruction d’apporter le module de mission central de secours de la chambre forte blindée, où ils le gardaient, à la chambre logique du navire pour l’installation.

Il s’agissait d’un long échange de codes et de protocoles d’urgence, les robots interrogeant les agents sur l’authenticité des instructions. Enfin, les robots étaient convaincus que toutes les procédures étaient correctes. Ils ont sorti le module de mission central de secours de son boîtier de stockage, l'ont sorti de la chambre de stockage, sont tombés du navire et ont filé dans le vide.

Cela a fourni le premier indice majeur quant à ce qui était faux.

Une enquête plus approfondie a rapidement permis de déterminer ce qui s'était passé. Une météorite avait percé un grand trou dans le vaisseau. Cela n’avait pas été détecté auparavant par le navire, car la météorite avait parfaitement assommé la partie de l’équipement de traitement du navire censée détecter si le navire avait été touché par une météorite.

La première chose à faire a été d’essayer de sceller le trou. Cela s'est avéré impossible, car les capteurs du navire ne pouvaient pas voir qu'il y avait un trou, et les superviseurs qui auraient dû dire que les capteurs ne fonctionnaient pas correctement ne fonctionnaient pas correctement et ont continué à dire que les capteurs allaient bien. Le navire ne pouvait que déduire l’existence du trou du fait que les robots en étaient clairement tombés, emportant son cerveau en réserve, ce qui lui aurait permis de voir le trou avec eux.

Le navire a essayé de réfléchir intelligemment à ce sujet, a échoué, puis a été complètement masqué pendant un moment. Il ne s'est pas rendu compte qu'il s'était éteint, bien sûr, parce qu'il l'avait été. Il était simplement surpris de voir les étoiles sauter. Après la troisième fois, les étoiles sautèrent et le navire réalisa finalement qu'il devait être masqué et qu'il était temps de prendre des décisions sérieuses.

Ça s'est détendu.

Ensuite, il s'est rendu compte qu'il n'avait pas encore pris les décisions sérieuses et a paniqué. Il s'est encore effacé un peu. Quand il s'est réveillé, il a scellé toutes les cloisons autour de l'endroit où il savait que le trou invisible devait se trouver.

De toute évidence, elle n’était pas encore arrivée à destination, pensa-t-il, mais comme elle n’avait plus la moindre idée de la destination ou de la destination, il semblait peu utile de continuer. Il a consulté les petits bouts d’instructions qu’il pourrait reconstruire à partir des lambeaux de son module de mission central.

"Votre !!!!! !!!!! !!!!! La mission de l'année est de !!!!! !!!!! !!!!! !!!!!, !!!!! !!!!! !!!!! !!!!!, terre !!!!! !!!!! !!!!! une distance de sécurité !!!!! !!!!! ..... ..... ..... ....., la terre ..... ..... ..... le surveiller. !!!!! !!!!! !!!!! ... "

Tout le reste était un déchet complet.

Avant d’être totalement occulté, le navire devrait transmettre ces instructions, telles qu’elles étaient, à ses systèmes subsidiaires plus primitifs.

Il doit également faire revivre tout son équipage.

Il y avait un autre problème. Alors que l'équipage était en hibernation, l'esprit de tous ses membres, leurs souvenirs, leur identité et leur compréhension de ce qu'ils étaient venus faire avaient tous été transférés dans le module de mission central du navire à des fins de sécurité. L'équipage n'aurait pas la moindre idée de qui il était ou de ce qu'il faisait là-bas. Tant pis.

Juste avant de s’écrouler pour la dernière fois, le navire s’est rendu compte que ses moteurs commençaient aussi à céder.

Le navire et son équipage ravivé et confus se retrouvent sous le contrôle de ses systèmes automatiques subsidiaires, qui cherchaient simplement à atterrir où ils pourraient trouver pour atterrir et surveiller tout ce qu’ils pourraient trouver à surveiller.

Essayez de prendre un langage interprété open source existant et voyez si vous pouviez adapter son implémentation pour inclure certaines de ces fonctionnalités. L'implémentation C par défaut de Python incorpore un verrou interne (appelé GIL, Global Interpreter Lock) qui est utilisé pour "manipuler". simultanéité entre les threads Python en prenant tour à tour toutes les instructions 'n' VM. Peut-être pourriez-vous vous connecter à ce même mécanisme pour contrôler l'état du code.

Pour qu'un programme continue là où il s'était arrêté si la machine perdait de la puissance, non seulement il aurait besoin de sauvegarder l'état à quelque part , mais le système d'exploitation devrait également "connaître" les informations. pour le reprendre.

Je suppose que la mise en place d'un "hibernation" Il est possible d’utiliser une fonctionnalité dans une langue, mais si cela se produit constamment en arrière-plan, il est donc prêt à intervenir en cas de problème, cela ressemble au travail du système d'exploitation, à mon avis.

  

Cependant, sa caractéristique principale devrait être la suivante: si le pouvoir meurt et que la chose redémarre, il faut qu'il en reste là (il ne se souvient pas seulement de l'endroit où il était, il se souviendra également des états variables). De plus, s’il s’est arrêté au milieu d’une copie de fichier, il reprendra correctement. etc etc.

     

... ...

     

J'ai déjà examiné erlang. Aussi gentil soit-il, il possède des fonctionnalités de tolérance aux pannes ... Il ne survit pas à un coup de force. Lorsque le code redémarre, vous devrez récupérer les pièces

Si une telle technologie existait, je serais TRES intéressé à le lire. Cela dit, la solution Erlang comporterait plusieurs nœuds - idéalement situés à différents emplacements - de sorte que si un emplacement tombait en panne, les autres nœuds pourraient prendre le relais. Si tous vos nœuds se trouvaient au même emplacement et sur la même source d'alimentation (ce qui n'était pas une très bonne idée pour les systèmes distribués), vous auriez de la chance, comme vous l'avez mentionné dans un suivi de commentaires.

Microsoft Robotics Group a introduit un ensemble de bibliothèques qui semblent s’appliquer à votre question.

  

Qu'est-ce que la concurrence et la coordination?   Runtime (CCR)?

     

Exécution simultanée et de coordination   (CCR) fournit un très concurrentiel   modèle de programmation basé sur   message de passage avec puissant   primitives d'orchestration permettant   coordination des données et travail sans   l'utilisation du filetage manuel, des serrures,   sémaphores, etc. CCR aborde les   besoin de multi-core et simultané   applications en fournissant un   modèle de programmation qui facilite   gérer les opérations asynchrones,   faire face à la concurrence, exploiter   matériel parallèle et manipulation partielle   échec.

     

Qu'est-ce qu'un logiciel décentralisé?   Services (DSS)?

     

Services logiciels décentralisés (DSS)   fournit un poids léger, orienté état   modèle de service qui combine   transfert d'état représentatif (REST)   avec une composition formalisée et   architecture de notification d'événement   permettant une approche au niveau système pour   applications de construction. Dans DSS,   les services sont exposés en tant que ressources   qui sont accessibles à la fois   par programmation et pour l'interface utilisateur   manipulation. En intégrant le service   composition, état structuré   manipulation, et notification d'événement   avec l'isolation des données, DSS fournit une   modèle uniforme pour écrire très   observable, faiblement couplé   applications fonctionnant sur un seul noeud   ou sur le réseau.

La plupart des réponses fournies sont des langages à usage général. Vous voudrez peut-être vous pencher sur des langages plus spécialisés utilisés dans les périphériques intégrés. Le robot est un bon exemple à prendre en compte. Que voudriez-vous et / ou attendriez-vous d'un robot lorsqu'il récupère d'une panne de courant?

Dans le monde intégré, cela peut être implémenté via une interruption de surveillance et une RAM sauvegardée sur batterie. Je l'ai écrit moi-même.

En fonction de votre définition du sinistre, la délégation de cette responsabilité à la langue peut aller de "difficile" à "pratiquement impossible".

D'autres exemples donnés incluent la persistance de l'état actuel de l'application dans NVRAM après l'exécution de chaque instruction. Cela ne fonctionne que tant que l'ordinateur n'est pas détruit.

Comment une fonctionnalité de niveau de langue sait-elle comment redémarrer l'application sur un nouvel hôte?

Et dans le cas de la restauration de l'application sur un hôte, que se passerait-il si un temps considérable s'était écoulé et que les hypothèses / vérifications effectuées auparavant étaient désormais invalides?

T-SQL, PL / SQL et d’autres langages transactionnels sont probablement aussi proches que possible de la «preuve du sinistre» - ils réussissent (et les données sont sauvegardées) ou ne le font pas. En excluant la désactivation de l'isolation transactionnelle, il est difficile (mais probablement pas impossible si vous essayez réellement) d'entrer dans des états «inconnus».

Vous pouvez utiliser des techniques telles que la mise en miroir SQL pour vous assurer que les écritures sont enregistrées simultanément dans au moins deux emplacements avant qu'une transaction ne soit validée.

Vous devez toujours vous assurer de sauvegarder votre état chaque fois que vous le sécurisez (commit).

Si je comprends bien votre question, je pense que vous demandez s’il est possible de garantir qu’un algorithme particulier (c’est-à-dire un programme plus les options de récupération fournies par l’environnement) sera achevé (après tout nombre arbitraire de récupérations / redémarre).

Si cela est correct, je vous renvoie au problème bloquant :

  

Etant donné la description d'un programme et une entrée finie, déterminez si le programme se termine ou sera exécuté définitivement, compte tenu de cette entrée.

Je pense que classer votre question parmi les exemples du problème stoppant est juste, étant donné que vous aimeriez idéalement que le langage soit "résistant aux catastrophes". - c’est-à-dire conférer une "perfection" programme défectueux ou environnement chaotique.

Cette classification réduit toute combinaison d'environnement, de langue et de programme en "programme et entrée finie".

Si vous êtes d’accord avec moi, vous serez déçu de lire que le problème qui s’arrête est indécidable. Par conséquent, aucune "prévention des sinistres" la langue, le compilateur ou l’environnement pourraient être prouvés.

Cependant, il est tout à fait raisonnable de concevoir un langage offrant des options de récupération pour divers problèmes courants.

En cas de panne de courant, cela me ressemble: "Lorsque ton seul outil est un marteau, chaque problème ressemble à un clou"

Vous ne résolvez pas les problèmes de coupure de courant dans un programme. Vous résolvez ce problème avec des alimentations de secours, des batteries, etc.

Si le mode de défaillance est limité à une défaillance matérielle, Tolérance aux pannes de VMware . prétend la même chose que vous voulez. Il exécute une paire de machines virtuelles sur plusieurs clusters et, à l'aide de ce qu'ils appellent vLockstep, la machine virtuelle principale envoie tous les états en temps réel à la machine virtuelle secondaire. Ainsi, en cas d'échec primaire, l'exécution passe de manière transparente au serveur secondaire.

Je suppose que cela ne résoudrait pas les problèmes de communication, ce qui est plus courant qu'une défaillance matérielle. Pour une haute disponibilité sérieuse, vous devez envisager des systèmes distribués comme l’approche de groupe de processus de Birman ( papier au format pdf , ou livre Systèmes distribués fiables: Technologies , Services Web et applications ).

L’approximation la plus proche semble être SQL. Ce n'est pas vraiment un problème de langue cependant; c'est principalement un problème de VM. Je pourrais imaginer une machine virtuelle Java avec ces propriétés; la mettre en œuvre serait une autre affaire.

Une approximation rapide et approximative est obtenue par un contrôle d'application. Vous perdez la "mort à tout moment" propriété, mais elle est assez proche.

Je pense que c'est une erreur fondamentale pour que la reprise ne soit pas un problème de conception majeur. Limiter la responsabilité à l’environnement conduit à une solution généralement fragile, intolérante aux défauts internes.

Si c’était moi, j’investirais dans un matériel fiable ET concevrais le logiciel de manière à ce qu’il soit capable de récupérer automatiquement de toute condition possible. Selon votre exemple, la maintenance de session de base de données doit être gérée automatiquement par une API de niveau suffisamment élevé. Si vous devez vous reconnecter manuellement, vous utilisez probablement la mauvaise API.

Comme d'autres l'ont déjà souligné, les langages de procédures intégrés aux systèmes de SGBDR modernes sont ce qu'il y a de mieux pour vous sans l'utilisation d'un langage exotique.

Les machines virtuelles en général sont conçues pour ce genre de chose. Vous pouvez utiliser une API de fournisseurs de machines virtuelles (vmware..et al) pour contrôler le contrôle périodique au sein de votre application, le cas échéant.

VMWare en particulier dispose d’une fonction de relecture (Enhanced Execution Record) qui enregistre TOUT et permet une lecture à un moment précis. De toute évidence, cette approche nuit énormément aux performances, mais elle répondrait aux exigences. Je voudrais simplement m'assurer que vos lecteurs de disque ont un cache en écriture protégé par batterie.

Vous serez probablement en mesure de trouver des solutions similaires pour le bytecode java exécuté dans une machine virtuelle java. JVM tolérante aux pannes de Google et vérification des machines virtuelles.

Si vous souhaitez que les informations du programme soient sauvegardées, où les sauvegarderiez-vous?

Il faudrait le sauvegarder, par exemple. sur le disque. Mais cela ne vous aiderait pas si le disque venait à tomber en panne, donc il n’est déjà pas à l’abri des catastrophes.

Vous n'obtiendrez qu'un certain niveau de granularité dans votre état enregistré. Si vous voulez quelque chose comme cela, alors la meilleure approche consiste probablement à définir votre niveau de granularité, en termes de ce qui constitue une opération atomique et à enregistrer l'état dans la base de données avant chaque opération atomique. Ensuite, vous pouvez restaurer au point de l'opération atomique de ce niveau.

Je ne connais pas de langue qui le ferait automatiquement, car le coût de sauvegarde de l'état sur le stockage secondaire est extrêmement élevé. Par conséquent, il existe un compromis entre le niveau de granularité et l'efficacité, difficile à définir dans une application arbitraire.

  • Commencez par implémenter une application tolérante aux pannes. Si vous disposez de 8 fonctionnalités et de 5 modes de défaillance, vous avez effectué l’analyse et le test permettant de démontrer que les 40 combinaisons fonctionnent comme prévu (et que le client spécifique le souhaite: il n’y aura probablement pas d’accord pour deux).
  • deuxièmement, ajoutez un langage de script au-dessus de l'ensemble pris en charge de fonctionnalités tolérantes aux pannes. Il doit être aussi proche que possible de l’apatridie, donc certainement quelque chose de non-complet.
  • Enfin, déterminez comment gérer la restauration et la réparation de l’état du langage de script adapté à chaque mode de défaillance.

Et oui, c’est à peu près roquette < a href = "http://www.aiaa.org/spaceops2006/presentations/56767.ppt" rel = "nofollow noreferrer"> science .

Windows Workflow Foundation peut résoudre votre problème. Il est basé sur .Net et est conçu graphiquement comme un workflow avec des états et des actions.

Il permet la persistance dans la base de données (automatiquement ou à l'invite). Vous pouvez le faire entre états / actions. Ceci sérialise la totalité de l'instance de votre flux de travail dans la base de données. Il sera réhydraté et son exécution se poursuivra lorsque l’une des conditions sera remplie (temps déterminé, programme réhydraté, événements déclenchés, etc.)

Lorsqu'un hôte WWF démarre, il vérifie la base de données de persistance et réhydrate les flux de travail qui y sont stockés. Il continue ensuite à s'exécuter à partir du point de persistance.

Même si vous ne souhaitez pas utiliser les aspects de flux de travail, vous pouvez toujours utiliser le service de persistance.

Tant que vos étapes ont été atomiques, cela devrait être suffisant, surtout que je suppose que vous avez un onduleur, vous pouvez donc surveiller les événements de l'onduleur et forcer la persistance si un problème d'alimentation est détecté.

Si je m'efforçais de résoudre votre problème, j'écrirais un démon (probablement en C) qui effectuait toutes les interactions de base de données dans les transactions, de sorte que vous n'obtiendriez aucune donnée erronée si elle était interrompue. Demandez au système de démarrer ce démon au démarrage.

Évidemment, développer du contenu Web en C est un peu plus lent que dans un langage de script, mais il fonctionnera mieux et sera plus stable (si vous écrivez un bon code bien sûr:).

En réalité, je l’écrirais en Ruby (ou en PHP ou autre chose) et je ferais exécuter quelque chose comme Delayed Job (ou cron ou tout autre programmateur) de temps en temps car je n’aurais pas besoin de mettre à jour chaque cycle.

J'espère que cela a du sens.

Selon moi, le concept de reprise après incident est, la plupart du temps, un problème commercial, et non un problème de matériel ou de langue.

Prenons un exemple: vous avez un niveau d’interface utilisateur et un sous-système. Le sous-système n’est pas très fiable, mais le client du niveau interface utilisateur doit le percevoir comme s’il l’était.

Maintenant, imaginez que votre sous-système plante, pensez-vous vraiment que le langage que vous imaginez peut penser pour vous comment gérer le niveau d'interface utilisateur en fonction de ce sous-système?

Votre utilisateur doit savoir explicitement que le sous-système n'est pas fiable. Si vous utilisez une messagerie extrêmement fiable, le client DOIT le savoir (s'il ne le sait pas, l'interface utilisateur peut simplement geler l'attente d'une réponse qui peut 2 semaines plus tard). S'il en a conscience, cela signifie que toute abstration destinée à le cacher finira par couler.

Par client, je veux dire utilisateur final. Et l'interface utilisateur doit refléter ce manque de fiabilité et ne pas le cacher, un ordinateur ne peut pas penser pour vous dans ce cas.

"Donc, une langue qui se souviendrait de son état à tout moment, peu importe si le courant est coupé, et continue là où elle s'est arrêtée."

"continue là où il s'est arrêté" n'est souvent pas la bonne stratégie de récupération. Aucune langue ou environnement dans le monde ne tentera de deviner comment récupérer automatiquement une erreur particulière. Le mieux que vous puissiez faire est de vous fournir des outils pour rédiger votre propre stratégie de récupération de manière à ne pas interférer avec votre logique métier, par exemple.

  • Gestion des exceptions (pour échouer rapidement tout en assurant la cohérence de l'état)
  • Transactions (pour annuler les modifications incomplètes)
  • Flux de travail (pour définir des routines de récupération appelées automatiquement)
  • Journalisation (pour rechercher la cause d’un défaut)
  • injection AOP / dependency (pour éviter d’avoir à insérer manuellement du code pour faire tout ce qui précède)

Ce sont des outils très génériques et disponibles dans de nombreux langages et environnements.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top