Hvor mange TPS er det på blokkjeden din?

Et favorittspørsmål om ethvert distribuert system fra en ikke-teknisk person er "Hvor mange tps er på blokkjeden din?" Tallet som gis som svar har imidlertid vanligvis lite til felles med det spørsmålsstilleren ønsker å høre. Faktisk ønsket han å spørre "vil blokkjeden din passe mine forretningskrav", og disse kravene er ikke ett tall, men mange betingelser - her er nettverksfeiltoleranse, endelighetskrav, størrelser, arten av transaksjoner og mange andre parametere. Så svaret på spørsmålet "hvor mange tps" er usannsynlig enkelt, og nesten aldri komplett. Et distribuert system med titalls eller hundrevis av noder som utfører ganske komplekse beregninger kan være i et stort antall forskjellige tilstander relatert til nettverkets tilstand, innholdet i blokkjeden, tekniske feil, økonomiske problemer, angrep på nettverket og mange andre årsaker . Stadiene der ytelsesproblemer er mulig, skiller seg fra tradisjonelle tjenester, og en blokkjedenettverksserver er en nettverkstjeneste som kombinerer funksjonaliteten til en database, webserver og torrentklient, noe som gjør den ekstremt kompleks med tanke på belastningsprofilen på alle delsystemer : prosessor, minne, nettverk, lagring

Det har seg slik at desentraliserte nettverk og blokkjeder er ganske spesifikk og uvanlig programvare for sentraliserte programvareutviklere. Derfor vil jeg fremheve viktige aspekter ved ytelsen og bærekraften til desentraliserte nettverk, tilnærminger til å måle dem og finne flaskehalser. Vi vil se på ulike ytelsesproblemer som begrenser hastigheten på å levere tjenester til blockchain-brukere og legge merke til funksjonene som er karakteristiske for denne typen programvare.

Stadier av en tjenesteforespørsel fra en blokkjedeklient

For å snakke ærlig om kvaliteten på en mer eller mindre kompleks tjeneste, må du ta hensyn til ikke bare gjennomsnittsverdier, men også maksimum/minimum, medianer, persentiler. Teoretisk kan vi snakke om 1000 tps i noen blokkjeder, men hvis 900 transaksjoner ble fullført med enorm hastighet, og 100 ble "sitt fast" i noen sekunder, så er ikke gjennomsnittstiden samlet over alle transaksjoner en helt rettferdig beregning for en klient som jeg ikke kunne fullføre transaksjonen på noen få sekunder. Midlertidige "hull" forårsaket av tapte konsensusrunder eller nettverksdelinger kan i stor grad ødelegge en tjeneste som har vist utmerket ytelse på testbenker.

For å identifisere slike flaskehalser er det nødvendig å ha en god forståelse av stadiene der en ekte blokkjede kan ha problemer med å betjene brukere. La oss beskrive syklusen for å levere og behandle en transaksjon, samt oppnå en ny tilstand av blokkjeden, hvorfra kunden kan bekrefte at transaksjonen hans er behandlet og regnskapsført.

  1. transaksjonen er dannet på klienten
  2. transaksjonen er signert på klienten
  3. klienten velger en av nodene og sender sin transaksjon til den
  4. klienten abonnerer på oppdateringer til tilstandsdatabasen til noden, og venter på at resultatene av transaksjonen skal vises
  5. noden distribuerer transaksjonen over p2p-nettverket
  6. flere eller én BP (blokkprodusent) behandler akkumulerte transaksjoner, og oppdaterer statsdatabasen
  7. BP danner en ny blokk etter å ha behandlet det nødvendige antallet transaksjoner
  8. BP distribuerer en ny blokk over p2p-nettverket
  9. den nye blokken leveres til noden som klienten har tilgang til
  10. node oppdaterer tilstandsdatabase
  11. noden ser oppdateringen angående klienten og sender ham et transaksjonsvarsel

La oss nå se nærmere på disse stadiene og beskrive de potensielle ytelsesproblemene på hvert trinn. I motsetning til sentraliserte systemer vil vi også vurdere kodekjøring på nettverksklienter. Ganske ofte, når man måler TPS, samles transaksjonsbehandlingstiden fra nodene, og ikke fra klienten - dette er ikke helt rettferdig. Klienten bryr seg ikke om hvor raskt noden behandlet transaksjonen sin; det viktigste for ham er øyeblikket da pålitelig informasjon om denne transaksjonen inkludert i blokkjeden blir tilgjengelig for ham. Det er denne beregningen som i hovedsak er transaksjonsgjennomføringstiden. Dette betyr at forskjellige klienter, selv som sender samme transaksjon, kan motta helt forskjellige tider, som avhenger av kanalen, belastningen og nærheten til noden, etc. Så det er helt nødvendig å måle denne tiden på klienter, siden dette er parameteren som må optimaliseres.

Forberede en transaksjon på klientsiden

La oss starte med de to første punktene: transaksjonen er dannet og signert av klienten. Merkelig nok kan dette også være en flaskehals for blokkjedeytelse fra kundens synspunkt. Dette er uvanlig for sentraliserte tjenester, som overtar alle beregninger og operasjoner med data, og klienten forbereder ganske enkelt en kort forespørsel som kan be om en stor mengde data eller beregninger, og får et ferdig resultat. I blokkjeder blir klientkoden kraftigere og kraftigere, og blokkjedekjernen blir mer og mer lett, og massive databehandlingsoppgaver overføres vanligvis til klientprogramvaren. I blokkjeder er det klienter som kan forberede en transaksjon i ganske lang tid (jeg snakker om forskjellige merkle-bevis, kortfattede bevis, terskelsignaturer og andre komplekse operasjoner på klientsiden). Et godt eksempel på enkel on-chain verifisering og tung forberedelse av en transaksjon på klienten er bevis på medlemskap i en liste basert på Merkle-tree, her artikkel.

Ikke glem at klientkoden ikke bare sender transaksjoner til blokkjeden, men først spør om tilstanden til blokkjeden - og denne aktiviteten kan påvirke overbelastningen av nettverket og blokkjedenodene. Så når du tar målinger, vil det være rimelig å etterligne oppførselen til klientkoden så fullstendig som mulig. Selv om det i blokkjeden din er vanlige lette klienter som setter en vanlig digital signatur på den enkleste transaksjonen for å overføre en eiendel, er det fortsatt mer massive beregninger på klienten hvert år, kryptoalgoritmer blir sterkere, og denne delen av behandlingen kan bli en betydelig flaskehals i fremtiden. Vær derfor forsiktig og ikke gå glipp av situasjonen når det i en transaksjon som varer i 3.5 s, brukes 2.5 s på å forberede og signere transaksjonen, og 1.0 s på å sende den til nettverket og vente på svar. For å vurdere risikoen ved denne flaskehalsen, må du samle inn beregninger fra klientmaskiner, og ikke bare fra blokkjede-noder.

Sende en transaksjon og overvåke statusen

Det neste trinnet er å sende transaksjonen til den valgte blokkjedenoden og motta statusen for å akseptere den i transaksjonspoolen. Dette stadiet ligner på en vanlig databasetilgang; noden må registrere transaksjonen i bassenget og begynne å distribuere informasjon om den gjennom p2p-nettverket. Tilnærmingen til å vurdere ytelsen her ligner på å vurdere ytelsen til tradisjonelle Web API-mikrotjenester, og selve transaksjonene i blokkjeder kan oppdateres og aktivt endre status. Generelt kan oppdatering av transaksjonsinformasjon på enkelte blokkkjeder skje flere ganger, for eksempel når du bytter mellom kjedegafler eller når BP-er kunngjør sin intensjon om å inkludere en transaksjon i en blokk. Begrensninger på størrelsen på denne poolen og antall transaksjoner i den kan påvirke ytelsen til blokkjeden. Hvis transaksjonspoolen er fylt til størst mulig størrelse, eller ikke får plass i RAM, kan nettverksytelsen falle kraftig. Blokkjeder har ingen sentraliserte midler for å beskytte mot en flom av useriøse meldinger, og hvis blokkjeden støtter høyvolumtransaksjoner og lave avgifter, kan dette føre til at transaksjonspoolen flyter over – en annen potensiell flaskehals i ytelsen.

I blokkjeder sender klienten en transaksjon til en hvilken som helst blokkjedennode han liker, hashen til transaksjonen er vanligvis kjent for klienten før sending, så alt han trenger å gjøre er å oppnå forbindelsen og, etter overføring, vente på at blokkjeden endres sin tilstand, noe som muliggjør transaksjonen hans. Merk at ved å måle "tps" kan du få helt forskjellige resultater for forskjellige metoder for å koble til en blokkjedennode. Dette kan være en vanlig HTTP RPC eller en WebSocket som lar deg implementere "abonner"-mønsteret. I det andre tilfellet vil klienten motta et varsel tidligere, og noden vil bruke mindre ressurser (hovedsakelig minne og trafikk) på svar om transaksjonsstatus. Så når du måler "tps" er det nødvendig å ta hensyn til måten klienter kobler til noder. Derfor, for å vurdere risikoen for denne flaskehalsen, må referanseblokkkjeden være i stand til å emulere klienter med både WebSocket og HTTP RPC-forespørsler, i proporsjoner som tilsvarer ekte nettverk, samt endre arten av transaksjoner og deres størrelse.

For å vurdere risikoen ved denne flaskehalsen, må du også samle inn beregninger fra klientmaskiner, og ikke bare fra blokkjedenoder.

Overføring av transaksjoner og blokker via p2p-nettverk

I blokkjeder brukes peer-to-peer (p2p) nettverk for å overføre transaksjoner og blokkeringer mellom deltakere. Transaksjoner spredt over hele nettverket, fra en av nodene, til de når produsenter av peer-blokker, som pakker transaksjoner i blokker og ved hjelp av samme p2p distribuerer nye blokker til alle nettverksnoder. Grunnlaget for de fleste moderne p2p-nettverk er ulike modifikasjoner av Kademlia-protokollen. Her et godt sammendrag av denne protokollen, og her - en artikkel med ulike målinger i BitTorrent-nettverket, hvorfra man kan forstå at denne typen nettverk er mer kompleks og mindre forutsigbar enn et stivt konfigurert nettverk av en sentralisert tjeneste. Også, her artikkel om måling av ulike interessante beregninger for Ethereum-noder.

Kort sagt, hver peer i slike nettverk opprettholder sin egen dynamiske liste over andre peers som den ber om blokker med informasjon fra som adresseres av innhold. Når en peer mottar en forespørsel, gir den enten den nødvendige informasjonen eller sender forespørselen til neste pseudo-tilfeldige peer fra listen, og etter å ha mottatt et svar, sender den den videre til rekvirenten og cacher den en stund, og gir dette blokk med informasjon tidligere neste gang. Dermed havner populær informasjon i et stort antall cacher hos et stort antall jevnaldrende, og upopulær informasjon blir gradvis erstattet. Peers fører oversikt over hvem som har overført hvor mye informasjon til hvem, og nettverket prøver å stimulere aktive distributører ved å øke deres rangeringer og gi dem et høyere servicenivå, og automatisk fortrenge inaktive deltakere fra peer-lister.

Så transaksjonen må nå distribueres over nettverket slik at blokkprodusenter kan se den og inkludere den i blokken. Noden "distribuerer" aktivt en ny transaksjon til alle og lytter til nettverket og venter på en blokk i indeksen som den nødvendige transaksjonen vil vises for for å varsle den ventende klienten. Tiden det tar for nettverket å overføre informasjon om nye transaksjoner og blokkeringer til hverandre i p2p-nettverk avhenger av et veldig stort antall faktorer: antall ærlige noder som jobber i nærheten (fra et nettverkssynspunkt), den "varme- opp" av cachene til disse nodene, størrelsen på blokker, transaksjoner, arten av endringer, nettverksgeografi, antall noder og mange andre faktorer. Komplekse målinger av ytelsesmålinger i slike nettverk er en kompleks sak; det er nødvendig å samtidig evaluere forespørselsbehandlingstiden på både klienter og jevnaldrende (blockchain-noder). Problemer i noen av p2p-mekanismene, feil utkasting og caching av data, ineffektiv styring av lister over aktive likemenn og mange andre faktorer kan forårsake forsinkelser som påvirker effektiviteten til hele nettverket som helhet, og denne flaskehalsen er den vanskeligste å analysere , test og tolkning av resultater.

Blokkjedebehandling og oppdatering av statens database

Den viktigste delen av blokkjeden er konsensusalgoritmen, dens anvendelse på nye blokker mottatt fra nettverket og behandlingen av transaksjoner med registrering av resultatene i statsdatabasen. Å legge til en ny blokk i kjeden og deretter velge hovedkjeden skal fungere så raskt som mulig. Men i det virkelige liv betyr ikke "bør" "fungerer", og man kan for eksempel forestille seg en situasjon der to lange konkurrerende kjeder konstant bytter mellom seg selv, og endrer metadataene til tusenvis av transaksjoner i bassenget ved hver bytte , og stadig rulle tilbake staten databasen. Dette stadiet, når det gjelder å definere flaskehalsen, er enklere enn p2p-nettverkslaget, fordi transaksjonsutførelse og konsensusalgoritme er strengt deterministiske, og det er lettere å måle hva som helst her.
Det viktigste er ikke å forveksle tilfeldig forringelse av ytelsen til dette stadiet med nettverksproblemer - noder er tregere med å levere blokker og informasjon om hovedkjeden, og for en ekstern klient kan dette se ut som et tregt nettverk, selv om problemet ligger i et helt annet sted.

For å optimalisere ytelsen på dette stadiet, er det nyttig å samle inn og overvåke beregninger fra selve nodene, og inkludere i dem de som er relatert til oppdatering av tilstandsdatabasen: antall blokker behandlet på noden, deres størrelse, antall transaksjoner, antall brytere mellom kjedegafler, antall ugyldige blokker, virtuell maskindriftstid, dataforpliktelsestid osv. Dette vil forhindre at nettverksproblemer forveksles med feil i kjedebehandlingsalgoritmer.

En virtuell maskin som behandler transaksjoner kan være en nyttig informasjonskilde som kan optimere driften av blokkjeden. Antall minneallokeringer, antall lese-/skriveinstruksjoner og andre beregninger knyttet til effektiviteten av kontraktskodeutførelse kan gi mye nyttig informasjon til utviklere. Samtidig er smarte kontrakter programmer, noe som betyr at de i teorien kan forbruke alle ressursene: cpu/minne/nettverk/lagring, så transaksjonsbehandling er et ganske usikkert stadium, som i tillegg endrer seg mye når man flytter mellom versjoner og ved endring av kontraktskoder. Derfor er det også behov for beregninger knyttet til transaksjonsbehandling for å effektivt optimalisere blokkjedeytelsen.

Mottak fra klienten av en melding om inkludering av en transaksjon i blokkjeden

Dette er det siste stadiet av blockchain-klienten som mottar tjenesten; sammenlignet med andre stadier er det ingen store overheadkostnader, men det er fortsatt verdt å vurdere muligheten for at klienten mottar et omfangsrikt svar fra noden (for eksempel en smart kontrakt returnere en rekke data). I alle fall er dette punktet det viktigste for den som stilte spørsmålet "hvor mange tps er det i blokkjeden din?", fordi I dette øyeblikket registreres tidspunktet for mottak av tjenesten.

På dette stedet er det alltid en sending av hele tiden som klienten måtte bruke på å vente på svar fra blokkjeden; det er denne gangen brukeren vil vente på bekreftelse i søknaden sin, og det er optimaliseringen som er hovedoppgaven til utviklerne.

Konklusjon

Som et resultat kan vi beskrive hvilke typer operasjoner som utføres på blokkjeder og dele dem inn i flere kategorier:

  1. kryptografiske transformasjoner, beviskonstruksjon
  2. peer-to-peer-nettverk, transaksjoner og blokkereplikering
  3. transaksjonsbehandling, utførelse av smarte kontrakter
  4. å bruke endringer i blokkjeden til statsdatabasen, oppdatere data om transaksjoner og blokker
  5. skrivebeskyttede forespørsler til statens database, blockchain node API, abonnementstjenester

Generelt er de tekniske kravene til moderne blockchain-noder ekstremt alvorlige - raske CPUer for kryptografi, en stor mengde RAM for å lagre og raskt få tilgang til statsdatabasen, nettverksinteraksjon med et stort antall samtidig åpne tilkoblinger og stor lagring. Slike høye krav og overfloden av forskjellige typer operasjoner fører uunngåelig til det faktum at noder kanskje ikke har nok ressurser, og da kan alle stadiene diskutert ovenfor bli en annen flaskehals for den totale nettverksytelsen.

Når du designer og evaluerer ytelsen til blokkjeder, må du ta hensyn til alle disse punktene. For å gjøre dette må du samle inn og analysere beregninger samtidig fra klienter og nettverksnoder, se etter korrelasjoner mellom dem, estimere tiden det tar å tilby tjenester til klienter, ta hensyn til alle hovedressursene: cpu/minne/nettverk/lagring , forstå hvordan de brukes og påvirke hverandre. Alt dette gjør det å sammenligne hastighetene til forskjellige blokkjeder i form av "hvor mange TPS" til en ekstremt utakknemlig oppgave, siden det er et stort antall forskjellige konfigurasjoner og tilstander. I store sentraliserte systemer, klynger av hundrevis av servere, er disse problemene også komplekse og krever også innsamling av et stort antall forskjellige beregninger, men i blokkjeder, på grunn av p2p-nettverk, virtuelle maskiner som behandler kontrakter, interne økonomier, antall grader friheten er mye større, noe som gjør testen selv på flere servere, den er ikke-indikativ og viser bare ekstremt omtrentlige verdier som nesten ikke har noen forbindelse med virkeligheten.

Derfor, når vi utvikler i blockchain-kjernen, for å evaluere ytelsen og svare på spørsmålet "har den forbedret seg sammenlignet med forrige gang?", bruker vi ganske kompleks programvare som orkestrerer lanseringen av en blokkjede med dusinvis av noder og automatisk lanserer en benchmark og samler inn beregninger ; uten denne informasjonen er det ekstremt vanskelig å feilsøke protokoller som fungerer med flere deltakere.

Så når du mottar spørsmålet "hvor mange TPS er i blokkjeden din?", tilbyr samtalepartneren din litt te og spør om han er klar til å se på et dusin grafer og også lytte til alle tre boksene med blokkjedeytelsesproblemer og forslagene dine for løser dem...

Kilde: www.habr.com

Legg til en kommentar