Nyár van, és nemsokára elmegyek szabadságra, ezért nem adom fel a kérdést, hogy magyarázzátok meg ...
Szóval volt egy szoftver, ami a weben keresztül szolgált ki kéréseket. A válasz összeállítása X darab adatbázis kérés után alakult ki, de mindenképpen 2mp-en belül kellett lennie a válaszidőnek. Az volt a megoldás, hogy aszinkron elindul a "számolás" és ha nincs válasz 2mp-en belül, akkor egy majdnem ugyanolyan jó konzerv választ fog kapni a felhasználó, mint amilyen a pontosan kiszámolt lett volna.
Hogy ez milyen alkalmazásnál tehető meg? Pont annál amit írtunk. Mindegy.
Szóval a rendszer várt egy aszinkron szálra, és ha az nem futott le 2mp-en belül, akkor nem várta meg, hanem leállította, és adott egy konzerv választ.
A baj ott volt, hogy az aszinkron thread használt egy adatbázis kapcsolatot. Az az adatbázis kapcsolat pool, amivel teszteltünk egy idő után észrevette, hogy senki sem hivatkozik a kapcsolatra, és a GC során visszarakta az adatbázis kapcsolatot a pool-ba. Ezt jól le is teszteltük.
Aztán az éles rendszeren egy másik DB pool volt a rendszer alatt.
A rendszer pedig elindult. Amíg nem volt túlterhelve, addig nem volt gond, működött. Méretezve is úgy volt, hogy bírja a terhelést, és naponta úgy 10...15 alkalommal fordult csak elő, hogy nem sikerült válaszolni 2mp-en belül. A 200 kapcsolatos pool kb. egy hét alatt fogyott el. Ahogy fogyott a pool egyre többször adott a rendszer konzerv választ, de ez a meghalást, a pool fogyását nem gyorsította, mert sokszor úgy ölte meg a szálat, hogy az még meg sem kapta a connection-t.
A legszebb a dologban az volt, hogy a connection pool észrevette, hogy felszabadult a kapcsolat, és még le is loggolta, hogy visszarakta a pool-ba, de nem tette. Csak amikor elkezdtük loggolni a pool méretét, akkor derült ki, hogy hiába mondja azt, hogy visszarakta, az ilyenkor eggyel mindig csökkent, mint a szamárbőr.
A legcsúnyább pedig az volt a dologban, hogy gondoltunk rá, hogy ez lehet egy számunkra ismeretlen connection pool implementációval, és ezért a szoftverben volt egy
if( true ){
megöljük a thread-et
}
jellegű kód, és felette 10 sorban komment és magyarázat, hogy miért kell az 'if' után false-t írni, mert különben a szoftver elveszítheti a megölt thread-ben használt DB kapcsolatot, és inkább egyen még egy kis erőforrást a thread amíg lefut, mintsem elfogyjanak a kapcsolatok.
És néztük százszor, és néztük ezerszer a kódot, és csak éppen nem szúrta ki a szemünket, hogy a kommentben 'false' van írva, de a kódban 'true'. Két hétig. Stílusosan mondhatnám, hogy beégett a szemünkbe.
Ez történt.
Na és mi az a beégetéses teszt? Nem ez. A beégetéses teszt nem az, hogy jól beégünk, hanem az, hogy hajtjuk a szoftvert változó, de valamennyire reprodukálható inputtal, terheléssel, és nézzük, hogy nem ég-e be, bírja-e a terhelést, vagy rendszeresen újra kell indítani. Napokig, hetekig, hónapokig akár, attól függően, hogy mennyi az az időszak, ameddig a szoftvernek folyamatosan kell bírnia.
Nem biztos, hogy az a cél, hogy ne kelljen újraindítani. (A mi esetünkben az volt, az üzleti konzekvenciákat nem írom le, de nem volt jó referencia.) Lehet az is, hogy egy 5x8-as szoftvernél elég ha egy napot kibír újraindítás nélkül, éjjel úgyis újra lehet indítani (esetleg automatikusan), és nem ad semmi előnyt azzal a költséggel szemben amit a hibakeresés mondjuk 3 mérnöknapja jelent. Elvileg. Gazdaságilag. Közgazdász szemmel. Aztán nekem az egyik szemem közgazdás, a másik meg mérnök. (Csak ezt kellene eldönteni, hogy melyik.)
Mindig benne van a (mérnök) emberben, hogy ha olyan hiba van a szoftverben, ami miatt minden éjjel újra kell indítani, akkor az más disznóságokat is csinálhat. De, mint tudjuk ilyen szoftverrel is lehet világbirodalmat építeni. Közgazdász szemmel.
Nekem viszont csak az egyik szemem a kancsal. A közgazdász, vagy a mérnök?
Azért a kommentekbe, ha veszi valaki a fáradtságot, kérem megfejtésnek egy francia író nevét.