Kurulum:
Fedora 8
Apache 2.2.8
Tomcat 5.5.8
Apache, AJP kullanarak istekleri iletiyor.
Sorun:
Belirli bir süre sonra (hiç sabit değil, bir ya da iki saat ya da bir ya da daha fazla gün arasında olabilir) Tomcat düşecektir. Ya yanıt vermiyor ya da 'Geçici Olarak Kullanılamayan Hizmeti' genel durumuna getiriyor.
Teşhis:
Aynı kurulumda iki sunucu var. Biri daha yüksek bir trafik web sitesine (saniyede birkaç istek), diğeri düşük trafikli bir web sitesine (birkaç dakikada bir istek) sahiptir. Her iki web sitesi de tamamen farklı kod tabanlarıdır, ancak benzer sorunlar gösterirler.
İlk sunucuda, sorun oluştuğunda, tüm iş parçacıkları sınıra ulaşıncaya kadar yavaş yavaş alınmaya başlar (MaxThreads 200). Bu noktada sunucu artık yanıt vermiyor (ve uzun bir süre sonra hizmet kullanılamıyor sayfasıyla geliyor).
İkinci sunucuda, sorun oluştuğunda istek uzun zaman alır ve tamamlandığında hizmetin kullanılamadığı tek sayfadır.
Tomth günlükleri MaxThreads sorunundan başka, buna neden olabilecek herhangi bir sorun belirtmez.
Ancak Apache günlüklerinde AJP'ye atıfta bulunan rastgele mesajlar görüyoruz. İşte gördüğümüz rastgele mesajın bir örneği (belirli bir sırayla):
[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)
Daha yüksek trafik sunucusunda fark ettiğimiz diğer garip şey, sorun ortaya çıkmadan hemen önce, veritabanı sorgularının öncekinden çok daha uzun sürmesi (normalde 5-50 ms'ye karşı 2000-5000 ms). Bu, MaxThreads mesajı gelmeden önce sadece 2-4 saniye sürer. Bu sunucu aniden çok fazla veri/trafik/iş parçacığı ile uğraşan bir sonucu olduğunu varsayıyorum.
Arka Plan Bilgileri:
Bu iki sunucu bir süredir sorunsuz çalışıyorlardı. Sistemler aslında bu süre zarfında her biri iki NIC kullanarak kuruldu. İç ve dış trafiği ayırdılar. Bir ağ yükseltmesinden sonra, bu sunucuları tek NIC'lere taşıdık (güvenlik/basitlik nedeniyle bize önerildi). Bu değişiklikten sonra sunucular bu sorunları yaşamaya başladı.
Çözünürlük:
Açık çözüm iki NIC kurulumuna geri dönmek olacaktır. Bununla ilgili sorunlar, ağ kurulumu ile bazı komplikasyonlara neden olması ve sorunu görmezden gelmek gibi görünüyor. Tek bir NIC kurulumunda çalıştırmayı denemeyi tercih ederiz.
Çeşitli hata mesajlarını incelemek yararlı bir şey sağlamadı (eski çözümler veya sorunumuzla ilgisi yok).
Çeşitli zaman aşımlarını ayarlamayı denedik, ancak bu, sunucunun ölmeden önce biraz daha uzun çalışmasını sağladı.
Sorunu daha fazla teşhis etmek için nereye bakacağımızdan emin değiliz. Problemin ne olabileceğini hala payetlerden alıyoruz:
1) AJP ve Tomcat ile kurulum yanlış veya eski (bilinen hatalar?)
2) Ağ kurulumu (bir NIC'ye karşı iki NIC) karışıklık veya üretim sorunlarına neden oluyor.
3) Web sitelerinin kendileri (ortak kod yok, kullanılan platform yok, sadece temel Java kodu)
Güncelleme 1:
David Pashley'nin yararlı tavsiyelerini takiben, sorun sırasında yığın izleri/iplik dökümü yaptım. Ne buldum 200 iş parçacığı aşağıdaki durumlardan birinde idi:
"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]
İlginç bir şekilde, 200 iş parçacığının yalnızca bir tanesi bu durumda idi:
"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]
Bu iş parçacığındaki Oracle sürücüsü, diğer tüm iş parçacıklarını tamamlanmasını beklemeye zorlayabilir. Bazı nedenlerden dolayı bu okuma durumunda takılı kalmalıdır (sunucu asla kendi başına kurtarılmaz, yeniden başlatma gerektirir).
Bu, sunucu ve veritabanı arasındaki ağla veya veritabanının kendisiyle ilişkili olması gerektiğini gösterir. Teşhis çabalarını sürdürüyoruz, ancak herhangi bir ipucu yardımcı olacaktır.
Oracle sürücüsünün bu sürümünün (class12 - oldukça eski) içinde bir kilitlenmeye neden olan çeşitli hatalar olduğu ortaya çıktı (yukarıda belirtilen TP-İşlemci2 durumunda görüldüğü gibi). Yeni ortama geçene kadar aktif olmadı. En son sürüme (ojdbc14) yükseltme birincil sunucudaki sorunu çözdü.
Açıklamasından, sorunun çok uzun sürdüğü veritabanı sorguları nedeniyle olabileceğini öneririm. Sorgular daha uzun sürüyorsa, istek daha uzun sürecektir ve bu nedenle bir kerede daha fazla çalışacaksınız. Gördüğünüz gibi, Tomcat iş parçacıklarınız bitiyor. Veritabanı ile ilgili sorunu çözdüğünüzde iyi olmalısınız.
/Etc/Tomcat7/server.xml dosyasında bulunan AJP bağlacınıza connectionTimeout ve keepAliveTimeout öğelerini ekleyin.
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" connectionTimeout="10000" keepAliveTimeout="10000" />
AJP konektörü hakkında bilgi https://Tomcat.Apache.org/Tomcat-7.0-doc/config/ajp.html
connectionTimeout = Bu Bağlayıcı, bağlantı kabul edildikten sonra istek URI satırının sunulması için bekleyeceği milisaniye sayısı. AJP protokolü bağlayıcıları için varsayılan değer -1'dir (yani sonsuz).
keepAliveTimeout = Bağlantıyı kapatmadan önce bu Bağlayıcının başka bir AJP isteği için bekleyeceği milisaniye sayısı. Varsayılan değer connectionTimeout özniteliği için ayarlanan değeri kullanmaktır.
ConnectionTimeout ve keepAliveTimeout değerleri tanımlanmamışsa, AJP bağlantıları sonsuz olarak canlı tutulur. Birçok iş parçacığına neden olan varsayılan maksimum iş parçacığı 200'dür.
Lambda Probe'dan çatallanmış Apache Tomcat için gelişmiş bir yönetici ve monitör olan psi-probe'u yüklemenizi tavsiye ederim. https://code.google.com/p/psi-probe/
AJP'nin çalışma şekli nedeniyle, Apache (mod_proxy_ajp veya mod_jk kullanarak) arasındaki kalıcı bağlantılar yalnızca güvenli bir şekilde kapatılabilir istemci tarafından. Bu durumda, istemci, çalışan işleminin ömrü için Tomcat ile bağlantı kuran Apache çalışanıdır.
Bu davranış nedeniyle Tomcat çalışan iş parçacıklarından daha fazla Apache çalışanınız olamaz. Bunu yapmak, ek http işçilerinin Tomcat'e bağlanamamasına neden olur (kabul sırası dolu olduğu için) ve arka ucunuzu AŞAĞI olarak işaretler!
Kararlılık açısından mod_ajp yerine mod_proxy ile daha iyi sonuçlar elde ettim, bu yüzden bu çözümü deneyin. İnvaziv değil - en iyi ihtimalle sorunu çözecek ve en kötüsü mod_ajp'yi dışlayacak.
Bunun dışında, Tomcats'ınız gibi sesler yanıt vermeyi durdurur ve tüm istek dizileri bağlanır. Geliştirici ekibinizin neler olup bittiğine bakmasını sağlayın - bir iplik dökümü alarak ve onlara teslim etmek yararlı olacaktır.
Bir sunucunun bir süre çalıştığını duyduğumda düşündüğüm ilk şey, aniden yavaşlar ve daha sonra servis hataları yaşamaya başlar = RAM ve thrashing swap. gördüğünüz AJP başarısızlıklarının zaman aşımlarına bağlı olup olmayacağı konusunda net, ancak tamamen mantıksız görünmüyor; NIC'ye bağlanması için açık bir yol görmüyorum.Herhangi bir durumda, bu olaylar meydana geldiğinde bellek kullanımınızda neler olup bittiğini gösteren resim.
RAM'iniz bitiyorsa, Apache
MaxClients aygıtınızı kapatmanız ve
ListenBacklog aygıtınızı artırmanız gerekebilir.
Bu arada, sorunuzu bu kadar düzenli ve eksiksiz yaptığınız için teşekkürler.
Redhat ortamında proxy_ajp ve Tomcat ile benzer günlük hataları yaşadım. Httpd paketi güncellenerek çözüldü:
yum update httpd
dan:
için:
Ardından Apache'yi yeniden başlattıktan sonra Tomcat'i yeniden başlattı.
Bu benim için sorunumu çözdü!