Što bi bilo kad bi vam netko rekao da se svi dokumenti iz Narodnih Novina mogu hostati u web aplikaciji s pretraživanjem i komentiranjem na "serveru" koji košta oko 400 kn i troši oko 2.5 W?

{height="200px"}

Morpheus:

Neo, sooner or later you're going to realize just as I did that there's a difference between knowing the path and walking the path.

Note: Ovo nije "best practice", preporuka ili želja da se infrastruktura radi na opisani način, nego ilustracija koliko je čak i vrlo slab moderni hardver jak u odnosu na potrebe smiješno male države kao što Hrvatska. Čak i iznimno slab hardver od prije nekoliko generacija je dovoljan za obavljanje ogromne količine zadataka kad je količina podataka mizerno mala i uz minimalne kompetencije može se napraviti puno više uz znatno manje troškove.

Matrix je izašao 1999. - već je prošlo skoro 15 godina - ali u ogromnoj većini IT-a u državnoj upravi vrijeme kao da je stalo početkom 80-ih. To je bastion zatvorenih tehnologija (onih koje se ne mogu koristiti izvan proizvođača i okruženja u kojima su nastale) i hardvera koji ne samo da je zastario sam po sebi nego je zastarjela i arhitektura i shvaćanje što uopće znači moderan IT i kako ga se uopće može, a kamoli treba koristiti. APIS, Mirovinsko i tko zna tko sve ne koriste Mainframeove (u

  1. stoljeću! to je praktički grijeh protiv tehnologije!), a ne samo da visoki management nema ideje kako moderan sustav može izgledati izvan naočnjaka koje po defaultu nose jer se druže isključivo jedni s drugima i s prodavačima točno istih starih rješenja bez prave razmjene novih mišljenja, nego i srednji manadžment ne zna implementirati ono što im je natovareno niti prenijeti programerima u rovovima što trebaju raditi. Malo je za reći da je takav sustav u raspadu i ne odgovara više potrebama modernog građanstva.

Da pokažem što se danas može s nikakvim hardverom i bez puno truda, napravio sam nešto korisno, s malo "razmišljanja izvan kutije".

U slobodno vrijeme, u po sat-dva dnevno tijekom otprilike tjedan dana, napravio sam pretraživu bazu dokumenata iz Narodnih novina koja još omogućuje i da:

  • se pretrage sačuvaju (kao bookmarks) i kasnije pregledavaju
  • se prema sačuvanim pretragama opcionalno pretražuju svi novi dokumenti koje NN objave, te ako ima podudaranja, šalje se e-mail obavijest
  • se pojedini dokumenti mogu označiti kao "omiljeni"
  • se mogu dodavati osobne bilješke na dokumente
  • se može komentirati odnosno raspravljati o svim dokumentima

Namjerno koristim riječ "dokumenti" jer NN osim zakona objavljuje i veliku količinu odluka, pravilnika i drugih službenih dokumenata. Efektivno, ova web aplikacija vam omogućuje da upišete neke pojmove koji vas zanimaju i na e-mail dobijete obavijest ako se pojavi novi dokument iz NN koji sadrži te pojmove.

Link na aplikaciju je ovdje

Naravno, prije korištenja pročitajte upute o korištenju i informacije o aplikaciji jer su u njima opisana i ograničenja aplikacije i budući planovi.

Ako ste samo krajnji korisnik ovakve aplikacije, upravo ste saznali sve što vam treba i želim vam sretno korištenje!

Ako želite znati detalje, čitajte dalje.

Server

Optimizacija informatičkih sustava s obzirom na performanse i efikasnost (tehničku ali i ekonomsku) mi je draga i zanimljiva tema - da sam umjetnik a ne inženjer rekao bi neku klišeiziranu izjavu kao "to je moja strast", ali nećemo ići tako daleko - posao je posao. Aplikaciju sam napravio na ovaj način i smjestio ju tu gdje jesam jednostavno da dokažem da se može i kako se može. I have a point to prove, rekli bi englezi.

Gore opisana aplikacija i njena baza podataka su smješteni na komadu hardvera koji se zove Raspberry Pi. Radi se o računalu baziranom na istoj vrsti procesora koje su koristili mobiteli prije 3-4 godine (dakle, za pojmove IT-a radi se o staroj platformi), s 512 MiB memorije. Ako ste imali originalni HTC Desire ili Googleov Nexus One iz 2010. godine, Raspberry Pi je praktički ista stvar, samo sporija. U Hrvatskoj se može nabaviti barem kod Primotronica i Altpro-a.

Kao digresija: Hrvatska je mala zemlja i podataka koji se u Hrvatskoj vrte je srazmjerno malo. Za ilustraciju: ako bi za svih 4.5 milijuna ljudi u zemlji postojalo po 250 A4 stranica gusto pisanoga teksta (doduše bez slika), svi ti podaci bi zauzeli 4.5 TB, odnosno skoro pa bi stali u disk koji košta 1.800 kn. Naravno, ne zagovaram da se to doista i napravi, u najmanju ruku treba razmišljati o performansama i trajnosti podataka, ali čak i takvo panopticon i centralizirano rješenje ne može koštati pet redova veličine više!

Proof is in the pudding, pa evo što sam napravio: NN od 1990. do danas su objavile preko 65,000 dokumenata. Ovo je smiješno mala količina podataka: u sirovom obliku (onom u kojem su objavljeni) HTML datoteke zauzimaju oko 1.7 GiB mjesta. Sjetite se koliko vaši mobiteli imaju mjesta za pohranu i koliko zauzima (recimo) neki film i razumjeti ćete što mislim.

Usput, ovaj blog se također poslužuje s tog istog Raspberry Pi-a. Ako vas zanima kako izgleda konkretan uređaj koji vam šalje tekst koji upravo čitate (ali i aplikaciju opisanu u ovom tekstu), evo ga:

{height="400px"}

Baza podataka

Rješenje koje sam zamislio koristi bazu podatka PostgreSQL (koja je otvorenog koda i nema troškova licenciranja), za koju znam da ima ugrađenu on-line kompresiju velikih podataka. Doista, kada se podaci prerade na način da se iz HTML dokumenata izbace zastarjeli i nestandardni tagovi i kodiraju kao UTF-8, PostgreSQL te podatke spremi u otprilike 200 MiB. Nažalost, to nije dovoljno jer je jedna mogućnost koju želim imati pretraživanje cjelokupnog teksta.

Da bi se implementiralo pretraživanje cjelokupnog teksta na način koji je dovoljno brz (jer pretraživanje svakog dokumenta pojedinačno i u cijelosti nije nikada dovoljno brzo), potrebno je izgraditi indeks za pretraživanje. PostgreSQL-ov modul za pretraživanje unutar teksta se zove tsearch2 i zapravo nije baš primjeren za ovako ograničene platforme jer se podaci za pretraživanje efektivno dupliraju: jednom u samoj tablici a jednom u indeksu. Prva varijanta koju sam napravio je uključivala i cijeli tekst dokumenata u samoj bazi, što je bilo preveliko: tablica je bila veličine oko 550 MB (tekst dokumenta + tsearch2 vector) i sam indeks (GIN) još oko 200 MB.

Pri dizajniranju baza podataka kod kojih je imalo bitna brzina, zlatno pravilo je da se uvijek nastoji postići da indeks može stati u memoriju. Zapravo sam originalno imao ranu verziju Raspberry Pi-a sa samo 256 MiB RAM-a pa sam morao kupiti noviju s više memorije, da bi indeks stao.

Prva varijanta nije naročito sretno rješenje jer PostgreSQL ima tu nezgodnu osobinu da se u slučaju pretraživanja cjelokupnog teksta čita i indeks ali još jednom i sam search vektor u tablici (zbog čega bi idealno trebao uzeti specijaliziranu bazu za pretraživanje - ali to mogu kasnije). Kako se dokumenti svejedno nalaze kao datoteke, odlučio sam ne raditi još kopiju sadržaja dokumenta u bazi nego im pristupati izravno nakon što se pretraživanje obavi. Ova varijanta je malo sretnija jer sada tablica i indeks zauzimaju oko 350 MB + 200 MB - otprilike taman za Raspberry Pi.

Memorijski buffer za PostgreSQL (shared_buffers) sam postavio na 250 MiB, da sigurno pokrije veličinu indeksa.

Raspberry Pi za pohranu koristi SD karticu i performanse sekvencijalnog čitanja i pisanja su oko 20 MiB/s. Međutim, nasumične operacije su izrazito spore, osobito pisanje (brzo dolazi do zasićenja i kartica počinje odgovarati na tek nekoliko IOPS), te ih treba izbjegavati. Pisanje na SD kartice treba izbjegavati i iz razloga što im to smanjuje trajanje (osobito u kombinaciji s multipliciranjem pisanja koje je prisutno sa slučajnim pisanjem), pa sam tijekom svih "glomaznih" operacija nad bazom (izvorno upisivanje podataka, stvaranje indeksa) privremeno isključio fsync.

Pretraživanje podataka u bazi koji su relativno često traženi ili koji su slični već traženim podacima je sada dosta brzo - daleko ispod pola sekunde - no problem je ako se pretražuju podaci koji nisu u cacheu. Tada je odziv i po 10-tak sekundi.

Web aplikacija

Samu Web aplikaciju sam napisao u okruženju Django, u jeziku koji se zove Python, koji definitivno nije baš najbrži na svijetu. Python i Django su vrlo dinamični, interpretirani, koriste relativno puno memorije i općenito su korisniji kada treba nešto napraviti jednostavno i u malo vremena nego kada to nešto treba imati velike performanse.

Da bi maskirao sporost baze podataka i servera, koristim agresivno cacheiranje na nekoliko mjesta: upiti za brojem dokumenata, za pretraživanjem pa čak i operacije pronalaženja korijena riječi sve koriste interni memorijski cache. U najboljim okolnostima (kada su svi ovi cachevi korišteni pri prikazivanju stranice), dostižu se performanse od preko 10 upita u sekundi. Ovo je dakako vrlo slab rezultat u apsolutnom smislu, no sjetite se: ovo je ARM procesor star nekoliko generacija, na 700 MHz, s pola gigabajta memorije, i u Djangu koji je isto spor imam 10 stranica u sekundi! S tom perspektivom se zapravo radi o impresivnom rezultatu.

Na laptopu koji samo 2-3 puta brži (AMD 1.4 GHz) i ima više gigabajta memorije, aplikacija i baza podataka doslovno lete i operacije su praktički trenutačne.

Operacija pronalaženja korijena riječi mi je bila iznenađujuće spora pa moram nešto reći i o njoj. Radi se o vrlo jednostavnom algoritmu koji pokušava "normalizirati" sufikse riječi, koji je baziran na relativno starom znanstvenom radu kojem sam nažalost zaboravio autore (javite mi se ako se prepoznajete), za kojeg sam napisao implementaciju za PostgreSQL (kao stemming modul za tsearch2) i Python koje su dostupne ovdje. Verzija za PostgreSQL je u C-u i relativno je brza no ekvivalent u Pythonu je bio dovoljno spor da sam morao raditi lookup tablicu kao cache.

Razlog zašto sam uopće radio verziju u Pythonu je što je, s druge strane, PostgreSQL-ova funkcija ts_headline koja daje "izvatke" iz teksta s boldanim riječima koje su pronađene katastrofalno spora i morao sam ju zamijeniti verzijom u Pythonu (da, toliko je spora).

Dodavanje osobnih bilježaka je vrlo jednostavna operacija i napravio sam ju izravno, ali za komentiranje (diskusiju) nema smisla izmišljati toplu vodu pa sam koristio Disqus.

Web aplikacija se izvodi kao FastCGI proces. Procesor u Raspberry Pi-u je jednojezgreni pa nema puno prostora za paralelizaciju. Efektivno, može se iskoristiti iowait stanje dok se nešto učitava iz baze podataka za obavljanje nečeg u Pythonu. S druge strane, Python sam po sebi nije baš pogodan za multithreading no količina memorije je takva da bi ju brzo zapunio novim instancama Python interpretera (forkanjem), pa sam se odlučio za nekakvo srednje rješenje: FastCGI server (Python instanca) je multithreadana, s 5 threadova. Zbog načina na koji Python radi, pristupanje bazi može biti konkurentno, ali sve skupa ne vrijedi imati previše koda koji se izvodi istovremeno. Web server je lighttpd.

Mreža

Raspberry Pi je trenutno smješten na stolu u mom stanu, no plan je staviti ga u neko bolje kućište i na mjesto gdje neće smetati, i spojen je na ADSL modem kao i druge stvari u stanu. Brzina uplinka (iz stana prema Internetu) je 768 kbps, ili 96 KiB/s, što nije puno, ali stranice ne sadrže slike i koristi se HTTP kompresija te je svako učitavanje stranice "teško" oko 5 KiB (što se prevodi u oko 19 stranica/s). Puno koristim vanjsko hostanje resursa kao što su JavaScript i CSS datoteke, što znači da se vrlo malo od ukupne količine podataka prenosi izravno preko mog ADSL-a.

ADSL je ovdje i najmanje pouzdani dio sustava, jer mi često puca veza (možda ovo pročita netko iz Amisa, hint, hint). Ako ne možete doći do aplikacije, u oko 80% slučajeva se radi o tome da je jednostavno pukla veza.

I na kraju

To je to... dokumenti Narodnih novina, pretraživi, s obavijestima na e-mail kad se pojave novi koji zadovoljavaju pretragu, s osobnim bilješkama i komentiranjem, na Raspberry Pi-u na 700 MHz, pola gigabajta memorije i SD kartici od 8 GiB, sve skupa manje od 500 Kn.

Ne kažem da je ovo optimalna platforma za takvu aplikaciju ili da je poželjno tako drastično štediti na infrastrukturi, ali sljedeći put kad budete nabavljali server, razmislite o tome.

Previous Post Next Post