V minulosti jsem si často všiml běžného přístupu, kdy vývojáři (včetně mě samozřejmě) používali stejné API pro čtení i zápis ve všech případech. Ještě více jsme se často spoléhali na stejný zdroj dat, jako je MySQL/PostgreSQL, abychom zvládli obě operace.
To znamená zapisovat do stejných sloupců a číst z nich, což často vede k problémům s optimalizací indexů na polích, která byla intenzivně dotazována.
Zjistili jsme tedy, že například často upravujeme indexy, abychom se přizpůsobili novým filtrům nebo zlepšili výkon dotazů, a pole používaná operátory jako LIKE představovala zvláštní problémy kvůli jejich dopadu na výkon.
Tyto změny často vedou k dalším úpravám backendu, včetně úpravy API, aby byla odhalena aktualizovaná funkčnost, měřené časy kvůli dalším JOINům a tak dále...
Abychom se vypořádali s výzvou ohledně přidávání nových filtrů a věcí do API, došlo k pokusům o optimalizaci procesu pomocí nástrojů a standardů, jako je Apicalypse a samozřejmě GraphQL .
Tato řešení měla za cíl zefektivnit generování dotazů API a snížit manuální úsilí potřebné k implementaci nových filtrů a funkcí, nabídnout dynamičtější přístup ke zpracování přístupu k datům, ale měla dlouhou dobu učení.
Se vzestupem CQRS (Command Query Responsibility Segregation) se začal objevovat nový přístup. Tento způsob myšlení povzbudil použití samostatných zdrojů pro psaní a čtení. Zápisy by mohly vysílat události a čtení by mohlo vytvářet pohledy z těchto událostí na vyhrazených místech. I když byly čtení a zápisy spravovány v rámci stejné databáze (ale různých tabulek), toto oddělení přineslo značné výhody a samozřejmě dokázalo zbavit se druhé výzvy – JOINů a vyhledávacích dotazů na doménových modelech, jako jsou modely čtení. běžně ve formě denormalizovaných JSON.
To však vyvolalo další problém. Při čtení jsme museli škálovat zápisy, což znamená, že jediným důvodem, proč jsme museli škálovat instance naší aplikace z X na Y, bylo čtení. Tento problém by se dal částečně zmírnit ukládáním do mezipaměti a ve světě mikroslužeb bychom mohli mít vyhrazené mikroslužby pro čtení.
Ale...
Přesto to nebylo ideální řešení pro jiné architektonické styly, jako jsou modulární monolity, kde takové oddělení nemusí být v souladu s filozofií designu systému. Další věc byla, že když bylo nefunkční API, nefungoval celý produkt, a když si uvědomíme, že většina produktů spoléhá na více čtení než zápisů, mohlo by to zbytečně ovlivnit podnikání (samozřejmě Aparat from down API ;) )
Co kdybychom se tedy těchto „zobrazení“, známých také jako modely čtení, mohli zeptat přímo, aniž bychom zapojovali rozhraní API a zpracovávali zatížení? Zde vstupují do hry řešení jako Meilisearch , AppSearch a další, využívající vzor zvaný „Valet Key“. Pomocí tohoto vzoru mohou frontendy přistupovat přímo k modelům optimalizovaným pro čtení, což snižuje závislost na backendových API. Samozřejmě, že frontend stále musí "požádat" API o "Valet key", ale frontend může klíče mezipaměti, takže i když API nefunguje, frontend může stále komunikovat a zobrazovat obsah.
S tímto přístupem se můžeme soustředit na čtenou databázi a nestarat se o zpracování provozu pro čtení v našem API. „Valet Key“ poskytnutý frontendu prostřednictvím našeho API je zabezpečen tak, že jej frontend nemůže změnit. Obsahuje předdefinované filtry a indexy.
Pokud frontend vyžaduje další funkce, může si je vyžádat prostřednictvím API, kde API může ověřit, zda je povolí. Stále je to méně hovorů.
Některé klady, které vidím, jsou:
Ale vždy existují nevýhody:
Tento přístup tedy není stříbrnou kulkou a představuje svou vlastní sadu výzev, ale pokud jste v pořádku s nevýhodami, pak malá změna na frontendu pravděpodobně nebude vyžadovat zapojení backendového týmu, zefektivnění procesu vývoje a zlepšení celková svižnost a samozřejmě škálovatelnost by měla být jednodušší.