Regjistri i shpërndarë për grupet e rrotave: Një përvojë me pëlhurën Hyperledger

Përshëndetje, unë punoj në projektin RRD KP (një regjistër i shpërndarë për monitorimin e ciklit jetësor të seteve të rrotave). Këtu, do të doja të ndaja përvojën e ekipit tonë në zhvillimin e një zinxhiri blockchain për ndërmarrje për këtë projekt brenda kufizimeve të teknologjisë. Do të diskutoj kryesisht për Hyperledger Fabric, por qasja e përshkruar këtu mund të ekstrapolohet në çdo zinxhir blockchain të lejuar. Qëllimi përfundimtar i hulumtimit tonë është të zhvillojmë zgjidhje zinxhiri blockchain për ndërmarrje që janë të këndshme për t'u përdorur dhe jo shumë të vështira për t'u mirëmbajtur.

Nuk do të ketë zbulime apo zgjidhje të papritura këtu, dhe unë nuk do të nxjerr në pah ndonjë zhvillim unik (sepse nuk kam asnjë). Thjesht dua të ndaj përvojën time modeste, të tregoj se "mund të ishte bërë" dhe ndoshta të lexoj për përvojat e të tjerëve duke marrë vendime të mira dhe jo aq të mira në komente.

Problemi: Blockchain-et nuk shkallëzohen ende

Sot, shumë zhvillues po punojnë për ta bërë blockchain-in një teknologji vërtet miqësore për përdoruesit, jo një bombë me sahat në një paketim të bukur. Kanalet shtetërore, përmbledhjet optimiste, plazma dhe sharding mund të bëhen të zakonshme. Një ditë. Ose ndoshta TON do ta vonojë lançimin e tij përsëri për gjashtë muaj, dhe një tjetër Grup Plazmash do të pushojë së ekzistuari. Ne mund të besojmë në një plan tjetër dhe të lexojmë dokumente të shkëlqyera natën, por këtu dhe tani, duhet të bëjmë diçka me atë që kemi. Bëjeni punën.

Sfida me të cilën përballet ekipi ynë në projektin aktual është përgjithësisht si më poshtë: ka shumë entitete, që numërohen në mijëra, të cilat nuk janë të gatshme të ndërtojnë marrëdhënie të bazuara në besim. Ne duhet të ndërtojmë një zgjidhje të bazuar në DLT që do të funksionojë në PC të rregullt pa ndonjë kërkesë të veçantë performance dhe që do të ofrojë një përvojë përdoruesi të krahasueshme me çdo sistem të centralizuar kontabiliteti. Teknologjia themelore duhet të minimizojë mundësinë e manipulimit të të dhënave me qëllim të keq - prandaj blockchain është zgjidhja.

Dokumentet zyrtare dhe sloganet mediatike na premtojnë se zhvillimi më i fundit do të mundësojë miliona transaksione në sekondë. Cili është realiteti?

Rrjeti kryesor i Ethereum aktualisht operon me një shpejtësi prej ~30 tps. Vetëm kjo e bën të vështirë ta konsiderosh atë një blockchain të përshtatshëm për nevojat e ndërmarrjeve. Ndër zgjidhjet e lejuara, dihet që testet krahasuese tregojnë 2000 tps (kuorum) ose 3000 tps (Pëlhurë Hyperledger, ka pak më pak në botim, por duhet të merret parasysh se testimi i pikës referuese u krye në motorin e vjetër të konsensusit). Ishte një përpjekje për një ridizajnim rrënjësor të Pëlhurës, i cili dha rezultate të mira—20000 tps—por për momentin, ky është vetëm një hulumtim akademik që pret një zbatim të qëndrueshëm. Nuk ka gjasa që një korporatë që mund të përballojë një departament zhvillimi të blockchain-it do të tolerojë shifra të tilla. Por problemi nuk është vetëm rendimenti; ka edhe vonesë.

gjendje latente

Vonesa nga momenti që një transaksion fillon deri në miratimin përfundimtar nga sistemi varet jo vetëm nga shpejtësia e kalimit të mesazhit nëpër të gjitha fazat e validimit dhe porositjes, por edhe nga parametrat e formimit të bllokut. Edhe nëse zinxhiri ynë i blloqeve na lejon të kryejmë transaksione me një shpejtësi prej 1000000 tps, por kërkon 10 minuta për të formuar një bllok prej 488 MB, a do t'i bëjë gjërat më të lehta?

Le të hedhim një vështrim më të afërt në ciklin jetësor të transaksioneve në Hyperledger Fabric për të kuptuar se ku shpenzohet koha dhe si lidhet ajo me parametrat e formimit të blloqeve.

Regjistri i shpërndarë për grupet e rrotave: Një përvojë me pëlhurën Hyperledger
marrë nga këtu: hyperledger-fabric.readthedocs.io/en/release-1.4/arch-deep-dive.html#swimlane

(1) Klienti formon një transaksion, e dërgon atë te kolegët miratues, këta të fundit simulojnë transaksionin (zbatojnë ndryshimet e bëra nga kodi zinxhir në gjendjen aktuale, por nuk e përcaktojnë atë në librin kryesor) dhe marrin një RWSet - emrat e çelësave, versionet dhe vlerat e marra nga një koleksion në CouchDB, (2) miratuesit ia dërgojnë RWSet-in e nënshkruar përsëri klientit, (3) klienti ose kontrollon për nënshkrime nga të gjithë kolegët e kërkuar (miratuesit) dhe më pas e dërgon transaksionin te shërbimi i porositjes, ose e dërgon atë pa verifikim (verifikimi do të ndodhë më vonë), shërbimi i porositjes formon një bllok dhe (4) e dërgon atë përsëri te të gjithë kolegët, jo vetëm te miratuesit; kolegët kontrollojnë që versionet kryesore në grupin e leximit përputhen me versionet në bazën e të dhënave, që të gjithë miratuesit kanë nënshkrime dhe në fund e përcaktojnë bllokun.

Por kjo nuk është e gjitha. Fraza "porositësi formon një bllok" mbulon jo vetëm renditjen e transaksioneve, por edhe tre kërkesa të njëpasnjëshme rrjeti nga udhëheqësi te ndjekësit dhe anasjelltas: udhëheqësi shton një mesazh në regjistër, ua dërgon ndjekësve, ndjekësit e shtojnë atë në regjistrin e tyre, i dërgojnë udhëheqësit një konfirmim të replikimit të suksesshëm, udhëheqësi e kryen mesazhin, u dërgon ndjekësve një konfirmim të kryerjes dhe ndjekësit e kryejnë kryerjen. Sa më e vogël të jetë madhësia e bllokut dhe koha e formimit, aq më shpesh shërbimi i porositjes do të duhet të krijojë konsensus.Hyperledger Fabric ka dy parametra të gjenerimit të blloqeve: BatchTimeout (koha e gjenerimit të bllokut) dhe BatchSize (madhësia e bllokut (numri i transaksioneve dhe madhësia e bllokut në bajt)). Sapo njëri prej këtyre parametrave arrin limitin, lëshohet një bllok i ri. Sa më shumë nyje porositëse të ketë, aq më gjatë do të zgjasë ky proces. Prandaj, BatchTimeout dhe BatchSize duhet të rriten. Megjithatë, meqenëse RWSets janë të versionuara, sa më i madh blloku, aq më e lartë është gjasa e konflikteve MVCC. Për më tepër, rritja e BatchTimeout degradon në mënyrë dramatike përvojën e përdoruesit. Unë besoj se zgjidhja e mëposhtme për këto probleme është e arsyeshme dhe e qartë.

Si të shmangni pritjen për përfundimin e bllokut dhe të jeni ende në gjendje të gjurmoni statusin e një transaksioni

Sa më e gjatë të jetë koha dhe madhësia e gjenerimit të bllokut, aq më e lartë është rendimenti i blloqeve. Ndërsa këto nuk janë pasoja të drejtpërdrejta, ia vlen të kujtojmë se vendosja e konsensusit në RAFT kërkon tre kërkesa rrjeti nga udhëheqësi te ndjekësit dhe anasjelltas. Sa më shumë nyje renditjeje, aq më gjatë do të zgjasë ky proces. Sa më e vogël të jetë koha dhe madhësia e gjenerimit të bllokut, aq më shumë ndërveprime të tilla do të ndodhin. Si mund ta rrisim kohën dhe madhësinë e gjenerimit të bllokut pa rritur kohën e reagimit të përdoruesit fundor?

Së pari, duhet të zgjidhim disi konfliktet MVCC të shkaktuara nga madhësi të mëdha blloqesh, të cilat mund të përfshijnë RWSet-e të ndryshme me të njëjtin version. Natyrisht, nga ana e klientit (në lidhje me rrjetin blockchain, ky mund të jetë shumë mirë backend-i, dhe pikërisht këtë dua të them) Trajneri i konfliktit MVCC, i cili mund të jetë ose një shërbim i veçantë ose një dekorues i rregullt mbi thirrjen që inicion transaksionin me logjikën e ripërpjekjes.

Riprovimi mund të zbatohet duke përdorur një strategji eksponenciale, por edhe latenca do të degradojë në mënyrë eksponenciale. Prandaj, duhet të përdoret ose një riprovim i rastësishëm brenda një diapazoni të caktuar të vogël ose një riprovim konstant, me kujdes në lidhje me përplasjet e mundshme me të parën.

Hapi tjetër është ta bëjmë bashkëveprimin e klientit me sistemin asinkron, në mënyrë që të mos ketë nevojë të presë për 15, 30 ose 10000000 sekondat që do të caktojmë si BatchTimeout. Megjithatë, ne ende duhet të jemi në gjendje të verifikojmë që ndryshimet e iniciuara nga një transaksion janë shkruar në zinxhirin e blloqeve.
Mund të përdorni një bazë të dhënash për të ruajtur statusin e transaksionit. Opsioni më i thjeshtë është CouchDB për shkak të lehtësisë së përdorimit: ka një ndërfaqe përdoruesi të gatshme për përdorim, një API REST dhe mund të konfigurohet lehtësisht për replikim dhe copëtim. Mund të krijoni thjesht një koleksion të veçantë në të njëjtën instancë të CouchDB që përdor Fabric për të ruajtur gjendjen e tij botërore. Ne duhet të ruajmë dokumente të këtij lloji.

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

Ky dokument shkruhet në bazën e të dhënave përpara se transaksioni t'u dërgohet kolegëve, ID-ja e entitetit i kthehet përdoruesit (e njëjta ID përdoret si çelës) nëse ky është një operacion krijimi, dhe më pas fushat Status, TxID dhe Gabim përditësohen ndërsa merren informacionet përkatëse nga kolegët.

Regjistri i shpërndarë për grupet e rrotave: Një përvojë me pëlhurën Hyperledger

Në këtë skemë, përdoruesi nuk pret që blloku të formohet më në fund, duke parë rrotën që rrotullohet në ekran për 10 sekonda; ai merr një përgjigje të menjëhershme nga sistemi dhe vazhdon të punojë.

Ne zgjodhëm BoltDB për ruajtjen e statuseve të transaksioneve sepse na duhej të kursenim memorie dhe nuk donim të humbisnim kohë në komunikimin në rrjet me një server të veçantë të bazës së të dhënave, veçanërisht kur ky komunikim bëhej përmes një protokolli teksti të thjeshtë. Nga rruga, pavarësisht nëse përdorni CouchDB për të zbatuar skemën e përshkruar më sipër ose thjesht për të ruajtur gjendjen botërore, ka kuptim të optimizoni metodën e ruajtjes së të dhënave në CouchDB. Si parazgjedhje, madhësia e nyjes së pemës b në CouchDB është 1279 bajt, që është dukshëm më e vogël se madhësia e sektorit të diskut, që do të thotë se si leximi ashtu edhe ribalancimi i pemës do të kërkojnë më shumë akses fizik në disk. Madhësia optimale përputhet me standardin. Formati i avancuar dhe është 4 kilobajt. Për optimizim, duhet të caktojmë parametrin btree_chunk_size e barabartë me 4096 në skedarin e konfigurimit të CouchDB. Për BoltDB, një ndërhyrje e tillë manuale nuk kërkohet.

Presioni i kundërt: strategjia e tamponit

Por mund të ketë një numër të madh mesazhesh. Më shumë sesa mund të përballojë sistemi, duke ndarë burime me dhjetëra shërbime të tjera përveç atyre të treguara në diagram - dhe e gjithë kjo duhet të funksionojë pa probleme edhe në makina ku ekzekutimi i IntelliJ IDEA do të ishte një detyrë e lodhshme.

Problemi i gjerësive të ndryshme të brezave midis sistemeve komunikuese, prodhuesit dhe konsumatorit, mund të zgjidhet në mënyra të ndryshme. Le të shohim se çfarë mund të bëjmë.

TërheqjaMund të themi se nuk mund të përpunojmë më shumë se X transaksione në T sekonda. Të gjitha kërkesat që tejkalojnë këtë limit hiqen. Kjo është mjaft e thjeshtë, por atëherë mund të harrosh përvojën e përdoruesit.

KontrollimiKonsumatori duhet të ketë një ndërfaqe përmes së cilës mund të kontrollojë TPS-në e prodhuesit në varësi të ngarkesës. Kjo nuk është keq, por i detyron zhvilluesit e klientit që gjeneron ngarkesën ta zbatojnë këtë ndërfaqe. Kjo është e papranueshme për ne, pasi blockchain përfundimisht do të integrohet në një numër të madh sistemesh ekzistuese.

bufferingNë vend që të përpiqemi të pengojmë rrjedhën e të dhënave hyrëse, ne mund t'i ruajmë në memorje dhe t'i përpunojmë ato me shpejtësinë e kërkuar. Kjo është qartë zgjidhja më e mirë për të siguruar një përvojë të mirë për përdoruesin. Ne e zbatuam memorjen duke përdorur një radhë në RabbitMQ.

Regjistri i shpërndarë për grupet e rrotave: Një përvojë me pëlhurën Hyperledger

Dy veprime të reja janë shtuar në skemë: (1) pasi një kërkesë të jetë marrë nga API, një mesazh me parametrat e nevojshëm për të thirrur transaksionin vendoset në radhë dhe klienti merr një mesazh se transaksioni është pranuar nga sistemi; (2) backend lexon të dhënat nga radha me një shpejtësi të specifikuar në konfigurim; inicion transaksionin dhe përditëson të dhënat në ruajtjen e statusit.
Tani mund ta rrisni kohën dhe kapacitetin e gjenerimit të blloqeve sa të dëshironi, duke i fshehur vonesat përdoruesit.

Mjete të tjera

Këtu nuk u tha asgjë për kodin zinxhir, sepse zakonisht nuk ka asgjë për t'u optimizuar. Kodi zinxhir duhet të jetë sa më i thjeshtë dhe i sigurt që të jetë e mundur - kjo është e gjitha që kërkohet prej tij. Një kornizë na ndihmon shumë të shkruajmë kodin zinxhir thjesht dhe në mënyrë të sigurt. SSKit nga S7 Techlab dhe analizuesi statik ringjallë^CC.

Për më tepër, ekipi ynë po zhvillon një sërë shërbimesh për ta bërë punën me Fabric të thjeshtë dhe të këndshme: eksplorues i blockchain-it, dobi për ndryshime automatike të konfigurimit të rrjetit (shtimi/heqja e organizatave, nyjet RAFT), shërbimi për anulimi i certifikatës dhe fshirja e identitetitNëse doni të kontribuoni, jeni të mirëpritur.

Përfundim

Kjo qasje lejon zëvendësimin e lehtë të Hyperledger Fabric me Quorum ose rrjete të tjera private Ethereum (PoA ose edhe PoW), duke zvogëluar ndjeshëm rendimentin aktual duke ruajtur një përvojë të qëndrueshme të përdoruesit (si për përdoruesit e shfletuesit ashtu edhe për sistemet e integruara). Kur zëvendësohet Fabric me Ethereum, vetëm logjika e shërbimit të riprovimit/dekoruesit duhet të ndryshohet nga trajtimi i konfliktit MVCC në rritjen dhe ridërgimin e nonce atomike. Ruajtja në memorje dhe ruajtja e statusit lejojnë shkëputjen e kohës së përgjigjes nga koha e gjenerimit të bllokut. Tani mund të shtoni mijëra nyje porosie pa u shqetësuar për gjenerimin e shpeshtë të blloqeve dhe mbingarkesën e shërbimit të porosive.

Kaq doja të ndaja. Do të isha i lumtur nëse kjo do të ndihmonte dikë në punën e tij.

Burimi: www.habr.com

Bleni një host të besueshëm për faqet me mbrojtje DDoS, serverë VPS VDS 🔥 Bleni hosting të besueshëm të faqeve të internetit me mbrojtje DDoS, servera VPS VDS | ProHoster