Distribuert register for hjulsett: En opplevelse med Hyperledger Fabric

Hei, jeg jobber i teamet til DRD KP-prosjektet (distribuert dataregister for overvåking av livssyklusen til hjulsett). Her vil jeg gjerne dele teamets erfaring med å utvikle en enterprise blockchain for dette prosjektet under teknologiens begrensninger. For det meste vil jeg snakke om Hyperledger Fabric, men tilnærmingen som er beskrevet her kan ekstrapoleres til enhver tillatt blokkjede. Det endelige målet med vår forskning er å utarbeide blokkjedeløsninger for bedrifter på en slik måte at sluttproduktet er behagelig å bruke og ikke for vanskelig å vedlikeholde.

Det vil ikke være oppdagelser, uventede løsninger, og ingen unike utviklinger vil bli dekket her (fordi jeg ikke har dem). Jeg vil bare dele min ydmyke erfaring, vise at «det var mulig» og kanskje lese om noen andres erfaring med å ta gode og ikke så gode beslutninger i kommentarfeltet.

Problem: blokkjeder er ennå ikke skalerbare

I dag er innsatsen til mange utviklere rettet mot å gjøre blokkjeden til en virkelig praktisk teknologi, og ikke en tikkende bombe i en vakker innpakning. Statlige kanaler, optimistisk rollup, plasma og sharding kan bli vanlig. En dag. Eller kanskje TON igjen utsetter lanseringen i seks måneder, og den neste Plasma Group vil slutte å eksistere. Vi kan tro på et annet veikart og lese strålende hvitebøker om natten, men her og nå må vi gjøre noe med det vi har. Få dritt unna.

Oppgaven som er tildelt teamet vårt i det nåværende prosjektet ser generelt slik ut: Det er mange fag, som når flere tusen, som ikke ønsker å bygge relasjoner på tillit; det er nødvendig å bygge på DLT en løsning som vil fungere på vanlige PC-er uten spesielle ytelseskrav og gi en brukeropplevelse som ikke er dårligere enn noen sentraliserte regnskapssystemer. Teknologien bak løsningen skal minimere muligheten for ondsinnet datamanipulasjon – det er derfor blockchain er her.

Slagord fra whitepapers og media lover oss at den neste utviklingen vil tillate millioner av transaksjoner per sekund. Hva er det egentlig?

Mainnet Ethereum kjører for tiden på ~30 tps. Bare på grunn av dette er det vanskelig å oppfatte det som en blokkjede som på noen måte er egnet for bedriftens behov. Blant tillatte løsninger er benchmarks som viser 2000 tps kjent (quorum) eller 3000 tps (Hyperledger Fabric, det er litt mindre i publikasjonen, men husk at benchmark ble utført på den gamle konsensusmotoren). Var et forsøk på å radikalt omarbeide Fabric, som ikke ga de verste resultatene, 20000 tps, men så langt er dette bare akademiske studier som venter på stabil implementering. Det er usannsynlig at et selskap som har råd til å opprettholde en avdeling med blokkjedeutviklere vil tåle slike indikatorer. Men problemet er ikke bare i gjennomstrømming, det er også latens.

Ventetid

Forsinkelsen fra det øyeblikket en transaksjon initieres til dens endelige godkjenning av systemet avhenger ikke bare av hastigheten på meldingen som passerer gjennom alle stadier av validering og bestilling, men også av blokkformasjonsparametrene. Selv om blokkjeden vår tillater oss å forplikte oss til 1000000 10 488 tps, men det tar XNUMX minutter å danne en XNUMX MB blokk, blir det noe lettere for oss?

La oss se nærmere på livssyklusen til en transaksjon i Hyperledger Fabric for å forstå hva som tar tid og hvordan det forholder seg til parametere for blokkdannelse.

Distribuert register for hjulsett: En opplevelse med Hyperledger Fabric
hentet herfra: hyperledger-fabric.readthedocs.io/en/release-1.4/arch-deep-dive.html#swimlane

(1) Klienten danner en transaksjon, sender den til støttende peers, sistnevnte simulerer transaksjonen (bruk endringene som er gjort av kjedekoden til gjeldende tilstand, men ikke forplikte seg til reskontroen) og motta RWSet - nøkkelnavn, versjoner og verdier hentet fra samlingen i CouchDB, (2) endossører sender et signert RWSet tilbake til klienten, (3) klienten sjekker enten etter signaturene til alle nødvendige peers (endorsere), og sender deretter transaksjonen til bestillingen tjenesten, eller sender den uten verifisering (verifiseringen vil fortsatt finne sted senere), danner bestillingstjenesten en blokk og ( 4) sender tilbake til alle jevnaldrende, ikke bare påtegnere; Peers sjekker at versjonene av nøklene i lesesett samsvarer med versjonene i databasen, signaturene til alle endossører, og til slutt begår blokkeringen.

Men det er ikke alt. Bak ordene "bestiller danner en blokk" skjules ikke bare bestilling av transaksjoner, men også 3 påfølgende nettverksforespørsler fra lederen til følgere og tilbake: lederen legger til en melding i loggen, sender til følgerne, sistnevnte legger til loggen deres, send bekreftelse på vellykket replikering til lederen, lederen forplikter meldingen, sender bekreftelse på forpliktelsen til følgere, følgere forplikter. Jo mindre blokkstørrelse og tid, desto oftere vil bestillingstjenesten måtte etablere konsensus. Hyperledger Fabric har to blokkformasjonsparametere: BatchTimeout - blokkformasjonstid og BatchSize - blokkstørrelse (antall transaksjoner og størrelsen på selve blokken i byte). Så snart en av parameterne når grensen, utstedes en ny blokk. Jo flere bestillernoder, jo lengre tid vil dette ta. Derfor må du øke BatchTimeout og BatchSize. Men siden RWS-sett er versjonert, jo større vi gjør blokken, jo høyere er sannsynligheten for MVCC-konflikter. I tillegg, med en økning i BatchTimeout, forringes UX katastrofalt. Det virker for meg rimelig og åpenbart følgende opplegg for å løse disse problemene.

Hvordan unngå å vente på blokkavslutning og ikke miste oversikten over transaksjonsstatus

Jo lengre dannelsestiden og blokkstørrelsen er, jo høyere gjennomstrømning av blokkjeden. Det ene følger ikke direkte av det andre, men det bør huskes at det å etablere konsensus i RAFT krever tre nettverksforespørsler fra lederen til følgerne og tilbake. Jo flere ordrenoder, desto lengre tid vil det ta. Jo mindre størrelsen og tidspunktet for blokkdannelse er, jo flere slike interaksjoner. Hvordan øke formasjonstiden og blokkstørrelsen uten å øke systemets responstid for sluttbrukeren?

Først må du på en eller annen måte løse MVCC-konflikter forårsaket av en stor blokkstørrelse, som kan inkludere forskjellige RWS-sett med samme versjon. Åpenbart, på klientsiden (i forhold til blockchain-nettverket, kan dette godt være en backend, og jeg mener det) MVCC konfliktbehandler, som enten kan være en egen tjeneste eller en vanlig dekoratør over en transaksjonsinitierende samtale med logikk på nytt.

Forsøk på nytt kan implementeres med en eksponentiell strategi, men da vil ventetiden også degraderes eksponentielt. Så du bør bruke enten et randomisert nytt forsøk innenfor visse små grenser, eller et konstant. Med øye for mulige påkjørsler i den første varianten.

Neste steg er å gjøre klientens interaksjon med systemet asynkron slik at den ikke venter i 15, 30 eller 10000000 XNUMX XNUMX sekunder, som vi vil sette som BatchTimeout. Men samtidig er det nødvendig å beholde muligheten til å sørge for at endringene initiert av transaksjonen blir registrert/ikke registrert i blokkjeden.
En database kan brukes til å lagre status for transaksjoner. Det enkleste alternativet er CouchDB på grunn av dens brukervennlighet: databasen har et brukergrensesnitt ut av esken, en REST API, og du kan enkelt sette opp replikering og sharding for den. Du kan bare lage en egen samling i samme CouchDB-forekomst som Fabric bruker til å lagre sin verdenstilstand. Vi må oppbevare slike dokumenter.

{
 Status string // Статус транзакции: "pending", "done", "failed"
 TxID: string // ID транзакции
 Error: string // optional, сообщение об ошибке
}

Dette dokumentet skrives til databasen før transaksjonen sendes til peers, enhets-IDen returneres til brukeren (samme ID brukes som nøkkel) hvis dette er en opprettelsesoperasjon, og deretter Status, TxID og Error-feltene er oppdateres etter hvert som relevant informasjon mottas fra fagfeller.

Distribuert register for hjulsett: En opplevelse med Hyperledger Fabric

I dette opplegget venter ikke brukeren på at blokken endelig skal dannes, ser på det spinnende hjulet på skjermen i 10 sekunder, han mottar et øyeblikkelig svar fra systemet og fortsetter å jobbe.

Vi valgte BoltDB for å lagre transaksjonsstatuser fordi vi trenger å spare minne og ikke ønsker å kaste bort tid på nettverksinteraksjon med en frittstående databaseserver, spesielt når denne interaksjonen foregår ved bruk av ren tekstprotokoll. Forresten, uansett om du bruker CouchDB til å implementere ordningen beskrevet ovenfor eller bare for å lagre verdensstaten, er det i alle fall fornuftig å optimalisere måten data lagres på i CouchDB. Som standard, i CouchDB, er størrelsen på b-tree noder 1279 byte, som er mye mindre enn sektorstørrelsen på disken, noe som betyr at både lesing og rebalansering av treet vil kreve mer fysisk disktilgang. Den optimale størrelsen oppfyller standarden Avansert format og er 4 kilobyte. For optimalisering må vi sette parameteren btree_chunk_size lik 4096 i CouchDB-konfigurasjonsfilen. For BoltDB slik manuell intervensjon ikke nødvendig.

Mottrykk: bufferstrategi

Men det kan være mange meldinger. Mer enn systemet kan håndtere, deler ressurser med et dusin andre tjenester enn de som er vist i diagrammet - og alt dette skal fungere feilfritt selv på maskiner der det ville være ekstremt kjedelig å kjøre Intellij Idea.

Problemet med ulik gjennomstrømning av kommunikasjonssystemer, produsent og forbruker, løses på ulike måter. La oss se hva vi kan gjøre.

slippe: vi kan hevde å kunne behandle maksimalt X transaksjoner på T sekunder. Alle forespørsler som overskrider denne grensen blir droppet. Det er ganske enkelt, men da kan du glemme UX.

Kontrollere: Forbrukeren må ha et grensesnitt som, avhengig av belastningen, kan kontrollere produsentens tps. Ikke dårlig, men det pålegger utviklerne av lastklienten en forpliktelse til å implementere dette grensesnittet. For oss er dette uakseptabelt, siden blokkjeden i fremtiden vil bli integrert i et stort antall lenge eksisterende systemer.

buffering: i stedet for å forsøke å motstå inndatastrømmen, kan vi bufre denne strømmen og behandle den med den nødvendige hastigheten. Selvfølgelig er dette den beste løsningen hvis vi ønsker å gi en god brukeropplevelse. Vi implementerte bufferen ved å bruke en kø i RabbitMQ.

Distribuert register for hjulsett: En opplevelse med Hyperledger Fabric

To nye handlinger er lagt til ordningen: (1) etter at en API-forespørsel er mottatt, settes en melding i kø med parametrene som er nødvendige for å kalle transaksjonen, og klienten mottar en melding om at transaksjonen er akseptert av systemet, ( 2) backend leser data med en hastighet spesifisert i konfigurasjonen fra køen; starter en transaksjon og oppdaterer dataene i statuslageret.
Nå kan du øke byggetiden og blokkere kapasiteten så mye du vil, og skjule forsinkelser fra brukeren.

Andre verktøy

Her ble det ikke sagt noe om kjedekode, for det er vanligvis ikke noe å optimalisere i den. Kjedekoden skal være så enkel og sikker som mulig – det er alt som kreves av den. Rammeverket hjelper oss mye med å skrive kjedekode enkelt og trygt. CSKit fra S7 Techlab og statisk analysator gjenopplive^CC.

I tillegg utvikler teamet vårt et sett med verktøy for å gjøre arbeidet med Fabric enkelt og morsomt: blockchain explorer, verktøy for automatisk rekonfigurering av nettverket (legg til/fjern organisasjoner, RAFT-noder), verktøy for sertifikattilbakekallelse og identitetsfjerning. Ønsker du å bidra, velkommen.

Konklusjon

Denne tilnærmingen gjør det enkelt å erstatte Hyperledger Fabric med Quorum, andre private Ethereum-nettverk (PoA eller til og med PoW), reduserer reell gjennomstrømning betydelig, men opprettholder samtidig normal UX (både for brukere i nettleseren og fra siden av integrerte systemer ). Når du erstatter Fabric med Ethereum i ordningen, er det bare logikken til gjenforsøkstjenesten/dekoratøren som må endres fra å håndtere MVCC-konflikter til en atomisk nonce-økning og resending. Bufring og statuslagring gjorde det mulig å koble fra responstiden fra blokkformasjonstiden. Nå kan du legge til tusenvis av bestillingsnoder og ikke være redd for at blokker dannes for ofte og laster bestillingstjenesten.

Generelt er dette alt jeg ønsket å dele. Jeg blir glad hvis det hjelper noen i arbeidet deres.

Kilde: www.habr.com

Legg til en kommentar