Megtanulni tanulni - avagy hogyan építettünk a nulláról skálázható ajánlórendszereket egy startupnál

A BME-n végeztem mérnök infósként, most pedig éppen az idionál munkálkodok, ahol óránként több százezer requestet feldolgozó és analizáló ajánlórendszert írunk, load balancelünk és nyelvfeldolgozunk. Éppen ezért lehet, furcsa, ha az én hátteremmel kérdezem, hogy kell-e felsőfokú oktatás ahhoz, hogy az emberből igazán jó szoftverfejlesztő váljék? Főiskola? Egyetem? Bedroom coder?

Én azt vallom és látom, hogy a felsőfokú oktatás nem egy szükséges és elégséges feltétele egy jó programozó születésének, inkább csak egy elég hasznos jó. És akkor hasznos csak igazán, ha az adott egyén megfelelően használja az ott töltött időt.

Ezek az intézményrendszerek csak másodsorban szolgálnak arra, hogy az ember a szakmában először igazán elmélyüljön és megismerje a hogyanokat és a mikénteket. Az IT mérnöki életben való elnavigáláshoz az ott megkapott dolgok egy erős kezdethez elegendőek. Viszont a kulcsszerepe ezeknek a suliknak abban van, hogy az ember - végre! - megtanuljon tanulni.

A legfontosabb képesség, amit az egyetemen felszedtem

Középsuliban én elmókázgattam, elbulizgattam, elröhögcséltem, és kitaláltam az irányt 18 évesen (legalábbis azt hittem) - és mentem is a felsőoktatásba. Számomra itt kezdődött meg igazán a tanulási folyamat.

Nagyobb anyagokat kellett megértenem, hosszabb projekteket végigcsinálnom, komoly beadandókat elkészíteni és nehéz vizsgákon kellett átmenni. Ehhez bizony kellett rengeteg fenéknagyobbítás könyvtárakban, egy csomó körmölés - és még több kávé. A középsulis tanulmányok "komolysága" egyre nevetségesebbnek tűnt, én pedig egyre inkább felismertem, hogy mivel állok szemben. Pedig még ki sem kerültem a való világba, és - utólag nézve - még csak az ottani tudásnak csak egy nagyon kicsi szeletébe haraptam bele a felsőoktatásban töltött pár év alatt.

Az egyetem és a főiskola leginkább egy szűrő. Azt szűri, hogy képes vagy-e a kezdeti ez meg mi a túró érzésből napok, hetek, vagy hónapok alatt elvergődni a kezdem érteni-n keresztül a totálisan vágom-ig. Ha nincs benned a kíváncsiság és türelem, hogy apró információ morzsákból eljussál ide, akkor jó eséllyel vagy nem végzed el a főiskolát vagy egyetemet. Ha pedig el is végzed, akkor csak nagyon nehezen és hosszú idő alatt.

Az egyetemi és főiskolai kapun kilépvén a legerősebb tudás, amit magammal vittem - a tanulás maga volt. Ekkor már képes voltam számomra eredendően elsőre zéró információmennyiségnek tűnő halmazból valamit építeni, és még jobb esetben a tudást rendszerezetten továbbadni. Nekem ezt az egyetemi évek adták - de ezt a tanulási képességet nem csak itt lehet megszerezni. Egyedül is el tudsz ide jutni - egy könyvtárban, a hálószobában vagy egy parkban is össze tud mindez állni kitartó gyakorlás után. Az egyetem és főiskola viszont ezt a folyamatot rendesen megkönnyíti és rendszerezi.

Első nap a startupnál és egy új programozási nyelv... amit még sosem használtam.

A tanulási képességre, a kíváncsiságra és a kitartásra az iparban viszont hatalmas szükség van. Erre Londonban jöttem rá - talán akár kicsit késve is, amikor már 3 éve itt dolgoztam. 2012 márciusában egy akkoriban már felívelő ágban levő startuphoz, az idiohoz csatlakoztam. Félreértés ne essék, addig sem malmoztam persze: tanultam új dolgokat és foglalkoztam új technológiákkal. Viszont az igazán tanulós érzés itt bukkant fel újra nagyon erősen.

Az idio egy ajánlórendszert (recommendation/personalisation engine-t) fejleszt, és amikor csatlakoztam, még az egész cég elfért egy pár négyzetméteres irodában. Kissé egymás hegyén-hátán voltunk, de a pozitív és profi légkör már az első naptól érezhető volt. Amíg mást lehet, hogy zavart volna az általános egymásba könyökölés, én észre sem vettem. Az első héttől fogva ugyanis egyből a mély vízbe dobtak, ráadásul mentőmellény nélkül.

A feladat? Írjunk recommender rendszert a jelenlegi mintájára, de új technológiákkal. A technológiák: ruby és a neo4j gráf adatbázis. Az idő limit? Maximum két hónap. A kihívás? Egyik technológiával sem dolgoztam még korábban. Rubyról persze már hallottam, de közöm még sosem volt hozzá. Gráfokhoz már volt szerencsém korábban, többnyire papíron, de gráf adatbázisokhoz még soha.

Ha eddig kételkedtem volna, hogy helyt tudok-e állni bármilyen projekten, akkor itt volt a lehetőség a bizonyításra. Feltűrtem az ingujjamat és nekiálltam doksit olvasni, próbálgatni, tanulni, kódolni és tesztelni, ahogy épp kellett. Lépésről lépésre, napról napra egyre többet és gyorsabban csináltam, és egyre jobban összeállt a kép.

Az eredmény? Kevesebb, mint két hónap alatt összehoztuk a terméket, tesztekkel, deploymenttel együtt. Nem volt piacvezető, de működött, és nem is ment rá minden időnk. (Körülbelül egy évvel később egyébként befutott egy hasonló projekt. Ekkor leporoltuk a kódot és egy Redis alapú cache kiegészítéssel, egy újabb hónap kódolás után egy production service-ként deployoltuk is).

Feladat: skálázható API írása. Releváns tapasztalat: zéró. Határidő: tegnap.

A recommender rendszer kiépítése után a következő nagy kihívás egy stabil és jól használható API fejlesztése volt. Nyilván eddigre már számolatlan mennyiségű API-t használtam életemben... de nulláról még sosem volt szerencsém építeni egyet. Se senki másnak a csapatban.

Hogy miért volt szükség az API-ra? Például több kliensünk akart webes cikkeket ajánlani cikkek mellé - de úgy, hogy ez személyre szabott legyen. Például ha Te tech cikkeket olvasol főleg, akkor tech cikkeket ajánljon, de ha wellnessben utazol és csak véletlenül kattintottál egy tech cikkre, akkor az ajánlások az ízlésednek megfelelőek legyenek. És itt nem csak webes tartalomról, hanem például testre szabott hírlevélről, hirdetési kampányról és még csomó más dologhoz is használható eszközre volt igény.

A backendünkön a felhasználókról egy teljes körű profilt építettünk. Ez elé akartuk az API-t rakni, hogy a klienseink felhasználónként tudjanak személyre szabott tartalmat lekérni. Az API-nak támogatnia kellett a megfelelő autentikációt, loggolást, illetve skálázhatónak és (amennyire lehet) hibamentesnek kellett lennie.

Neki is álltunk az API-t lekódolni PHP-ban, MySQL és ElasticSearch háttérrel, nginx szerveren futtatni az AWS platformon. Na, ez a rendszer első körben minden volt, csak épp nem skálázható vagy hibatűrő. Nagyobb terhelés alatt elhasalt az nginx, a kódot és a MySQL adatbázist pedig komolyan kellett optimalizálnunk, és még úgy is rendesen akadozott. Ez elég rossz hír volt, de mit lehetett tenni? Talán még jobban optimalizálni? Nem is hülye ötlet...

... a következő pár hétben pedig folyamatosan terheléses teszteket futtattam, az AWS architektúrájáról vadásztam infót és nginx optimalizálási stratégiákat bújtam. És persze, még több terheléses tesztet végeztem. És az eredmény? Az is jött: a rendszer ugyanezzel a felállással rendesen működik. Mindössze két szerverrel naponta könnyedén szolgál ki 1.5-2 millió kérést. Hetente 3-500 ezer email küldéshez, valamint napközben több millió aktív felhasználó személyre szabott tartalommal való kiszolgálásához járul hozzá.

És hogy hogy is jutottunk a nulláról addig, hogy egy több milliós terhelés alatt is vígan muzsikáló API-t építettünk? Folyamatosan tanulva, az infó morzsákat egyesével csipegettünk össze. Ennek az eredményeként pedig most már elég szép mennyiségű AWS és nginx tudást is összeszedtem... mert nem volt más választásom!

Írjunk egy analitika szolgáltatást. Új nyelvvel, új platformra.

Miután a recommendation rendszer és az API elkészült, egy új projekten kezdtünk dolgozni: egy analitika service-en. A rendszer lényege az volt, hogy:

  • Dobáljunk bele felhasználói webes klikkeket és analizáljuk őket
  • Szűrjük ki a botokat
  • Nézzük meg, hogy ismerjük-e már a felhasználót és az olvasott tartalmat
    • Ha nem: hozzunk létre egy új profilt, valamit építsünk felhasználói profilokat már létező python kód felhasználásával
    • Ha igen: akkor frissítsük a profiljukat

Mivel már meglévő python kódra építettünk, egyértelmű volt, hogy ezt a nyelvet fogjuk használni. Már a szemem se rebbent, ugyanis korábban pythont se használtam soha - de már tudtam, hogy pár hét alatt felszedem a szükséges infót, főleg, hogy volt egy srác a csapatban, aki már dolgozott vele.

Rám hárult a feladat, hogy a rendszer vázához használt keretrendszert kiválasszam a lehetséges opciók közül. A követelmény: legyen robusztus, skálázható és gyors. Egy kis kutakodás után az Apache Storm lett a jelölt. Ez egy java alapú, elosztott, valós idejű eseménykezelő rendszer, amibe könnyen tudtuk integrálni a python kódunkat.

Ahogy a többi projektnél, itt sem ugrottunk fejest az egész rendszer lekódolásába, hanem lépésről lépésre haladtunk. Egy bolt - a Storm-on belül egy építőkocka elem - lekódolásával kezdtünk, amivel megerősítettük, hogy jól választottunk keretrendszert. Ezután elkezdtük az üzleti logikát átültetni a Storm keretrendszeren belülre.

Ahogy épült a rendszer, a bolt-ok, a tesztek, a fejvakarások és Storm konfigurálási kérdések száma nőttön nőtt. Két hónappal a projekt kezdése után a csapat két tagja - hogy, hogy nem, kliens lihegéssel a nyakukban - ezen problémák megoldásán küszködött. Ez nagyrészt levelező listás kérdések olvasást, véget nem érő Stackoverflow böngészést jelentett, akár IRC (igen, IRC!) segítségkéréssel. Az eszköz első éles verziója két hónap alatt, a rendszer további része lépésről lépésre fél év alatt elkészült. Ma pedig 15 bolt felhasználásával, jelenleg 15 szerverből álló elosztott rendszerként fut. Egy átlagos napon óránként körülbelül félmillió klikk fut át rajta könnyedén és nap mint nap 150 millió felhasználó olvasási szokásait analizálja. Nem rossz ahhoz képest, hogy megint a nulláról kezdtünk!

Startupoknál tanul az ember. Rengeteget.

A fenti három projektet mind egy éven belül fejlesztettük le az idionál. A cégnél akkoriban egy tucat - nem több, mint 12 - mérnök dolgozott. És ahogy a sztorikból is látszik, az esetek többségében a projektek ezzel a mondattal kezdődtek: "Hogy a túróba...? Ez meg mi...? Hogyan lehetne...?"

Ehhez képest pár hónap alatt elég komoly dolgokat fejlesztettünk. És a hozzáállásunk minden esetben? Folyamatosan tanultunk, mindig kérdésekkel kezdtünk, rengetegszer trial & error hozzáálással.

Külön hangsúlyoznám, hogy mindegyik projektben komoly csapatmunka folyt, minden egyes csapattag a saját képességeihez legközelebb álló modullal és feladattal foglalkozott. Talán ami még fontosabb, hogy senki nem volt rest segítséget kérni a másiktól, és kérdéseket feltenni, ha úgy adódott. Ezeket a kérdéseket feltéve és kellő kíváncsisággal képesek voltunk több ízben is a nulláról egy élesben működő, minőségi rendszert létrehozni. Amíg pedig ez a kíváncsiság, a motiváció és a kitartás megvan, addig igenis van miért dolgozni ebben az iparban.

A kommenteket a Disqus jeleníti meg