Налаштування:
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)
Інша дивна річ, яку ми помітили на сервері більш високого трафіку, - це те, що перед початком проблеми запити до бази даних займають набагато довше, ніж раніше (2000-5000 мс проти звичайно 5-50 мс). Це триває лише 2-4 секунди до появи повідомлення MaxThreads. Я припускаю, що це результат того, що сервер раптом має справу з занадто великою кількістю даних / трафіку / потоків.
Довідкова інформація:
Ці два сервери працювали без проблем досить довгий час. Системи насправді налаштовувались за допомогою двох NIC протягом цього часу. Вони розділили внутрішній та зовнішній трафік. Після оновлення мережі ми перемістили ці сервери на єдині NIC (це було рекомендовано нам з міркувань безпеки / простоти). Після цієї зміни у серверів почалися проблеми.
Розв’язання
. Очевидним рішенням було б повернутися до налаштування двох NIC. Проблеми з цим полягають у тому, що це може спричинити деякі ускладнення при налаштуванні мережі, і здається, ігнорування проблеми. Ми вважаємо за краще спробувати запустити його на одній установці NIC.
Гуглінг різних повідомлень про помилки не дав нічого корисного (як старі рішення, так і не пов'язані з нашою проблемою).
Ми спробували коригувати різні тайм-аути, але це просто змусило сервер працювати трохи довше, перш ніж померти.
Ми не впевнені, де шукати, щоб далі діагностувати проблему. Ми досі розуміємо соломинку, яка проблема може бути:
1) Налаштування з AJP та Tomcat є неправильним або застарілим (тобто відомі помилки?)
2) Налаштування мережі (два NIC проти одного NIC) викликає плутанину або пропускну здатність.
3) Самі веб-сайти (немає загального коду, не використовуються платформи, просто основний код Java з сервлетами та JSP)
Оновлення 1:
Користуючись корисною порадою Девіда Пашлі, я зробив скидання стека / потоку під час випуску. Я виявив, що всі 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 у цій нитці змушує всі інші потоки чекати його завершення. Чомусь він повинен застрягнути в такому стані читання (сервер ніколи не відновлюється самостійно, він вимагає перезавантаження).
Це говорить про те, що вона повинна бути пов'язана або з мережею між сервером і базою даних, або з самою базою даних. Ми продовжуємо зусилля з діагностики, але будь-які поради будуть корисні.