Thiết lập:
Fedora 8
Apache 2.2.8
Tomcat 5.5.8
Apache đang chuyển tiếp các yêu cầu bằng AJP.
Vấn đề:
Sau một khoảng thời gian nhất định (không có hằng số nào, có thể là giữa một hoặc hai giờ hoặc một hoặc nhiều ngày) Tomcat sẽ đi xuống. Hoặc là nó dừng đáp ứng, hoặc nó đưa ra 'Dịch vụ tạm thời không khả dụng'.
Chẩn đoán:
Có hai máy chủ có cùng thiết lập. Một trang web có lưu lượng truy cập cao hơn (một vài yêu cầu mỗi giây), một yêu cầu lưu lượng truy cập thấp (một số ít yêu cầu cứ sau vài phút). Cả hai trang web là các cơ sở mã hoàn toàn khác nhau, nhưng chúng thể hiện các vấn đề tương tự.
Trên máy chủ đầu tiên, khi sự cố xảy ra, tất cả các luồng bắt đầu được xử lý cho đến khi đạt đến giới hạn (MaxThreads 200). Tại thời điểm đó, máy chủ không còn phản hồi (và đi kèm với trang không có dịch vụ sau một thời gian dài).
Trên máy chủ thứ hai, khi sự cố xảy ra, các yêu cầu mất nhiều thời gian và khi chúng được thực hiện, tất cả những gì bạn thấy là trang không có dịch vụ.
Khác với việc đề cập đến vấn đề MaxThreads, nhật ký Tomcat không chỉ ra bất kỳ vấn đề cụ thể nào có thể gây ra sự cố này.
Tuy nhiên, trong nhật ký Apache, chúng ta thấy các thông báo ngẫu nhiên đề cập đến AJP. Đây là một mẫu thông báo ngẫu nhiên mà chúng ta thấy (không theo thứ tự cụ thể):
[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)
Một điều kỳ lạ khác mà chúng tôi nhận thấy trên máy chủ lưu lượng cao hơn là ngay trước khi sự cố bắt đầu xảy ra, các truy vấn cơ sở dữ liệu mất nhiều thời gian hơn trước (2000-5000 ms so với thông thường 5-50ms). Điều này chỉ tồn tại trong 2-4 giây trước khi thông báo MaxThreads xuất hiện. Tôi cho rằng đây là kết quả của việc máy chủ đột nhiên xử lý quá nhiều dữ liệu / lưu lượng / luồng.
Thông tin cơ bản:
Hai máy chủ này đã chạy mà không gặp sự cố trong một thời gian. Các hệ thống đã thực sự thiết lập từng cái bằng cách sử dụng hai NIC trong thời gian đó. Họ tách giao thông nội bộ và bên ngoài. Sau khi nâng cấp mạng, chúng tôi đã chuyển các máy chủ này sang các NIC đơn (điều này được khuyến nghị cho chúng tôi vì lý do bảo mật / đơn giản). Sau thay đổi đó, các máy chủ bắt đầu gặp những vấn đề này.
Giải pháp:
Giải pháp rõ ràng sẽ là quay trở lại thiết lập hai NIC. Vấn đề với điều đó là nó sẽ gây ra một số phức tạp với thiết lập mạng và có vẻ như bỏ qua vấn đề. Chúng tôi muốn thử và chạy nó trên một thiết lập NIC.
Googling các thông báo lỗi khác nhau không cung cấp bất cứ điều gì hữu ích (giải pháp cũ hoặc không liên quan đến vấn đề của chúng tôi).
Chúng tôi đã thử điều chỉnh thời gian chờ khác nhau nhưng điều đó chỉ khiến máy chủ chạy lâu hơn một chút trước khi chết.
Chúng tôi không chắc chắn nơi để tìm chẩn đoán vấn đề hơn nữa. Chúng tôi vẫn đang nắm bắt được ống hút về vấn đề có thể là gì:
1) Thiết lập với AJP và Tomcat không chính xác hoặc lỗi thời (nghĩa là các lỗi đã biết?)
2) Thiết lập mạng (hai NIC so với một NIC) đang gây ra sự cố nhầm lẫn hoặc thông lượng.
3) Bản thân các trang web (không có mã chung, không có nền tảng nào được sử dụng, chỉ có mã Java cơ bản với servlets và JSP)
Cập nhật 1:
Theo lời khuyên hữu ích của David Pashley, tôi đã thực hiện một dấu vết ngăn xếp / luồng trong suốt vấn đề. Những gì tôi tìm thấy là tất cả 200 chủ đề ở một trong các trạng thái sau:
"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]
Thật kỳ lạ, chỉ có một chủ đề trong số 200 chủ đề ở trạng thái này:
"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]
Có thể là trình điều khiển Oracle trong luồng này đang buộc tất cả các luồng khác phải đợi nó hoàn thành. Vì một số lý do, nó phải bị kẹt trong trạng thái đọc này (máy chủ không bao giờ tự phục hồi, nó yêu cầu khởi động lại).
Điều này cho thấy rằng nó phải liên quan đến mạng giữa máy chủ và cơ sở dữ liệu hoặc chính cơ sở dữ liệu. Chúng tôi đang tiếp tục nỗ lực chẩn đoán, nhưng bất kỳ lời khuyên nào cũng hữu ích.