Combien de TPS y a-t-il dans votre blockchain ?

La question préférée de tout non-initié concernant un système décentralisé est : « Combien de TPS y a-t-il dans votre blockchain ? ». Cependant, le chiffre donné en réponse a généralement peu à voir avec ce que l'interlocuteur espérait entendre. En réalité, il voulait demander : « Votre blockchain répond-elle à mes exigences commerciales ? », et ces exigences ne se résument pas à un seul chiffre, mais constituent un ensemble de conditions — ici, la résilience du réseau, les exigences de finalité, la taille, la nature des transactions et de nombreux autres paramètres. Ainsi, la réponse à la question « combien de TPS » ne sera probablement pas simple, et presque jamais complète. Un système décentralisé avec des dizaines et des centaines de nœuds exécutant des calculs relativement complexes peut se trouver dans un grand nombre d'états différents, en rapport avec l'état du réseau, le contenu de la blockchain, les pannes techniques, les problèmes économiques, les attaques sur le réseau et de nombreuses autres raisons. Les étapes où des problèmes de performance peuvent survenir diffèrent de celles des services traditionnels, et le serveur du réseau blockchain est un service en réseau combinant les fonctions d'une base de données, d'un serveur web et d'un client torrent, ce qui le rend extrêmement complexe en termes de profil de charge sur tous les sous-systèmes : processeur, mémoire, réseau, stockage.

Il se trouve que les réseaux décentralisés et les blockchains sont des logiciels assez spécifiques et peu familiers pour les développeurs de logiciels centralisés. C'est pourquoi je voudrais mettre en lumière des aspects importants de la performance et de la résilience des réseaux décentralisés, ainsi que des approches pour les mesurer et identifier les goulets d'étranglement. Nous examinerons divers problèmes de performance qui limitent la rapidité de fourniture de services aux utilisateurs de blockchains et soulignerons les caractéristiques spécifiques à ce type de logiciel.

Étapes de la demande de service par le client de la blockchain.

Pour parler honnêtement de la qualité de tout service un peu complexe, il faut prendre en compte non seulement les valeurs moyennes, mais aussi les valeurs maximales/minimales, les médianes et les percentiles. Théoriquement, on peut évoquer 1000 tps dans une blockchain, mais si 900 transactions ont été exécutées à une vitesse incroyable, tandis que 100 ont « accroché » pendant plusieurs secondes, alors le temps moyen, calculé sur l'ensemble des transactions, n'est pas une métrique tout à fait honnête pour le client qui n'a pas pu finaliser sa transaction en quelques secondes. Les « creux » temporels causés par des tours de consensus manqués ou par une division de réseau peuvent gravement détériorer un service qui a montré d'excellentes performances sur des bancs d'essai.

Pour identifier de tels goulets d'étranglement, il est nécessaire de bien comprendre les étapes aux cours desquelles une blockchain réelle peut rencontrer des difficultés à servir les utilisateurs. Décrivons le cycle de livraison et de traitement des transactions, ainsi que l'obtention d'un nouvel état de la blockchain, permettant au client de s'assurer que sa transaction a été traitée et prise en compte.

  1. la transaction se forme sur le client
  2. la transaction est signée sur le client
  3. le client choisit un des nœuds et envoie sa transaction
  4. le client s'abonne aux mises à jour de la base de données d'état du nœud, attendant les résultats de l'exécution de sa transaction
  5. le nœud diffuse la transaction sur le réseau p2p
  6. plusieurs, ou un seul BP (block producer) traitent les transactions accumulées, mettant à jour la base de données d'état
  7. le BP forme un nouveau bloc, après avoir traité le nombre requis de transactions
  8. le BP diffuse le nouveau bloc sur le réseau p2p
  9. le nouveau bloc est livré au nœud auquel le client s'adresse
  10. le nœud met à jour la base de données d'état
  11. le nœud voit la mise à jour concernant le client et lui envoie une notification sur sa transaction

Examinons maintenant ces étapes en détail et décrivons les problèmes potentiels de performance à chaque étape. Contrairement aux systèmes centralisés, nous allons également considérer l'exécution du code sur les clients du réseau. Il arrive souvent que lors de la mesure du TPS, le temps de traitement des transactions soit recueilli à partir des nœuds, et non des clients - ce n'est pas tout à fait juste. Pour le client, peu importe à quelle vitesse le nœud a traité sa transaction, ce qui compte le plus pour lui, c'est le moment où l'information vérifiée sur cette transaction, intégrée dans la blockchain, lui sera accessible. Cette métrique est en fait le temps d'exécution de la transaction. Cela signifie que différents clients, même en envoyant la même transaction, peuvent avoir des temps complètement différents, qui dépendent du canal, de la charge et de la proximité du nœud, etc. Par conséquent, il est essentiel de mesurer ce temps du côté des clients, car c'est ce paramètre qu'il faut optimiser.

Préparation de la transaction du côté du client

Commençons par les deux premiers points : la transaction est formée et signée par le client. Étrangement, cela peut être aussi un goulot d'étranglement de la performance de la blockchain du point de vue du client. C'est inhabituel pour les services centralisés, qui prennent tous les calculs et les opérations de données pour eux, tandis que le client prépare simplement une courte requête capable de demander un grand volume de données ou de calculs, recevant un résultat prêt. Dans les blockchains, le code client devient de plus en plus puissant, tandis que le noyau de la blockchain devient de plus en plus léger, et les tâches de calcul massives sont traditionnellement confiées au logiciel client. Dans les blockchains, il existe des clients qui peuvent préparer une seule transaction assez longtemps (je parle des différents merkle proofs, succinct proofs, signatures seuil et d'autres opérations complexes côté client). Un bon exemple de vérification on-chain légère et de préparation lourde de la transaction côté client est la preuve d'appartenance à une liste basée sur un arbre Merkle. article.

Il ne faut pas oublier que le code client ne se contente pas d'envoyer des transactions à la blockchain, mais commence par interroger l'état de la blockchain — cette activité peut affecter la congestion du réseau et des nœuds de blockchain. Ainsi, lors de la réalisation de mesures, il est raisonnable d'émuler aussi fidèlement que possible le comportement du code client. Même si votre blockchain utilise des clients légers qui apposent une signature numérique standard sur une simple transaction de transfert d'un actif, la quantité de calculs sur le client augmente chaque année, les algorithmes cryptographiques se renforcent, et cette partie du traitement peut devenir un goulot d'étranglement significatif à l'avenir. Par conséquent, soyez vigilant et ne manquez pas une situation où, dans une transaction de 3,5 secondes, 2,5 secondes sont consacrées à la préparation et à la signature de la transaction, et 1,0 seconde à l'envoi sur le réseau et à l'attente de la réponse. Pour évaluer les risques de l'apparition de ce goulot d'étranglement, il est nécessaire de collecter des métriques à partir des machines clientes, et pas seulement des nœuds de blockchain.

Envoi de la transaction et suivi de son statut

L'étape suivante consiste à envoyer la transaction au nœud blockchain sélectionné et à obtenir le statut de son acceptation dans le pool de transactions. Cette étape est similaire à une requête classique à une base de données, le nœud doit enregistrer la transaction dans le pool et commencer à diffuser les informations à son sujet via le réseau p2p. L'approche pour évaluer la performance ici est semblable à celle utilisée pour évaluer le fonctionnement des microservices traditionnels via une API Web, d'autant plus que les transactions dans les blockchains peuvent être mises à jour, changeant activement de statut. En fait, la mise à jour des informations sur une transaction dans certaines blockchains peut se produire plusieurs fois, par exemple lors de commutations entre des forks de chaînes ou lorsque des BP annoncent leur intention d'inclure une transaction dans un bloc. Les limitations sur la taille de ce pool et le nombre de transactions qu'il contient peuvent influencer la performance de la blockchain. Si le pool de transactions est plein à sa capacité maximale, ou ne tient pas en mémoire vive, la performance du réseau peut chuter brusquement. Les blockchains ne disposent pas de moyens centralisés pour se protéger contre le flot de messages indésirables, et si la blockchain supporte des transactions de grande taille et des frais bas, cela peut mener à un débordement du pool de transactions — c'est un autre goulot d'étranglement potentiel en matière de performance.

Dans les blockchains, le client envoie une transaction à n'importe quel nœud de la blockchain qui lui plaît, le hachage de la transaction étant généralement connu du client avant l'envoi. Tout ce qu'il lui reste à faire est d'établir une connexion et, après le transfert, d'attendre que la blockchain modifie son état en intégrant sa transaction. Il convient de noter qu'en mesurant le « tps », on peut obtenir des résultats très différents selon les manières dont on se connecte au nœud de la blockchain. Cela peut être un RPC HTTP classique ou un WebSocket, permettant de mettre en œuvre le modèle « subscribe ». Dans le second cas, le client recevra une notification plus tôt et le nœud dépensiera moins de ressources (principalement mémoire et trafic) pour répondre sur l'état de la transaction. Ainsi, lors de la mesure du « tps », il est essentiel de prendre en compte le mode de connexion des clients aux nœuds. Par conséquent, pour évaluer les risques d'apparition de ce goulet d'étranglement, le benchmark de la blockchain doit être capable d'émuler des clients à la fois avec des requêtes WebSocket et RPC HTTP, dans des proportions correspondant aux réseaux réels, tout en variant la nature des transactions et leurs tailles.

Pour évaluer les risques d'apparition de ce goulet d'étranglement, il est également important de collecter des métriques depuis les machines clientes, et pas seulement depuis les nœuds de la blockchain.

Transmission de transactions et de blocs par un réseau P2P

Dans les blockchains, le transfert de transactions et de blocs entre participants utilise le peer-to-peer (P2P) networking. Les transactions se propagent dans le réseau à partir d'un des nœuds, jusqu'à atteindre des pairs — des producteurs de blocs — qui empaquent les transactions en blocs et, à l'aide du même P2P, diffusent les nouveaux blocs à tous les nœuds du réseau. La plupart des réseaux P2P modernes reposent sur différentes modifications du protocole Kademlia. Voici un bon aperçu de ce protocole, et voici — un article avec diverses mesures dans le réseau BitTorrent, qui permet de comprendre que ce type de réseau est plus complexe et moins prévisible qu'un réseau rigoureusement configuré d'un service centralisé. De plus, voici un article sur la mesure de diverses métriques intéressantes pour les nœuds Ethereum.

En résumé, chaque pair dans ce type de réseau maintient sa propre liste dynamique d'autres pairs, à partir de laquelle il demande des blocs d'informations, adressés par leur contenu. Lorsqu'il reçoit une demande, un pair fournit soit l'information requise, soit transmet la demande à un autre pair pseudo-aléatoire de sa liste. Une fois la réponse obtenue, il la renvoie à la personne qui a demandé et met temporairement cette information en cache, la fournissant plus rapidement la prochaine fois. Ainsi, les informations populaires se retrouvent dans de nombreux caches de divers pairs, tandis que les informations moins populaires sont progressivement évincées. Les pairs tiennent compte de qui a transmis quoi, et le réseau essaie de stimuler les contributeurs actifs en augmentant leur classement et en leur offrant un meilleur niveau de service, tout en évincant automatiquement les participants inactifs des listes de pairs.

Ainsi, la transaction doit maintenant être diffusée sur le réseau pour que les producteurs de blocs puissent la voir et l'inclure dans un bloc. Le nœud « distribue » activement la nouvelle transaction à tous les intéressés et écoute le réseau, attendant le bloc dans lequel la transaction désirée apparaîtra pour en informer le client en attente. Le temps que le réseau met pour échanger des informations sur les nouvelles transactions et blocs dans les réseaux p2p dépend d'un très grand nombre de facteurs : le nombre de nœuds honnêtes et fonctionnels à proximité (du point de vue réseau), l'« état » des caches de ces nœuds, la taille des blocs, des transactions, la nature des changements, la géographie du réseau, le nombre de nœuds et bien d'autres facteurs. La mesure complexe des métriques de performance dans ces réseaux est un défi, nécessitant une évaluation simultanée du temps de traitement des requêtes à la fois sur les clients et sur les pairs (nœuds de blockchain). Des problèmes dans l'un des mécanismes p2p, un évincement et un cache incorrects des données, une gestion inefficace des listes de pairs actifs, et de nombreux autres facteurs peuvent entraîner des retards qui affectent l'efficacité du réseau dans son ensemble, et ce goulet d'étranglement est le plus difficile à analyser, tester et interpréter.

Traitement de la chaîne de blocs et mise à jour de la base de données d'état

La partie la plus importante du fonctionnement de la blockchain est l'algorithme de consensus, son application aux nouveaux blocs obtenus du réseau et le traitement des transactions avec l'enregistrement des résultats dans la base de données d'état. L'ajout d'un nouveau bloc à la chaîne et le choix de la chaîne principale qui s'ensuit doivent fonctionner aussi rapidement que possible. Cependant, dans la vie réelle, « doit » ne signifie pas « fonctionne », et on peut, par exemple, imaginer une situation où deux chaînes concurrentes longues se déplacent continuellement l'une vers l'autre, modifiant les métadonnées de milliers de transactions dans le pool à chaque basculement, et produisant des retours d'état constants dans la base de données d'état. Cette étape, en termes de définition du goulet d'étranglement, est plus simple que la couche p2p réseau, car l'exécution des transactions et l'algorithme de consensus sont strictement déterministes, et il est plus facile d'y mesurer quoi que ce soit.
L'essentiel est de ne pas confondre la dégradation aléatoire des performances à ce stade avec des problèmes de réseau : les nœuds délivrent plus lentement les blocs et les informations sur la chaîne principale et, pour le client externe, cela peut ressembler à un réseau lent, bien que le problème se cache en réalité ailleurs.

Pour optimiser les performances à ce stade, il est utile de collecter et de surveiller les métriques provenant des nœuds eux-mêmes, en incluant celles qui concernent la mise à jour de la base de données d'état : le nombre de blocs traités sur le nœud, leur taille, le nombre de transactions, le nombre de basculements entre les branches de la chaîne, le nombre de blocs invalides, le temps d'exécution de la machine virtuelle, le temps de validation des données, etc. Cela permettra de ne pas confondre les problèmes de réseau avec les erreurs dans les algorithmes de traitement des chaînes.

La machine virtuelle traitant les transactions peut être une source d'information utile pour optimiser le fonctionnement de la blockchain. Le nombre d'allocations de mémoire, le nombre d'instructions de lecture/écriture et d'autres métriques concernant l'efficacité de l'exécution du code des contrats peuvent fournir beaucoup d'informations précieuses aux développeurs. En même temps, les contrats intelligents sont des programmes, et donc, en théorie, ils peuvent consommer n'importe lequel des ressources : cpu/mémoire/réseau/stockage, donc le traitement des transactions est une étape assez indéfinie, qui de plus change considérablement lors des transitions entre les versions et lors du changement de code des contrats. Par conséquent, les métriques concernant le traitement des transactions sont également nécessaires pour une optimisation efficace des performances de la blockchain.

Notification to the client about the transaction being included in the blockchain

This is the final stage of the client obtaining blockchain services. Compared to other stages, there are no significant overhead costs here, but it's still important to consider the possibility of receiving a large response from the node (for example, a smart contract returning an array of data). In any case, this moment is crucial for anyone asking the question, 'what's the tps in your blockchain?', as the time of service receipt is recorded at this moment.

At this point, the total time spent by the client waiting for a response from the blockchain must be forwarded. This is the time the user will expect confirmation in their application, and optimizing it is the main task for developers.

Conclusion

As a result, we can describe the types of operations performed in blockchains and divide them into several categories:

  1. cryptographic transformations, proof construction
  2. peer-to-peer networking, transaction and block replication
  3. transaction processing, execution of smart contracts
  4. applying changes in the blockchain to the state database, updating transaction and block data
  5. read-only queries to the state database, API of the blockchain node, subscription services

In general, the technical requirements for nodes of modern blockchains are extremely serious — fast CPUs for cryptography, large amounts of RAM to store and quickly access the state database, network interactions using many simultaneously open connections, extensive storage. Such high demands and the abundance of various types of operations inevitably lead to the situation where nodes may lack resources, making any of the above stages a potential bottleneck for the overall network performance.

Lors de la conception et de l'évaluation des performances des blockchains, il est essentiel de prendre en compte tous ces aspects. Pour cela, il faut collecter et analyser les métriques à la fois des clients et des nœuds du réseau, rechercher des corrélations entre elles, évaluer le temps de réponse aux clients, prendre en compte toutes les ressources principales : cpu/mémoire/réseau/stockage, et comprendre comment elles sont utilisées et s'influencent mutuellement. Tout cela rend la comparaison des vitesses des différentes blockchains sous la forme de « combien de TPS » extrêmement ingrate, car il existe une multitude de configurations et d'états différents. Dans de grands systèmes centralisés, des clusters de centaines de serveurs, ces problèmes sont également complexes et nécessitent la collecte d'un grand nombre de métriques variées. Cependant, dans les blockchains, à cause des réseaux p2p, des machines virtuelles, des contrats intelligents, et de l'économie interne, le nombre de degrés de liberté est beaucoup plus élevé, rendant le test sur seulement quelques serveurs peu concluant et ne donnant que des valeurs très approximatives, presque sans lien avec la réalité.

Ainsi, lors du développement dans le cœur même de la blockchain, pour évaluer les performances et répondre à la question « a-t-il été amélioré par rapport à la dernière fois ? », nous utilisons un logiciel assez complexe orchestrant le lancement de la blockchain avec des dizaines de nœuds et un lancement automatique du benchmark et de la collecte de métriques. Sans ces informations, il est extrêmement difficile de déboguer les protocoles fonctionnant avec de nombreux participants.

Donc, face à la question « combien de TPS dans votre blockchain ? », offrez une tasse de thé à votre interlocuteur et demandez-lui s'il est prêt à examiner une dizaine de graphiques ainsi qu'à écouter les trois grands problèmes de performance des blockchains et vos propositions pour les résoudre…

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