Tomboy kinnita php. PHP andmete filtreerimine ja kinnitamine. Sagedased vead. Paralleel- ja jadaarvutus

Materjal on mõeldud peamiselt algajatele veebiprogrammeerijatele.

Sissejuhatus. Sageli pöörduvad minu poole kliendid, kes on installinud isekirjutatud CMS-i või algajate veebiprogrammeerijate kirjutatud mooduleid, kes ei saa aru, mida on vaja andmete kaitsmiseks ja sageli kopeerivad filtreerimisfunktsioone, mõtlemata, kuidas need töötavad ja mida nendega täpselt teha tuleb. .

Siin püüan võimalikult üksikasjalikult kirjeldada PHP-skriptis andmete filtreerimisel levinud vigu ja anda lihtsaid näpunäiteid andmete korrektseks filtreerimiseks.

Internetis on palju artikleid andmete filtreerimise kohta, kuid need pole täielikud ja ilma üksikasjalike näideteta.

Debriifing. Filtreerimine. Viga nr 1 Numbriliste muutujate puhul kasutatakse järgmist kontrolli:
$number = $_GET["sisend_number"]; if (intval($number)) ( ... käivita SQL-päring... )
Miks see viib SQL-i süstimiseni? Fakt on see, et kasutaja saab määrata väärtuse muutujas input_number:
1"+LIIT+VALI
Sellistel juhtudel sooritatakse kontroll edukalt, sest funktsioon intval saab muutuja täisarvu, s.t. 1, kuid muutujas $number endas pole midagi muutunud, nii et kogu pahatahtlik kood edastatakse SQL-päringule.
Õige filtreerimine:
$number = intval($_GET["sisend_number"]); if ($number) ( ... käivita SQL päring... )
Muidugi võib tingimus muutuda, näiteks kui teil on vaja saada ainult teatud vahemik:
if ($number >= 32 JA $number dir = PÕHIDIR . "/template/" . $config["nahk"];
Sel juhul saate asendada muutuja $_COOKIE["nahk"] väärtuse ja põhjustada tõrke, mille tulemusena näete saidi kausta absoluutset teed.
Kui kasutate andmebaasi salvestamiseks küpsise väärtust, kasutage mõnda ülalkirjeldatud filtreerimist, see kehtib ka muutuja $_SERVER kohta. Viga nr 5. Direktiiv register_globals on lubatud. Kui see on sisse lülitatud, lülitage see kindlasti välja.
Mõnes olukorras saate edastada muutuja väärtuse, mida poleks tohtinud edastada, näiteks kui saidil on rühmad, siis 2. rühma puhul peaks muutuja $group olema tühi või võrdne 0-ga, kuid piisab võltsimisest vormi lisades koodi:

PHP-skriptis on muutuja $group võrdne 5-ga, kui seda ei deklareeritud skriptis vaikeväärtusega. Viga nr 6. Kontrollige allalaaditud faile.
Kontrollige järgmisi punkte:
  • Faililaiend. Soovitav on keelata failide allalaadimine laiendiga: php, php3, php4, php5 jne.
  • Kas fail on serverisse üles laaditud move_uploaded_file
  • faili suurus
  • Läbivaatus. Viga nr 1. Kohtasin juhtumeid, kui AJAX-i päringuks (näiteks maine tõstmine) edastati kasutaja nimi või ID (kellele maine tõusis), kuid PHP-s endas sellise kasutaja olemasolu ei kontrollitud.
    Näiteks:
    $kasutaja_id = intval($_TAOTLUS["kasutaja_id"]); ... INSERT INTO REPLOG SET uid = "($kasutaja_id)", pluss = "1" ... ... UPDATE Kasutajad SET maine = maine+1 WHERE kasutaja_id = "($kasutaja_id)" ...
    Selgub, et loome andmebaasi kirje, mis on meile täiesti kasutu. Viga nr 2. Andmetega erinevat tüüpi toimingute tegemisel (lisamine, redigeerimine, kustutamine) ärge unustage kontrollida kasutaja õigusi sellele funktsioonile ja lisafunktsioonidele juurde pääseda (kasutades html-silte või võimalust avaldada materjali ilma kontrollimata).

    Parandasin ammu ühes foorumi moodulis sarnase vea, kui suvaline kasutaja sai administratsioonile saadetud teadet redigeerida.

    Läbivaatus. Viga nr 3. Kui kasutate mitut php-faili, tehke lihtne kontroll.
    Enne muude php-failide lisamist kirjutage faili index.php (või mis tahes muusse põhifaili) järgmine rida:
    define("READFILE", true);
    Teiste php-failide alguses kirjutage:
    if (! defineeritud ("READFILE")) ( exit ("Viga, vale faili viis.
    Mine põhile."); }
    Nii piirate juurdepääsu failidele. Viga nr 4. Kasutage kasutajate jaoks räsi. See aitab vältida selle või selle funktsiooni kutsumist XSS-i kaudu.
    Näide kasutajate jaoks räsi koostamise kohta:
    $salajane_võti = md5(strtolower("http://site.ru/" . $liige["nimi"] . sha1($parool) . date("Ymd"))); // $salajane_võti on meie räsi
    Järgmisena asendage kõigis olulistes vormides sisend kasutaja praeguse räsi väärtusega:

    Skripti käitamise ajal kontrollige:
    if ($_POST["salajane_võti"] !== $salajane_võti) ( exit ("Viga: salajane_võti!"); ) Kontrollige. Viga nr 5. SQL-i vigade väljastamisel seadke teabele juurdepääsule lihtne piirang. Näiteks määrake muutuja GET parool:
    if ($_GET["passsql"] == "parool") ( ... SQL-i veaväljund... ) else ( ... Lihtsalt teave vea kohta, üksikasjad puuduvad... )
    See võimaldab teil häkkeri eest peita teavet, mis võib aidata tal saiti häkkida. Viga nr 5. Proovige faile mitte kaasata, hankides failinimesid väljastpoolt.
    Näiteks:
    if (isset($_GET["faili_nimi"])) ( include $_GET["faili_nimi"] ..php"; )
    Kasutage lülitit

    Teen PHP-s ühe lihtsa nimekirja, kuhu kasutaja saab lisada nime, vanuse, meilid jne. Olen lisanud ka kustutamisvõimaluse, kuid soovin lisada kinnitusteate, kui kasutaja klõpsab kustutamisnupul.

    Proovisin Google'ist otsida, kuid leidsin ainult jQuery ja JavaScripti lahendusi. Kas seda saab teha ainult PHP-ga?

    Kustuta.php

    V

    Kui soovite seda teha ainult PHP-s, peate oma skriptile lisama "sammud", näiteks järgmiselt:

    Samm 1 (kuva vormi) -> samm 2 (küsi kinnitust) -> samm 3 (kinnita)

    Selleks saate vormi sisu salvestamiseks kasutada seansse ja selle sammu jälgimiseks parameetrit GET. Muidu on lihtsaim lahendus JavaScripti kasutamine:

    Kaja" x"; //kasutage js-i jaoks jutumärke php-s!

    See on see, mida sa vajad

    While($query2=mysql_fetch_array($query1)) ( echo " ".$query2["nimi"].""; kaja" ".$query2["vanus"].""; kaja" Muuda"; kaja" x"; ) in while($query2=mysql_fetch_array($query1)) ( echo " ".$query2["nimi"].""; kaja" ".$query2["vanus"].""; kaja" Muuda"; kaja" x"; }

    ja luua javascripti funktsioon

    Funktsiooni kinnitusDelete(ankur) ( var conf = confirm("Kas soovite kindlasti selle kirje kustutada?"); if(conf) window.location=anchor.attr("href"); )

    usu mind, see on töö :)

    Dialoogi avamiseks lisage onClicki sündmus ja javascript:return confirm("kas olete kindel, et soovite selle kustutada?");

    Kaja" x";

    function deletetconfig())( var del=confirm("Kas soovite kindlasti selle kirje kustutada?"); if (del==true)( alert ("kirje kustutatud") ) return del; ) //add onclick event onclick ="tagasta deletetconfig()"

    töötab minu jaoks, kuid muuda seda:

    Onclick="javascript:confirmationDelete($(this));return false;"

    Onclick="confirmationDelete(this);return false;"

    Allpool on ülaltoodu variatsioon, mis annab kinnitusvälja ja edastab muutuja PHP-st Javascripti ja tagasi PHP-sse.
    Kasutasin seda raadionupu valimiseks faili eemaldamiseks failide loendist.
    Vaadake Javascriptis OnClicki päästikufunktsiooni nimega php $fileName, kinnitage failinimega ja kui jah, siis minge väärtusele href koos muutujatega $_GET jaoks

    PHP/HTML kood:

    Artikkel ei puuduta klastreid, replikatsiooniga jagamist ega isegi pilvi. Artikkel käsitleb ülimalt töökindla arvutusarhitektuuri ülesehitamist, milles kasutajate arv ja nende taotlused võivad laviinina kasvada. Ja äri jaoks on kriitilise tähtsusega, et veebiteenus võtaks vastu iga päringu, töötleks seda õigesti ja lõpuni (olenemata mõne komponendi riketest ja tõrgetest) ning garanteeriks, et see edastaks kliendile vastuse. Ja muidugi ilma "astronoomiliste" seadmete ja süsteemiadministraatorite palkadeta.

    Teisisõnu mõelge kõigepealt küsimusele "kas mul on seda vaja?" Kui kellelgi on internetipood, kus müüakse rääkivaid hamstreid, mille käive on 100 tellimust kuus, siis ilmselt mitte. Ja kui plaanite juhtida ettevõtet, mis mahutab sadu tuhandeid ja miljoneid kasutajaid, nõuab palju arvutusi, töötab väga väärtuslike andmetega, tagab iga äriprotsessi tehingulisuse ja nõuab paralleelset andmetöötlust, siis see on see. .

    Finantssektor, suured veebipoed sadade tuhandete ühikute kaupa, veebioksjonid, hotelli- ja lennupiletite broneerimissüsteemid, uued pilved või sotsiaalteenused, mille eesmärk on saada miljondik kasutajabaas järgmisel päeval pärast reklaami algust. on potentsiaalselt huvitatud teie veebiteenuste väga töökindlast süsteemist.

    Kellele see materjal on suunatud?

    1. Suurte veebiprojektide arendajad, kes on huvitatud suure koormusega ja tõrketaluvate arvutusteenuste loomisest.

    2. Uute või laienevate ettevõtete omanikud, kes ootavad kasutajaskonna plahvatuslikku kasvu ja seavad andmetöötlusele kõrgeid nõudmisi.

    3. Tehnilised juhid ja suurte veebiprojektide juhid, kes ei ole hetkeseisuga rahul ja mõtlevad põhimõttelisele ümberkorraldusele.

    Miks räägitakse nii palju "arvutitest"?

    Kuna suurte veebiprojektide lähitulevik peitub just “Big data” valdkonnas – see on trend, mis veel 2011. aastal märgiti virtualiseerimise, energiasäästu ja monitooringu kõrval ühe tippu ning alates 2013. aastast on see kindlalt võttis oma koha tööstuses ja sai isegi üheks akadeemiliseks õppeaineks suuremates välismaa ülikoolides.

    Äriprobleemide lahendamiseks töödeldavate andmete maht kasvab täna pidevalt ja tulevikus see protsess vaid kiireneb. Kui kümme aastat tagasi piisas kasutajale tootega „online vitriinist” näitamisest, siis aasta tagasi piisas sellest, et analüüsida kasutaja teed läbi saidi ja näidata talle rangelt asjakohast toodet (nn. „käitumistehnoloogiad”). , kuid tänapäeval peetakse normiks teada kasutaja kohta kõike, sealhulgas pikkust, kaalu, vanust ja lemmikkoera nime.

    Loomuliku konkurentsi seadused nõuavad, et kui soovite pakkuda oma klientidele rohkem väärtust kui teie konkurendid, on teil vaja rohkem andmeid ja rohkem andmetöötlust. Ja varem või hiljem võib teie projekt ilma õigete lähenemisteta neisse uppuda – nii nagu praegu upuvad mitmesugused projektid kõikjal: mõni toe keerukuse tõttu, mõni lihtsalt halva koodi tõttu, mõni moodulite suure sidumise tõttu. , mõned ebausaldusväärsete komponentide kasutamise tõttu.

    Seetõttu saab igaüks, kes täna alustab suurte ambitsioonidega veebiprojekti, konkurentide ees rohkem eeliseid, kui ta käsitleb oma projekti esialgu mitte ainult programmikoodina, vaid ka arvutuskeskkonnana – süsteemina, millel on oma eksisteerimise ja arengu seadused. Mida rohkem tähelepanu pöörate andmetöötluse haldamine alguses, seda suurem on võimalus lähiaastatel konkurentidest mööduda.

    Nende ridade autor on veendunud, et “klassikalisel” kaasaegsel lähenemisel suure koormusega veebiteenuste ehitamisele on mitmeid tõsiseid puudujääke. Mõelgem välja, miks. Esiteks vaatame tüüpilist kaasaegset skeemi:

    Klassikaline lähenemine suure koormusega veebiteenuse loomisele

    1. Paljud serverid on jagatud rollideks.

    2. Osa serveritest (Frontend roll) on loodud teenindama staatilisi ressursse (pildid, CSS, JS-failid) ja "jaotama" sissetuleva liikluse esiosa madalama taseme sõlmede vahel. Peamine tarkvara on tavaliselt Nginx.

    3. Allavoolu sõlmed (taustaroll) tegelevad dünaamiliste arvutustega. Lihtsamalt öeldes võib see olla tüüpiline Apache + PHP kombinatsioon.

    4. Teine serverite rühm on mõeldud andmete salvestamiseks. Need on MySQL, Memcache, Redis ja nii edasi.

    5. Veebiteenuse kood ise (selles näites PHP kood) kopeeritakse võrdselt kõikidesse sõlmedesse, kus Apache+PHP asub, ja töötleb võrdselt ka konkreetsesse sõlme saabuvaid päringuid.

    6. Kasutades teatud tüüpi jaotust, jaotatakse andmebaasid nende serverite rühmas laiali ja nende koormust tasakaalustatakse sarnaselt.

    Tähelepanelik lugeja märkab, et diagrammil ei mainita DNS-i tasakaalustamist ja CDN-i, kuid autor jättis need teadlikult välja, et skeemi mitte liiga keeruliseks ajada. Nende asjade tööpõhimõte on väga sarnane ülalloetletutega.

    Klassikalise lähenemise miinused

    1. Peamine trend on komplikatsioon. Projekti eluea jooksul muutub "klassikaline" skeem üha keerulisemaks. Iga uue serveri lisamisel peate selle sisestama liikluse jaotusskeemi. Muidugi on suurtes projektides serveri rolli sissetoomine “ühe nupuga” toiming, kuid sellegipoolest on see infrastruktuuri suurendamine, mida tuleb toetada. Ja veelgi enam, kui andmebaasi praegusest mahust enam ei piisa ja peate andmebaasi uutesse serveritesse üle kandma või levitama (ilma teenust peatamata).

    Kuid kõige olulisem probleem on see, et liikluse jaotusklastri laiendamine ei too kaasa programmikoodi keerukuse vähenemist. Saate klastri ehitada veatult, kuid kood jääb samaks.

    2. Kasutuselevõtt ei ole tuumakas. Lihtsamalt öeldes võtab projekti uue versiooni tootmisserveritesse üleslaadimine veidi aega. Peate failid füüsiliselt alla laadima N-kahekümnesse masinasse, tegema andmebaasis muudatusi, lähtestama vahemälud (paljud erinevad vahemälud) ja samal ajal kõigis serverites lõpetama päringute töötlemise "vana koodiga" ja alustama töötlemist "uuega". kood”. Vastasel juhul võivad tekkida väikesed konfliktid, kui osa kasutaja päringust töödeldakse vanal viisil, osa uutmoodi, osa läks andmebaasi “vana skeemi järgi”, osa “uuest” jne. peal.

    Seetõttu soovivad ideaaljuhul kõik värskenduse ajaks (mõni sekund või kümned sekundid) teenuse peatada ja seejärel uuesti sisse lülitada. Tegelikkuses, vooga vähemalt 1000 päringut sekundis, ei tee seda keegi, eelistades väiksemaid kokkupõrkeid regulaarselt "käsitsi" parandada või katta need kaitsva programmeerimisega, mis toetab tagasiühilduvust "kuni seitsmenda põlvkonnani". Tark lugeja võib ise mõelda, kuidas regulaarne tagasiühilduvuse toetamine programmeerijate elu keerulisemaks teeb (ja projekti kui terviku maksumust suurendab).

    3. Kasutatakse HTTP-d. HTTP-protokoll on ilmselgelt moraalselt ja tehniliselt vananenud ning kui jälgida (näiteks) mobiiliarendust, siis tead, et see on kõikjal asendatud kergemate protokollidega. Kuid peamine puudus on erinev: HTTP-protokoll “brauseris” nõuab tsükli lõpuleviimist - see nõuab vastust piiratud aja jooksul. See kohustab teenust arvutama ja koostama vastuse rangelt selle väikese aja jooksul, mille brauser seda võimaldab. Kui teenus on praegu ülekoormatud, kaob taotlus jäädavalt.

    Seetõttu kasutavad nad "tüüpilistes veebiprojektides" mitmesuguseid nippe, nagu pikk küsitlus või muud perioodilised päringud, mis mitte ainult ei muuda arhitektuuri keeruliseks, vaid koormab teenust ka tarbetu "raisatud tõmblemisega".

    4. Iga päringu skripti lähtestamine. See on HTTP ja skriptikeelte (nt PHP) kasutamise tagajärg, mis pika traditsiooni kohaselt taaskäivitatakse vastuseks igale päringule. Jah, jah, vastuseks igale 1000 päringule sekundis käivitub PHP skript uuesti, lähtestab uuesti kõik muutujad ja loob uuesti ühendused andmebaasiga. Praktikas juhtub, et päringu töötlemiseks kulub 0,005 sekundit, kuid skript initsialiseeritakse umbes 0,05 sekundiga – kümme korda kauem!

    Teisisõnu, 90% ajast on teie serverid hõivatud mitte kliendi taotluste töötlemisega, vaid skriptide kasutu lähtestamise kasutamisega. Proovige see rahaks tõlkida. Seetõttu on selle ebameeldiva efekti leevendamiseks leiutatud palju lahendusi, näiteks OP-koodi vahemällu salvestamine, püsivad ühendused andmebaasiga, kohalikud vahemälud, nagu Memcache või Redis.

    5. Monoliitne rakendus. Olenemata sellest, kuidas te rakenduse mooduliteks jagate, kui kõvasti proovite koodi keerulises kataloogistruktuuris levitada, olenemata sellest, millist laiska automaatlaadimist te kasutate, on ainult üks kriteerium: kui teil on vaja kogu rakendus üles laadida. vähemalt ühe muudatuse avaldamiseks, siis on teil monoliitne rakendus. Muud võimalust pole.

    Monoliitsete rakenduste puudusi on kirjanduses laialdaselt kirjeldatud. Lühidalt võib välja tuua ühe peamise: kui tahad, et ka kõige väiksem funktsioon oleks tootmises hiljemalt tunni pärast, tuleb kogu tootmisahel ühte tundi mahutada. Probleemi sõnastamine, juurutamine, tagasiühilduvuse kontrollimine, testide kirjutamine, dokumentatsiooni kirjutamine, käsitsi testimise osakonna läbimine, vigade parandamine – kõik ühe tunni jooksul.

    Sest kui vabastate kogu rakenduse iga tunni täpselt 00 minutil, peaksite iga tunni lõpuks tulemuseks olema kogu rakendus stabiilsesse olekusse.

    6. Veebiliidese renderdab taustaprogramm. Tüüpilisel juhul renderdatakse projekti lehtede välimus (ja vastavalt ka HTML-kood) taustaprogrammi poolel, tavaliselt vastuseks igale päringule. See on ülemäärane, põhjendamatu ressursside ja raha kulutamine.

    7. Osakondade poliitiline jaotus. Süsteemiadministraatorite osakond vastutab selle eest, et sissetulev liiklus oleks laiali laotatud paljude serverite vahel, millel PHP kood töötab. PHP koodi eest vastutab programmeerimisosakond. Kui PHP-koodil ei olnud aega konkreetse päringu töötlemiseks, on ebaselge, kes selle eest vastutab - kas administraator, kes "saatis" serverisse liiga palju liiklust ja koormas selle üle, või programmeerija, kes kirjutas ebaoptimaalse skripti. Kui andmebaas hakkab aeglustuma, siis jääb ka arusaamatuks, kes jääb äärmusesse: kas administraator, kes ei taibanud õigel ajal “selgitada”, või programmeerija, kes oleks samuti võinud selle välja mõelda.

    Kui näited tunduvad teile liialdatud ja "mitte päriselust", pidage meeles, et autor töötas projektis, mida majutati 200 serveris ja 60 neist kasutati andmebaaside jaoks. On hirmutav meenutada, kui palju inimesi selle projekti ülalpidamiseks tööle võeti.

    Peamine puudus

    Kordame ülaltoodud mõtet: klassikalise skeemi peamiseks puuduseks on autori sõnul see, et tehnilised spetsialistid optimeerivad vale asja. Nad optimeerivad sissetulevate päringute esiosa, tegelikult "hajutades" selle suurele masinarühmale, selle asemel, et optimeerida põhiolemust - arvutuslikku osa. Ja see on palju lihtsam, kui tundub.

    Teoreetiline ideaal

    Oh, kuidas me sooviksime, et saaksime:

    1. Loobuge kallitest serveritest ja kasutage ühte või kahte väikest rühma.

    2. Loobuge skeemist Nginx->Apache->PHP, kus on kulutatud ressursside osas metsik "üldkulu", mis maksab raha.

    3. Samal põhjusel kaotage PHP skriptide initsialiseerimise koletu kulud.

    4. Likvideerige vajadus "renderdada" lehti taustaprogrammis. Oleks absoluutne unistus, kui veebiteenus töötaks ebastabiilse või puuduva internetiühendusega (näiteks maanteel mobiilsidevõrku kasutades).

    5. Vabanege HTTP ajalõpu "loopusest", edastage vastus kliendile alles siis, kui see vastus on valmis ja tarnegarantiiga.

    6. Uuenda projekti väikeste osadena, peatumata ja ühtki kliendi soovi kaotamata.

    7. Ärge muretsege kaotsiläinud taotluste pärast, kui osa projektist (mõni komponent) "kukkus" või lülitati ajutiselt silumise eesmärgil välja.

    Ebareaalne? Lihtsalt!

    Esimesed sammud ideaali poole

    Kõigepealt mõistame Mida me peame seda tegema, nii et arutame seda - Kuidas.

    1. Kujundage kogu süsteem SOA-na (teenusele orienteeritud arhitektuur) koos ESB-ga (ettevõtte sõnumside siin), loobudes monoliitsest lähenemisest, nii et iga sõltumatut äriloogikat töötleb eraldi "teenus" ja nad suhtlevad üksteist sõltumatu vahetusbussi kaudu.

    2. Keeldu sünkroonsusest. Näiteks sünkroonses "päringu-töötlus-vastuse" skeemis on see üks HTTP-silmus, millel ei ole lõpetamise üle ranget kontrolli ja mida saab kergesti katkestada. Asünkroonses on kolm eraldi protsessi: päring (saadetud ja kinnitatud), töötlemine (tõrke korral kordamisega), vastuse edastamine (garantiiga).

    3. Jaga projekt kaheks rakenduseks – Frontend ja Backend. Veebiteenuse puhul on esiotsaks (tavaliselt) JavaScripti rakendus. Asi on selles, et rakendused töötavad asünkroonselt ja üksteisest lahtiühendatult, vahetades sõnumeid kahepoolse sideprotokolli kaudu.

    4. Loobu HTTP-st ja vali WebSocketi. WebSocketi protokollil on HTTP-ga võrreldes fantastiline kiirus, sellel pole "ajalõppudega silmuseid" ja see võimaldab teil edastada mis tahes andmeid (sh binaarseid) mõlemas suunas.

    5. Pakkuge pooleliolevate päringute "salvestusruumi". Kui kliendi taotlus on vastu võetud, öelge talle "Kinnita" ja salvestage see päring. Niipea kui taustaprogramm on eelmisest töötlemistsüklist vaba, edastage taotlus sellele. Sel ajal, kui taotlus liigub taustasõlmede vahel, salvestage see hetkest, kui see sõlme "sisenes", ja kinnitage see kohe, kui see sõlmest "lahkus". Seega, kui mõni sõlm "kukkub", ei kaota süsteem päringut ja saadab selle kohe tagasi töötlemisele. Pärast töötlemise lõpetamist saatke tulemus kliendile ja säilitage seda seni, kuni klient ütleb "Kinnita".

    6. Tagada paralleelsus nende operatsioonide puhul, mida saab äriloogika seisukohalt paralleelselt teha, ja järjepidevus nende puhul, mida tuleb teha rangelt järjestikku. See lõik ei ole kirjutatud väitega "Captain Obviousness", vaid selleks, et näidata, et mitte iga äriprotsessi ei saa "pimesi panna" mitme lõimega koodile.

    7. Loobuge stsenaariumide kirjutamisest "deemonite" kasuks. Deemon on protsess, mis käivitub üks kord ja seejärel pidevalt "ripub" mällu. Kuna see töötab pidevalt, ei pea see raiskama aega iga päringu taaskäivitamiseks. Tulevikku vaadates ütlen, et PHP deemonil (kui kasutate PHP kaasaegseid versioone) pole põhimõttelisi erinevusi tavalisest PHP-skriptist.

    SOA disainilahendus

    SOA – teenustele orienteeritud arhitektuur – ei ole uus trend. Selle tarkvaraarenduse modulaarse lähenemisviisi algatas IBM eelmisel sajandil ning praegu toetavad ja propageerivad seda tööstuse juhid, peamiselt .NET- ja JAVA-keelte „ettevõttetasemel” toodetes.

    Klassikalises lähenemises veebiteenuste programmeerimisele PHP-s ja sarnastes keeltes algab disain mudelitest, nende omadustest ja nendel tehtavatest toimingutest. Mudelid esindavad reaalse maailma objekte ja toimingud objektidel toimuvaid toiminguid. Kuid nagu praktika näitab, on tegelik maailm palju mitmetahulisem ja keerulisem ning seda kirjeldatakse palju tõhusamalt sündmuste ja neile reageerimise keeles (postitus on pühendatud sellele üksikasjalikumalt #1593 koos kirjelduse ja näidetega).

    Reaalne maailm koosneb sündmustest, mis toimuvad samaaegselt (programmeerimise mõistes "paralleelselt") ja suuresti ilma meie osaluseta ning millele erinevad reaktsioonid toimuvad või ei toimu. Reaktsioonid võivad omakorda tekitada edasisi sündmusi. SOA arhitektuur sobib ideaalselt "pärismaailma programmeerimiseks", kuna kõige mugavam on opereerida sündmuste, nendevaheliste seoste ja reaktsioonidega. Veelgi enam, õige lähenemisviisi korral arhitektuuri korraldamisele toimuvad nii sündmused kui ka reaktsioonid neile paralleelselt, isegi kui kasutate "ühe lõimega" programmeerimiskeelt nagu PHP.

    SOA-toote kujundamisel peate lähtuma sellest, millised sündmused teie äriloogikas toimuvad, kuidas need on üksteisega seotud või peaksid üksteisele järgnema, millised reaktsioonid peaksid teatud sündmustele reageerima ja kes neid või muid sündmusi täpselt töötleb. muud üritused. Andmemudelite juurutamine ja nendega tehtavad toimingud jäävad tagaplaanile (kapselduvad "teenusesse") ning esiplaanile kerkib "teenuste" loend ja nendevaheline interaktsiooniplaan (teenustevaheline API).

    Rakendamine: esimene lähendus

    1. Frontend iseseisva rakendusena. Rakendamiseks sobib iga populaarne JavaScript-MVC raamistik. Praktikast panen aga tähele, et kui sõnad “JavaScript, MVC ja raamistik” ühte lausesse liites hakkavad hambad valutama, läheb sul raskeks. Rakendus peab suutma renderdada kõiki oma "ekraane" ilma taustaprogrammi juurde pääsemata, pakkuma kasutajale navigeerimist (üleminekuid "ekraanide" vahel) ka ilma taustaprogrammi juurde pääsemata ning säilitama taustaprogrammiga kahesuunalist sidekanalit.

    2. WebSocketi ühenduse sisenemispunkt taustaprogrammiga. NodeJS-is on mitmeid valmislahendusi, mis toetavad ka pika pollimise ja ajaxi tagavarataotlusi. ideoloogiliselt aegunud brauserid. Märgin edaspidiseks, et sellele sõlmele pääseb juurde ka puhta HTTP-ga, kui peate kirjutama mõne lüüsi teiste inimeste teenustega, kuid selle lihtsustamiseks on võimalik kirjutada eraldi "puhas HTTP" sõlm.

    Sisendpunkt pakub kahesuunalist sidekanalit eesprogrammi rakendusega (teisisõnu brauseriga), võttes vastu sellelt päringuid ja tagastades sellele vastuseid.

    3. Käimasolevate päringute salvestamine süsteemi. Populaarne AMQP server, mis pakub sõnumijärjekordi ja nende vahelist marsruutimist, sobib selleks ideaalselt. Niipea, kui saabub kliendilt järgmine päring, asetage see "sissetulevate" järjekorda. Järgmisena otsib deemon selle sellest järjekorrast, mis analüüsib päringu sisu ja saadab selle süsteemi kaudu marsruutimisele (mis tegelikult tähendab selle ülekandmist ühte või mitmesse järjekorda vastavalt teatud algoritmidele). Iga deemon, mis tegeleb oma osaga äriloogikast, saab "oma" sissetulevast järjekorrast ühe või teise sõnumi, töötleb seda ja asetab vastuse "väljaminevasse" järjekorda.

    Märgin, et populaarse maakleri RabbitMQ terminoloogias pole väljaminevate järjekordade mõistet. Sõnumid avaldatakse vahetusena, kust maakler ise suunab need vastavalt marsruudireeglitele konkreetsetesse järjekordadesse. Siin on tingimuslikuks mõistmiseks kirjas, et vastust ei saadeta otse päringu esitajale.

    4. Deemonite juhtimine (juhendaja). Lihtsa PHP-skripti deemonina käivitamiseks mässige käivitatav kood lahtrisse while(true) (...) ja tippige käsureale midagi sellist nagu "php your-script.php". Kuid selleks on parem kasutada suvalist sobivat juhendajat, kes teeb sisuliselt sama asja, aga tagab ka vajaliku keskkonnaseisundi, jälgib protsessi seisukorda ja teeb muid kasulikke asju.

    Päriselus on PHP deemon tehtud veidi keerulisemaks: ta peab vastu võtma juhtsignaale ja ümberseadistusteateid, ei tohi mälu lekkida, peab säilitama (või taastama) ebaõnnestunud ühendused andmebaasiga – aga üldiselt pole see keerulisem. kui PHP-skriptid, millega olete harjunud.

    Üks samm reaalsusele lähemale: sündmustepõhine lähenemine SOA-le

    Mõned (autori arvates vananenud) lähenemisviisid modulaarsete rakenduste loomiseks põhinevad RPC (Remote Procedure Calling) põhimõttel, mis eeldab otsest väljakutsumist konkreetsetele meetoditele või protseduuridele kaugprojekti komponendis. Selline lähenemine hävitab täielikult kõik SOA eelised, kuna see tähendab tavaliselt otsest ja jäika ühendust saatva ja täitva sõlme vahel. Kompleksse toote kavandamisel ja juurutamisel tuleks võimalikult palju kinni pidada lõdvalt seotud komponentide põhimõttest, kuna arhitektuuri ja koodi keerukus määrab lõppkokkuvõttes omamiskulu (toote paranduste ja muudatuste tegemine pärast selle käivitamine).

    Sündmustele orienteeritud lähenemine SOA-s eeldab, et komponendid (teenused) suhtlevad üksteisega asünkroonsete sündmuste (“sündmused”, sõnast Event) saates. Sündmus on sõnum (näiteks AMQP terminoloogias), millel on pealkiri (nimi) ja parameetrite komplekt. Sündmus on mõeldud süsteemile teatamiseks, et midagi on juhtunud, või süsteemile küsimuse esitamiseks. Üldiselt saadetakse sündmused "süsteemi" (täpsemalt ühisele ESB siinile) adresseerimata - see tähendab ilma konkreetsete kavatsusteta konkreetsetele sõlmedele või täitjatele edastamiseks.

    Vastupidi, konkreetsed sõlmed (komponendid, teenused) kuulavad ühist siini teatud sündmuste suhtes, millele nad on valmis reageerima. See võib tähendada, et teenus on valmis mõnda sündmust kuulama ja vastava toimingu sooritama. Või on teenusel mingid teadmised (näiteks omab andmebaasi kasutajate kohta käivate andmetega) ja on valmis seda „päringu“ peale pakkuma. Mõlemal juhul genereerib sündmusele reageerimise tulemus uue sündmuse (teise nime ja muude parameetritega), mida saavad kuulda ka teised sellest huvitatud teenused.

    Ühise ESB siini õige korralduse korral saadavad ja võtavad teenused vastu sündmusi asünkroonselt, üksteist ootamata. See tähendab, et saatjateenus saab ilma ajaliste viivitusteta saata ESB-le nii palju sündmusi, kui soovib, ning liikuda edasi järgmiste ülesannete lahendamisega. Võrrelge seda klassikalise HTTP-ga, mis hõlmab vastuse ootamist praeguses töötlemistsüklis, ja saate aru selle eelistest. Ja vastuvõtvad teenused saavad ka uued sündmused asünkroonselt, üksteisest sõltumatult, kohe pärast eelmise sündmuse töötlemise lõpetamist.

    SOA sündmuse mudel programmikoodis

    Lühidalt, peate oma koodi vaatama mitte kui funktsioonide (meetoditega) klasse, vaid kui sündmusi ja toiminguid, mis toimuvad vastusena neile sündmustele. Pealegi on tegude tulemused ka sündmused. Seoses käsitletava arhitektuuriga võime öelda, et kohalikud sündmused on sündmused, mis toimusid konkreetse PHP skripti sees, ja kaugsündmused on sündmused, mis tulid sellesse skripti AMQP järjekorrast (või saadeti sinna selle tulemusena). Kui käsitlete kogu oma koodi nii, toob see kohe kaasa üllatava ja väga olulise efekti:

    Kui kohalikud ja kaugjuhtimise sündmused on samad, siis kohalikud ja kaughaldurid on samad!

    Miks see nii oluline on? Sest teie meeskonna programmeerijad jätkavad tavalise PHP-koodi kirjutamist, mõtlemata sellele, kus seda või teist sündmust töödeldakse – kas selles või naabruses asuvas PHP-skriptis või kuskil süsteemi teises otsas, teises deemonis, isegi mõnes teises programmeerimiskeeles. Kui teete projekti avaliku API-ga, saavad kõik kolmandast osapoolest osalejad teie sündmustele oma koodi tellida (ja neid töödelda) või vastupidi – saata teile oma koodi, et te töötleksite nende sündmusi päringutena. (ja saate selle eest raha, kui kasutate tasulist SAAS-i ärimudelit, nagu Amazon).

    Pidage meeles, mida nimetasime klassikaliste suurte veebiprojektide peamiseks puuduseks - pidevalt kasvav keerukust ja seega ka omamiskulusid, tugikulusid ja muudatusi. Sündmuspõhise SOA arhitektuuri puhul - raskused vähenevad pidevalt, kuna "keerulisi sõlme" saab hõlpsasti jagada sõltumatuteks teenusteks (antud juhul deemoniteks), samas kui süsteemi põhimõtted jäävad muutumatuks ja selle jõudlus ainult suureneb.

    Juurutage uus versioon praeguseid protsesse kaotamata

    Kuna teil pole enam monoliitset süsteemi, ei pea te kogu süsteemi juurutama. Pealegi võib komponendi (teenuse, deemoni) juurutamine võtta aega, loomulikult mõistlikes piirides. Oluline on see, et komponendi juurutamise ajal (need paar sekundit või mitukümmend sekundit) ei katkestaks kogu projekt teenust hetkekski. Kuidas seda tehakse?

    Lihtsalt lülitate värskendamist vajava teenuse välja. Värskendage selle koodi ja andmebaasi struktuuri (vajadusel), seejärel käivitage see uuesti. Kõik selle teenuse praegused taotlused ootavad AMQP järjekorras, kuni teenus ilmub. Märgin, et kuna teenused on väikesed (väike hulk koodi on vaja vaid väikese osa äriloogikast lahendamiseks), toimub see palju kiiremini kui terve monoliitse rakenduse juurutamine. Kuid igal juhul kaotusi ei teki.

    Probleemid veebiliidesega

    Kiire ja tundlik veebiliides on suure koormusega projekti eeltingimus. Mõelgem välja, miks võib veebiliides üldiselt aeglustuda klassikalise juurutamise lähenemisviisiga:

    1. Liides renderdatakse taustaprogrammis, mis on ülekoormatud ja teeb seda aeglaselt. Lehtede vahel navigeerimine on aeglane. Isegi AJAX-iga joonistatakse plokke ümber liiga aeglaselt.

    2. Liidese lähtekood (HTML, CSS, JS) on üleliigne ja edastatakse aeglaselt sidekanalite kaudu, eriti kui seda tehakse iga lehe laadimisel, kui kasutaja liideses navigeerib.

    3. Liides sisaldab suurel hulgal optimeerimata JavaScripti loogikat, mis töötab nõrkades seadmetes (peamiselt mobiilsetes) aeglaselt.

    Proovime neid probleeme lahendada:

    Kuidas luua kiire ja tundlik veebiliides

    1. Esiteks, mis kõige tähtsam, liidese lähtekood tuleks kliendile üle kanda mitte rohkem kui üks kord. Ainus tsiviliseeritud viis selle saavutamiseks on täisväärtusliku JavaScripti rakenduse loomine. See laaditakse kliendile üks kord alla (samal ajal saate näidata ilusat animeeritud eellaadijat) ja seejärel ei pea klient enam allalaadimist ootama kogu teenusega töötamise aja.

    2. Kõik üleminekud veebiliidese “ekraanide” vahel peavad toimuma JavaScripti rakenduses ja mitte mingil juhul eraldi päringutena taustaprogrammile. On olemas vastav termin - "ühe lehe veebirakendus", milles navigeerimine toimub sisuliselt "ekraanide" vahetamise teel, samal ajal kui aadressiriba sisu muutub dünaamiliselt, luues klassikalise "lehe navigeerimise" täieliku tunde.

    3. Sõnumite (sündmuste) saatmine taustaprogrammi ja vastuste vastuvõtmine peavad olema üksteisest ja kasutaja navigeerimisest lahti ühendatud (asünkroonne). Eespool mainitud WebSocket “soovitab” just sellist teostust. Kõik kaua kestnud toimingud ei tohiks ka liidest blokeerida, välja arvatud juhul, kui seda tehakse spetsiaalselt.

    Seega vajab kasutaja Interneti-ühendust vaid rakenduse esmaseks allalaadimiseks (mõned sekundid). Siis saab ta teenusega töötada ka ajutise ühenduse puudumise korral (näiteks mobiilseadmest metroos, väljaspool linna, välismaa rahvarohkes hotellis jne) - rakendus salvestab päringud ja proovib saata need kohe, kui Internet ilmub, ja saada vastused samal viisil.

    Loomulikult ei vabasta see arendajat vajadusest koodi optimeerida ja minimeerida. Kuid nagu praktika näitab (näiteks Trello teenus), pole see ülesanne teistest keerulisem.

    Märkus kahtlevatele mobiilseadmete veebiteenuste arendajatele: autori praktika kohaselt töötavad 2013. aastal iPadis edukalt veebisoketi transporti kasutavad ühelehelised JavaScripti rakendused.

    Kasutajakogemus mitmest seadmest

    Töölt kasutab ta teie teenust oma töölauaarvutis, koju minnes võtab ta iPhone'i välja ja kodus lülitab sisse tahvelarvuti. Kui kasutaja saatis teenusele liidesest mõne käsu, ootab ta vastust töötlemistulemuste kohta. On lihtne mõista, et kui töötlemine (kui) võttis märgatavalt aega, tuleb vastus saata täpselt sellele seadmele, mida kasutaja parasjagu kasutab (vabandust sõnamängu eest). vastuse edastamine, mitte taotluse esitamise ajal.

    Probleem on selles, et pole võimalik üheselt öelda, kas kasutaja on lõpetanud (vabandan veel kord) selle või teise seadme kasutamise. Võib-olla sulges ta brauseri. Võib-olla on tema aku tühi. Võib-olla läks ta metrootunnelisse, kus ühendus puudub, ja poole minuti pärast ilmub ta uuesti. Võimalusi on palju ja autor ei tea, kuidas seda kõige paremini määrata. Siin on aga see, mis võib teile kasulikuks osutuda:

    1. Salvestage (taustaprogrammis) kõik kasutaja seadmed ja nende viimase tegevuse aeg.

    2. Liigitage süsteemisündmused, millest tuleb kasutajale teatada, nendeks, mis tuleb edastada ainult aktiivsetele seadmetele, ja sündmusteks, mis tuleb edastada "edastuseks" (kõikidele seadmetele).

    3. Võtta kasutusele täiendav abstraktsioonikiht – teenus, mis püüab kinni teatud kasutajat huvitavad sündmused ja genereerib nendest sõnumeid. Nii saate hõlpsalt edastada sama sõnumi operatsiooni õnnestumise kohta mitut tüüpi: lühike teade mobiilseadmesse, veidi pikem teade brauserisse, üksikasjalik teade e-posti teel.

    4. Pakkuge saatmisjärjekorrad igale kasutajale igal individuaalsel sidekanalil (veebiliides, mobiilseade, post). Standardne AMQP funktsionaalsus aitab teid ka sõnumite aegumise ajalõppude puhul, et need ei lebaks seal kauem kui teatud aeg ega ummistaks süsteemi. Kui kasutaja saab teatud kanali kaudu "ühendatud", edastatakse talle teatud tüüpi värsked ootel sõnumid.

    Autor võib lisada, et sama süsteemi alusel on võimalik üles ehitada teatiste hilinenud saatmine (mis saadetakse mitte varem kui teatud kuupäeval) ja isegi reaalse paberkandjal perioodilise kirjavahetuse (aktid, maksed jne) saatmine, kuid see on eraldi artikli teema.

    Lubage mul rõhutada peamist: ärge pidage edastatud sõnumeid mingisugusteks teatisteks, millega olete Facebookis või Vkontakte'is tuttavad. Edastatavad sõnumid on just sellised. päringu tulemused kasutaja! Kõik kasutajaliideses tehtavad toimingud, mis viitavad teatud tüüpi päringutele taustaprogrammile, saavad vastused ühtse "edastatud sõnumite" kujul ühe ühtse sidekanali kaudu. Ja siis mõtleb veebirakenduse algoritm välja, mida selle või teise sõnumiga teha tuleb – joonistada tekstiga märguanne, lisada tabelisse rida, midagi liideses ümber lülitada ja nii edasi.

    Paralleel- ja jadaarvutus

    Kui teie taustaprogramm on aeglane, oleks kasutu kujundada esiotsa kiiret veebiliidest. Ei, me ei räägi niitidest, kahvlitest ega Erlangist. Kasutame tavalist PHP-d, mis on kättesaadav igale algajale/kesktaseme programmeerijale.

    Miks on paralleelsust üldse vaja? Isegi kui me ei räägi üldiselt ühelõimeliste keelte puudustest, kiirendab paralleelsus märkimisväärselt ülesande arvutamist, mis tähendab, et see vähendab oluliselt nõudeid riistvararessurssidele (riistvarale) ja suurendab kasutajate rahulolu tööst. liides (nad saavad kiiremini tulemusi).

    Võtke oma veebiprojektis mõni üsna keeruline äriprotsess ja joonistage see sammude ahelana. Saate süsteemis toimingute jada päringust vastuseni. Tõenäoliselt toimub esmalt mõned kontrollid, seejärel põhiülesande täitmine, seejärel sekundaarsed alamülesanded ja lõpuks tulemuse väljund. Vaadake hoolikalt: kas mõnda toimingut saab teha paralleelselt?

    Lubage mul tuua näide: oletame, et kasutaja soovib osta teenust, mis on tema tariifiplaanis tasulise lisavalikuna kaasatud. Valikute arv on piiratud. Kui valik on edukalt sisse lülitatud, peate saatma kasutajale brauseris teatise, saatma duplikaatmeili, kandma raha tema arvelduskontolt maha ja teavitama kliendiosakonda. Joonistame ahela:

    1. Süsteem sai taotluse selle valiku lubamiseks.
    2. Autoriseerige kasutaja ja uurige välja tema tariifiplaan.
    3. Kontrollime, kas seda valikut saab kasutaja tariifiplaani järgi üldse lubada.
    4. Kontrollime, kas kasutaja kontol on piisavalt raha.
    5. Kontrollige, kas see valik ei ole vastuolus muude seadistustega.
    6. Kui kõik on korras, siis lubage valik.
    7. Saatke brauserile teatis.
    8. Saadame teate posti teel.
    9. Kandke raha arveldusse.
    10. Teavitame kliendiosakonda.

    Tähelepanelik lugeja võib viga leida tegevuste järjestuses, kuid autor tuletab meelde, et see on ligikaudne näide.

    Mida me näeme? Pange tähele, et pole põhjust teha kõiki samme järjestikku. Palju õigem oleks "paralleeleerida" 3,4,5 kolmeks niidiks ja lõpuks - 7,8,9,10 neljaks niidiks.

    Kas mõtlete niitide ja kahvlite peale? Asjata, teil on SOA!

    Kuidas teha SOA-s paralleelset andmetöötlust

    Lugejatele, kes on äsja artiklis selle punktini kerinud, selgitan, et me ei räägi sama ülesande paralleelistamisest SOA-s - selleks piisab üldiselt deemoni käivitamisest N eksemplaris ja selle eest hoolitsemisest. vaidlusi andmebaasile juurdepääsu pärast.

    Nii et selles näites on meil kolm või neli või mitu erinevat ülesannet, mida täidavad erinevad teenused, mida soovime paralleelselt täita. Paralleeltöötluseks saatmine pole keeruline: piisab, kui saata üks sündmus “kas kasutajanimi lubab valiku X?” ja kõik selle sündmusega tellitud teenused püüavad selle kinni, teostavad kontrolli ja saadavad sellest tulenevad sündmused.

    Probleem on just nende sündmuste kogumises, kui vajame nende töö kogutulemust, et edasi liikuda. Näiteks ülaltoodud loendis vajame tulemust 3+4+5, kuid 7+8+9+10 võib ignoreerida.

    Tegelikult on kõrgete nõuetega tehingute kohustuslikule täitmisele vaja iga ahelat lõpuni kontrollida, kuid sellest räägime hiljem.

    Loomulikult, kui meie deemon "ripub ja ootab", kulutades ressursse (nn "tühikäik"), siis ei saa niimoodi ehitada ühtegi kõrgelt koormatud teenust. Asi on selles, et deemon lahendaks muid probleeme ja teenindaks teiste klientide muid päringuid, samal ajal kui kolm eraldi "lõime" (3, 4, 5) lahendavad oma alamülesandeid. Raskust lisab asjaolu, et sellest tulenevad sündmused võivad saabuda juhuslikus järjekorras. Seda kõike saab aga lihtsalt ja lihtsalt lahendada:

    Autorile teadaolevalt ei võimalda ükski tänapäeval "kastist väljas" eksisteeriv AMQP rakendustest oodata ja "liimida" mitut sündmust üheks, et saada ainult see – üks resultant. Nii et peate selle eest ise hoolitsema, näiteks järgmiselt:

    1. Enne sündmuse saatmist AMQP-le salvestage kiirmällu (kasutage mis tahes sobivat mälusisest salvestusruumi) nende sündmuste nimede loend, mida teenus ootab, ning sündmuse nimi (nimetagem seda " R), mis tuleb saata koos tulemuste summaga.

    2. Pärast seda lõpetab teenus praeguse sündmuse töötlemise tsükli ja vabastatakse järgmisteks ülesanneteks.

    3. Niipea kui mõni sündmus meie mällu salvestatud loendist saabub, pakib teenus selle lahti ja salvestab selle sisu mällu, määrates selle sündmuse nimele. Samal ajal kontrollib, kas selles loendis on veel sündmusi, millele pole vastust saadud. Kui see on olemas, lõpeb tsükkel sellel hetkel.

    4. Vastasel juhul, st kui vastus on laekunud kõikidele loendis olevatele sündmustele, liidab teenus need kokku ja saadab liidetud tulemuse varem meelde jäetud sündmuse nime “R” alla. Pärast seda kustutatakse mälu säästmiseks lihtsalt tulemustega loend mälust - seda pole enam vaja.

    5. Sama teenus või mõni muu (süsteemi kujundaja äranägemisel) saab tulemuseks oleva sündmuse “R” koos kõigi paralleeltöötluse tulemustega. Edasine on ilmne.

    Kui kirjelduse põhjal tundus, et see on pikk, siis selgitan - me räägime tuhandetest ja kümnetest tuhandetest sündmustest sekundis (!) ühes keskmises serveris.

    Mälusisese salvestusruumi kasutamine tähendab, et isegi kui teenus peatatakse (krahhitakse, värskendatakse), ei lähe praegune äriprotsess kaotsi. Pärast teenuse taaskäivitamist jätkab see sündmuste vastuvõtmist ESB-lt ja töötleb neid vastavalt ülalkirjeldatud algoritmile.

    Tehingulisus, tagasivõtmine ja tõrkestsenaariumid SOA-s

    Kuna võrdõiguslikud sündmused "rändavad" läbi ESB SOA-s, on teil vaja mingit märki, mis näitaks, et "see vastus" viitab "sellele päringule". Siin pole vaja ühtegi ratast uuesti leiutada – mis tahes populaarse protokolli spetsifikatsioonidest leiate parameetri nimega correlation_id type. Tavaliselt on see string. See peab sisalduma iga üksiku äriprotsessi kõigi sündmuste parameetrites sisendist väljundini, et tuvastada sellesse äriprotsessi kuuluv sõnumite ahel. Veebiliideselt vaadates salvestab veebirakendus praegused aktiivsed (saadetud) päringud ja korrelatsiooni_id põhjal “mõistab”, millisele päringule iga konkreetne vastus tuli.

    Mõistame terminoloogiat: tehingulisus on süsteemi omadus sooritada mitut toimingut ühe üldise toiminguna, mis on mõttekas ja mida saab teha ainult täielikult. Kuna paralleelsete lõimedega hajutatud süsteemis on füüsiliselt võimatu mitut toimingut atomaalselt teha, pakub süsteem nn tõrkeskripte ja tagasipööramisi.

    Tõrke skript on üldiselt toiming, mis tuleb tõrke ilmnemisel sooritada. Tagasivõtmine on selles kontekstis toimingute skript, mis tuleb sooritada, et tühistada rida varasemaid toiminguid, mis lõpuks tõrkeni viisid. Jämedalt öeldes on tagasivõtmised protsessid, mis on vastupidised süsteemi tavalistele äriprotsessidele.

    Tagasivõtmine ei ole alati vajalik ja mitte alati võimalik. Näiteks kui ühendasite kasutajaga mõne optsiooni ja seejärel "kukkusite" arveldamisele, siis saab selle võimaluse tagasi keelata. Noh, siis võite proovida uuesti, automaatselt või kasutaja teise käsuga. Ja kui kustutasite sisu füüsiliselt ja mõned järgnevad toimingud ei toiminud... Olukord on mitmetähenduslik.

    Seetõttu tuleb ebaõnnestunud stsenaariumitele ja tagasivõtmistele läheneda targalt. Autor võib soovitada järgmist viisi: kirjutage alati ebaõnnestunud skripte, kuid mitte alati kirjutage tagasipööramisi. Teie failid kajastuvad koheselt monitooringus – ja tugimeeskond suudab kiiresti käsitsi olukorra parandada, omandada kogemusi ja koostada programmeerijatele tehnilised näitajad. Unikaalselt õige nullist tagasipööramise kirjutamine võib olla väga-väga keeruline.

    Siiski tuleb mõista, et tagasipööramine, tagasivõtmine ja veaolukordade käsitlemine on äriprotsessid nagu kõik muu. Need põhinevad ka süsteemi läbivatel sündmustel. Oleks tore, kui paneksite igas sündmuses ja igas käsitlejas alguses kaks vastandlikku teed (edasi ja tagasi, edu ja ebaõnnestumine), et neid konkreetsetes ülesannetes rakendada.

    SOA skaleerimine

    Iga süsteem vajab varem või hiljem laiendamist. SOA puhul tehakse seda lihtsalt ja loomulikult:

    1. Sisenemispunkti duplikaat. See viitab samale WebSocketi lüüsile, mida vaatasime artikli alguses. Seda saab dubleerida piiramatu arv kordi, kuna suhtlus selle ja kliendi vahel on ühtne ja lahutatud süsteemi sisemistest osadest ning side selle ja süsteemi vahel on omakorda lahutatud suhtlusest kliendiga.

    2. Teenuste eksemplaride (eksemplaride) dubleerimine. Teenused, mis ei nõua andmebaasi või ainult neid loevad, on kergesti dubleeritud. Ja RabbitMQ standardfunktsionaalsus võimaldab tellida samasse järjekorda N eksemplari, millest saabuvad sõnumid juhuslikult ühte või teise eksemplari. Väliste rakendustega (andmebaasid, kolmanda osapoole tarkvara) tegelevate teenuste dubleerimisel peate arvestama, kuidas need rakendused tagavad tehingutaotlused mitmelt paralleelselt kliendilt.

    3. Andmehoidlate dubleerimine. Siin saate vabalt kasutada mis tahes teadaolevat killustikku. Kui teil on 10 miljonit kasutajat ja see tundub teile palju, jagage need 10 baasiks miljoni kohta (näiteks kasutaja sisselogimise CRC32 või muu tsüklilise meetodi alusel). Kui ühe teenuse andmebaas pidevalt kasvab ja muutub keerukamaks, jaga see kaheks teenuseks.

    4. AMQP maakleri ja mälusisese salvestusruumi dubleerimine. Autori kogemuse põhjal täidavad RabbitMQ ja Redis oma rolli suurepäraselt. Kui teil on seadmeid rohkem kui ühes alalisvoolurekis, valige Rabbit-režiim, mis talub võrguühenduse tõrkeid.

    5. Tervete masinate dubleerimine. Kaasaegsete virtualiseerimistehnoloogiate (KVM) ja konfiguratsiooniga (Chef) taandub sama masina kasvatamise ülesanne ühe nupuvajutusega.

    Liikluse krüpteerimine esi- ja taustaprogrammi vahel

    WebSocketi ühendus on soovitatav korraldada SSL-i kaudu. Lisaks kõigele suurendab see "läbitungimist" mahajäänud kontoriteenuse pakkujate vastu, kes blokeerivad "mis tahes kummalise liikluse", välja arvatud HTTP[S].

    Kui aga see tundub teile ebapiisav, saate iga kliendi sisselogimise jaoks genereerida võtmepaarid (üks paar esiosas, teine ​​tagaosas), vahetada avalikke võtmeid ja seejärel krüpteerida kogu liiklus tavalise RSA-ga.

    Kaitse DDOS-i ja sarnaste kuritarvituste eest

    SYN-i üleujutamise ja kanalite sadade gigabittidega üleujutamise puhul jätab autor teadlikult välja küsimuse "madala taseme" kaitsest, kuna selle kohta on kirjutatud sadu raamatuid erialast kirjandust. Räägime sellest, kuidas kaitsta süsteemi juba sees, selle loogilisel tasemel, kui ründaja on leidnud viisi, kuidas teie süsteem (SOA+ESB) tuhandete sündmustega üle ujutada.

    1. Esimene reegel: midagi ei tohi töödelda enne, kui selle kehtivus on kinnitatud. Kui ootate sisendiks väikest teksti JSON-is, mis on mähitud BASE64-sse, tuleks sissetulevast stringist, mis on pikem kui megabait, selgelt ära visata – ärge proovige seda lahti pakkida. Mitte-ladina tähti sisaldav string on sarnane. Kui olete stringi lahti pakkinud, ärge proovige json_decode'i kohe teha, vaid kontrollige esmalt sulgude arvu ja sidumist. Ja nii edasi.

    See näib olevat paranoia, kuid muidu võib teid kergesti "pähe jätta", see tähendab, et see võib põhjustada teenuse tõrke, sundides seda kasutama kogu talle saadaoleva RAM-i.

    2. Sissetulevaid sõnumeid töötlev teenus ei tohiks midagi mällu, andmebaasi või muusse salvestusruumi kirjutada. Põhjus on sama. Esmalt veenduge, et sõnum tervikuna on kehtiv, ja alles seejärel edastage see süsteemi "sügavamale".

    3. Teenus, mida saab sundida sageli andmebaasi külastama, peab olema kaitstud vahemällu salvestamisega. Lihtne näide on kasutaja autoriseerimisteenus. Kui see pole kaitstud, võib ründaja saata järjest tuhandeid autoriseerimistaotlusi, koormates seeläbi andmebaasi üle.

    4. Süsteemi sissepääsu juures vajate teenust, mis lükkab tagasi päringud "kahtlastest" allikatest, näiteks "musta nimekirja" IP-aadressidelt.

    Tundub klassikaline nõuanne, nii et milles asi? Peamine probleem seisneb selles, et kui paigaldame süsteemi sissepääsu juurde analüüsi-filtreerimisteenuse (nagu tehakse klassikalistes veebiprojektides), siis ei ületa kogu süsteemi jõudlus selle analüsaatori-filtri jõudlust. Iga sõnumi "reaalajas" kahtluse tuvastamine on äärmiselt kulukas. Saate ja peaksite seda tegema hiljem ning toimige järgmiselt.

    1. Looge teenus, mis "kuulab" kõiki süsteemis olevaid sõnumeid. RabbitMQ-s saavutatakse see marsruutimisvõtme "#" tellimisega.

    2. Õpetage sellele teenusele teatavad reeglid, mille järgi saab see "kahtlasi" saatjaid diagnoosida. Näiteks on need saatjad, kes saadavad teatud aja jooksul liiga palju sarnaseid sõnumeid või kes saadavad korduvalt sõnumeid või saadavad sama kasutaja nimel sõnumeid erinevatelt IP-aadressidelt... Võimalusi on palju, kasutage oma kujutlusvõime. Sel juhul pole vahet, kui kiiresti selline teenus töötab (muidugi mõistlikes piirides) – see ei mõjuta kogu süsteemi kiirust.

    3. Niipea kui teenus teeb järelduse, et selline ja selline saatja on kahtlane, saadab ta selle sündmuse süsteemi ja jätkab oma äri.

    4. Paigaldage sisendisse väga lihtne ja kiiresti toimiv deemon - filtreerimisteenus, mille ülesandeks on lihtsalt kahtlaste saatjate "loll" blokeerimine. Ei mingit analüüsi, ei analüüsi ega lisakulusid. Keda peetakse kahtlaseks, on lihtne ära arvata: teenus saab nende kohta teada eelmises lõigus kirjeldatud sündmustest ja lisab need oma sisemisse musta nimekirja.

    Esimese osa lõpp. Jätkamine: SOA: hajutatud arhitektuur ja selle hooldus .

    Olen IT-projektide mentor. See tähendab, et kui olete omanik või juht, aitan teil viia teie ettevõtte uutesse kõrgustesse. Seadke asjad korda, mõistke meeskonna motivatsiooni, rakendage tööriistu ja saavutage konkreetsed eesmärgid. Ma ei õpeta sulle äri ajama, vaid aitan sul lihtsalt mööda teed heldelt laiali pillutatud rehadest mööda saada. .