Apache Tomcat 300 bağlantıdan sonra boğuluyor


16

EC2'de barındırılan Tomcat'in önünde bir apache web sunucumuz var, örnek türü 34GB bellek ile ekstra büyük.

Bizim uygulama çok sayıda dış web hizmetleri ile ilgilenir ve yoğun saatlerde isteklere cevap neredeyse 300 saniye sürer çok berbat bir dış web hizmet var.

Yoğun saatlerde sunucu yaklaşık 300 httpd işlemini boğar. ps -ef | grep httpd | wc -l = 300

Ben googled ve çok sayıda öneri buldum ama hiçbir şey işe yarıyor gibi .. aşağıdaki doğrudan çevrimiçi kaynaklardan alınan bazı yapılandırma vardır.

Hem apache hem de tomcat'te max bağlantı ve max istemcilerinin sınırlarını artırdım. yapılandırma ayrıntıları:

// apache

   <IfModule prefork.c>
    StartServers 100
    MinSpareServers 10
    MaxSpareServers 10
    ServerLimit 50000
    MaxClients 50000
    MaxRequestsPerChild 2000
    </IfModule>

// erkek kedi

    <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
           connectionTimeout="600000"
           redirectPort="8443"
           enableLookups="false" maxThreads="1500"
           compressableMimeType="text/html,text/xml,text/plain,text/css,application/x-javascript,text/vnd.wap.wml,text/vnd.wap.wmlscript,application/xhtml+xml,application/xml-dtd,application/xslt+xml"
           compression="on"/>

//Sysctl.conf

 net.ipv4.tcp_tw_reuse=1
 net.ipv4.tcp_tw_recycle=1
 fs.file-max = 5049800
 vm.min_free_kbytes = 204800
 vm.page-cluster = 20
 vm.swappiness = 90
 net.ipv4.tcp_rfc1337=1
 net.ipv4.tcp_max_orphans = 65536
 net.ipv4.ip_local_port_range = 5000 65000
 net.core.somaxconn = 1024

Çok sayıda öneri deniyorum ama boşuna .. nasıl düzeltilir? Eminim m2xlarge sunucusu 300'den fazla istekte bulunmalıdır, muhtemelen konfigürasyonumda yanlış gidiyor olabilirim ..

Sunucu yalnızca yoğun saatlerde ve [300 saniye gecikmeli] web hizmetinin yanıt vermesini bekleyen 300 eşzamanlı istek olduğunda boğulur.

Sadece netstat ile tcp bağlantılarını izliyordum

i TIME_WAIT durumda yaklaşık 1000 bağlantı bulundu, performans açısından ne anlama geleceği konusunda hiçbir fikrim yok, bu soruna eklenmesi gerekir eminim.

TOP Çıkışı

 8902  root      25   0 19.6g 3.0g  12m S  3.3  8.8  13:35.77 java
 24907 membase   25   0  753m 634m 2528 S  2.7  1.8 285:18.88 beam.smp
 24999 membase   15   0  266m 121m 3160 S  0.7  0.3  51:30.37 memcached
 27578 apache    15   0  230m 6300 1536 S  0.7  0.0   0:00.03 httpd
 28551 root      15   0 11124 1492  892 R  0.3  0.0   0:00.25 top


 Output of free -m
 total       used       free     shared    buffers    cached
 35007       8470       26536    0          1         61
 8407        26599
 15999       15         15984

 output of iostat
 avg-cpu:  %user   %nice %system %iowait  %steal   %idle
      26.21    0.00    0.48    0.13    0.02   73.15

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
sda1             14.36         4.77       329.37    9005402  622367592
sdb               0.00         0.00         0.00       1210         48

Ayrıca yoğun zamanda membase sunucusuna yaklaşık 10-15k tcp bağlantısı vardır [yerel]

MODJK GÜNLÜĞÜNDEKİ BAZI HATALAR, umarım bu konuya biraz ışık tutar ..

[Wed Jul 11 14:39:10.853 2012] [8365:46912560456400] [error]         ajp_send_request::jk_ajp_common.c (1630): (tom2) connecting to backend failed. Tomcat is probably not started or is listening on the wrong port (errno=110)
[Wed Jul 11 14:39:18.627 2012] [8322:46912560456400] [error] ajp_send_request::jk_ajp_common.c (1630): (tom2) connecting to backend failed. Tomcat is probably not started or is listening on the wrong port (errno=110)
[Wed Jul 11 14:39:21.358 2012] [8351:46912560456400] [error] ajp_get_reply::jk_ajp_common.c (2118): (tom1) Tomcat is down or refused connection. No response has been sent to the client (yet)
[Wed Jul 11 14:39:22.640 2012] [8348:46912560456400] [error] ajp_get_reply::jk_ajp_common.c (2118): (tom1) Tomcat is down or refused connection. No response has been sent to the client (yet)

~

Worker.properties
workers.tomcat_home=/usr/local/tomcat/
worker.list=loadbalancer
worker.tom1.port=8009
worker.tom1.host=localhost
worker.tom1.type=ajp13
worker.tom1.socket_keepalive=True
worker.tom1.connection_pool_timeout=600
worker.tom2.port=8109
worker.tom2.host=localhost
worker.tom2.type=ajp13
worker.tom2.socket_keepalive=True
worker.tom2.connection_pool_timeout=600
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=tom1,tom2
worker.loadbalancer.sticky_session=True
worker.tom1.lbfactor=1
worker.tom1.socket_timeout=600
worker.tom2.lbfactor=1
worker.tom2.socket_timeout=600

// çözüldü

Tüm değerli önerileriniz için thansk .. AJP 1.3 konektörü için maxThreads ayarlarını kaçırdım .. Şimdi her şey kontrol altında görünüyor.

Ayrıca nginx gibi tabanlı sunuculara bile bakmaya başlarım.


Keepalive ayarlarınız nasıl?
Tom O'Connor

İstemciler bir sayfayı yüklemeye çalışırken ne tür bir hata alır?
Shane Madden

1
Apache / httpd kullanıcısı için izin verilen maksimum açık dosya tanımlarını artırdınız mı?
golja

@Tom Canlı Kalma Ayarları httpd.conf'da KeepAliveTimeout 10'dur
john titus

3
topBu zamanlarda ortaya çıkan çıktı neye benziyor? Nasıl free -m? Ve son olarak iostat?
Zypher

Yanıtlar:


13

8009 numaralı bağlantı noktasındaki AJP 1.3 Bağlayıcısı'nda maxThreads değerini artırdınız mı?


Tomcat örneği başına sahip olduğum şey 1500
john titus

@john, Belirttiğiniz her Bağlayıcı için maxThreads = "1500" olduğunu mu söylüyorsunuz? AJP 1.3 Konnektörü (port 8009) için stanzalarınızı gönderebilir misiniz?
HTTP500

bunu işaret ettiğiniz için teşekkürler .. AJP1.3 için hiç maxThreads ayarı hiç .. nedeni bu olabilir mi?
john titus

1
Evet, bu Bağlayıcı için stanzaya maxThreads ekleyin. Varsayılan değer 200'dür.
HTTP500

6

Apache gibi nginxveya lighttpdönünde eşzamansız bir proxy sunucusu kurmayı düşünün . Apache içeriği eşzamanlı olarak sunar, böylece istemciler oluşturulan içeriği tam olarak indirene kadar çalışanlar engellenir (daha fazla ayrıntı burada ). Eşzamansız (engellemeyen) bir proxy ayarlamak genellikle durumu önemli ölçüde iyileştirir (eşzamanlı olarak çalışan Apache çalışanlarının sayısını nginxön uç proxy olarak kullanarak 30'dan 3-5'e düşürürdüm).


5

Sorununuzun tomcat'te zaten göstermiş olduğunuz günlüklerden apache değil olduğundan şüpheleniyorum. Tomcat'e tekrar bağlanmaya çalışırken 'hata 110'u aldığınızda, artık hizmet vermeyi bekleyen ve artık Tomcat'teki dinleme soketi için dinleme biriktirme kurulumuna sığmayacak bir bağlantı kuyruğunuz olduğunu gösterir.

From the listen manpage:
   The  backlog  parameter defines the maximum length the queue of pending 
   connections may grow to.  If a connection request arrives with
   the queue full the client may receive an error with an indication
   of ECONNREFUSED or, if the underlying protocol supports  
   retransmission, the request may be ignored so that retries succeed.

Tahmin etmek zorunda kaldım, sunucu "boğulma" olduğunda HTTP isteklerinin büyük çoğunluğunun tomcat'ten geri gelmek için bekleyen bir şey engellendiğinden şüphelenirim. Eğer normalde 'boğulma' olsa bile, bu apache (tomcat proxied yerine) doğrudan sunulan bazı statik içerik getirmeye çalıştıysanız bahse girerim.

Ne yazık ki tomcat'e aşina değilim, ama bunun yerine eşzamanlılık ayarlarını değiştirmenin bir yolu var mı?

Oh, ve aynı zamanda dış ağ servisleri şu bu bağlantı sayısını sınırlama olasılığını dikkate almak gerekebilir o yapıyor size bunu ön tarafında yapıyoruz ne kadar eşzamanlılık manipüle fark etmez, böylece 300'e aşağı hemen hemen her bağlantınız harici bir web hizmetleri yanıtına bağlıysa.

Yorumlarınızdan birinde, verilerin 2 dakika sonra eski haline geldiğini söylediniz. Harici web hizmetine sürdüğünüz eşzamanlı bağlantı miktarını azaltmak için bu hizmetten aldığınız yanıtı iki dakika önbelleğe almanızı öneririm.


2

Bu sorunu gidermek için ilk adım Apache'nin mod_status özelliğini etkinleştirmek ve raporunu incelemek - bunu yapana kadar aslında körü körüne yürüyorsunuz. Bu doğru değil. ;-)

Bahsetmemiz gereken ikinci şey (kendi başıma sormadığım soruların cevaplarını söylemekten hoşlanmıyorum, ama ...) gibi daha verimli ve özel ön uç sunucuları kullanıyor nginx.

Ayrıca, tam olarak yaptım restartapache, ya da sadece gracefully yeniden onu? :)


Apache yeniden başladı .. zarif bir yeniden yükleme değil
john titus

@johntitus, mod_statuszaten arkadaşın. :)
poige

1

Her türlü kurumsal-y konuşlandırması için prefork MPM, yapabileceğiniz en kötü seçimdir: hiç kimsenin işi gibi kaynakları kaldırır ve iş parçacıklarını yeniden başlatmak diğer MPM'lere kıyasla FOREVER alır.

En geçiş azından işçi daha iyisi - - MPM (apache 2.2 ve üstü) veya varsayılan ile geçerli kararlı sürümü 2.4.2 yükseltme olayı MPM.

Bunların her ikisi de çok az yük ile binlerce eşzamanlı bağlantıyı kolayca idare edecek.


teşekkürler .. bunu da denedim .. hayır şans. TIME_WAIT bağlantıları artmaya devam ediyor. Sunucu 350 bağlantıda yanıt vermiyor
john titus

1
En kötü seçim olduğunu kabul etmiyorum - bu bağlam için kötü bir seçim ve muhtemelen dişli sunucu kullanarak sorunları hafifletmek olacaktır, ancak daha iyi bir çözüm olay tabanlı bir sunucu (nginx veya lighttpd) kullanmak olacaktır. Olay tabanlı Apache, kurumsal dağıtım IMHO'sundan dikkate alınacak kadar olgun değildir.
symcbean

1

Eski bir hikaye olduğunu biliyorum, ama 2 yorumum var.

Bir Orada sabit sınır için ServerLimit Direktifi. http://httpd.apache.org/docs/2.2/mod/mpm_common.html#serverlimit en fazla 20000 / 200K olduğunu göreceksiniz.

Sunucuya derlenmiş sabit bir ServerLimit 20000 sınırı vardır (prefork MPM 200000 için). Bu, yazım hatalarının neden olduğu kötü etkilerden kaçınmayı amaçlamaktadır.

2. Görünüşe göre nodybo, bu 2'yi bire ayarlamanın çok kötü bir fikir olduğunu belirtti :

net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1

Bu, zaman aşımını erkenden yeniden kullandığınız anlamına gelir, tahmin edin ne oldu? sunucu ağır yük altında yanlış istemciyle konuşabilir.

Bunu açıklayan çok iyi bir makale buldum ama - fransız ;-) http://vincent.bernat.im/fr/blog/2014-tcp-time-wait-state-linux.html


0

34GB bellek ile ekstra büyük.

Büyük demir, sadece darboğazları hareket ettirdiğiniz web hizmetini ölçeklendirmenin yolu değildir. Ancak bu kadar bellekle bile, 50000 bağlantıların özellikle aşağıdaki durumlarda sistemin yapabildiklerini zorladığından şüpheleniyorum:

Yoğun saatlerde sunucu yalnızca yaklaşık 300 httpd işlemini boğar

"Sunucu bobinleri" ile ne demek istediğini açıkladıysanız yararlı olacaktır.

Bağlantılar için bu kadar yüksek bir limite, ancak histerezis için çok düşük bir limite (min / maks yedek sunucular) sahip olmak da çok garip.

Sağladığınız hataların özeti 'çok fazla açık dosya' mesajını göstermese de, açık dosya tanımlayıcılarının sayısına ve ulimit ayarlarına bakarak başladım.


Sunucu CHokes olduğu gibi normal html dosyalarına bile yanıt
vermez

MaxClients'ı şimdi 3000 olarak değiştirdim .. hala aynı sorun
John Titus

0

Belki de Apache kullanıcısının izin verilen dosya tanıtıcıları bitiyor? Gönderinizde hiç bahsetmediniz. Apache'nin şu anda kaç dosya tanıtıcısına sahip olmasına izin veriliyor?


128192 dosya tanıtıcısı
john titus

0

Bu daha çok bir yorum gibidir, ancak daha az itibarım olduğu için yapamam. @John titus vardı tam olarak benzer bir sorunla karşılaştı.

MaxThreadsSorunu çözmek için AJP bağlayıcısını Apache Thread sınırımıza yakın hale getirdik .

Bunu izlemek için AJP portumuzda netstat komutuyla SYN_SENT netstat port durumu yardımı aradık .

netstat -an | grep :8102 | grep SYN_SENT | wc -l

Bu 0'a düştü, bu da AJP Bağlayıcısı'nda ayarlanan MaxThread sınırından önce her zaman büyük bir sayı idi.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.