PDA

View Full Version : چطور –noclassgc شب من رو خراب کرد!



mazdadoost
پنج شنبه 19 دی 1387, 12:37 عصر
سلام!
دو ماهی میشه که به شکل مشترک با شرکت گاز در حال کار رویه راه اندازی طرحه حفظت کاتدی خود کار وهوشمند در 80 ایستگاه گاز شهر ... هستیم.
چند هفته ای هست که پروژه وارد فازه پایلوت شده و منهم کلی بیکار شده بودم!(به جز آموزش به چند تا گیگیلی برایه راهبری قسمتی از برنامه که بامن بوده!)
قسمتی که با من بود شامل log کردن پیام هایه سیستم (هر Node سیستم که فعلا فقط 12تاش عملیاتی شده!) رویه سرور راهبری هست که تمام با Log4J پیاده سازی شده.(Remote Appender ,,,). منابع لاگ هم تو فازه پایلوت خیلی زیاده از ردگیری متد هایه برنامه تا پیام هایی که از منابع سخت افزاری طراحی شده برایه کنترل حفاظت کاتدی میان(اون قسمت با JNI پیاده شده) .
تا دیشب مشکلی نبود .حدود ساعت 4 بود که مسئول محترمم خانم ... زنگید به تلفن منزل گفت یه مشکلی پیش اومده برنگ فلان جا کارت دارن!
تماس گرفتم گفت سرور مرکزی از کار افتاده(هنگ فقط مربوط به Jrun بود.).و همونطور که گفتین سرور رو دست نزدیم تا با شما هماهنگی کنیم.گفتم دسش نزنید تا خودم بیام!
رفتم و دیدم :
1-پروسه JVM تقریبا 85 تا 92 درصد CPU تایم رو به خودش اختصاص داده(یکی از چهار هسته بقیه هم بین 10 تا 50 60 درصد درگیر بودن!).
2-Heap وضعیت خوبی داشت و تا 50 درصد و کم و بیش همینقدر بود.

پروفایلر رو نمیتونستم اجرا کنم .تا میخواست به JVM بچسبه سیستم یخ میزد!
تنها کاری که تونستم انجام بدم Dump کردن حافظه JVM بود. و بعدم به پروسه ننگ آورش خاتمه دادم. و رفتم دوباره (خوشبختانه تمام Node ها خودشون میتونن لاگها رودر صورت قعط اتصال به شکل محلی ذخیره کنن و بعد به محض اتصال با سرور مرکزی سینک شن). پروفایلر رو اجرا کردم و سرور رو تو مد Debug بالا اوردم .

همه چیز خوب پیش میرفت . حدود 2 ساعتی سیستم رو Prob کردم و در نهایت رفتم سراغه Snapshot هایه پروفایلر .

متوجه شدم آخرایه Prob فعالیت GC به شکل مسخره ای بالا رفته البته نه در حد هنگ ولی ادامهدار شده.در کل GC یک Heap یک GiG نباید بیشتر از چند ms طول بکشه.اما حدود چند ثانیه طول کشیده بود.
اینجا بود که شکم برد به تنظیمات JVM .
کنسول Jrun روباز کردم و به تنظیمات JVM نگاه کردم! بله سرور با پارامتر –noclassgc اجر شده بود.این پارامتر و چند تا پارامتر دیگه مورد علاقه راهبر Jrun ماست!
–noclassgc رو حذف کردم و سرور رو دوباره تو Debug Mode بالا اوردم. و تا صبح Prob ش کردم.هیچ مشکلی پیش نیومد.چند خطی نوشتم تو دفتره مستندات و رفتم دفتر و یه جستجو در باره –noclassgc کردم.میدونستم کار این پارمتر چیه امامیخواستم ببینم Issue چیزی داره که مشکل پیش اومده!(تمام کلاس هایه برنامه در یه فضایه حافظه جداگانه از Heap به اسم permanent space قرار میگیرند.بعد هر وقت نیاز به شی از اینکلاس باشه JVM از رویه این کلاس هایه کش شده شی رو در Heap ایجادمیکنه. این حافظه هم GC میشه .مگر اینکه JVM رو با پارامتر – noclassgc
اجرا کنیم! اینطوری هیچ کلاسی از permanent space\پاک نمیشه!و permanent space پر میشه) .
چیزی که از جستجوم متوجه شدم این بود که وقتی JVM سان رو با –noclassgc
اجرا میکنیم با پر شدن permanent space جاوا GC رو فراخانی میکنه اما نمیتونه permanent space رو خالی کنه پس میره و اشیائ حذفی Heap روپاک میکنهو دوباره به permanent space نگاه میکنه و باز با دیدن وضعیت permanent space که هیچ تغیری نکردهو پره دوباره Heap رو GC میکنه و تو این چرخه گیر میفته و بعد از یه هنگ درستو حسابی Out of memory میده!

فکر کردم توضیح این تجربه شاید برایه سایر دوستان هم مفید باشه.و چنانه رویه JVM ی غیر از سان کار میکنند شاید اگر با چنین مشکلی مواجه شدن دلشون خواست تو این تاپیک یا تاپیک مشابهی مسئله رو طرح کنند.
موفق باشید.

unhandled_event
سه شنبه 01 بهمن 1387, 06:56 صبح
سلام
ممنون از اینکه تجربتون رو اینجا مطرح کردید.
با اجازه یکی دوتا شایدم سه تا یا بیشتر :چشمک: سوال داشتم شرمنده.
اول اینکه شما از چه app server یی استفاده میکنید ؟ آیا جزو سرورهای شناخته شده هست یا اینکه خودتون یک برنامه نوشتید و بصورت برنامه مستقل بالا میاد؟ محدودیتی نیست برای استفاده از jvm های غیر از sun ؟
سوال دوم اینکه :
ما با Oracle Application Server 10.1.x.x کار میکنیم خدا نصیب نکنه بنظر بسیار پر دردسر و سخته. برعکس طرز تفکر عمومی شاید یک admin خوب باید سالها تجربه برنامه نویسی و سروکله زدن با j2ee رو هم داشته باشه که من تازه اول راهم. در هر مشکلی قبل از تسلیم شدن و دور زدن مساله باید دنبال راه حل اصولیش هم بود. ظاهر همه چیز این اوراکل حساب کتاب داره و هر کاری که کردن و هر پیچیدگی حتما دلیلی داشته .
تا جاییکه فهمیدم سه قسمت اصلی در کنار خیلی چیزهای دیگه داره :
1- یک وب سرور Apache
2- یک ماژول بزرگ بنام opmn که وظیفه مدیریت ، log ، مونیتور و خلاصه مدیریت داستان رو داره.
3- چند Instance از Oc4j که سرویسها و برنامه ها رو هاست میکنه که خودشون دنیای دیگه ای دارن.

چند چیز عجیب اینجاست :
1- بنظر میاد بعضی از ماژولها با jre 1.4 (سان) که روی دایرکتوری اصلی سرور یا home هست بالا میاد اما application های وب ما با جاوای 1.5 کامپایل میشن و deploy میکنیم و مشکلی هم نداره. ظاهرا oc4j داره با 1.5 jre کار میکنه چطور ممکنه آیا اینها دوتا jvm در کنار همن ؟ این میتونه ایجاد اشکالات ناشناخته بکنه ؟

2- بعد از حدود 15 تا 20 روز کار کردن ، مقدار free memory سرور (لینوکس ردهت هست) بشدت کاهش پیدا میکنه و به همین دلیل cpu usage کم کم میره بالا حتی با stopو start کردن تک تک application ها هم مشکل حل نمیشه قاعدتا درصورت پایداری سرور نباید اینطور باشه اما انگار بعنوان مسکن GC میخواد که من دقیقا نمیدونم کجاست بهرحال این راه حل نیست رفتم سراغ پارامترهای jvm چیز خاصی نبود یا من نمیدونم و چاره ای نیست جز restart کردن سرور. مشکل از کجاست ؟ این میتونه باگ سرویسها یا agent هاش باشه یا اینکه طبیعیه و بریم سراغ خط به خط برنامه های خودمون ؟ noclassgc میتونه کلید مشکل باشه ؟

3- طبق معمول همه سرورها oracle هم با log4j کار میکنه. آیا کلا در این سرور و بقیه سرورها مثل weblogic یا sun میشه log رو بیشتر در اختیار گرفت و برد در سطوح مختلف هر application یا هر context ؟ بنظر میاد log4j.properties داخل application کار چندانی در این مورد انجام نمیده و جاهای دیگه ای هم هست اما مستندات زیادی در مورد استفاده خوب از log4j و استفاده اون در سرورهای مختلف وجود نداره. لطفا اگر کتاب یا رفرنس خوبی درمورد log4j میشناسین معرفی کنین متشکرم .

handinux
پنج شنبه 03 بهمن 1387, 13:28 عصر
جناب مزدادوست من هم تشکر می کنم.بسیار مفید بود

mazdadoost
جمعه 04 بهمن 1387, 00:33 صبح
سلام
ممنون از اینکه تجربتون رو اینجا مطرح کردید.
با اجازه یکی دوتا شایدم سه تا یا بیشتر :چشمک: سوال داشتم شرمنده.
اول اینکه شما از چه app server یی استفاده میکنید ؟ آیا جزو سرورهای شناخته شده هست یا اینکه خودتون یک برنامه نوشتید و بصورت برنامه مستقل بالا میاد؟ محدودیتی نیست برای استفاده از jvm های غیر از sun ؟
سوال دوم اینکه :
ما با Oracle Application Server 10.1.x.x کار میکنیم خدا نصیب نکنه بنظر بسیار پر دردسر و سخته. برعکس طرز تفکر عمومی شاید یک admin خوب باید سالها تجربه برنامه نویسی و سروکله زدن با j2ee رو هم داشته باشه که من تازه اول راهم. در هر مشکلی قبل از تسلیم شدن و دور زدن مساله باید دنبال راه حل اصولیش هم بود. ظاهر همه چیز این اوراکل حساب کتاب داره و هر کاری که کردن و هر پیچیدگی حتما دلیلی داشته .
تا جاییکه فهمیدم سه قسمت اصلی در کنار خیلی چیزهای دیگه داره :
1- یک وب سرور Apache
2- یک ماژول بزرگ بنام opmn که وظیفه مدیریت ، log ، مونیتور و خلاصه مدیریت داستان رو داره.
3- چند Instance از Oc4j که سرویسها و برنامه ها رو هاست میکنه که خودشون دنیای دیگه ای دارن.

چند چیز عجیب اینجاست :
1- بنظر میاد بعضی از ماژولها با jre 1.4 (سان) که روی دایرکتوری اصلی سرور یا home هست بالا میاد اما application های وب ما با جاوای 1.5 کامپایل میشن و deploy میکنیم و مشکلی هم نداره. ظاهرا oc4j داره با 1.5 jre کار میکنه چطور ممکنه آیا اینها دوتا jvm در کنار همن ؟ این میتونه ایجاد اشکالات ناشناخته بکنه ؟

2- بعد از حدود 15 تا 20 روز کار کردن ، مقدار free memory سرور (لینوکس ردهت هست) بشدت کاهش پیدا میکنه و به همین دلیل cpu usage کم کم میره بالا حتی با stopو start کردن تک تک application ها هم مشکل حل نمیشه قاعدتا درصورت پایداری سرور نباید اینطور باشه اما انگار بعنوان مسکن GC میخواد که من دقیقا نمیدونم کجاست بهرحال این راه حل نیست رفتم سراغ پارامترهای jvm چیز خاصی نبود یا من نمیدونم و چاره ای نیست جز restart کردن سرور. مشکل از کجاست ؟ این میتونه باگ سرویسها یا agent هاش باشه یا اینکه طبیعیه و بریم سراغ خط به خط برنامه های خودمون ؟ noclassgc میتونه کلید مشکل باشه ؟

3- طبق معمول همه سرورها oracle هم با log4j کار میکنه. آیا کلا در این سرور و بقیه سرورها مثل weblogic یا sun میشه log رو بیشتر در اختیار گرفت و برد در سطوح مختلف هر application یا هر context ؟ بنظر میاد log4j.properties داخل application کار چندانی در این مورد انجام نمیده و جاهای دیگه ای هم هست اما مستندات زیادی در مورد استفاده خوب از log4j و استفاده اون در سرورهای مختلف وجود نداره. لطفا اگر کتاب یا رفرنس خوبی درمورد log4j میشناسین معرفی کنین متشکرم .

دوست عزیز : unhandled_event ضمن سلام به شما دوست عزیزم handinux و تشکر به خاطر لطف تون به بنده.

در مورد AppServer ما از Jrun استفاده می کنیم.که اولش ماله شرکت Allaire بود بعد Macromedia خریدش بعد هم که به Adobe رسید.آخرین ورژنش 4 هست که مدت هاست تغیری نکرده ولی آپدیت میشه و Adobe هنوز حمایتش میکنه.بیشتر برای پروژه های کوچیک تا متوسط بدرد می خوره و لایسنس نسبتا مناسبی داره.
تا الان که فرصت نکردم از اراکل و محصولاتش استفاده کنم چون دلیلی نداشته و وقت هم نداشتم. این اواخر سعی کردم یه مقداری روی Glassfish تمرکز کنم که با چند تا از بجه های فعال و علاقه مند داریم روش کار میکنیم.

محدودیتی در استفاده از JRE و JDK غیر از سان ندارید مگر :
1-ورژن برنامه هاتون و نرم افزار سرورتون با اون JVM سازگار نباشه.
2-مطمئن باشید از سازنده و منبع قابل اعتمادی فراهم میکنید!(ممکنه یه هکر JVM رو طوری باز نویسی کنهکه کل مکانیزم امنیتی جاوا بی اثر شه و سیستمتون نسبت به اجرای کد های محرب آسب پذیر بشه!)

در مورد JRE های مختلف در سیستم:
ببینید در سیستم در آن واحد چند JVM میتونن در حال اجرا باشن .هر JVM هم میتونه با توجه به ورژن JRE یا JDK ش میتونه ورژن خاصه خودش رو داشته باشه.مثلا Appserver تون میتونه در JVM ی اجرا شه که ورژن JRE ش 1.5 باشه.همین سرور میتونه Instance های مختلفی داشته باشه که هر Instance هم در یک JVM جداگانه که مربوط به یک ورژن مخصوص به خودش و حتی سازنده خواص خودش در حال اجرا باشه!(اگه Task Manager ویندوز رو باز کنید میبینید که چند پروسه بانام Java.exe یا javaws.exe در حال اجرا هستن و هر کدوم هم رم مخصوص به خودش رو داره!)
حتی میتونید مادامی که کد های سرورتون با JVM مورد نظرتون سازگار باشه JVM سرور رو تغیر بدین .مثلا در JRUN میشه با کپی اینترپرتر JDK 1.6 در فولدر System32 و تغیر چند کلید رجیستری کاری کرد که Jrun با جاوا 5 به جای 1.4 بالا بیاد!

در مورد حافظه همونطور که گفتم با سرور مورد نظر شما تجربه ای ندارم. اما قبل از جواب یهم بگید که Free memory سیستم کاهش پبدا میکنه یا Heap پر میشه؟ جواب این سوال در اینکه تشخیص افتراقی در اینکه نشته حافظه مربوط به JVM هست یا کل سیستم کمک کنندس.

در مورد log4j ببینید هر برنامه ای میتونه log داشته باشه . log های appserver ها مربوط به خودشونه و ربط چندانی به مکانیزم برنامه شما نداره . appserver از این لاگ ها برای دنبال کردن وضعیت برنامه شما استفاده میکنه .برای اینکه خود برنامه رو لاگ کنبد باید از واسط Log4j استفاده کنید یا یه سطح بالاتر از AOP.

توصیه من اینه که از AOP استفاده کنید. Jrun که ازش استفاده می کنیم از EE5 به شکل مستقیم پشتیبانی نمیکنه . و اون موقعی که ما کار با JRun رو شروع کردیم EE5 نبود! ما از Spring استفاده می کنیم ومی کردیم. در Spring میتونیم بدون درگیری با مسائل درونی log4j با چند تا خط در فایل applicationcontex.xml خیلی ساده با AOP هر جای برنامه رو که بخوایم لاگ کنیم. اما برای آشنایی کامل با log4j بد نیست به این کتاب مراجعه کنید :
O'Reilly - Llog4j - The Complete Manual
میتونید از سایت pdfchm.com دانلودش کنید.
موفق باشید.