Apache Tomcat tersedak setelah 300 koneksi

16

Kami memiliki server web apache di depan Tomcat yang dihosting di EC2, tipe instance lebih besar dengan memori 34GB.

Aplikasi kami berurusan dengan banyak layanan web eksternal dan kami memiliki layanan web eksternal yang sangat buruk yang membutuhkan waktu hampir 300 detik untuk menanggapi permintaan selama jam sibuk.

Selama jam sibuk server tersedak di sekitar 300 proses httpd. ps-id | grep httpd | wc -l = 300

Saya telah mencari di Google dan menemukan banyak saran tetapi sepertinya tidak ada yang berhasil .. berikut adalah beberapa konfigurasi yang telah saya lakukan yang diambil langsung dari sumber daya online.

Saya telah meningkatkan batas koneksi maks dan maks klien di apache dan kucing jantan. berikut adalah detail konfigurasi:

// apache

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

//kucing jantan

    <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

Saya sudah mencoba banyak saran tetapi sia-sia .. bagaimana cara memperbaikinya? Saya yakin server m2xlarge harus melayani lebih dari 300 permintaan, mungkin saya mungkin salah dengan konfigurasi saya ..

Server tersedak hanya selama jam sibuk dan ketika ada 300 permintaan bersamaan menunggu layanan web [300 detik tertunda] untuk merespons.

Saya baru saja memonitor koneksi tcp dengan netstat

saya menemukan sekitar 1000 koneksi dalam keadaan TIME_WAIT, tidak tahu apa artinya dalam hal kinerja, saya yakin itu pasti menambah masalah.

Output dari TOP

 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

Juga pada waktu sibuk ada sekitar 10-15k koneksi tcp untuk membase server [lokal]

BEBERAPA KESALAHAN DALAM MODJK LOG, Saya harap ini menyoroti masalah ini ..

[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

//Terpecahkan

thansk all untuk saran Anda yang berharga .. saya melewatkan pengaturan maxThreads untuk konektor AJP 1.3 .. Sekarang semuanya tampak terkendali.

Saya juga akan mulai melihat server berbasis bahkan seperti nginx.

john titus
sumber
Seperti apa pengaturan Keepalive Anda?
Tom O'Connor
Kesalahan apa yang didapatkan klien saat mencoba memuat halaman?
Shane Madden
1
Apakah Anda meningkatkan uraian file terbuka maks yang diizinkan untuk pengguna apache / httpd?
golja
@Tom Pengaturan Keep My Alive adalah KeepAliveTimeout 10 di httpd.conf
john titus
3
Seperti apa hasil dari toptampilan selama waktu ini? Bagaimana dengan free -m? Dan terakhir iostat?
Zypher

Jawaban:

13

Sudahkah Anda meningkatkan MaxThreads di AJP 1.3 Connector pada port 8009?

HTTP500
sumber
1500 adalah apa yang saya miliki per contoh kucing jantan
john titus
@ John, Apakah Anda mengatakan bahwa untuk setiap Konektor yang Anda tentukan maxThreads = "1500"? Bisakah Anda memposting bait Anda untuk AJP 1.3 Connector (port 8009)?
HTTP500
terima kasih telah menunjukkan ini .. tidak ada pengaturan maxThreads untuk AJP1.3 sama sekali .. mungkinkah ini alasannya?
john titus
1
Ya, tambahkan maxThreads ke bait untuk Connector itu. Standarnya adalah 200.
HTTP500
6

Pertimbangkan untuk menyiapkan server web proxy yang tidak sinkron seperti nginxatau lighttpddi depan Apache. Apache menyajikan konten secara sinkron sehingga pekerja diblokir hingga klien mengunduh konten yang dihasilkan secara lengkap (detail lebih lanjut di sini ). Menyiapkan proksi asinkron (non-pemblokiran) biasanya memperbaiki situasi secara dramatis (Saya dulu menurunkan jumlah pekerja Apache yang berjalan bersamaan dari 30 menjadi 3-5 menggunakan nginxsebagai proxy frontend).

Alex
sumber
5

Saya menduga masalah Anda adalah di tomcat bukan apache, dari log yang telah Anda tunjukkan. Ketika Anda mendapatkan 'kesalahan 110' yang mencoba menghubungkan kembali ke kucing jantan itu menunjukkan Anda memiliki antrian koneksi yang menunggu untuk dilayani yang tidak ada lagi yang bisa masuk ke pengaturan backlog mendengarkan untuk soket mendengarkan di kucing jantan.

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.

Jika saya harus menebak, saya akan curiga bahwa sebagian besar permintaan HTTP ketika server "tersedak" diblokir menunggu sesuatu untuk kembali dari kucing jantan. Saya yakin jika Anda mencoba untuk mengambil beberapa konten statis yang langsung dilayani oleh apache (daripada proksi untuk kucing jantan) bahwa ini akan bekerja bahkan ketika itu biasanya 'tersedak'.

Sayangnya saya tidak akrab dengan kucing jantan, tetapi apakah ada cara untuk memanipulasi pengaturan konkurensi ini?

Oh, dan Anda mungkin perlu juga mempertimbangkan kemungkinan bahwa dengan layanan jaringan eksternal thats di membatasi jumlah koneksi yang itu melakukan untuk Anda turun ke 300, sehingga tidak ada bedanya berapa banyak manipulasi concurrency Anda lakukan pada sisi depan Anda jika praktis setiap koneksi yang Anda lakukan bergantung pada respons layanan web eksternal.

Dalam salah satu komentar Anda, data yang Anda sebutkan menjadi basi setelah 2 menit. Saya sarankan caching respons yang Anda dapatkan dari layanan ini selama dua menit untuk mengurangi jumlah koneksi bersamaan yang Anda kendarai ke layanan web eksternal.

Matthew Ife
sumber
2

Langkah pertama untuk memecahkan masalah ini adalah mengaktifkan mod_status Apache dan mempelajari laporannya - sampai Anda selesai melakukannya, sebenarnya Anda berjalan dengan buta. Itu tidak benar. ;-)

Hal kedua yang saya sebutkan (saya sendiri tidak suka diberi jawaban atas pertanyaan yang tidak saya tanyakan, tapi ...) menggunakan server front-end yang lebih efisien dan istimewa seperti nginx.

Juga, apakah Anda benar-benar restartapache, atau baru saja gracefulmemuatnya kembali ? :)

poige
sumber
Apache memulai kembali .. bukan memuat ulang dengan anggun
john titus
@ johntitus, well, mod_statusini temanmu. :)
poige
1

Untuk segala jenis penyebaran perusahaan-y, MPM prefork hanya tentang pilihan terburuk yang dapat Anda buat: itu melahap sumber daya seperti bisnis siapa pun, dan memulai kembali utas membutuhkan SELAMANYA dibandingkan dengan MPM lainnya.

Setidaknya beralih ke MPM pekerja (apache 2.2 dan lebih tinggi) atau - lebih baik lagi - upgrade ke versi stabil saat ini 2.4.2 dengan MPM acara default .

Kedua hal ini akan dengan mudah menangani ribuan koneksi bersamaan dengan overhead yang sangat sedikit.

adaptr
sumber
terima kasih .. mencobanya juga .. tidak berhasil. Koneksi TIME_WAIT terus meningkat. Server berhenti merespons pada 350 koneksi
john titus
1
Saya tidak setuju bahwa ini adalah pilihan terburuk - ini adalah pilihan yang buruk untuk konteks ini dan kemungkinan masalahnya akan berkurang dengan menggunakan server berulir, tetapi solusi yang lebih baik adalah dengan menggunakan server berbasis peristiwa (nginx atau lighttpd). Apache berbasis acara hampir tidak cukup matang untuk dipertimbangkan dari IMHO penyebaran perusahaan.
symcbean
1

Saya tahu ini adalah cerita lama, tapi saya punya 2 komentar.

Ada batasan kode keras untuk ServerLimit Directive. http://httpd.apache.org/docs/2.2/mod/mpm_common.html#serverlimit Anda akan melihat bahwa maks. 20000 / 200K.

Ada batas keras ServerLimit 20000 dikompilasi ke server (untuk prefork MPM 200000). Ini dimaksudkan untuk menghindari efek buruk yang disebabkan oleh kesalahan ketik.

2nd Rupanya nodybo menyebutkan bahwa pengaturan 2 to one adalah ide yang sangat buruk :

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

itu berarti Anda menggunakan kembali timewait lebih awal, coba tebak? server dapat berbicara dengan klien yang salah di bawah beban berat.

Saya menemukan artikel yang sangat bagus untuk menjelaskan itu tetapi - ini adalah bahasa Perancis ;-) http://vincent.bernat.im/fr/blog/2014-tcp-time-wait-state-linux.html

Nadir
sumber
0

ekstra besar dengan memori 34GB.

Setrika besar bukan cara untuk mengukur webserving Anda hanya memindahkan kemacetan di sekitar. Tetapi bahkan dengan memori sebanyak ini, saya curiga bahwa 50000 koneksi mendorong apa yang mampu dilakukan oleh sistem terutama jika:

Selama jam sibuk server tersedak di sekitar 300 proses httpd

Akan sangat membantu jika Anda menjelaskan apa yang Anda maksud dengan "server choke".

Ini juga sangat aneh untuk memiliki batas koneksi yang tinggi tetapi batas yang sangat rendah untuk hysteresis (server cadangan min / max).

Meskipun ekstrak kesalahan yang Anda berikan tidak menunjukkan tanda 'terlalu banyak file terbuka', saya akan mulai dengan melihat jumlah deskriptor file terbuka dan pengaturan ulimit.

symcbean
sumber
Server Tersedak seperti di dalamnya bahkan tidak menanggapi file html normal ..
john titus
Saya mengubah maxClients menjadi 3000 sekarang .. masih masalah yang sama
john titus
0

Mungkin pengguna Apache kehabisan pegangan file yang diizinkan? Anda tidak menyebutkannya sama sekali di pos Anda. Berapa banyak file yang ditangani oleh Apache saat ini?

Janne Pikkarainen
sumber
128192 file menangani
john titus
0

Ini lebih seperti komentar, tetapi karena tidak bisa karena saya kurang memiliki reputasi. Datang di masalah yang persis sama seperti @ john titus.

Kami membuat konektor AJP MaxThreadsdekat dengan batas Apache Thread kami untuk menyelesaikan masalah.

Untuk memantau ini, kami mencari SYN_SENT bantuan status port netstat dengan perintah netstat pada port AJP kami.

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

Ini turun ke 0, yang selalu beberapa angka besar sebelum batas MaxThread ditetapkan pada Konektor AJP.

Vineeth
sumber