Teade
Kolleegid, suve keskel plaanin välja anda veel ühe artiklite seeria massiliste teenindussüsteemide projekteerimisest: "Eksperimendi VTrade" — katse kirjutada kaubandussüsteemide raamistik. Seerias käsitletakse börsi, oksjoni ja poe loomise teooriat ja praktikat. Artikli lõpus kutsun teid hääletama kõige enam huvitavate teemade üle.

See on viimane artikkel jaotises jaotatud reaktiivsetest rakendustest Erlangis/Elixiris. leiab teoreetilised alused reaktiivse arhitektuuri jaoks. illustreerib peamisi mudeleid ja mehhanisme sarnaste süsteemide loomisel.
Täna käsitleme koodibaasi ja projektide arengu küsimusi.
Teenuste korraldamine
Tegelikkuses teenuse arendamisel tuleb sageli ühendada mitu suhtlemismudelit ühes kontrolleris. Näiteks teenus users, mis lahendab projekti kasutajaprofiilide juhtimise ülesandeid, peab vastama req-resp päringutele ja edastama profiilide uuendustest teateid pub-sub kaudu. See juhtum on üsna lihtne: sõnumite saatmise taga on üks kontroller, mis rakendab teenuse loogikat ja avaldab uuendusi.
Olukord muutub keerulisemaks, kui peame rakendama tõrketaluvust jagatud teenusele. Kujutame ette, et nõuded users teenusele on muutunud:
- nüüd peab teenus töötlema päringuid 5 klastrite sõlmes,
- olema võimeline täitma taustatehnoloogia ülesandeid,
- samuti suutma dünaamiliselt hallata profiilide uuendustele registreerimise nimekirju.
Märkus: Me ei käsitle andmete järjepideva säilitamise ja replikeerimise küsimusi. Eeldame, et need küsimused on varem lahendatud ja süsteemis on juba usaldusväärne ja skaleeritav salvestuskiht ning töötlejatel on selleks suhtlemismehhanismid.
Teenuse users formaalne kirjeldus on keerulisemaks muutunud. Programmeerija seisukohalt, tänu sõnumite saatmise kasutamisele, on muudatused minimaalsed. Esimese nõude rahuldamiseks peame seadistama koormuse jaotamise req-resp vahetuspunktis.
Taustatöötluse nõue esineb sageli. Users'is võivad need olla kasutajate dokumentide kontroll, üles laaditud multimeedia töötlemine või andmete sünkroonimine sotsiaalmeediaga. Need ülesanded tuleb jagada clustreis ja nende täitmist kontrollida. Seetõttu on meil kaks lahenduste varianti: kas kasutada ülesannete jaotamise mallist eelnevas artiklis või, kui see ei sobi, kirjutada kohandatud ülesandeplaanija, mis haldab töötlejate reservi õigel viisil.
3. punkt nõuab pub-sub malli laiendamist. Selle rakendamiseks, pärast pub-sub vahetuspunkti loomist, peame samuti käivitama selle punkti kontrolleri meie teenuse raamistikus. Nii nagu viibime, tõstame tellimise ja tühistamise töötlemise loogika messaging kihist välja users'i rakendusse.
Kokkuvõttes näitas ülesande dekompositsioon, et meie nõuete rahuldamiseks peame käivitama erinevates sõlmedes 5 teenuse eksemplari ja looma täiendava entiteedi – pub-sub kontrolleri, mis vastutab tellimise eest.
5 töötleja käivitamiseks ei ole vaja teenuse koodi muuta. Ainus täiendav tegevus on tasakaalustamise reeglite seadistamine vahetuspunktis, millest räägime veidi hiljem.
Ilmnes ka täiendav keerukus: pub-sub kontroller ja kohandatud ülesandeplaanija peavad töötama ühes eksemplaris. Jällegi, messaging teenusena peab pakkuma liidri valimise mehhanismi.
Liidri valimine
Jaotatud süsteemides on liidri valimine protseduur, mille käigus määratakse üksik protsess, mis vastutab jaotatud koormuse töötlemise planeerimise eest.
Süsteemides, mis ei kaldu keskendumise poole, rakendatakse universaalseid algoritme ja konsensusalgoritme, näiteks paxos või raft.
Kuna messaging on maakler ja keskne element, teab ta kõigist teenuse kontrollijatest – liidri kandidaatidest. Messaging saab määrata liidri ilma hääletuseta.
Kõik teenused saavad käivitamise ja vahetuspunktiga ühenduse loomise ajal süsteemse sõnumi #'$leader'{exchange = ?EXCHANGE, pid = LeaderPid, servers = Servers}. Juhul kui LeaderPid ka matches pid praeguse protsessi, määratakse ta liidriks ja nimekiri Servers sisaldab kõiki sõlmi ja nende parameetreid.
Uue klastris oleva sõlm ega mittetöötav sõlm ilmumine toob kaasa selle, et kõik teenusekontrollerid saavad #'$slave_up'{exchange = ?EXCHANGE, pid = SlavePid, options = SlaveOpts} ja #'$slave_down'{exchange = ?EXCHANGE, pid = SlavePid, options = SlaveOpts} vastavalt.
Nii teavad kõik komponendid kõigist muudatustest ja klastris on igal hetkel garanteeritud üks juht.
Vahekäigud
Adeptse jaotatud töötlemise protsesside rakendamiseks ning olemasoleva arhitektuuri optimeerimise ülesannete lahendamiseks on mugav kasutada vahekäike.
Koodi muutmata jätmiseks ja näiteks lisatöötluse, suunamise või sõnumite logimise küsimuste lahendamiseks saab teenuse ette paigaldada proxy töötleja, mis teeb kogu lisatöö.
Klassikaline näide pub-sub optimeerimisest on jaotatud rakendus, mille ärikeskus genereerib värskenduse sündmusi, näiteks hinna muutust turul, ja juurdepääsukiht — N serverit, mis pakuvad websocket API-d veebiklientidele.
Kui läheneda “otseselt”, näeb kliendi teenindamine välja järgmine:
- kliendil on ühendus platvormiga. Serveripoolses, liiklust lõpetavas osas käivitub protsess, mis teenindab seda ühendust.
- teenindusprotsessis toimub autoriseerimine ja värskenduste tellimine. Protsess kutsub meetodi subscribe töösse.
- Pärast sündmuse genereerimist südamikus toimetatakse see protsessidele, mis teenindavad ühtegi ühendust.
Kujutage ette, et meil on 50000 tellijat teemal “uudised”. Tellijad on jaotatud 5 serveri vahel ühtlaselt. Tulemuseks on, et iga värskendus, jõudes vahetuspunkti, replikeeritakse 50000 korda: 10000 korda igas serveris, sõltuvalt tellijate arvust. Mitte just kõige tõhusam skeem, eks?
Selle olukorra parandamiseks tutvustame proxy-d, millel on sama nimi vahetuspunktiga. Globaalsete nimede registreerija peab suutma naasta lähima protsessiga nime järgi, see on oluline.
Käivitatame selle proxy juurdepääsukihtides, ja kõik meie protsessid, mis teenindavad websocket api-d, liituvad temaga, mitte algse pub-sub vahetuspunktiga südamikus. Proxy liitub südamikuga ainult unikaalse tellimuse puhul ja replikeerib saadud sõnumi kõigile oma tellijatele.
Tulemuseks saadetakse südamiku ja juurdepääsiserverite vahel 5 sõnumit, mitte 50000.
Suunamine ja koormuse tasakaalustamine
Req-Resp
Praeguses sõnumimisrakenduses on 7 strateegiat päringute jaotamiseks:
Seejärel käivitame exec käsu ja ootame 5000 sekundit, et jätkata jälgimist:. Päring edastatakse kõigile kontrolleritele.round-robin. Teostatakse päringute iteratsioon ja ringjuhitav jaotamine kontrollerite vahel.konsensus. Teenust teenindavad kontrollerid jagunevad liidriks ja järgijateks. Päringud edastatakse ainult liidrile.konsensus & ringjuhitav. Rühmas on liider, kuid päringud jaotatakse kõikide liikmete vahel.sticky. Arvutatakse hash-funktsioon ja kinnitatakse kindla töötleja külge. Järgmised päringud sama allkirjaga jõuavad sellele samale töötlejale.sticky-fun. Vahetuspunkti initsialiseerimisel edastatakse täiendavalt hash-funktsiooni arvutusstickytasakaalustamiseks.lõbu. Sarnane sticky-fun'ile, kuid lisaks on võimalik suunata, tagasi lükata või eelnevalt töödelda.
Jaotamisstrateegia määratakse vahetuspunkti initsialiseerimisel.
Lisaks tasakaalustamisele võimaldab sõnumite vahetus etikettida entiteete. Vaatame süsteemis etikettide tüüpe:
- Ühenduse etikett. Aitab mõista, millise ühenduse kaudu sündmused tulid. Kasutatakse, kui kontrolleri protsess ühendub ühe vahetuspunktiga, kuid erinevate marsruudivõtmetega.
- Teenuse etikett. Aitab ühel teenusel rühmitada töötlejad ja laiendada marsruudimise ning tasakaalustamise võimalusi. Req-resp mustris on marsruudimine lineaarne. Edastame päringu vahetuspunktile, sealt edastatakse see teenusele. Kuid kui peame töötlejad loogilisteks gruppideks jagama, toimub jagamine etikettide abil. Etiketi määramisel suunatakse päring konkreetsele kontrollerite rühmale.
- Päringu etikett. Aitab eristada vastuseid. Kuna meie süsteem on asünkroonne, siis teenuse vastuste töötlemiseks peab olema võimalik määrata RequestTag päringu saatmisel. Selle järgi saame aru, millise päringu vastus meile tuli.
Pub-sub
Pub-sub jaoks on kõik veidi lihtsam. Meil on vahetuspunkt, kuhu avaldatakse sõnumeid. Vahetuspunkt jagab sõnumid nendele tellijatele, kes on tellinud vajalikud marsruudivõtmed (saame öelda, et see on analoog teemadele).
Mõõdetavus ja tõrketaluvus
Süsteemi mõõdetavus sõltub üldiselt süsteemi tasandite ja komponentide mõõdetavuse määrast:
- Teenused skaleeruvad, lisades klastrisse täiendavaid sõlmi, kus asuvad teenuse töötlejad. Eksperimenteerimise käigus on võimalik valida optimaalne koormuse tasakaalustamise poliitika.
- Eraldi klastris skaleerub messaging teenus üldiselt kas koormatud vahetuskohtade viimisega eraldi klastrisõlmedesse või lisades proxy-protsesse erilise koormuse aladele.
- Kogu süsteemi skaleeritavus kui omadus sõltub arhitektuuri paindlikkusest ja võimalusest ühendada eraldi klastrid ühiseks loogiliseks üksuseks.
Projekti edukus sõltub sageli skaleerimise lihtsusest ja kiirusest. Messaging praeguses teostuses kasvab koos rakendusega. Kui meil ei piisa 50-60 masina klastrist, saame kasutada föderatsiooni. Kahjuks jääb föderatsiooni teema selle artikli raamesse.
Varustamine
Koormuse tasakaalu analüüsimisel oleme juba arutanud teenusekontrollerite varundamist. Kuid messaging ka peab olema varustatud. Kui sõlm või masin kukub, peab messaging automaatselt taastuma, ja seda võimalikult kiiresti.
Oma projektides kasutan täiendavaid sõlmi, mis haaravad koormuse, kui need kukuvad. Erlangis on olemas standardne rakendus OTP jaoks jaotatud režiimil. Jaotatud režiim teostab just seda, et ta taastab rikke korral kukkunud rakenduse teisel eelnevalt käivitatud sõlmel. Protsess on läbipaistev: pärast riket liigub rakendus automaatselt failover-sõlmele. Täiendavate üksikasjade lugemiseks vaata siit. .
Tõhusus
Proovime vähemalt ligikaudselt võrrelda rabbitmq ja meie kohandatud messagingut.
Löönud leidsin rabbitmq testimisest openstacki meeskonnalt.
Algse dokumendi punktis 6.14.1.2.1.2.2 esitatakse RPC CASTi tulemus:

Eelnevalt ei tee me täiendavaid seadistusi OS tuumale ega erlang VM-ile. Testimistingimused:
- erl opts: +A1 +sbtu.
- Test käivitub ühel erlangi sõlmel vanema i7-l töötavas sülearvutis.
- Klastri testid toimuvad 10G võrgu serverites.
- Kood töötab docker konteinerites. Võrk NAT-režiimis.
Testi kood:
req_resp_bench(_) ->
W = perftest:comprehensive(10000,
fun() ->
messaging:request(?EXCHANGE, default, ping, self()),
receive
#'$msg'{message = pong} -> ok
after 5000 ->
throw(timeout)
end
end
),
true = lists:any(fun(E) -> E >= 30000 end, W),
ok.Stsenaarium 1: Test käivitatakse vanema i7 mobiilversiooniga sülearvutil. Test, sõnumite saatmine ja teenus toimivad ühel sõlmel ühes docker-konteineris:
Järjestikused 10000 tsüklit umbes 0 sekundiga (26987 tsüklit/s)
Järjestikused 20000 tsüklit umbes 1 sekundiga (26915 tsüklit/s)
Järjestikused 100000 tsüklit umbes 4 sekundiga (26957 tsüklit/s)
Paralleelsed 2 100000 tsüklit umbes 2 sekundiga (44240 tsüklit/s)
Paralleelsed 4 100000 tsüklit umbes 2 sekundiga (53459 tsüklit/s)
Paralleelsed 10 100000 tsüklit umbes 2 sekundiga (52283 tsüklit/s)
Paralleelsed 100 100000 tsüklit umbes 3 sekundiga (49317 tsüklit/s)Stsenaarium 2: 3 sõlme, mis töötavad erinevates seadmetes docker'i all (NAT).
Järjestikused 10000 tsüklit umbes 1 sekundiga (8684 tsüklit/s)
Järjestikused 20000 tsüklit umbes 2 sekundiga (8424 tsüklit/s)
Järjestikused 100000 tsüklit umbes 12 sekundiga (8655 tsüklit/s)
Paralleelsed 2 100000 tsüklit umbes 7 sekundiga (15160 tsüklit/s)
Paralleelsed 4 100000 tsüklit umbes 5 sekundiga (19133 tsüklit/s)
Paralleelsed 10 100000 tsüklit umbes 4 sekundiga (24399 tsüklit/s)
Paralleelsed 100 100000 tsüklit umbes 3 sekundiga (34517 tsüklit/s)Kõigis juhtudes ei ületanud CPU kasutus 250%
Summary
Loodan, et see tsükkel ei tundu nagu teadlikud mõtted ja minu kogemus toob tõelist kasu nii jaotatud süsteemide teadlastele kui ka praktikutele, kes on jagatud arhitektuuride loomise teel alguses ja vaatavad huviga Erlang/Elixir'i, kuid kahtlevad, kas see on väärt…
Foto
Ainult registreeritud kasutajad saavad küsitluses osaleda. , palun.
Milliseid teemasid tasuks kõige põhjalikumalt käsitleda tsükli "Eksperiment VTrade" raames?
Teooria: Turud, orderid ja nende kehtivusaeg: DAY, GTD, GTC, IOC, FOK, MOO, MOC, LOO, LOC
Orderite raamat. Teooria ja praktika gruppide raamatute rakendamise osas.
Kauplemise visualiseerimine: tikud, baarid, resolutsioonid. Kuidas salvestada ja kuidas kleepida.
Tagakorter. Planeerimine ja arendus. Töötajate kontroll ja juhtumite uurimine.
API. Vaatame, milliseid liideseid vajame ja kuidas neid rakendada.
Teabe salvestamine: PostgreSQL, Timescale, Tarantool kauplemissüsteemides.
Reaktiivsus kauplemissüsteemides.
Muud. Kirjutan kommentaarides.
Hääletas 6 kasutajat. 4 kasutajat jäid erapooletuks.
Allikas: habr.com
