Monday, April 28, 2008

Override service.

เมื่อวันก่อน ผมพึ่งพบปัญหา java process กิน cpu ไป 99% ตลอดเวลา
ในขั้นแรกก็จัดการ "kill -3" เสีย เพื่อที่มันจะได้ให้มัน dump stack trace ออกมาให้เราดู
"ajp-8009-2" daemon prio=1 tid=0x08c76ef0 nid=0x3d52 runnable [0x6aeb6000..0x6aeb8040]
at java.lang.ClassLoader.loadClass(ClassLoader.java:299)
- waiting to lock <0x7e734d70> (a sun.misc.Launcher$AppClassLoader)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268)
- locked <0x7e734d70> (a sun.misc.Launcher$AppClassLoader)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1267)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1198)
at java.beans.Introspector.instantiate(Introspector.java:1453)
at java.beans.Introspector.findExplicitBeanInfo(Introspector.java:410)
- locked <0x6ebe1848> (a java.lang.Class)
at java.beans.Introspector.<init>(Introspector.java:359)
at java.beans.Introspector.getBeanInfo(Introspector.java:222)
at java.beans.Introspector.<init>(Introspector.java:368)
at java.beans.Introspector.getBeanInfo(Introspector.java:222)
...
at org.apache.tapestry.util.exception.ExceptionAnalyzer.buildDescription(ExceptionAnalyzer.java:129)
at org.apache.tapestry.util.exception.ExceptionAnalyzer.analyze(ExceptionAnalyzer.java:86)
at org.apache.tapestry.util.exception.ExceptionAnalyzer.reportException(ExceptionAnalyzer.java:378)
at org.apache.tapestry.error.RequestExceptionReporterImpl.reportRequestException(RequestExceptionReporterImpl.java:59)

จากการไล่ stack trace ก็พบว่า มันมีปัญหาในส่วนของ introspector
ซึ่งเกิดจากหน้าจอรายงาน Error ของ Tapestry, พยายามที่จะ dump ข้อมูล nested Exception ออกมาให้เรา
โดยมันพยายามจะใช้กลไก Introspector ในการอธิบายปัญหาที่เกิดขึ้น, แต่ไม่รู้ด้วยเหตุใด เจ้า introspector มันดันหา class บางตัวไม่พบ
มันก็เลย lock, waiting to lock classloader อยู่

สาเหตุของปัญหาจริงๆ ยังจับไม่ได้คาหนังคาเขา แต่คาดว่าน่าจะเกิดจากการ stop webapp บางตัวลงไป กลางอากาศ ณ ขณะที่ user กำลังใช้งานอยู่
เมื่อยังจับต้นตอไม่ได้ แต่ก็ไม่อยากให้เกิดเหตุการณ์ cpu 99% อีก
ผมก็เลยต้องหาวิธีการแก้ปัญหาชั่วคราวก่อน

สิ่งที่เราต้องการก็คือ เราต้องการ replace function ในส่วนของการพยายามอธิบายรายละเอียด exception ที่เกิดขึ้น
(ให้มันลดการอธิบายรายละเอียดลง)
ในการแก้ปัญหานี้ ถ้าเจ้า framework ไม่ได้ออกแบบมาดีพอ เรามักจะต้องใช้วิธี download source code ของ framework มาแก้ไขแล้วก็็ build custom version เอาเอง
(หรือไม่ก็ใช้ AOP ซึ่งก็ยุ่งไปอีกแบบ)

โชคดีที่ tapestry ไม่ได้อยู่ในกลุ่มนี้
Howard ออกแบบ tapestry มาอย่างยอดเยี่ยม
มีความเป็น modular สูง สามารถถอด,เพิ่มเปลี่ยน function ได้ง่าย

ในกรณีนี้ สิ่งที่เราต้องก็คือไล่หาว่า service ตัวไหน รับผิดชอบงานนั้นอยู่
เมื่อเจอแล้ว ก็ทำตามคู่มือ ว่าด้วยการ Overriding a Service
(production ผมยังใช้ tapestry 4 อยู่)

Related link from Roti

1 comment:

roofimon said...

เทพครับ Tapestry