การติดตั้ง:
Fedora 8
Apache 2.2.8
Tomcat 5.5.8
Apache กำลังส่งต่อคำขอโดยใช้ AJP
ปัญหา:
หลังจากช่วงระยะเวลาหนึ่ง (ไม่มีค่าคงที่เลยอาจอยู่ระหว่างหนึ่งหรือสองชั่วโมงหรือหนึ่งวันหรือมากกว่านั้น) Tomcat จะลง ไม่ว่าจะหยุดตอบสนองหรือวาง 'บริการชั่วคราวไม่พร้อมใช้งาน' ทั่วไป
การวินิจฉัย:
มีเซิร์ฟเวอร์สองเครื่องที่มีการตั้งค่าเดียวกัน เว็บไซต์หนึ่งเป็นเว็บไซต์ที่มีปริมาณการใช้งานสูง (หลายคำขอต่อวินาที) ส่วนอีกเว็บไซต์หนึ่งมีปริมาณการใช้ข้อมูลต่ำ เว็บไซต์ทั้งสองนั้นมีฐานรหัสที่แตกต่างกันโดยสิ้นเชิง แต่มีปัญหาที่คล้ายกัน
บนเซิร์ฟเวอร์แรกเมื่อปัญหาเกิดขึ้นเธรดทั้งหมดจะเริ่มต้นรับอย่างช้า ๆ จนกว่าจะถึงขีด จำกัด (MaxThreads 200) ณ จุดนี้เซิร์ฟเวอร์จะไม่ตอบสนองอีกต่อไป (และเกิดขึ้นกับหน้าบริการไม่พร้อมใช้งานหลังจากช่วงเวลานาน)
บนเซิร์ฟเวอร์ที่สองเมื่อปัญหาเกิดขึ้นคำขอใช้เวลานานและเมื่อพวกเขาทำทั้งหมดที่คุณเห็นคือหน้าบริการไม่พร้อมใช้งาน
นอกเหนือจากการกล่าวถึงปัญหา MaxThreads บันทึก Tomcat ไม่ได้ระบุปัญหาเฉพาะใด ๆ ที่อาจทำให้เกิดปัญหานี้
อย่างไรก็ตามในบันทึก Apache เราเห็นข้อความแบบสุ่มที่อ้างถึง AJP นี่คือตัวอย่างข้อความสุ่มที่เราเห็น (ไม่มีคำสั่งซื้อเฉพาะ):
[error] (70007)The timeout specified has expired: ajp_ilink_receive() can't receive header
[error] (104)Connection reset by peer: ajp_ilink_receive() can't receive header
[error] proxy: AJP: disabled connection for (localhost)
[error] ajp_read_header: ajp_ilink_receive failed
[error] (120006)APR does not understand this error code: proxy: read response failed from 127.0.0.1:8009 (localhost)
[error] ap_proxy_connect_backend disabling worker for (localhost)
อีกอย่างที่เราสังเกตเห็นบนเซิร์ฟเวอร์ทราฟฟิกที่สูงกว่านั้นคือก่อนที่ปัญหาจะเกิดขึ้นการสืบค้นฐานข้อมูลจะใช้เวลานานกว่าก่อนหน้า (2,000-5,000 ms เทียบกับปกติ 5-50ms) ซึ่งจะใช้เวลา 2-4 วินาทีก่อนที่ข้อความ MaxThreads จะปรากฏขึ้น ฉันสมมติว่านี่เป็นผลมาจากเซิร์ฟเวอร์จัดการกับข้อมูล / ปริมาณการใช้ / เธรดมากเกินไป
ข้อมูลความเป็นมา:
เซิร์ฟเวอร์ทั้งสองนี้ทำงานโดยไม่มีปัญหามาระยะหนึ่งแล้ว ระบบถูกตั้งค่าจริง ๆ โดยใช้ NIC สองตัวในช่วงเวลานั้น พวกเขาแยกการจราจรภายในและภายนอก หลังจากอัปเกรดเครือข่ายเราย้ายเซิร์ฟเวอร์เหล่านี้ไปยัง NIC เดียว (แนะนำให้เราใช้เหตุผลด้านความปลอดภัย / ความเรียบง่าย) หลังจากการเปลี่ยนแปลงเซิร์ฟเวอร์เริ่มมีปัญหาเหล่านี้
การแก้ไข:
ทางออกที่ชัดเจนคือการย้ายกลับไปยังการตั้งค่าของ NIC สองตัว ปัญหาที่เกิดขึ้นคือมันจะทำให้เกิดปัญหาบางอย่างกับการตั้งค่าเครือข่ายและดูเหมือนว่าจะไม่สนใจปัญหา เราต้องการลองและทำให้มันทำงานในการตั้งค่า NIC เดียว
Googling ข้อความแสดงข้อผิดพลาดต่างๆไม่ได้ให้ประโยชน์อะไรเลย (ทั้งวิธีแก้ไขปัญหาเก่าหรือไม่เกี่ยวข้องกับปัญหาของเรา)
เราได้ลองปรับการหมดเวลาต่างๆ แต่นั่นทำให้เซิร์ฟเวอร์ทำงานได้นานขึ้นเล็กน้อยก่อนจะตาย
เราไม่แน่ใจว่าจะค้นหาปัญหาได้ที่ไหน เรายังคงเข้าใจถึงปัญหาที่อาจเป็นไปได้:
1) การตั้งค่าด้วย AJP และ Tomcat ไม่ถูกต้องหรือล้าสมัย (เช่นข้อบกพร่องที่รู้จักกัน?)
2) การตั้งค่าเครือข่าย (NIC สองตัวต่อหนึ่ง NIC) ก่อให้เกิดปัญหาความสับสนหรือปริมาณงาน
3) เว็บไซต์เหล่านั้น (ไม่มีรหัสทั่วไป, ไม่มีแพลตฟอร์มที่ใช้งาน, เพียงแค่โค้ด Java ขั้นพื้นฐานที่มี servlets และ JSP)
อัปเดต 1: ทำ
ตามคำแนะนำที่เป็นประโยชน์ของ David Pashley ฉันได้ทำการติดตามสแต็ก / เธรดดัมพ์ระหว่างปัญหา สิ่งที่ฉันพบคือกระทู้ทั้งหมด 200 หัวข้ออยู่ในสถานะใดสถานะหนึ่งต่อไปนี้:
"TP-Processor200" daemon prio=1 tid=0x73a4dbf0 nid=0x70dd waiting for monitor entry [0x6d3ef000..0x6d3efeb0]
at oracle.jdbc.pool.OracleConnectionCacheImpl.getActiveSize(OracleConnectionCacheImpl.java:988)
- waiting to lock <0x7e3455a0> (a oracle.jdbc.pool.OracleConnectionCacheImpl)
[further stack trace removed for brevity]
"TP-Processor3" daemon prio=1 tid=0x08f142a8 nid=0x652a waiting for monitor entry [0x75c7d000..0x75c7ddb0]
at oracle.jdbc.pool.OracleConnectionCacheImpl.getConnection(OracleConnectionCacheImpl.java:268)
- waiting to lock <0x7e3455a0> (a oracle.jdbc.pool.OracleConnectionCacheImpl)
[further stack trace removed for brevity]
อยากรู้อยากเห็นเพียงหนึ่งกระทู้จากทั้งหมด 200 กระทู้อยู่ในสถานะนี้:
"TP-Processor2" daemon prio=1 tid=0x08f135a8 nid=0x6529 runnable [0x75cfe000..0x75cfef30]
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at oracle.net.ns.Packet.receive(Unknown Source)
at oracle.net.ns.DataPacket.receive(Unknown Source)
at oracle.net.ns.NetInputStream.getNextPacket(Unknown Source)
at oracle.net.ns.NetInputStream.read(Unknown Source)
at oracle.net.ns.NetInputStream.read(Unknown Source)
at oracle.net.ns.NetInputStream.read(Unknown Source)
[further stack trace removed for brevity]
อาจเป็นไปได้ว่าไดรเวอร์ Oracle ในเธรดนี้บังคับให้เธรดอื่นทั้งหมดรอให้เสร็จสมบูรณ์ ด้วยเหตุผลบางอย่างมันจะต้องติดอยู่ในสถานะการอ่านนี้ (เซิร์ฟเวอร์ไม่เคยกู้คืนด้วยตนเองมันต้องเริ่มต้นใหม่)
สิ่งนี้ชี้ให้เห็นว่ามันจะต้องเกี่ยวข้องกับทั้งเครือข่ายระหว่างเซิร์ฟเวอร์และฐานข้อมูลหรือฐานข้อมูลเอง เรากำลังทำการวิเคราะห์อย่างต่อเนื่อง แต่เคล็ดลับใด ๆ จะเป็นประโยชน์