Anksčiau dažnai pastebėjau įprastą požiūrį, kai kūrėjai (žinoma, įskaitant mane patį) naudojo tą pačią API tiek skaitymui, tiek rašymui kiekvienu atveju. Dar daugiau, mes dažnai pasitikėjome tuo pačiu duomenų šaltiniu, pvz., MySQL / PostgreSQL, kad atliktume abi operacijas.
Tai reiškia, kad reikia rašyti į tuos pačius stulpelius ir skaityti iš jų, todėl dažnai kyla problemų optimizuojant indeksus laukuose, kuriuose buvo daug užklausų.
Taigi, pavyzdžiui, dažnai keisdavome indeksus, kad pritaikytume naujus filtrus arba pagerintume užklausos našumą, o laukai, naudojami su tokiais operatoriais kaip LIKE, kėlė ypatingų iššūkių dėl jų įtakos našumui.
Dėl šių pakeitimų dažnai reikia toliau koreguoti pagrindinę programą, įskaitant API modifikavimą, kad būtų atskleistos atnaujintos funkcijos, išmatuotas laikas dėl papildomų JOIN ir pan.
Siekiant išspręsti iššūkius, susijusius su naujų filtrų ir kitų dalykų įtraukimu į API, buvo bandoma optimizuoti procesą naudojant tokius įrankius ir standartus kaip Apicalypse ir, žinoma, GraphQL .
Šiais sprendimais buvo siekiama supaprastinti API užklausų generavimą ir sumažinti rankines pastangas, reikalingas naujiems filtrams ir funkcijoms įdiegti, siūlydami dinamiškesnį duomenų prieigos tvarkymo metodą, tačiau jie turėjo aukštą mokymosi kreivę.
Atsiradus CQRS (Command Query Responsibility Segregation), pradėjo atsirasti naujas požiūris. Ši mąstysena paskatino naudoti atskirus šaltinius rašymui ir skaitymui. Rašymas galėtų skleisti įvykius, o skaitymas galėtų sukurti vaizdus iš tų įvykių tam skirtose vietose. Net jei skaitymas ir rašymas buvo valdomi toje pačioje duomenų bazėje (bet skirtingose lentelėse), šis atskyrimas atnešė didelę naudą ir, žinoma, sugebėjo atsikratyti antrojo iššūkio - JOIN ir paieškos užklausų domenų modeliuose, nes skaitymo modeliai yra dažniausiai denormalizuotų JSON forma.
Tačiau tai iškėlė kitą problemą. Skaitydami turėjome pakeisti rašymo mastelį, o tai reiškia, kad vienintelė priežastis, dėl kurios turėjome pakeisti programos egzempliorius nuo X iki Y, buvo skaitymas. Šią problemą būtų galima iš dalies sušvelninti naudojant talpyklą, o mikropaslaugų pasaulyje galėtume turėti skaitymui skirtas mikropaslaugas.
Bet...
Vis dėlto tai nebuvo idealus sprendimas kitiems architektūros stiliams, pvz., moduliniams monolitams, kur toks atskyrimas gali nelabai derėti su sistemos projektavimo filosofija. Kitas dalykas buvo tai, kad kai API neveikė, visas produktas neveikė, ir turint omenyje, kad dauguma produktų priklauso nuo daugiau skaitymo nei rašymo, tai gali be reikalo paveikti verslą (žinoma, kad API neveikia ;) )
Taigi, kas būtų, jei galėtume paklausti tų „vaizdų“, dar vadinamų skaitymo modeliais, tiesiogiai, neįtraukdami API ir netvarkydami apkrovų? Čia pradeda veikti sprendimai, tokie kaip „Meilisearch“ , „AppSearch“ ir kiti, naudojant modelį, vadinamą „Valet Key“. Naudodamos šį šabloną priekinės programos gali tiesiogiai pasiekti skaitymui optimizuotus modelius, sumažindamos priklausomybę nuo galinių API. Žinoma, „frontend“ vis tiek turi „prašyti“ API „Valet rakto“, tačiau priekinė sistema gali išsaugoti raktus talpykloje, todėl net ir tada, kai API neveikia, sąsaja vis tiek gali bendrauti ir rodyti turinį.
Taikydami šį metodą galime sutelkti dėmesį į skaitymo duomenų bazę ir nesijaudinti dėl skaitymo srauto tvarkymo mūsų API. „Valet Key“, pateiktas sąsajai per mūsų API, yra apsaugotas taip, kad sąsaja negalėtų jo pakeisti. Tai apima iš anksto nustatytus filtrus ir indeksus.
Jei sąsajai reikia papildomų galimybių, ji gali jų paprašyti per API, kur API gali patvirtinti, ar jas leisti. Tai vis tiek mažiau skambučių.
Kai kurie privalumai, kuriuos matau, yra šie:
Tačiau visada yra trūkumų:
Taigi, šis metodas nėra paprastas ir kelia savo iššūkių, bet jei jums tinka ir minusai, nedideliems priekinės sistemos pakeitimams greičiausiai nereikės įtraukti užpakalinės sistemos komandos, supaprastinti kūrimo procesą ir tobulinti. bendras judrumas ir, žinoma, mastelio keitimas turėtų būti lengvesnis.