Comment une architecture web rĂ©siliente est-elle mise en Ɠuvre sur la plateforme Mail.ru Cloud Solutions

Comment une architecture web rĂ©siliente est-elle mise en Ɠuvre sur la plateforme Mail.ru Cloud Solutions

Bonjour, Habr ! Je suis Artem Karamyshev, responsable de l'Ă©quipe d'administration systĂšme. Mail.Ru Cloud Solutions (MCS). Au cours de la derniĂšre annĂ©e, nous avons lancĂ© de nombreux nouveaux produits. Nous voulions nous assurer que les services API soient facilement Ă©volutifs, fiables et prĂȘts Ă  rĂ©pondre rapidement Ă  une charge d'utilisateur croissante. Notre plateforme est basĂ©e sur OpenStack, et je souhaite partager les problĂšmes de rĂ©silience des composants que nous avons dĂ» rĂ©soudre pour obtenir un systĂšme rĂ©silient. Je pense que cela intĂ©ressera ceux qui dĂ©veloppent Ă©galement des produits sur OpenStack.

La rĂ©silience globale de la plateforme dĂ©pend de la fiabilitĂ© de ses composants. Nous allons donc passer progressivement par tous les niveaux oĂč nous avons identifiĂ© des risques et les avons attĂ©nuĂ©s.

Vous pouvez visionner la version vidéo de cette histoire, qui est issue d'une présentation lors de la conférence Uptime Day 4, organisée par ITSumma, sur la chaßne YouTube de Uptime Community. Résilience de l'architecture physique.

La partie publique du cloud MCS est actuellement basée dans deux centres de données de niveau Tier III, entre lesquels il existe une fibre sombre réservée au niveau physique par différentes liaisons, avec une capacité de 200 Gbit/s. Le niveau Tier III garantit le niveau nécessaire de résilience pour l'infrastructure physique.

La fibre sombre est réservée à la fois au niveau physique et logique. Le processus de réservation des canaux a été itératif, avec des problÚmes surgissant, et nous améliorons constamment la connexion entre les centres de données.

Par exemple, récemment, lors de travaux dans un puits prÚs de l'un des centres de données, un excavateur a percé un tuyau, à l'intérieur duquel se trouvaient à la fois un cùble optique principal et de secours. Notre canal de communication résilient avec le centre de données s'est avéré vulnérable à un point, dans le puits. Par conséquent, nous avons perdu une partie de l'infrastructure. Nous avons tiré des leçons de cette expérience et avons entrepris certaines actions, notamment en installant de la fibre optique supplémentaire dans le puits voisin.

Par exemple, il n'y a pas si longtemps, lors des travaux dans un puits prĂšs de l'un des centres de donnĂ©es, une pelle a percutĂ© un tuyau. À l'intĂ©rieur de ce tuyau se trouvaient Ă  la fois le cĂąble de fibre optique principal et le cĂąble de secours. Notre canal de communication redondant avec le centre de donnĂ©es s'est avĂ©rĂ© vulnĂ©rable Ă  un point, dans le puits. Par consĂ©quent, nous avons perdu une partie de notre infrastructure. Nous avons tirĂ© des leçons de cet incident et avons pris plusieurs mesures, y compris l'installation d'une fibre optique supplĂ©mentaire dans le puits voisin.

Dans les centres de données, il y a des points de présence des fournisseurs de services, auxquels nous transmettons nos préfixes via BGP. Pour chaque direction de réseau, la meilleure métrique est choisie, permettant d'assurer la meilleure qualité de connexion à nos différents clients. Si la connexion via un fournisseur est interrompue, nous réajustons notre routage à travers les fournisseurs disponibles.

En cas de défaillance d'un fournisseur, nous basculons automatiquement vers le suivant. En cas de défaillance d'un des centres de données, nous disposons d'une copie miroir de nos services dans un second centre de données, qui prend toute la charge.

Comment une architecture web rĂ©siliente est-elle mise en Ɠuvre sur la plateforme Mail.ru Cloud Solutions
Résilience de l'infrastructure physique

Ce que nous utilisons pour la résilience au niveau des applications

Notre service est construit sur un certain nombre de composants opensource.

ExaBGP — un service qui implĂ©mente un certain nombre de fonctions en utilisant le protocole de routage dynamique basĂ© sur BGP. Nous l'utilisons activement pour annoncer nos adresses IP publiques, grĂące auxquelles les utilisateurs accĂšdent Ă  l'API.

HAProxy — un Ă©quilibrage de charge hautement chargĂ© permettant de configurer des rĂšgles d'Ă©quilibrage du trafic trĂšs flexibles Ă  diffĂ©rents niveaux du modĂšle OSI. Nous l'utilisons pour Ă©quilibrer devant tous les services : bases de donnĂ©es, courtiers de messages, services API, services web, nos projets internes — tout repose sur HAProxy.

Application API — une application web Ă©crite en python, qui permet Ă  l'utilisateur de gĂ©rer son infrastructure, son service.

Application Worker (ci-aprĂšs simplement worker) — dans les services OpenStack, c'est un dĂ©mon d'infrastructure qui permet de traduire les commandes API en infrastructure. Par exemple, la crĂ©ation d'un disque se produit justement dans le worker, tandis que la demande de crĂ©ation se fait dans l'application API.

Architecture standard de l'application OpenStack

La plupart des services dĂ©veloppĂ©s sous OpenStack tentent de suivre une seule et mĂȘme paradigm. Un service se compose gĂ©nĂ©ralement de 2 parties : l'API et les workers (exĂ©cutants du backend). En rĂšgle gĂ©nĂ©rale, l'API est une application WSGI en python qui s'exĂ©cute soit comme un processus autonome (daemon), soit Ă  l'aide d'un serveur web dĂ©jĂ  prĂȘt comme Nginx ou Apache. L'API traite les requĂȘtes des utilisateurs et transmet des instructions supplĂ©mentaires Ă  l'application worker. La transmission se fait par le biais d'un broker de messages, gĂ©nĂ©ralement RabbitMQ, les autres Ă©tant peu soutenus. Lorsque les messages parviennent au broker, ils sont traitĂ©s par les workers qui, si besoin, retournent une rĂ©ponse.

Ce paradigme implique des points de dĂ©faillance isolĂ©s : RabbitMQ et la base de donnĂ©es. Cependant, RabbitMQ est isolĂ© dans le cadre d'un seul service et peut idĂ©alement ĂȘtre individuel pour chaque service. Ainsi, chez MCS, nous sĂ©parons au maximum ces services, en crĂ©ant une base sĂ©parĂ©e et un RabbitMQ pour chaque projet distinct. Cette approche a l'avantage que, en cas d'incident dans certaines zones vulnĂ©rables, seul une partie du service est affectĂ©e, et non l'ensemble.

Le nombre d'applications worker n'est limité par rien, donc l'API peut facilement se mettre à l'échelle horizontalement derriÚre des équilibres de charge pour améliorer les performances et la tolérance aux pannes.

Dans certains services, une coordination au sein du service est nécessaire - lorsque des opérations séquentielles complexes se déroulent entre l'API et les workers. Dans ce cas, un centre de coordination unique est utilisé, un systÚme cluster tel que Redis, Memcache, etcd, qui permet à un worker de dire à un autre que cette tùche lui est assignée (« toi, ne la prends pas »). Nous utilisons etcd. En général, les workers communiquent activement avec la base de données, écrivant et lisant des informations. Pour cela, nous utilisons mariadb, qui se trouve dans un cluster multimaster.

Un service classique et isolĂ© est organisĂ© de maniĂšre standard pour OpenStack. Il peut ĂȘtre considĂ©rĂ© comme un systĂšme autonome, pour lequel les mĂ©thodes d'Ă©volutivitĂ© et de tolĂ©rance aux pannes sont suffisamment Ă©videntes. Par exemple, pour garantir la tolĂ©rance aux pannes, il suffit de mettre un Ă©quilibreur de charge devant l'API. L'Ă©volutivitĂ© des workers est atteinte en augmentant leur nombre.

Le point faible de tout le systÚme réside dans RabbitMQ et MariaDB. Leur architecture mérite un article à part. Dans cet article, je souhaite me concentrer sur la résilience de l'API.

Comment une architecture web rĂ©siliente est-elle mise en Ɠuvre sur la plateforme Mail.ru Cloud Solutions
Architecture de l'application Openstack. Équilibrage de charge et rĂ©silience de la plateforme cloud.

Rendre le répartiteur HAProxy résilient grùce à ExaBGP.

Pour que nos API soient Ă©volutives, rapides et rĂ©silientes, nous avons placĂ© un rĂ©partiteur devant elles. Nous avons choisi HAProxy. À mon avis, il possĂšde toutes les caractĂ©ristiques nĂ©cessaires pour notre tĂąche : Ă©quilibrage Ă  plusieurs niveaux de l'OSI, interface de gestion, flexibilitĂ© et Ă©volutivitĂ©, de nombreuses mĂ©thodes d'Ă©quilibrage, prise en charge des tables de session.

Le premier problĂšme Ă  rĂ©soudre Ă©tait la rĂ©silience du rĂ©partiteur lui-mĂȘme. Installer simplement un rĂ©partiteur crĂ©e aussi un point de dĂ©faillance : si le rĂ©partiteur tombe en panne, le service s'arrĂȘte. Pour Ă©viter cela, nous avons utilisĂ© HAProxy avec ExaBGP.

ExaBGP permet de mettre en Ɠuvre un mĂ©canisme de vĂ©rification de l'Ă©tat du service. Nous avons utilisĂ© ce mĂ©canisme pour vĂ©rifier le bon fonctionnement de HAProxy et, en cas de problĂšme, dĂ©sactiver le service HAProxy depuis BGP.

Schéma ExaBGP+HAProxy.

  1. Installer le logiciel nécessaire, ExaBGP et HAProxy, sur trois serveurs.
  2. Créer une interface de boucle sur chacun des serveurs.
  3. Sur les trois serveurs, configurer cette interface avec la mĂȘme adresse IP publique.
  4. L'adresse IP publique est annoncée sur Internet via ExaBGP.

La rĂ©silience est obtenue en annonçant la mĂȘme adresse IP depuis les trois serveurs. Du point de vue du rĂ©seau, la mĂȘme adresse est accessible depuis trois diffĂ©rents next hops. Le routeur voit trois routes identiques et choisit la plus prioritaire selon sa propre mĂ©trique (gĂ©nĂ©ralement la mĂȘme option), et le trafic est dirigĂ© uniquement vers l'un des serveurs.

En cas de problÚme avec le fonctionnement de HAProxy ou de défaillance d'un serveur, ExaBGP cesse d'annoncer la route, et le trafic bascule en douceur vers un autre serveur.

Ainsi, nous avons atteint la résilience du répartiteur.

Comment une architecture web rĂ©siliente est-elle mise en Ɠuvre sur la plateforme Mail.ru Cloud Solutions
Résilience des répartiteurs HAProxy.

Le schéma n'est pas idéal : nous avons appris à rendre HAProxy redondant, mais nous n'avons pas su répartir la charge au sein des services. Nous avons donc élargi ce schéma : nous avons opté pour un équilibrage entre plusieurs adresses IP publiques.

Équilibrage basĂ© sur DNS et BGP

La question de l'équilibrage de charge devant nos HAProxy reste à résoudre. Néanmoins, il est assez simple de le faire, comme nous l'avons fait chez nous.

Pour équilibrer trois serveurs, il faudra trois adresses IP publiques et le bon vieux DNS. Chacune de ces adresses est définie sur l'interface loopback de chaque HAProxy et annoncée sur Internet.

Dans OpenStack, un rĂ©pertoire de services est utilisĂ© pour gĂ©rer les ressources, dans lequel est dĂ©fini le point de terminaison API de chaque service. Dans ce rĂ©pertoire, nous inscrivons le nom de domaine — public.infra.mail.ru, qui est rĂ©solu via DNS avec trois adresses IP diffĂ©rentes. En consĂ©quence, nous obtenons une rĂ©partition de charge entre les trois adresses par le biais de DNS.

Cependant, lorsque nous annonçons des adresses IP publiques, nous ne gérons pas les priorités de sélection du serveur, ce qui n'est pas encore de l'équilibrage. En général, un seul serveur sera choisi selon la hiérarchie de l'adresse IP, tandis que les deux autres resteront inactifs, car aucune métrique n'est spécifiée dans BGP.

Nous avons commencé à annoncer des routes via ExaBGP avec différentes métriques. Chaque équilibrage annonce les trois adresses IP publiques, mais l'une d'entre elles, celle principale pour cet équilibrage, est annoncée avec la métrique minimale. Donc, tant que les trois équilibrages sont en fonctionnement, les demandes à la premiÚre adresse IP atteignent le premier équilibrage, celles à la seconde vont au second, et ainsi de suite.

Que se passe-t-il lorsque l'un des équilibrages échoue ? Lorsque n'importe quel équilibrage échoue, son adresse principale est toujours annoncée par les deux autres, et le trafic entre eux est redistribué. Ainsi, nous fournissons à l'utilisateur plusieurs adresses IP via DNS. Grùce à un équilibrage par DNS et à une métrique différente, nous obtenons une répartition uniforme de la charge sur les trois équilibreurs. Et nous ne perdons pas en tolérance aux pannes.

Comment une architecture web rĂ©siliente est-elle mise en Ɠuvre sur la plateforme Mail.ru Cloud Solutions
Équilibrage HAProxy basĂ© sur DNS + BGP

Interaction entre ExaBGP et HAProxy

Nous avons donc mis en place une tolĂ©rance aux pannes en cas de dĂ©faillance d'un serveur, basĂ©e sur l'arrĂȘt de l'annonce des routes. Mais HAProxy peut aussi tomber pour d'autres raisons que la dĂ©faillance d'un serveur : erreurs d'administration, pannes au sein du service. Nous souhaitons retirer un Ă©quilibrage dĂ©faillant de la charge et dans ces cas-lĂ , un autre mĂ©canisme est nĂ©cessaire.

Ainsi, en Ă©largissant le schĂ©ma prĂ©cĂ©dent, nous avons mis en Ɠuvre un heartbeat entre ExaBGP et HAProxy. C'est une implĂ©mentation logicielle de l'interaction entre ExaBGP et HAProxy, lorsque ExaBGP utilise des scripts personnalisĂ©s pour vĂ©rifier l'Ă©tat des applications.

Pour cela, il est nĂ©cessaire de configurer un vĂ©rificateur d'Ă©tat dans la configuration d'ExaBGP qui pourra contrĂŽler le statut de HAProxy. Dans notre cas, nous avons configurĂ© un backend de vĂ©rification d'Ă©tat dans HAProxy, et cĂŽtĂ© ExaBGP, nous vĂ©rifions avec une simple requĂȘte GET. Si l'annonce cesse d'avoir lieu, cela signifie que HAProxy ne fonctionne probablement pas, et il ne faut pas l'annoncer.

Comment une architecture web rĂ©siliente est-elle mise en Ɠuvre sur la plateforme Mail.ru Cloud Solutions
Vérification d'état de HAProxy

Paires HAProxy : synchronisation des sessions

La prochaine Ă©tape consistait Ă  synchroniser les sessions. Lorsqu'on utilise des rĂ©partiteurs de charge distribuĂ©s, il est difficile d'organiser la conservation des informations sur les sessions des clients. Mais HAProxy est l'un des rares rĂ©partiteurs capable de le faire grĂące Ă  la fonctionnalitĂ© Peers — la possibilitĂ© de transfĂ©rer des tables de sessions entre diffĂ©rents processus HAProxy.

Il existe diffĂ©rentes mĂ©thodes de rĂ©partition : des mĂ©thodes simples, telles que round-robin, et des mĂ©thodes avancĂ©es, oĂč la session du client est mĂ©morisĂ©e, et il est dirigĂ© Ă  chaque fois vers le mĂȘme serveur qu'auparavant. Nous souhaitions mettre en Ɠuvre la seconde option.

Dans HAProxy, pour la conservation des sessions clients, on utilise des stick-tables. Elles sauvegardent l'adresse IP d'origine du client, l'adresse cible choisie (backend) et certaines informations auxiliaires. En gĂ©nĂ©ral, les stick-tables sont utilisĂ©es pour enregistrer les paires source-IP + destination-IP, ce qui est particuliĂšrement utile pour les applications qui ne peuvent pas transmettre le contexte de la session utilisateur lors du passage Ă  un autre rĂ©partiteur, par exemple — en mode de rĂ©partition RoundRobin.

Si l'on apprend Ă  la stick-table Ă  se dĂ©placer entre diffĂ©rents processus HAProxy (entre lesquels la rĂ©partition s'effectue), nos rĂ©partiteurs pourront travailler avec un seul pool de stick-tables. Cela permettra un passage fluide du rĂ©seau client en cas de dĂ©faillance de l'un des rĂ©partiteurs ; le travail sur les sessions des clients continuera sur les mĂȘmes backends qui avaient Ă©tĂ© choisis prĂ©cĂ©demment.

Pour un bon fonctionnement, il est nécessaire de résoudre le problÚme de l'adresse IP source du répartiteur à partir duquel la session a été établie. Dans notre cas, il s'agit d'une adresse dynamique sur l'interface loopback.

Le bon fonctionnement des pairs n'est possible que dans certaines conditions. En d'autres termes, les dĂ©lais d'attente TCP doivent ĂȘtre suffisamment longs ou le basculement doit ĂȘtre assez rapide pour Ă©viter que la session TCP ne se rompe. Cela permet nĂ©anmoins un basculement transparent.

Nous avons un service dans l'IaaS basĂ© sur la mĂȘme technologie. Il s'agit de Load Balancer en tant que service pour OpenStack, qui s'appelle Octavia. Il est basĂ© sur une infrastructure de deux processus HAProxy, avec une prise en charge initiale des pairs. Dans ce service, ils ont fait leurs preuves.

L'image illustre schématiquement le déplacement des tables de pairs entre trois instances HAProxy, avec une configuration proposée pour la mise en place :

Comment une architecture web rĂ©siliente est-elle mise en Ɠuvre sur la plateforme Mail.ru Cloud Solutions
HAProxy Peers (synchronisation des sessions)

Si vous implĂ©mentez un schĂ©ma similaire, il faut le tester attentivement. Il n'est pas garanti que cela fonctionne de la mĂȘme maniĂšre dans 100 % des cas. Cependant, vous ne perdrez pas les tables de stick lorsque vous devez vous souvenir de l'adresse IP source du client.

Limitation du nombre de requĂȘtes simultanĂ©es d'un mĂȘme client

Tous les services accessibles publiquement, y compris nos API, peuvent ĂȘtre sujets Ă  des vagues de requĂȘtes. Les raisons peuvent ĂȘtre variĂ©es, allant d'erreurs des utilisateurs Ă  des attaques ciblĂ©es. Nous subissons pĂ©riodiquement des attaques DDoS par adresses IP. Les clients se trompent souvent dans leurs scripts, ce qui nous cause de mini-DDoS.

Quoi qu'il en soit, il est nĂ©cessaire de prĂ©voir une protection supplĂ©mentaire. Une solution Ă©vidente consiste Ă  limiter le nombre de requĂȘtes Ă  l'API et Ă  ne pas perdre de temps processeur Ă  traiter des requĂȘtes malveillantes.

Pour mettre en place de telles limitations, nous appliquons des taux limites, organisĂ©s sur la base d'HAProxy, en utilisant les mĂȘmes tables de stick. Les limites sont configurĂ©es assez simplement et permettent de restreindre l'utilisateur par le nombre de requĂȘtes Ă  l'API. L'algorithme mĂ©morise l'adresse IP source d'oĂč proviennent les requĂȘtes et limite le nombre de requĂȘtes simultanĂ©es d'un mĂȘme utilisateur. Bien sĂ»r, nous avons calculĂ© le profil moyen de charge sur l'API pour chaque service et avons Ă©tabli une limite d'environ 10 fois supĂ©rieure Ă  cette valeur. Nous continuons Ă  surveiller attentivement la situation, en gardant un Ɠil sur le pouls.

Quel est le rendu en pratique ? Nous avons des clients qui utilisent constamment nos API pour l'autoscaling. Ils crĂ©ent environ deux Ă  trois cents machines virtuelles le matin et les suppriment le soir. Pour OpenStack, crĂ©er une machine virtuelle avec des services PaaS nĂ©cessite au moins 1000 requĂȘtes API, car l'interaction entre les services se fait Ă©galement via API.

Ces transferts de tùches génÚrent une charge assez importante. Nous avons évalué cette charge, collecté les pics quotidiens, les avons multipliés par dix, et cela est devenu notre taux limite. Nous restons vigilants. Nous voyons souvent des bots, des scanners qui essaient de vérifier s'il y a des scripts CGA à lancer, et nous les bloquons activement.

Comment mettre Ă  jour la base de code sans que les utilisateurs le remarquent

Nous mettons en Ɠuvre la rĂ©silience Ă©galement au niveau des processus de dĂ©ploiement du code. Des pannes peuvent survenir lors des dĂ©ploiements, mais leur impact sur la disponibilitĂ© des services peut ĂȘtre minimisĂ©.

Nous mettons constamment Ă  jour nos services et devons garantir le processus de mise Ă  jour de la base de code sans impact pour les utilisateurs. Nous avons pu rĂ©soudre cette tĂąche en utilisant les fonctionnalitĂ©s de gestion de HAProxy et la mise en Ɠuvre du Graceful Shutdown dans nos services.

Pour rĂ©soudre cette tĂąche, il Ă©tait nĂ©cessaire d'assurer la gestion du rĂ©partiteur de charge et l'arrĂȘt 'correct' des services :

  • Dans le cas de HAProxy, la gestion se fait via un fichier stats, qui est essentiellement un socket dĂ©fini dans la configuration de HAProxy. Les commandes peuvent y ĂȘtre transmises via stdio. Mais notre principal outil de contrĂŽle des configurations est Ansible, donc il contient un module intĂ©grĂ© pour gĂ©rer HAProxy. Que nous utilisons activement.
  • La plupart de nos services API et Engine prennent en charge les technologies de graceful shutdown : lors de l'arrĂȘt, ils attendent l'achĂšvement total de la tĂąche en cours, qu'il s'agisse d'une requĂȘte http ou d'une tĂąche administrative. Il en va de mĂȘme pour le worker. Il connaĂźt toutes les tĂąches qu'il exĂ©cute et se termine lorsqu'il a tout rĂ©ussi.

Grùce à ces deux points, notre algorithme de déploiement sécurisé est le suivant.

  1. Le développeur assemble un nouveau paquet de code (pour nous, c'est un RPM), le teste dans l'environnement de développement, le teste dans l'environnement de pré-production, et le laisse dans le dépÎt de pré-production.
  2. Le développeur établit la tùche de déploiement avec une description aussi détaillée que possible des « artefacts » : version du nouveau package, description des nouvelles fonctionnalités et d'autres détails sur le déploiement si nécessaire.
  3. L'administrateur systĂšme commence la mise Ă  jour. Il lance le playbook Ansible, qui, Ă  son tour, effectue les actions suivantes :
    • Il prend le package du dĂ©pĂŽt de staging et met Ă  jour la version du package dans le dĂ©pĂŽt de production.
    • Il dresse la liste des backends du service en cours de mise Ă  jour.
    • Il dĂ©sactive le premier service Ă  mettre Ă  jour dans HAProxy et attend la fin de ses processus. GrĂące Ă  un arrĂȘt en douceur, nous sommes assurĂ©s que toutes les demandes en cours des clients seront traitĂ©es avec succĂšs.
    • AprĂšs l'arrĂȘt complet de l'API, des worker, et l'arrĂȘt de HAProxy, la mise Ă  jour du code a lieu.
    • Ansible dĂ©marre les services.
    • Pour chaque service, il exĂ©cute des « hooks » spĂ©cifiques qui effectuent des tests unitaires sur un certain nombre de tests clĂ©s prĂ©dĂ©finis. Une vĂ©rification de base du nouveau code est rĂ©alisĂ©e.
    • Si aucune erreur n'est dĂ©tectĂ©e Ă  l'Ă©tape prĂ©cĂ©dente, le backend est activĂ©.
    • Nous passons au backend suivant.
  4. AprÚs la mise à jour de tous les backends, des tests fonctionnels sont lancés. S'il en manque, le développeur examine toute nouvelle fonctionnalité qu'il a développée.

Le déploiement est maintenant terminé.

Comment une architecture web rĂ©siliente est-elle mise en Ɠuvre sur la plateforme Mail.ru Cloud Solutions
Le cycle de mise Ă  jour du service

Ce schĂ©ma ne fonctionnerait pas s'il n'y avait pas une rĂšgle. Nous faisons fonctionner simultanĂ©ment l'ancienne et la nouvelle version. Au prĂ©alable, au stade de dĂ©veloppement du logiciel, il est prĂ©vu que mĂȘme s'il y a des modifications dans la base de donnĂ©es du service, elles ne casseront pas le code prĂ©cĂ©dent. En consĂ©quence, il y a une mise Ă  jour progressive de la base de code.

Conclusion

En partageant mes réflexions sur l'architecture web tolérante aux pannes, je souhaite souligner à nouveau ses points clés :

  • tolĂ©rance aux pannes physiques ;
  • tolĂ©rance aux pannes rĂ©seau (Ă©quilibreurs, BGP) ;
  • tolĂ©rance aux pannes des logiciels utilisĂ©s et dĂ©veloppĂ©s.

À tous, un uptime stable !

Source : habr.com

Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS đŸ”„ Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster