2012. október 24., szerda

DynaTrace - A feltárt szerver oldali hibák 2.

Az előző post folytatásaként ismét néhány jellegzetes hibatípust gyűjtöttem össze amelyekkel jómagam foglalkoztam a stabilizációs projekt kapcsán. Hát igen, a DynaTrace ezen hibák megtalálásában is elég hasznosnak bizonyult, nézzük is meg hogy hogyan segített.

Hiányzó TimeOut-ok

Sok helyen találkoztam azzal, hogy a WebService, EJB, URLConnection vagy DB lekérdezéseknél nem voltak timeout-ok definiálva. A timeout-ok hiánya néha komoly stabilitási problémákhoz is vezetett, pl. többször is előfordult, hogy egy belassult web-szolgáltatás miatt a kérések feltorlódtak így a válaszidők is megnövekedtek. Ha már a timeout-okat állítgatjuk, a programozott (java kódbeli) megadás helyett érdemes inkább a konfigurációs paraméterrel való megadást választani, így akár futásidőben is módosíthatjuk az értékét.

Ahogy az alábbi ábra is mutatja, a timeout jellegű hibákat a DynaTrace segítségével elég egyszerűen be lehet azonosítani!


Prepared Statement problémák

Szintén gyakori eset, hogy az SQL lekérdezések paraméterei string konkatenációval voltak beillesztve a PreparedStatement-nél preferált paraméter binding helyett. Ezzel két probléma is van, egyrészt SQL injection-ra adhat lehetőséget másrészt a statement cache-t nem tudjuk majd jól kihasználni.

A lekérdezések végrehajtása alapvetően 2 fázisra osztható az előkészítésre és a paraméterek behelyettesítésével történő végrehajtásra. Az előkészítés egy cpu igényes művelet, ami minden statement legelső végrehajtásakor lefut. Ez a fázis a parszolás, a szintaktikai ellenőrzés és fordítás valalmint a végrehajtási terv elkészítésének a lépéseit tartalmazza. Az előkészített statement, a db connection-onként nyilvántartott statement cache-ben eltárolódik és amíg ebben a cache-ben megtalálható, addig a következő végrehajtások során csak a paramétereket kell behelyettesíteni, az erőforrás igényes előkészítést már nem kell újból végrehajtani.

Nézzünk erre egy példát! Vegyük a "SELECT ID id, DESCRIPTION desc FROM mytable WHERE BL=? ORDER BY desc" lekérdezést, ahol is helyesen a WHERE feltételnél található paraméter nincs beégetve, így ebben a formában a lekérdezés a statement cache-ben csak 1 helyet foglal, függetlenül attól hogy milyen paramétert használunk a lekérdezés során. Az alábbi DynaTrace-el beazonosított SQL lekérdezés pedig a kerülendő változat, miszerint ugyanaz a lekérdezés 8 helyet foglal el a statement cache-ben mivel a paraméter be lett égetve a lekérdezésbe.


Érdemes tudni, hogy a WebSphere alkalmazás szerver alatt a prepared statement cache size alapértelmezett értéke 10, JBoss alatt pedig ha nincs definiálva akkor 0, így ennek az értékét még akkor is érdemes megnövelni ha egyébként paraméterezett sql-eket használtunk!

A statement cache pontos bekonfigurálásához érdemes monitorozást végezni a WebSphere admin console integrált IBM TivoliPerformance Viewer vagy a DynaTrace segítségével a Prepared Statement Cache Discard Count PM-re feliratkozva. Sőt a DynaTrace ezen felül lehetőséget biztosít a parszolás nélkül végrehajtott lekérdezések arányának a monitorozásához is az Executions without parse ratio metrika segítségével.

Java implementációs hibák sokasága

A konfigurációs problémák mellett rengeteg java implementációs hiba is napvilágra került, éppen csak néhány példát megemlítve:

  • Néhány lapozó komponens lekérte az összes rekordot, nemcsak az adott oldalon megjelenítendőket.
  • Explicit garbage collector hívások a Java kódban.
  • Túl gyakori és felesleges Runtime.exec() hívások.
  • Le nem kezelt (és néha a felületre is kijutott) kivételek.
  • Memória szivárgások. (Memory Leak)
  • Custom megoldások implementációs hibái: Saját DB Connection Pool szinkronizációs és logikai hibák.

Ne maradj le a folytatásról sem!


2012. október 8., hétfő

DynaTrace - A feltárt szerver oldali hibák 1.

A stabilizációs projekt során közel 500 hibát sikerült beazonosítanunk és megoldanunk, melyek döntő többsége valamilyen kódolási vagy konfigurációs problémára volt visszavezethető. A következő néhány bejegyzésemben ezekből emelnék ki néhány fontosabbat és írnék a megoldásukról is!

Nem optimális JVM beállítások

Az éles banki környezetben több mint 10 WebSphere klaszter volt kialakítva. A WAS szerverekhez kapcsolódó performancia problémák nyomozásakor találtunk környezetenkénti konfigurációs eltéréseket (melyek megelőzéséről egy későbbi cikkemben fogok írni) valamint nem optimális és hiányzó beállításokat melyekből most csak egyet emelnék ki, mégpedig a JVM Garbage Collector beállításait.

Amikor egy alkalmazás szerveren tranzakcionális jellegű web-alkalmazásokat futtatunk (melyeknél sok a rövid életű objektum), akkor IBM JVM esetén a gencon lesz a nyerő Garbage Collector stratégia! Ennek ellenére a szerverek többségénél nem volt megadva gc policy (alapértelmezett az optthruput) vagy egy másik gc policy volt definiálva, ahol pedig a gencon volt beállítva a nursery terület mérete túl alacsonynak bizonyult, feltehetően nem volt finomhangolva.

Habár a JVM GC tunning a VisualVM eszközzel is megoldható lett volna,  nekünk pont jól jött hogy a DynaTrace is támogatja a JVM monitorozását. A gc suspension time és a heap memória kihasználtság monitorozásához így összedobtunk egy DynaTrace-es dashboard-ot, az optimalizálás során pedig közel 90%-os GC suspension time csökkenést sikerült elérni, ami várakozási időben elég komoly javulást jelentett. (lásd az alábbi ábrákat)


Hiányzó IceFaces konfigurációs paraméterek

A DynaTrace beépített Exceptions nézetét használtuk fel, hogy a keretrendszeri és az alkalmazásokhoz tartozó kivételeket láthatóvá tegyük. Esetünkben a top 20-as listában jópár IceFaces-es kivétel keletkezett, melyek hiányzó web.xml konfigurációs paraméterekre voltak visszavezethetők!


Persze felmerülhet a kérdés, hogy milyen költséges lehet egy kivétel feldobása? Általában elhanyagolható, azonban a fenti esetben ez a kb. 10.000 IceFaces-es kivétel mindössze 10 perc alatt gyűlt össze, így egyértelműen javítani kellett! Amire érdemes odafigyelni, hogy nagy számú kivétel esetén a catch ágban elhelyezett kompenzációs logika valamint a több rétegen keresztül gyűjtögetett stack trace-ek kinaplózása okozhat még jelentősebb performancia problémát!

A folytatás hamarosan következik...