Obsah | Dal¹à | Pøedchozà |
Tato kapitola se podrobnì zabývá serverovými komponentami systému Agent. Nejprve v èásti Architektura serverù systému Agent (5.1) popisuje serverovou èást systému Agent jako celek a poté také to, co majà oba servery spoleèné, tedy jaké koncepty a technologie sdÃlejÃ. Dále je v èásti Vyhledávacà server (search_svr) (5.2) popsán vyhledávacà server systému Agent. Dùle¾itá je zejména kapitola Databázový stroj (5.2.1) popisujÃcà implementaci jádra systému Agent - plnotextového vyhledávacÃho stroje. Kapitola Sûový server (net_svr) (5.3) se zabývá specifiky sûového serveru systému Agent.
Na obrázku 5.1-1 vidÃte logický pohled na architekturu serverù systému Agent. Pro jednoduchost je zobrazen pouze jeden vyhledávacà a jeden sûový server. Z obrázku je patrná modularita návrhu systému, která se samozøejmì promÃtla i do vlastnà implementace.
Obrázek 5.1-1 - architektura serverù Agent
V následujÃcÃch odstavcÃch probereme nìkteré dùle¾ité
prvky implementace. Za prvé je to charakter databázového
stroje, ten je koncipován jako knihovna. Neobsahuje tedy
¾ádné øÃdÃcà objekty - ¾ádná vlastnà vlákna
výpoètu. NavÃc je zcela oddìlen od zbytku vyhledávacÃho
serveru a komunikovat s nÃm lze pouze skrze pøesnì definovanou
mno¾inu objektù tvoøÃcÃch rozhranà k databázovému stroji.
Toto rozhranà tvoøà objektový model databázového stroje a
umo¾òuje jeho budoucà vyjmutà a znovupou¾ità v jiném
systému. Dal¹à samostatný podsystém tvoøà filtry. I ty
jsou zcela nezávislou èástà sytému a øÃdÃcà objekty
serveru s nimi komunikujà pouze prostøednictvÃm objektu FilterManager
.
Rovnì¾ komunikaènà vrstva serveru se neprojevila na designu jádra serverù. Naopak rámec (framework) architektury, podrobnì rozebraný v následujÃcà kapitole, je koncipován tak, aby bylo mo¾né snadno vymìnit komunikaènà vrstvu za jinou. Toho také bylo vyu¾ito v prùbìhu vývoje systému. O rozhranà sûového serveru bylo rozhodnuto hned na poèátku vývoje: nic jiného ne¾ TCP/IP se nejevilo jako smysluplné. Naopak o rozhranà mezi vyhledávacÃm serverem a sûovým serverem dlouho nebylo jasno. Pùvodnà zámìr poèÃtal s vyu¾itÃm technologie OLE Automation, zalo¾ené na komponentovém modelu COM. Nakonec se v¹ak ukázalo, ¾e tato technologie má jistá omezenà týkajÃcà se práce s vÃce vlákny v prostøedà Windows 95, která by ohrozila ¹kálovatelnost a výkon vyhledávacÃho serveru. Proto bylo i pro komunikaci mezi vyhledávacÃm serverem a sûovým serverem zvoleno osvìdèené TCP/IP.
Stejnì jako vìt¹ina serverù na Internetu (HTTP servery, FTP servery) i systém Agent pou¾Ãvá pro komunikaci se svými klienty textové rozhranÃ1). Fyzické rozhranà serverù tedy splòuje jednoduchý model typu po¾adavek/odpovìï (request/response) a celá slo¾itost rozhranà se pøesouvá dovnitø serverù. Toto øe¹enà má tu výhodu, ¾e dle specifikace jazyka rozhranà mù¾e kdokoliv v jakémkoliv programovacÃm jazyce umo¾òujÃcÃm komunikaci pøes TCP/IP napsat klienta systému Agent. Nevýhoda v¹ak spoèÃvá ve slo¾itosti vyhodnocovánà takového jazyka jak na stranì serveru tak na stranì klienta. Servery systému Agent èelà tomuto problému tÃm, ¾e interpretaci jazyka a indikaci chybných povelù zaji¹»uje automat vygenerovaný na základì gramatiky uvedené ve speciálnÃm konfiguraènÃm souboru. To umo¾òuje pru¾né zmìny jazyka i znaèné znovuvyu¾ità parsovacÃho kódu obìma servery. Zároveò se tÃm znaènì eliminovala potenciálnà chybovost, která by hrozila pøi manuálnÃm implementovánà této funkcionality.
Poznámka 1: Rozhranà serverù nenà èistì textové. Ka¾dá zpráva, která má být serverem pøijata, i ka¾dá, která je serverem odeslána, obsahuje binárnà hlavièku o délce deset bajtù. VÃce o komunikaènà vrstvì se dozvÃte v kapitole Konektory (5.1.2).
Z povahy problému øe¹eného pøi návrhu architektury serverù systému Agent vyplynulo, ¾e bude nutné pomìrnì masivnì nasadit vÃcevláknové zpracovánà (multithreading). Av¹ak implementace aplikacà umo¾òujÃch konkurentnà nebo (na vÃceprocesorových poèÃtaèÃch) paralelnà zpracovánà dat s sebou èasto nesou znaènì zvý¹ené nároky na odbornost a obezøetnost implementace a znaèné dodateèné náklady na odladìnà systému.
Abychom zabránili tìmto problémùm, bylo tøeba zajistit, aby se problematika vÃce vláken dotýkala pokud mo¾no minimálnà èásti kódu. To bylo zaji¹tìno na nìkolika úrovnÃch. Pøednì byly u¾ pøi návrhu eliminovány ve¹keré aktivnà objekty z databázového jádra. Dále bylo pøedem jasnì deklarováno, které datové struktury budou potenciálnì vyu¾Ãvány vÃce vlákny najednou a u tìchto datových struktur (týká se to zejména databázového jádra) bylo vy¾adováno zaji¹tìnà konzistence s pou¾itÃm synchronizaènÃch primitiv operaènÃho systému. Z výkonnostnÃch ani implementaènÃch dùvodù v¹ak nebylo vhodné, aby mno¾ina takto o¹etøených objektù obsahovala v¹echny nebo velkou vìt¹inu objektù vyskytujÃcÃch se v serverech systému Agent.
Proto byla architektura systému navr¾ena tak, aby objekty, které nemusà být nutnì sdÃleny, sdÃleny nebyly a navÃc ani nebyly zasa¾eny synchronizaènÃm kódem. Naopak tyto objekty ¾ijà v umìle vytvoøeném prostøedÃ, které se chová jako by bylo souèástà jednoduché jednovláknové aplikace. Ve¹kerou problematiku vÃcevláknového zpracovánà a zaji¹tìnà synchronizace aktivnÃch objektù si berou na svá bedra tak zvané výkonné objekty jádra. Tyto objekty tvoøà kostru architektury serverù systému Agent a jsou pro oba servery shodné.
Na obrázku 5.1.1-1 vidÃte
schematické zobrazenà konceptu. Ten lze struènì shrnout do
následujÃcÃch nìkolika odstavcù. Konkurenènà zpracovánÃ
je v serverech systému Agent zaji¹tìno pomocà metody zvané thread
pool, tedy skupiny rovnocenných vláken, která jsou
vzájemnì zamìnitelná. V¹echna vlákna jsou v systému Agent
implementována jako objekty, jejich¾ tøÃdy dìdà od
spoleèného pøedka zvaného Runnable
. Vlákna
sdru¾ená ve thread poolu jsou instancemi tøÃdy zvané EaterThread
.
Tyto objekty nedìlajà nic jiného, ne¾ ¾e ètou zprávy ze
vstupnà fronty zpráv. Ve chvÃli kdy pøeètou zprávu,
povìøà svou instanci potomka abstraktnà tøÃdy Worker
,
aby zpracoval po¾adavek, a poté zapùà výsledek do
výstupnà fronty.
Obrázek 5.1.1-1 - schematické zobrazenà architektury serveru
V¹echnu vlastnà práci tedy vykonajà objekty typu Worker
.
Jak ji¾ bylo uvedeno vý¹e, ka¾dé vlákno ve thread poolu má
svého "dìlnÃka". Ten je inicializován tak, ¾e
"vidÃ" v¹echny potøebné datové struktury, nebo si
je umà vytvoøit. Èást tìchto struktur je sdÃlena mezi
vlákny výpoètu (a ty musà být zabezpeèeny) a èást z nich
vlastnà ka¾dý "dìlnÃk" jako kopii pro svou
vlastnà potøebu. Ka¾dý "dìlnÃk" tedy ¾ije ve
svém vlastnÃm svìtì a nevà nic o ostatnÃch ani o tom, ¾e
bì¾à v prostøedà s vÃce vlákny.
Je samozøejmé, ¾e v¹echno nenà tak jednoduché. Jak jsme øekli ji¾ vý¹e jednotlivá vlákna ve thread poolu jsou zamìnitelná. Je tedy jedno, které z vláken zpracuje právì pøÃchozà po¾adavek. Aby tento mechanismus správnì fungoval, musà být zaji¹tìno korektnà ulo¾enà stavu výpoètu. Jinými slovy, lokálnà datové struktury mù¾e ka¾dý "dìlnÃk" pou¾Ãvat pouze pro ulo¾enà doèasného stavu výpoètu. Data jsou tedy platná pouze v rámci vyøizovánà jednoho po¾adavku. Informace, které majà pøeèkat tuto dobu, aby mohly být pou¾ity pøi zpracovánà nìjakého následujÃcÃho po¾adavku, musà být ulo¾eny ve sdÃlených datových strukturách dostupných i pro "dìlnÃky" z jiných vláken. Vlastnà "dìlnÃci" tedy musà být bezstavové objekty.
Synchronizaènà body - øÃdÃcà objekty
Jaké jsou tedy synchronizaènà body v architektuøe serverù systému Agent? Jednak jsou to zabezpeèená mÃsta ve sdÃlených datových strukturách a jednak to jsou vstupnà fronta po¾adavkù a výstupnà fronta odpovìdÃ. Jeliko¾ pracovnà thready jsou zamìnitelné a jejich objekty de facto bezstavové, je mo¾né pru¾nì mìnit jejich poèet. Vstupnà a výstupnà fronty se zamykajà pouze na dobu vlo¾enà a vyjmutà prvku. ©kálovatelnost celého systému je tedy pøÃmo (a pouze) závislá na propustnosti sdÃlených datových struktur, v na¹em pøÃpadì databázového stroje.
Do skupiny "konektory" øadÃme ty objekty v systému Agent, které majà zajistit komunikaci mezi jednotlivými servery, pøÃpadnì mezi servery a klienty. Jak ji¾ bylo uvedeno vý¹e, konektory v systému Agent zapouzdøujà komunikaci nad protokolem TCP/IP.
Pro potøeby projektu Agent byl stanoven protokol pracujÃcà jako nadstavba nad TCP/IP. Aplikace v rámci systému pou¾Ãvajà proudovì orientované (stream oriented) spojenà poskytované protokolem TCP/IP. Aplikace v systému Agent v¹ak nepracujà s proudy, nýbr¾ s po¾adavky a odpovìïmi (requests/responses). Data tedy teèou ve formì zpráv. Jeliko¾ jsou tyto zprávy asynchronnà nesou si svoji identifikaci. Pokud klient posÃlá po¾adavek na server, oznaèà po¾adavek (pro sebe) unikátnÃm èÃslem. Odpovìï na po¾adavek pøijde oznaèena stejným èÃslem. Server identifikuje ka¾dou zprávu uspoøádanou dvojicà <identifikace klienta, identifikace zprávy>. Nenà tedy nutné, aby identifikátory zpráv byly globálnì unikátnÃ.
Celá zpráva, vèetnì identifikace zprávy, po¾adavku i odpovìdi je zapouzdøena do objektového typu. Proto je jádro systému nezávislé na pou¾ité komunikaènà vrstvì. Pokud se zmìnà komunikaènà vrstva a zmìnà se napøÃklad zpùsob identifikace klienta, jádro se o tom vùbec nedozvÃ, proto¾e se o identifikaci zprávy nestará. Jak jste si jistì v¹imli z pøedchozÃho výkladu a obrázkù, jádro prostì vezme po¾adavek z fronty, vyøÃdà ho a zase ulo¾à do fronty. Správné mapovánà odpovìdà ke správným klientùm zaøÃdà a¾ komunikaènà vrstva, která ète zprávy z fronty odpovìdÃ. Ta samozøejmì musà obsahu identifikace zprávy rozumìt, ov¹em zajÃmá se opìt pouze o identifikaci klienta. Interpretace èÃsla pøiøazeného zprávì je a¾ na klientovi.
Jak vyplývá z pøedchozÃho odstavce, jediné co musà zpráva posÃlaná mezi aplikacemi v systému Agent obsahovat je lokálnì unikátnà èÃslo, které umo¾nà spárovat po¾adavky a odpovìdi. Ve skuteènosti to v¹ak nenà v¹echno. Spolu se zprávou se zasÃlá je¹tì délka datového obsahu zprávy. To slou¾à jako bezpeènostnà opatøenÃ. Servery systému Agent majà zakódovanou maximálnà délku zprávy, kterou mohou akceptovat. Pokud je pøi pøijÃmánà zprávy poru¹en formát hlavièky nebo délka zprávy pøekroèà povolenou mez, je serverem vyslána chybová zpráva a klient je okam¾itì odpojen.
Podrobný popis formátu hlavièky naleznete ve zdrojovém
souboru genericsocket.h. V pøÃpadì, ¾e chcete
psát klienta systému Agent, nenà nutné tento formát
studovat. Existujà toti¾ právì zmiòované tøÃdy, které
zapouzdøujà komunikaci se servery systému Agent. Tyto tøÃdy
jsou implementovány pro jazyk C++ a Java. Pro jazyk C++ se
jedná o tøÃdy Agent::GenericSocket
a Agent::ClientSocket
,
pro Javu pak agent.HeaderRW
a agent.HeaderSet
.
1999-03-05 | Jaroslav Gergic |