Apache+Tomcat 通訊時出現問題。不清楚的錯誤訊息。關閉 Tomcat 下託管的網站

Apache+Tomcat 通訊時出現問題。不清楚的錯誤訊息。關閉 Tomcat 下託管的網站

設定:
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 毫秒) 。在 MaxThreads 訊息出現之前,這只持續 2-4 秒。我假設這是伺服器突然處理太多資料/流量/線程的結果。

背景資訊:
這兩台伺服器已經運行了一段時間沒有出現任何問題。在此期間,系統實際上是使用兩個 NIC 進行設定的。他們將內部和外部流量分開。網路升級後,我們將這些伺服器移至單一 NIC(出於安全/簡單原因,建議我們這樣做)。更改之後,伺服器開始出現這些問題。

解決:
顯而易見的解決方案是恢復到兩個 NIC 的設定。這樣做的問題是,它會導致網路設定出現一些複雜化,而且似乎忽略了這個問題。我們更願意嘗試讓它在單一 NIC 設定上運行。

谷歌搜尋各種錯誤訊息沒有提供任何有用的信息(舊的解決方案或與我們的問題無關)。

我們嘗試過調整各種超時,但這只是讓伺服器在死亡之前運行的時間稍微長一些。

我們不確定在哪裡可以進一步診斷問題。我們仍在抓住問題的根源:

1) AJP 和 Tomcat 的設定不正確或過時(即已知錯誤?)
2) 網路設定(兩個 NIC 與 1 個 NIC)導致混亂或吞吐量問題。
3) 網站本身(沒有通用程式碼,沒有使用平台,只有 servlet 和 JSP 的基本 Java 程式碼)

更新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 驅動程式可能會強制所有其他執行緒等待其完成。由於某種原因,它必須停留在這種讀取狀態(伺服器永遠不會自行恢復,它需要重新啟動)。

這表明它必須與伺服器和資料庫之間的網路或資料庫本身有關。我們正在繼續進行診斷工作,但任何提示都會有所幫助。

答案1

事實證明,這個版本(classes12 - 相當舊)的 Oracle 驅動程式存在各種導致死鎖的錯誤(如上面引用的 TP-Processor2 狀態所示)。直到我們切換到新環境後它才變得活躍。升級到最新版本(ojdbc14)已解決主伺服器上的問題。

答案2

從描述來看,我認為問題可能是由於資料庫查詢花費的時間太長。如果查詢花費的時間更長,請求也會花費更長的時間,因此您將同時執行更多的查詢。正如您所看到的,您的 tomcat 線程已經用完。當您解決資料庫問題時,您應該沒問題。

  • 使用 jstack 或使用kill -3 $process_id 取得堆疊追蹤。查看線程死亡時正在做什麼。如果他們都在等待資料庫,那就是我的理論的一個很好的指示。他們可能都在等待某個鎖。
  • 安裝 LambdaProbe。這對於了解你的 tomcat 在做什麼是非常有價值的。
  • 升級你的 tomcat。 5.5.8 太舊了。我想他們現在是 5.5.27。

答案3

將 connectionTimeout 和 keepAliveTimeout 新增至 /etc/tomcat7/server.xml 中的 AJP 連接器。

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" 
           connectionTimeout="10000" keepAliveTimeout="10000" />

有關 AJP 連接器的信息,請訪問https://tomcat.apache.org/tomcat-7.0-doc/config/ajp.html

  • connectionTimeout = 此連接器在接受連線後等待呈現請求 URI 行的毫秒數。 AJP 協定連接器的預設值為-1(即無限)。

  • keepAliveTimeout = 此連接器在關閉連線之前等待另一個 AJP 請求的毫秒數。預設值是使用為connectionTimeout 屬性設定的值。

如果未定義connectionTimeout和keepAliveTimeout值,則AJP連線將無限期保持活動狀態。導致執行緒較多,預設最大執行緒數為200。

我建議安裝 psi-probe - Apache Tomcat 的高級管理器和監視器,從 Lambda Probe 分叉。https://code.google.com/p/psi-probe/

答案4

在穩定性方面,我使用 mod_proxy 而不是 mod_ajp 獲得了更好的結果,所以請嘗試解決方案。它是非侵入性的——最好的情況下它會解決問題,最壞的情況下它會排除 mod_ajp。

除此之外,聽起來您的 Tomcat 停止回應並且所有請求線程都被佔用。讓你的開發團隊調查一下發生了什麼 -進行線程轉儲並將其交付給他們將會很有用。

相關內容