Bausteng vun verdeelt Uwendungen. Zweet Approximatioun

Announcement

Kollegen, an der Mëtt vum Summer plangen ech eng aner Serie vun Artikelen iwwer den Design vu Schlaangsystemer ze verëffentlechen: "The VTrade Experiment" - e Versuch, e Kader fir Handelssystemer ze schreiwen. D'Serie wäert d'Theorie an d'Praxis ënnersichen fir en Austausch, Auktioun a Buttek ze bauen. Um Enn vum Artikel invitéieren ech Iech fir d'Themen ze stëmmen déi Iech am meeschten interesséieren.

Bausteng vun verdeelt Uwendungen. Zweet Approximatioun

Dëst ass de leschten Artikel an der Serie iwwer verdeelt reaktiv Uwendungen am Erlang / Elixir. IN éischten Artikel Dir kënnt déi theoretesch Fundamenter vun der reaktiver Architektur fannen. Zweeten Artikel illustréiert d'Basismuster a Mechanismen fir esou Systemer ze bauen.

Haut wäerte mir Themen vun der Entwécklung vun der Code Basis a Projeten am Allgemengen erhéijen.

Organisatioun vu Servicer

Am richtege Liewen, wann Dir e Service entwéckelt, musst Dir dacks verschidde Interaktiounsmuster an engem Controller kombinéieren. Zum Beispill, de Benotzer Service, deen de Problem vun der Gestioun vum Projet Benotzer Profiler léist, muss op Req-resp Ufroen äntweren an Profil Aktualiséierungen via Pub-Sub mellen. Dëse Fall ass ganz einfach: hannert Messagerie gëtt et ee Controller deen d'Servicelogik implementéiert an Updates publizéiert.

D'Situatioun gëtt méi komplizéiert wa mir e Feeler-tolerant verdeelt Service musse implementéieren. Loosst eis virstellen datt d'Ufuerderunge fir d'Benotzer geännert hunn:

  1. elo soll de Service Ufroen op 5 Clusternoden veraarbechten,
  2. fäeg sinn Hannergrondveraarbechtungsaufgaben auszeféieren,
  3. an och kënnen dynamesch Abonnement Lëschte fir Profil Aktualiséierungen verwalten.

Kommentéieren: Mir betruechten net d'Thema vu konsequent Späicheren an Datereplikatioun. Loosst eis unhuelen datt dës Themen virdru geléist goufen an de System schonn eng zouverlässeg an skalierbar Späicherschicht huet, an d'Handler hunn Mechanismen fir matzemaachen.

Déi formell Beschreiwung vum Benotzerservice ass méi komplizéiert ginn. Aus der Siicht vun engem Programméierer sinn Ännerungen minimal wéinst der Notzung vu Messagerie. Fir déi éischt Ufuerderung ze erfëllen, musse mir d'Balance um Req-resp Austauschpunkt konfiguréieren.

D'Ufuerderung fir Hannergrondaufgaben ze veraarbechten geschitt dacks. Bei Benotzer kann dëst Benotzerdokumenter kontrolléieren, erofgeluede Multimedia veraarbecht oder Daten mat sozialen Medien synchroniséieren. Netzwierker. Dës Aufgaben mussen iergendwéi am Cluster verdeelt ginn an de Fortschrëtt vun der Ausféierung iwwerwaacht ginn. Dofir hu mir zwou Léisungsoptiounen: entweder benotzt d'Taskverdeelungsschabloun aus dem viregten Artikel, oder, wann et net passt, schreift e personaliséierten Taskplaner deen de Pool vu Prozessoren verwalten wéi mir brauchen.

Punkt 3 erfuerdert d'Pub-Sub Schabloun Extensioun. A fir d'Ëmsetzung, nodeems mir e Pub-Sub-Austauschpunkt erstallt hunn, musse mir zousätzlech de Controller vun dësem Punkt an eisem Service starten. Also ass et wéi wa mir d'Logik fir d'Veraarbechtung vun Abonnementer an d'Abonnementer vun der Messagerie Schicht an d'Ëmsetzung vun de Benotzer réckelen.

Als Resultat huet d'Zersetzung vum Problem gewisen datt fir den Ufuerderunge gerecht ze ginn, musse mir 5 Instanzen vum Service op verschiddene Wirbelen starten an eng zousätzlech Entitéit kreéieren - e Pub-Sub Controller, verantwortlech fir den Abonnement.
Fir e lafen 5 Handler, Dir musst net de Service Code änneren. Déi eenzeg zousätzlech Aktioun ass d'Gläichgewiichtregelen am Austauschpunkt opzestellen, iwwer déi mir e bësse méi spéit schwätzen.
Et gëtt och eng zousätzlech Komplexitéit: de Pub-Sub Controller an de personaliséierten Task Scheduler muss an enger eenzeger Kopie schaffen. Erëm muss de Messagerie Service, als fundamental, e Mechanismus ubidden fir e Leader ze wielen.

Leader Auswiel

A verdeelt Systemer ass d'Leaderwahl d'Prozedur fir en eenzege Prozess ze ernennen, deen verantwortlech ass fir verdeelt Veraarbechtung vun enger Laascht ze plangen.

A Systemer déi net ufälleg fir Zentraliséierung sinn, ginn universell a Konsens-baséiert Algorithmen, wéi Paxos oder Floss, benotzt.
Zënter Messagerie ass e Broker an en zentrale Element, weess et iwwer all Servicecontroller - Kandidateleader. Messagerie kënnen e Leader ernennen ouni ze stëmmen.

Nom Start a Verbindung mam Austauschpunkt kréien all Servicer e Systemmeldung #'$leader'{exchange = ?EXCHANGE, pid = LeaderPid, servers = Servers}. Wann LeaderPid fällt mat pid aktuellen Prozess, et gëtt als Leader ernannt, an d'Lëscht Servers enthält all Noden an hir Parameteren.
Am Moment erschéngt en neien an e funktionnéierende Cluster Node gëtt ofgeschalt, all Service Controller kréien #'$slave_up'{exchange = ?EXCHANGE, pid = SlavePid, options = SlaveOpts} и #'$slave_down'{exchange = ?EXCHANGE, pid = SlavePid, options = SlaveOpts} respektéiert.

Op dës Manéier sinn all Komponenten all Ännerungen bewosst, an de Stärekoup ass garantéiert zu all Moment ee Leader ze hunn.

Vermëttler

Fir komplex verdeelt Veraarbechtungsprozesser ëmzesetzen, wéi och a Probleemer fir eng existent Architektur ze optimiséieren, ass et bequem Intermédiairen ze benotzen.
Fir de Service Code net z'änneren an zum Beispill Probleemer vun der zousätzlech Veraarbechtung, Routing oder Logging Messagen ze léisen, kënnt Dir e Proxy Handler virum Service aktivéieren, deen all zousätzlech Aarbecht ausféiert.

E klassescht Beispill vu Pub-Sub-Optimiséierung ass eng verdeelt Applikatioun mat engem Geschäftskär, deen Update-Evenementer generéiert, sou wéi Präisännerungen um Maart, an eng Zougangsschicht - N Server déi e Websocket API fir Webclienten ubidden.
Wann Dir direkt décidéiert, da gesäit de Clientsservice esou aus:

  • de Client stellt Verbindunge mat der Plattform. Op der Säit vum Server, deen de Traffic ofschléisst, gëtt e Prozess gestart fir dës Verbindung ze servéieren.
  • Am Kontext vum Serviceprozess geschitt Autorisatioun an Abonnement op Updates. De Prozess nennt d'Abonnementsmethod fir Themen.
  • Wann en Event am Kernel generéiert gëtt, gëtt et an d'Prozesser geliwwert, déi d'Verbindunge servéieren.

Loosst eis virstellen datt mir 50000 Abonnente fir d'Thema "News" hunn. Abonnente sinn gläichméisseg iwwer 5 Server verdeelt. Als Resultat gëtt all Update, deen um Austauschpunkt ukomm ass, 50000 Mol replizéiert: 10000 Mol op all Server, no der Unzuel vun den Abonnenten op et. Net e ganz efficace Schema, richteg?
Fir d'Situatioun ze verbesseren, loosst eis e Proxy aféieren, deen deeselwechten Numm huet wéi den Austauschpunkt. De globale Numm Registrar muss fäeg sinn den nootste Prozess mam Numm zréckzeginn, dëst ass wichteg.

Loosst eis dëse Proxy op den Zougangsschichtserver lancéieren, an all eis Prozesser, déi de Websocket API servéieren, abonnéieren dorop, an net op den originelle Pub-Sub-Austauschpunkt am Kärel. Proxy abonnéiert de Kär nëmmen am Fall vun engem eenzegaartegen Abonnement a replizéiert den erakommen Message un all seng Abonnenten.
Als Resultat ginn 5 Messagen tëscht dem Kernel an dem Zougangsserver geschéckt, anstatt 50000.

Routing a Balance

Req-Resp

An der aktueller Messagerie Implementatioun ginn et 7 Ufro Verdeelungsstrategien:

  • default. D'Ufro gëtt un all Controller geschéckt.
  • round-robin. Ufroe ginn opgezielt a zyklesch tëscht Controller verdeelt.
  • consensus. D'Controller, déi de Service servéieren, sinn a Leader a Sklaven opgedeelt. Ufroe ginn nëmmen un de Leader geschéckt.
  • consensus & round-robin. De Grupp huet e Leader, awer Ufroe ginn ënnert all Member verdeelt.
  • sticky. D'Hash Funktioun gëtt berechent an un engem spezifeschen Handler zougewisen. Spéider Ufroe mat dëser Ënnerschrëft ginn un dee selwechte Handler.
  • sticky-fun. Beim Initialiséiere vum Austauschpunkt gëtt d'Hash Berechnungsfunktioun fir sticky ausgeglach.
  • fun. Ähnlech wéi Sticky-Spaass, nëmmen Dir kënnt et zousätzlech viruleeden, refuséieren oder virveraarbechten.

D'Verdeelungsstrategie gëtt festgeluecht wann den Austauschpunkt initialiséiert gëtt.

Zousätzlech zum Balance, erlaabt Messagerie Iech Entitéiten ze taggen. Loosst eis d'Zorte vun Tags am System kucken:

  • Verbindung Tag. Erlaabt Iech ze verstoen duerch wéi eng Verbindung d'Evenementer koumen. Benotzt wann e Controllerprozess mam selwechten Austauschpunkt verbënnt, awer mat verschiddene Routingschlësselen.
  • Service Tag. Erlaabt Iech Handler a Gruppen fir ee Service ze kombinéieren an d'Routing- a Balancefäegkeeten auszebauen. Fir de req-resp Muster ass Routing linear. Mir schécken eng Demande un den Austauschpunkt, da gëtt se un de Service weider. Awer wa mir d'Handler a logesch Gruppen opdeelen mussen, da gëtt d'Spaltung mat Tags gemaach. Wann Dir en Tag spezifizéiert, gëtt d'Ufro un eng spezifesch Grupp vu Controller geschéckt.
  • Ufro Tag. Erlaabt Iech tëscht Äntwerten z'ënnerscheeden. Well eise System asynchron ass, musse mir fäeg sinn e RequestTag ze spezifizéieren fir d'Servicereaktiounen ze veraarbecht wann Dir eng Ufro schéckt. Vun et wäerte mir fäeg sinn d'Äntwert ze verstoen op déi Ufro bei eis koum.

Pub-Sub

Fir Pub-Sub ass alles e bësse méi einfach. Mir hunn en Austauschpunkt op deen Messagen publizéiert ginn. Den Austauschpunkt verdeelt Messagen tëscht Abonnenten, déi sech op d'Routing-Schlësselen abonnéiert hunn, déi se brauchen (mir kënne soen datt dëst analog zu Themen ass).

Skalierbarkeet a Feelertoleranz

D'Skalierbarkeet vum System als Ganzt hänkt vum Grad vun der Skalierbarkeet vun de Schichten a Komponente vum System of:

  • D'Servicer ginn skaléiert andeems zousätzlech Noden an de Stärekoup mat Handlere fir dëse Service bäigefüügt ginn. Während Prozess Operatioun, kënnt Dir déi optimal Equiliber Politik wielen.
  • De Messagerie Service selwer an engem getrennten Cluster gëtt allgemeng skaléiert entweder duerch d'Bewegung vu besonnesch geluedenen Austauschpunkten op getrennte Clusternoden, oder andeems Proxy-Prozesser zu besonnesch gelueden Gebidder vum Cluster bäigefüügt ginn.
  • D'Skalierbarkeet vum ganze System als Charakteristik hänkt vun der Flexibilitéit vun der Architektur an der Fäegkeet fir eenzel Cluster an eng gemeinsam logesch Entitéit ze kombinéieren.

Den Erfolleg vun engem Projet hänkt dacks vun der Einfachheet an der Geschwindegkeet vun der Skaléierung of. Messagerie a senger aktueller Versioun wiisst zesumme mat der Applikatioun. Och wa mir e Stärekoup vu 50-60 Maschinnen feelen, kënne mir op Federatioun zréckgräifen. Leider ass d'Thema vun der Federatioun iwwer den Ëmfang vun dësem Artikel.

Reservatioun

Wann Dir Laaschtbalancéierung analyséiert, hu mir scho Redundanz vu Servicecontroller diskutéiert. Allerdéngs muss Messagerie och reservéiert ginn. Am Fall vun engem Node oder Maschinn Crash, Messagerie soll automatesch recuperéieren, an der kuerzer Zäit.

A menge Projete benotzen ech zousätzlech Noden, déi d'Laascht am Fall vun engem Fall ophuelen. Erlang huet eng Standard verdeelt Modus Implementatioun fir OTP Uwendungen. Verdeelt Modus mécht Erhuelung am Fall vun Echec duerch d'Start vun der gescheitert Applikatioun op engem aneren virdrun lancéiert Node. De Prozess ass transparent; No engem Feeler geet d'Applikatioun automatesch op de Failover Node. Dir kënnt méi iwwer dës Funktionalitéit liesen hei.

Produktivitéit

Loosst eis probéieren op d'mannst d'Performance vun rabbitmq an eise personaliséierte Messagerie ze vergläichen.
ech hu fonnt offiziell Resultater rabbitmq Testen vum Openstack Team.

Am Paragraph 6.14.1.2.1.2.2. D'Original Dokument weist d'Resultat vun der RPC CAST:
Bausteng vun verdeelt Uwendungen. Zweet Approximatioun

Mir wäerte keng zousätzlech Astellunge fir den OS Kernel oder erlang VM am Viraus maachen. Konditioune fir Testen:

  • erl opts: +A1 +sbtu.
  • Den Test an engem eenzegen Erlang Node gëtt op engem Laptop mat engem alen i7 an der mobiler Versioun lafen.
  • Cluster Tester ginn op Servere mat engem 10G Netz duerchgefouert.
  • De Code leeft an Docker Container. Netz am NAT Modus.

Test Code:

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.

Szenario 1: Den Test gëtt op engem Laptop mat enger aler i7 mobiler Versioun ausgeführt. Den Test, Messagerie a Service ginn op engem Node an engem Docker Container ausgefouert:

Sequential 10000 cycles in ~0 seconds (26987 cycles/s)
Sequential 20000 cycles in ~1 seconds (26915 cycles/s)
Sequential 100000 cycles in ~4 seconds (26957 cycles/s)
Parallel 2 100000 cycles in ~2 seconds (44240 cycles/s)
Parallel 4 100000 cycles in ~2 seconds (53459 cycles/s)
Parallel 10 100000 cycles in ~2 seconds (52283 cycles/s)
Parallel 100 100000 cycles in ~3 seconds (49317 cycles/s)

Szenario 2: 3 Wirbelen Lafen op verschiddene Maschinnen ënner Docker (NAT).

Sequential 10000 cycles in ~1 seconds (8684 cycles/s)
Sequential 20000 cycles in ~2 seconds (8424 cycles/s)
Sequential 100000 cycles in ~12 seconds (8655 cycles/s)
Parallel 2 100000 cycles in ~7 seconds (15160 cycles/s)
Parallel 4 100000 cycles in ~5 seconds (19133 cycles/s)
Parallel 10 100000 cycles in ~4 seconds (24399 cycles/s)
Parallel 100 100000 cycles in ~3 seconds (34517 cycles/s)

An alle Fäll ass d'CPU Notzung net méi wéi 250%

Resultater

Ech hoffen, datt dësen Zyklus net ausgesäit wéi e Geescht Dump an meng Erfahrung wäert wierklech profitéieren fir Fuerscher vu verdeelte Systemer an Praktiker, déi am Ufank sinn fir verdeelt Architekturen fir hir Geschäftssystemer ze bauen an Erlang / Elixir mat Interesse kucken , mee Zweifel ass et wäert ...

Foto @chuttersnap

Nëmme registréiert Benotzer kënnen un der Ëmfro deelhuelen. Umellen, wann ech glift.

Wéi eng Themen soll ech méi am Detail als Deel vun der VTrade Experiment Serie ofdecken?

  • Theorie: Mäert, Bestellungen an hir Timing: DAY, GTD, GTC, IOC, FOK, MOO, MOC, LOO, LOC

  • Buch vun Commanden. Theorie a Praxis fir e Buch mat Gruppéierungen ëmzesetzen

  • Visualiséierung vum Handel: Ticks, Baren, Resolutiounen. Wéi späicheren a wéi gekollt

  • Backoffice. Planung an Entwécklung. Employé Iwwerwachung an Tëschefall Enquête

  • API. Loosst eis erausfannen wéi eng Interfaces gebraucht ginn a wéi se se ëmsetzen

  • Informatiounsspeicher: PostgreSQL, Timescale, Tarantool an Handelssystemer

  • Reaktivitéit an Handelssystemer

  • Aner. Ech schreiwen an de Kommentaren

6 Benotzer hunn gestëmmt. 4 Benotzer hu sech enthalen.

Source: will.com

Setzt e Commentaire