Maginhawang mga pattern ng arkitektura

Hoy Habr!

Dahil sa kasalukuyang mga kaganapan dahil sa coronavirus, ilang mga serbisyo sa Internet ang nagsimulang tumanggap ng mas mataas na load. Halimbawa, Ang isa sa mga retail chain ng UK ay huminto lamang sa online na site ng pag-order nito., dahil walang sapat na kapasidad. At hindi laging posible na pabilisin ang isang server sa pamamagitan lamang ng pagdaragdag ng mas malakas na kagamitan, ngunit ang mga kahilingan ng kliyente ay dapat iproseso (o mapupunta sila sa mga kakumpitensya).

Sa artikulong ito, tatalakayin ko nang maikli ang tungkol sa mga sikat na gawi na magbibigay-daan sa iyo na lumikha ng isang mabilis at fault-tolerant na serbisyo. Gayunpaman, mula sa posibleng mga scheme ng pag-unlad, pinili ko lamang ang mga kasalukuyang madaling gamitin. Para sa bawat item, mayroon kang mga handa na aklatan, o mayroon kang pagkakataong lutasin ang problema gamit ang isang cloud platform.

Pahalang na pag-scale

Ang pinakasimple at pinakakilalang punto. Karaniwan, ang pinakakaraniwang dalawang scheme ng pamamahagi ng pagkarga ay pahalang at patayong scaling. Sa unang kaso pinapayagan mo ang mga serbisyo na tumakbo nang magkatulad, sa gayon ay namamahagi ng load sa pagitan ng mga ito. Sa pangalawa mag-order ka ng mas makapangyarihang mga server o i-optimize ang code.

Halimbawa, kukuha ako ng abstract cloud file storage, iyon ay, ilang analogue ng OwnCloud, OneDrive, at iba pa.

Ang isang karaniwang larawan ng naturang circuit ay nasa ibaba, ngunit ipinapakita lamang nito ang pagiging kumplikado ng system. Pagkatapos ng lahat, kailangan nating i-synchronize ang mga serbisyo kahit papaano. Ano ang mangyayari kung mag-save ang user ng file mula sa tablet at pagkatapos ay gusto itong tingnan mula sa telepono?

Maginhawang mga pattern ng arkitektura
Ang pagkakaiba sa pagitan ng mga diskarte: sa vertical scaling, handa kaming dagdagan ang kapangyarihan ng mga node, at sa horizontal scaling, handa kaming magdagdag ng mga bagong node upang ipamahagi ang load.

CQRS

Paghihiwalay ng Responsibilidad ng Command Query Isang medyo mahalagang pattern, dahil pinapayagan nito ang iba't ibang mga kliyente na hindi lamang kumonekta sa iba't ibang mga serbisyo, ngunit upang makatanggap din ng parehong mga stream ng kaganapan. Ang mga benepisyo nito ay hindi masyadong halata para sa isang simpleng aplikasyon, ngunit ito ay lubhang mahalaga (at simple) para sa isang abalang serbisyo. Ang kakanyahan nito: ang mga papasok at papalabas na daloy ng data ay hindi dapat magsalubong. Ibig sabihin, hindi ka makakapagpadala ng kahilingan at makakaasa ng tugon; sa halip, magpadala ka ng kahilingan sa serbisyo A, ngunit makatanggap ng tugon mula sa serbisyo B.

Ang unang bonus ng diskarteng ito ay ang kakayahang masira ang koneksyon (sa malawak na kahulugan ng salita) habang nagsasagawa ng mahabang kahilingan. Halimbawa, kumuha tayo ng higit pa o mas kaunting karaniwang pagkakasunud-sunod:

  1. Nagpadala ang kliyente ng kahilingan sa server.
  2. Nagsimula ang server ng mahabang oras ng pagproseso.
  3. Tumugon ang server sa kliyente kasama ang resulta.

Isipin natin na sa punto 2 ang koneksyon ay nasira (o ang network ay muling kumonekta, o ang gumagamit ay pumunta sa isa pang pahina, sinira ang koneksyon). Sa kasong ito, magiging mahirap para sa server na magpadala ng tugon sa user na may impormasyon tungkol sa kung ano ang eksaktong naproseso. Gamit ang CQRS, ang pagkakasunud-sunod ay bahagyang naiiba:

  1. Nag-subscribe ang kliyente sa mga update.
  2. Nagpadala ang kliyente ng kahilingan sa server.
  3. Tumugon ang server ng "tinanggap ang kahilingan."
  4. Tumugon ang server kasama ang resulta sa pamamagitan ng channel mula sa puntong "1".

Maginhawang mga pattern ng arkitektura

Tulad ng nakikita mo, ang pamamaraan ay medyo mas kumplikado. Bukod dito, nawawala dito ang intuitive na diskarte sa paghiling-tugon. Gayunpaman, tulad ng nakikita mo, ang isang break na koneksyon habang pinoproseso ang isang kahilingan ay hindi hahantong sa isang error. Bukod dito, kung sa katunayan ang user ay nakakonekta sa serbisyo mula sa ilang device (halimbawa, mula sa isang mobile phone at mula sa isang tablet), maaari mong tiyakin na ang tugon ay darating sa parehong mga device.

Kapansin-pansin, ang code para sa pagproseso ng mga papasok na mensahe ay nagiging pareho (hindi 100%) para sa mga kaganapan na naimpluwensyahan mismo ng kliyente, at para sa iba pang mga kaganapan, kabilang ang mga mula sa iba pang mga kliyente.

Gayunpaman, sa katotohanan ay nakakakuha kami ng karagdagang bonus dahil sa katotohanan na ang unidirectional flow ay maaaring pangasiwaan sa isang functional na istilo (gamit ang RX at katulad). At ito ay isang seryosong plus, dahil sa esensya ang application ay maaaring gawing ganap na reaktibo, at gumagamit din ng isang functional na diskarte. Para sa mga matabang programa, makakatipid ito nang malaki sa pag-unlad at mga mapagkukunan ng suporta.

Kung pagsasamahin namin ang diskarteng ito sa pahalang na pag-scale, bilang isang bonus, makakakuha kami ng kakayahang magpadala ng mga kahilingan sa isang server at makatanggap ng mga tugon mula sa isa pa. Kaya, ang kliyente ay maaaring pumili ng serbisyo na maginhawa para sa kanya, at ang system sa loob ay magagawa pa ring magproseso ng mga kaganapan nang tama.

Pagkuha ng Kaganapan

Tulad ng alam mo, ang isa sa mga pangunahing tampok ng isang distributed system ay ang kawalan ng isang karaniwang oras, isang karaniwang kritikal na seksyon. Para sa isang proseso, maaari kang gumawa ng isang pag-synchronize (sa parehong mga mutex), kung saan sigurado ka na walang ibang nagpapatupad ng code na ito. Gayunpaman, ito ay mapanganib para sa isang distributed system, dahil mangangailangan ito ng overhead, at papatayin din ang lahat ng kagandahan ng scaling - ang lahat ng mga bahagi ay maghihintay pa rin para sa isa.

Mula dito nakakakuha kami ng isang mahalagang katotohanan - isang mabilis na ipinamamahagi na sistema ay hindi maaaring i-synchronize, dahil pagkatapos ay babawasan namin ang pagganap. Sa kabilang banda, madalas nating kailangan ang isang tiyak na pagkakapare-pareho sa pagitan ng mga bahagi. At para dito maaari mong gamitin ang diskarte sa tuluyang pagkakapare-pareho, kung saan ginagarantiyahan na kung walang pagbabago sa data sa loob ng ilang yugto ng panahon pagkatapos ng huling pag-update ("sa huli"), ibabalik ng lahat ng query ang huling na-update na halaga.

Mahalagang maunawaan na para sa mga klasikong database ay madalas itong ginagamit malakas na pagkakapare-pareho, kung saan ang bawat node ay may parehong impormasyon (ito ay madalas na nakakamit sa kaso kung saan ang transaksyon ay itinuturing na itinatag lamang pagkatapos tumugon ang pangalawang server). Mayroong ilang mga relaxation dito dahil sa mga antas ng paghihiwalay, ngunit ang pangkalahatang ideya ay nananatiling pareho - maaari kang mabuhay sa isang ganap na harmonized na mundo.

Gayunpaman, bumalik tayo sa orihinal na gawain. Kung ang bahagi ng sistema ay maaaring itayo gamit ang tuluyang pagkakapare-pareho, pagkatapos ay maaari nating buuin ang sumusunod na diagram.

Maginhawang mga pattern ng arkitektura

Mga mahahalagang tampok ng diskarteng ito:

  • Ang bawat papasok na kahilingan ay inilalagay sa isang pila.
  • Habang pinoproseso ang isang kahilingan, ang serbisyo ay maaari ring maglagay ng mga gawain sa iba pang mga pila.
  • Ang bawat papasok na kaganapan ay may isang identifier (na kinakailangan para sa deduplication).
  • Ang pila ay gumagana nang ideolohikal ayon sa scheme na "idagdag lamang". Hindi mo maaaring alisin ang mga elemento mula dito o muling ayusin ang mga ito.
  • Ang pila ay gumagana ayon sa FIFO scheme (paumanhin para sa tautolohiya). Kung kailangan mong gumawa ng parallel execution, pagkatapos ay sa isang yugto dapat mong ilipat ang mga bagay sa iba't ibang mga pila.

Ipaalala ko sa iyo na isinasaalang-alang namin ang kaso ng online na pag-iimbak ng file. Sa kasong ito, magiging ganito ang hitsura ng system:

Maginhawang mga pattern ng arkitektura

Mahalaga na ang mga serbisyo sa diagram ay hindi nangangahulugang isang hiwalay na server. Kahit na ang proseso ay maaaring pareho. Ang isa pang bagay ay mahalaga: sa ideolohikal, ang mga bagay na ito ay pinaghihiwalay sa paraang madaling mailapat ang horizontal scaling.

At para sa dalawang user ang diagram ay magiging ganito (ang mga serbisyong inilaan para sa iba't ibang mga user ay ipinahiwatig sa iba't ibang kulay):

Maginhawang mga pattern ng arkitektura

Mga bonus mula sa naturang kumbinasyon:

  • Ang mga serbisyo sa pagproseso ng impormasyon ay pinaghihiwalay. Hiwalay din ang mga pila. Kung kailangan nating dagdagan ang throughput ng system, kailangan lang nating maglunsad ng higit pang mga serbisyo sa mas maraming server.
  • Kapag nakatanggap kami ng impormasyon mula sa isang user, hindi namin kailangang maghintay hanggang sa ganap na mai-save ang data. Sa kabaligtaran, kailangan lang nating sagutin ang "ok" at pagkatapos ay unti-unting magsimulang magtrabaho. Kasabay nito, ang pila ay nagpapakinis ng mga taluktok, dahil ang pagdaragdag ng isang bagong bagay ay nangyayari nang mabilis, at ang gumagamit ay hindi kailangang maghintay para sa isang kumpletong pagpasa sa buong ikot.
  • Bilang halimbawa, nagdagdag ako ng serbisyo ng deduplication na sumusubok na pagsamahin ang magkaparehong mga file. Kung ito ay gumagana nang mahabang panahon sa 1% ng mga kaso, halos hindi ito mapapansin ng kliyente (tingnan sa itaas), na isang malaking plus, dahil hindi na kami kinakailangan na maging XNUMX% na bilis at maaasahan.

Gayunpaman, ang mga kawalan ay agad na nakikita:

  • Nawala ang mahigpit na pagkakapare-pareho ng aming system. Nangangahulugan ito na kung, halimbawa, nag-subscribe ka sa iba't ibang mga serbisyo, sa teoryang maaari kang makakuha ng ibang estado (dahil ang isa sa mga serbisyo ay maaaring walang oras upang makatanggap ng isang abiso mula sa panloob na pila). Bilang isa pang kahihinatnan, ang sistema ngayon ay walang karaniwang oras. Iyon ay, imposible, halimbawa, na pag-uri-uriin ang lahat ng mga kaganapan sa pamamagitan lamang ng oras ng pagdating, dahil ang mga orasan sa pagitan ng mga server ay maaaring hindi magkasabay (at saka, ang parehong oras sa dalawang server ay isang utopia).
  • Walang mga kaganapan na maaari na ngayong i-roll back (tulad ng maaaring gawin sa isang database). Sa halip, kailangan mong magdagdag ng bagong kaganapan βˆ’ kaganapan sa kabayaran, na magpapabago sa huling estado sa kinakailangan. Bilang isang halimbawa mula sa isang katulad na lugar: nang walang muling pagsusulat ng kasaysayan (na masama sa ilang mga kaso), hindi mo maibabalik ang isang commit sa git, ngunit maaari kang gumawa ng isang espesyal na rollback commit, na mahalagang ibinabalik lamang ang lumang estado. Gayunpaman, pareho ang maling commit at ang rollback ay mananatili sa kasaysayan.
  • Maaaring magbago ang schema ng data mula sa release hanggang release, ngunit hindi na maa-update ang mga lumang event sa bagong standard (dahil hindi mababago ang mga event sa prinsipyo).

Gaya ng nakikita mo, gumagana nang maayos ang Event Sourcing sa CQRS. Bukod dito, ang pagpapatupad ng isang sistema na may mahusay at maginhawang mga pila, ngunit nang hindi naghihiwalay sa mga daloy ng data, ay mahirap na sa sarili nito, dahil kakailanganin mong magdagdag ng mga punto ng pag-synchronise na mag-neutralize sa buong positibong epekto ng mga pila. Ang paglalapat ng parehong mga diskarte nang sabay-sabay, kinakailangan upang bahagyang ayusin ang code ng programa. Sa aming kaso, kapag nagpapadala ng isang file sa server, ang tugon ay darating lamang "ok", na nangangahulugan lamang na "ang pagpapatakbo ng pagdaragdag ng file ay na-save." Sa pormal, hindi ito nangangahulugan na ang data ay magagamit na sa iba pang mga device (halimbawa, ang deduplication service ay maaaring muling buuin ang index). Gayunpaman, pagkaraan ng ilang oras, makakatanggap ang kliyente ng isang abiso sa istilong "nai-save na ang file X."

Ang resulta:

  • Ang bilang ng mga katayuan sa pagpapadala ng file ay tumataas: sa halip na ang klasikong "file na ipinadala," makakakuha tayo ng dalawa: "ang file ay naidagdag sa queue sa server" at "ang file ay nai-save sa storage." Ang huli ay nangangahulugan na ang iba pang mga aparato ay maaari nang magsimulang tumanggap ng file (naayos para sa katotohanan na ang mga pila ay gumagana sa iba't ibang bilis).
  • Dahil sa katotohanan na ang impormasyon sa pagsusumite ay dumarating na ngayon sa iba't ibang mga channel, kailangan naming makabuo ng mga solusyon upang matanggap ang katayuan ng pagproseso ng file. Bilang kinahinatnan nito: hindi tulad ng klasikong kahilingan-tugon, ang kliyente ay maaaring i-restart habang pinoproseso ang file, ngunit ang katayuan ng pagpoprosesong ito mismo ay magiging tama. Bukod dito, gumagana ang item na ito, mahalagang, sa labas ng kahon. Bilang resulta: mas mapagparaya na tayo sa mga kabiguan.

Sharding

Gaya ng inilarawan sa itaas, ang mga sistema ng pag-sourcing ng kaganapan ay walang mahigpit na pagkakapare-pareho. Nangangahulugan ito na maaari kaming gumamit ng ilang mga imbakan nang walang anumang pag-synchronize sa pagitan ng mga ito. Paglapit sa ating problema, maaari nating:

  • Paghiwalayin ang mga file ayon sa uri. Halimbawa, maaaring i-decode ang mga larawan/video at maaaring pumili ng mas mahusay na format.
  • Paghiwalayin ang mga account ayon sa bansa. Dahil sa maraming batas, maaaring kailanganin ito, ngunit awtomatikong nagbibigay ng ganitong pagkakataon ang scheme ng arkitektura na ito

Maginhawang mga pattern ng arkitektura

Kung gusto mong maglipat ng data mula sa isang storage patungo sa isa pa, hindi na sapat ang mga karaniwang paraan. Sa kasamaang palad, sa kasong ito, kailangan mong ihinto ang pila, gawin ang paglipat, at pagkatapos ay simulan ito. Sa pangkalahatang kaso, ang data ay hindi maaaring ilipat "on the fly", gayunpaman, kung ang queue ng kaganapan ay ganap na nakaimbak, at mayroon kang mga snapshot ng mga nakaraang estado ng storage, maaari naming i-replay ang mga kaganapan tulad ng sumusunod:

  • Sa Pinagmulan ng Kaganapan, ang bawat kaganapan ay may sariling identifier (sa isip, hindi bumababa). Nangangahulugan ito na maaari tayong magdagdag ng field sa storage - ang id ng huling naprosesong elemento.
  • Doblehin namin ang queue upang ang lahat ng mga kaganapan ay maproseso para sa ilang mga independiyenteng imbakan (ang una ay ang isa kung saan ang data ay nakaimbak na, at ang pangalawa ay bago, ngunit wala pa ring laman). Ang pangalawang pila, siyempre, ay hindi pa pinoproseso.
  • Inilunsad namin ang pangalawang pila (iyon ay, sinimulan naming i-replay ang mga kaganapan).
  • Kapag medyo walang laman ang bagong queue (iyon ay, ang average na pagkakaiba ng oras sa pagitan ng pagdaragdag ng isang elemento at pagkuha nito ay katanggap-tanggap), maaari mong simulan ang paglipat ng mga mambabasa sa bagong storage.

Gaya ng nakikita mo, wala kami, at wala pa rin, mahigpit na pagkakapare-pareho sa aming system. Nagkakaroon lamang ng pagpapatuloy, iyon ay, isang garantiya na ang mga kaganapan ay naproseso sa parehong pagkakasunud-sunod (ngunit posibleng may iba't ibang mga pagkaantala). At, gamit ito, medyo madali nating mailipat ang data nang hindi humihinto sa system sa kabilang panig ng mundo.

Kaya, ang pagpapatuloy ng aming halimbawa tungkol sa online na imbakan para sa mga file, ang ganitong arkitektura ay nagbibigay na sa amin ng ilang mga bonus:

  • Maaari naming ilipat ang mga bagay na mas malapit sa mga user sa isang dynamic na paraan. Sa ganitong paraan mapapabuti mo ang kalidad ng serbisyo.
  • Maaari kaming mag-imbak ng ilang data sa loob ng mga kumpanya. Halimbawa, ang mga user ng Enterprise ay madalas na nangangailangan ng kanilang data na maiimbak sa mga kinokontrol na data center (upang maiwasan ang mga pagtagas ng data). Sa pamamagitan ng sharding madali nating masusuportahan ito. At ang gawain ay mas madali kung ang customer ay may katugmang ulap (halimbawa, Self-host si Azure).
  • At ang pinakamahalagang bagay ay hindi natin kailangang gawin ito. Pagkatapos ng lahat, sa simula, magiging masaya kami sa isang storage para sa lahat ng mga account (upang makapagsimulang magtrabaho nang mabilis). At ang pangunahing tampok ng sistemang ito ay kahit na ito ay napapalawak, sa paunang yugto ito ay medyo simple. Hindi mo lang kailangang agad na magsulat ng code na gumagana sa isang milyong magkakahiwalay na mga independiyenteng pila, atbp. Kung kinakailangan, maaari itong gawin sa hinaharap.

Static Content Hosting

Ang puntong ito ay maaaring mukhang medyo halata, ngunit ito ay kinakailangan pa rin para sa isang mas marami o mas kaunting karaniwang na-load na aplikasyon. Ang kakanyahan nito ay simple: ang lahat ng static na nilalaman ay ibinahagi hindi mula sa parehong server kung saan matatagpuan ang application, ngunit mula sa mga espesyal na partikular na nakatuon sa gawaing ito. Bilang resulta, ang mga operasyong ito ay ginagawa nang mas mabilis (ang kondisyon nginx ay naghahatid ng mga file nang mas mabilis at mas mura kaysa sa isang Java server). Dagdag na arkitektura ng CDN (Nilalaman Delivery Network) ay nagbibigay-daan sa amin na mahanap ang aming mga file nang mas malapit sa mga end user, na may positibong epekto sa kaginhawaan ng pagtatrabaho sa serbisyo.

Ang pinakasimple at pinakakaraniwang halimbawa ng static na nilalaman ay isang hanay ng mga script at larawan para sa isang website. Ang lahat ay simple sa kanila - kilala sila nang maaga, pagkatapos ay na-upload ang archive sa mga server ng CDN, mula sa kung saan ibinahagi ang mga ito sa mga end user.

Gayunpaman, sa katotohanan, para sa static na nilalaman, maaari kang gumamit ng diskarte na medyo katulad ng arkitektura ng lambda. Bumalik tayo sa ating gawain (online file storage), kung saan kailangan nating ipamahagi ang mga file sa mga user. Ang pinakasimpleng solusyon ay ang lumikha ng isang serbisyo na, para sa bawat kahilingan ng user, ginagawa ang lahat ng kinakailangang pagsusuri (awtorisasyon, atbp.), at pagkatapos ay direktang i-download ang file mula sa aming storage. Ang pangunahing kawalan ng diskarteng ito ay ang static na content (at ang file na may partikular na rebisyon, sa katunayan, static na content) ay ipinamamahagi ng parehong server na naglalaman ng business logic. Sa halip, maaari mong gawin ang sumusunod na diagram:

  • Nagbibigay ang server ng URL ng pag-download. Maaari itong nasa anyo na file_id + key, kung saan ang key ay isang mini-digital na lagda na nagbibigay ng karapatang i-access ang mapagkukunan sa susunod na 24 na oras.
  • Ang file ay ipinamamahagi sa pamamagitan ng simpleng nginx na may mga sumusunod na opsyon:
    • Pag-cache ng nilalaman. Dahil ang serbisyong ito ay matatagpuan sa isang hiwalay na server, iniwan namin ang aming sarili ng isang reserba para sa hinaharap na may kakayahang mag-imbak ng lahat ng pinakabagong na-download na mga file sa disk.
    • Sinusuri ang susi sa oras ng paggawa ng koneksyon
  • Opsyonal: pagpoproseso ng nilalaman ng streaming. Halimbawa, kung i-compress namin ang lahat ng mga file sa serbisyo, maaari naming gawin ang pag-unzipping nang direkta sa module na ito. Bilang resulta: Ang mga operasyon ng IO ay ginagawa kung saan sila nabibilang. Ang isang archiver sa Java ay madaling maglalaan ng maraming dagdag na memorya, ngunit ang muling pagsulat ng isang serbisyo na may lohika ng negosyo sa mga kondisyong Rust/C++ ay maaari ding hindi epektibo. Sa aming kaso, iba't ibang mga proseso (o kahit na mga serbisyo) ang ginagamit, at samakatuwid ay maaari naming lubos na epektibong paghiwalayin ang lohika ng negosyo at mga operasyon ng IO.

Maginhawang mga pattern ng arkitektura

Ang scheme na ito ay hindi masyadong katulad ng pamamahagi ng static na nilalaman (dahil hindi namin ina-upload ang buong static na package sa isang lugar), ngunit sa katotohanan, ang diskarteng ito ay tiyak na nababahala sa pamamahagi ng hindi nababagong data. Bukod dito, ang scheme na ito ay maaaring gawing pangkalahatan sa iba pang mga kaso kung saan ang nilalaman ay hindi lamang static, ngunit maaaring kinakatawan bilang isang hanay ng mga hindi mababago at hindi matatanggal na mga bloke (bagaman maaari silang idagdag).

Bilang isa pang halimbawa (para sa reinforcement): kung nagtrabaho ka sa Jenkins/TeamCity, alam mo na ang parehong mga solusyon ay nakasulat sa Java. Pareho sa mga ito ay isang proseso ng Java na humahawak sa parehong pagbuo ng orkestra at pamamahala ng nilalaman. Sa partikular, pareho silang may mga gawain tulad ng "maglipat ng file/folder mula sa server." Bilang isang halimbawa: pag-isyu ng mga artifact, paglilipat ng source code (kapag hindi na-download ng ahente ang code nang direkta mula sa repository, ngunit ginagawa ito ng server para sa kanya), pag-access sa mga log. Ang lahat ng mga gawaing ito ay naiiba sa kanilang IO load. Iyon ay, lumalabas na ang server na responsable para sa kumplikadong lohika ng negosyo ay dapat sa parehong oras ay maaaring epektibong itulak ang malalaking daloy ng data sa pamamagitan ng sarili nito. At ang pinaka-kawili-wili ay ang naturang operasyon ay maaaring italaga sa parehong nginx ayon sa eksaktong parehong pamamaraan (maliban na ang data key ay dapat idagdag sa kahilingan).

Gayunpaman, kung babalik kami sa aming system, makakakuha kami ng katulad na diagram:

Maginhawang mga pattern ng arkitektura

Tulad ng nakikita mo, ang sistema ay naging radikal na mas kumplikado. Ngayon ito ay hindi lamang isang mini-proseso na nag-iimbak ng mga file nang lokal. Ngayon ang kailangan ay hindi ang pinakasimpleng suporta, kontrol sa bersyon ng API, atbp. Samakatuwid, pagkatapos maiguhit ang lahat ng mga diagram, pinakamahusay na suriin nang detalyado kung ang pagpapalawak ay katumbas ng halaga. Gayunpaman, kung gusto mong mapalawak ang system (kabilang ang pagtatrabaho sa mas malaking bilang ng mga user), kakailanganin mong pumunta para sa mga katulad na solusyon. Ngunit, bilang isang resulta, ang sistema ay handa sa arkitektura para sa mas mataas na pagkarga (halos bawat bahagi ay maaaring i-clone para sa pahalang na pag-scale). Maaaring i-update ang system nang hindi ito pinipigilan (sa ilang mga operasyon ay bahagyang babagal).

Tulad ng sinabi ko sa pinakadulo simula, ngayon ang isang bilang ng mga serbisyo sa Internet ay nagsimulang tumanggap ng mas mataas na load. At ang ilan sa kanila ay nagsimulang tumigil sa pagtatrabaho nang tama. Sa katunayan, ang mga sistema ay nabigo nang eksakto sa sandaling ang negosyo ay dapat na kumita ng pera. Ibig sabihin, sa halip na ipagpaliban ang paghahatid, sa halip na imungkahi sa mga customer na "planohin ang iyong paghahatid para sa mga darating na buwan," sinabi lang ng system na "pumunta sa iyong mga kakumpitensya." Sa katunayan, ito ang presyo ng mababang produktibidad: tiyak na magaganap ang mga pagkalugi kapag pinakamataas ang kita.

Konklusyon

Ang lahat ng mga pamamaraang ito ay kilala noon. Ang parehong VK ay matagal nang gumagamit ng ideya ng Static Content Hosting upang magpakita ng mga larawan. Maraming online na laro ang gumagamit ng Sharding scheme upang hatiin ang mga manlalaro sa mga rehiyon o upang paghiwalayin ang mga lokasyon ng laro (kung ang mundo mismo ay iisa). Ang diskarte sa Pag-source ng Kaganapan ay aktibong ginagamit sa email. Karamihan sa mga application ng kalakalan kung saan ang data ay patuloy na natatanggap ay aktwal na binuo sa isang CQRS na diskarte upang ma-filter ang data na natanggap. Well, ang pahalang na pag-scale ay ginamit sa maraming serbisyo sa loob ng mahabang panahon.

Gayunpaman, ang pinakamahalaga, ang lahat ng mga pattern na ito ay naging napakadaling ilapat sa mga modernong aplikasyon (kung naaangkop sila, siyempre). Nag-aalok ang Clouds ng Sharding at horizontal scaling kaagad, na mas madali kaysa sa pag-order ng iba't ibang dedikadong server sa iba't ibang data center. Ang CQRS ay naging mas madali, kung dahil lamang sa pagbuo ng mga aklatan tulad ng RX. Mga 10 taon na ang nakalipas, maaaring suportahan ito ng isang bihirang website. Ang Event Sourcing ay napakadaling i-set up salamat sa mga nakahandang container na may Apache Kafka. 10 taon na ang nakalipas ito ay isang makabagong ideya, ngayon ito ay karaniwan. Ito ay pareho sa Static Content Hosting: dahil sa mas maginhawang mga teknolohiya (kabilang ang katotohanan na mayroong detalyadong dokumentasyon at isang malaking database ng mga sagot), ang diskarte na ito ay naging mas simple.

Bilang isang resulta, ang pagpapatupad ng isang bilang ng mga medyo kumplikadong mga pattern ng arkitektura ay naging mas simple, na nangangahulugang mas mahusay na tingnan ito nang mas maaga. Kung sa isang sampung taong gulang na aplikasyon ang isa sa mga solusyon sa itaas ay inabandona dahil sa mataas na halaga ng pagpapatupad at pagpapatakbo, ngayon, sa isang bagong aplikasyon, o pagkatapos ng refactoring, maaari kang lumikha ng isang serbisyo na magiging architecturally parehong extensible ( sa mga tuntunin ng pagganap) at handa na sa mga bagong kahilingan mula sa mga kliyente (halimbawa, upang i-localize ang personal na data).

At ang pinakamahalaga: mangyaring huwag gamitin ang mga pamamaraang ito kung mayroon kang isang simpleng aplikasyon. Oo, maganda at kawili-wili ang mga ito, ngunit para sa isang site na may pinakamataas na pagbisita ng 100 katao, madalas kang makakalampas sa isang klasikong monolith (kahit sa labas, lahat ng nasa loob ay maaaring hatiin sa mga module, atbp.).

Pinagmulan: www.habr.com

Magdagdag ng komento