Kinerja Apache menurun drastis di atas ~ 256 permintaan secara bersamaan

14

Saya menjalankan situs dengan lalu lintas yang relatif rendah yang mengalami lonjakan besar pengunjung seminggu sekali setelah pembaruan situs. Selama lonjakan ini, kinerja situs sangat buruk dibandingkan dengan sisa minggu ini. Beban yang sebenarnya di server tetap sangat rendah, andal di bawah 10% CPU dan di bawah 30% RAM (perangkat keras harus benar-benar berlebihan untuk apa yang sebenarnya kita lakukan), tetapi untuk beberapa alasan Apache tampaknya tidak dapat mengatasi kuantitasnya. permintaan. Kami menjalankan apache 2.2.3 pada RHEL 5.7, kernel 2.6.18-274.7.1.el5, x86_64.

Mencoba mereproduksi perilaku ini selama jam kerja dengan ab, saya menemukan penurunan kinerja yang besar ketika melebihi sekitar 256 pengguna. Menjalankan tes dengan kasus penggunaan sekecil mungkin yang dapat saya buat dengan (file teks statis sedang diambil, total 223 byte) kinerja secara konsisten normal dengan 245 permintaan simultan:

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       15   25   5.8     24      37
Processing:    15   65  22.9     76      96
Waiting:       15   64  23.0     76      96
Total:         30   90  27.4    100     125

Percentage of the requests served within a certain time (ms)
  50%    100
  66%    108
  75%    111
  80%    113
  90%    118
  95%    120
  98%    122
  99%    123
 100%    125 (longest request)

Tetapi segera setelah saya ratchet hingga 265 permintaan secara bersamaan, sebagian dari mereka mulai mengambil jumlah waktu yang absurd untuk menyelesaikan:

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       13  195 692.6     26    3028
Processing:    15   65  21.3     72     100
Waiting:       15   65  21.3     71      99
Total:         32  260 681.7    101    3058

Percentage of the requests served within a certain time (ms)
  50%    101
  66%    108
  75%    112
  80%    116
  90%    121
  95%   3028
  98%   3040
  99%   3044
 100%   3058 (longest request)

Hasil-hasil ini sangat konsisten di berbagai proses. Karena ada lalu lintas lain menuju kotak itu, saya tidak yakin persis di mana cutoff kerasnya akan, jika ada, tetapi tampaknya mendekati 256.

Secara alami, saya berasumsi bahwa ini disebabkan oleh batas utas pada prefork, jadi saya melanjutkan dan menyesuaikan konfigurasi untuk menggandakan jumlah utas yang tersedia dan untuk mencegah kumpulan benang tumbuh dan menyusut secara tidak perlu:

<IfModule prefork.c>
StartServers     512
MinSpareServers  512
MaxSpareServers  512
ServerLimit      512
MaxClients       512
MaxRequestsPerChild  5000
</IfModule>

mod_status mengonfirmasi bahwa saya sekarang menjalankan dengan 512 utas yang tersedia

8 requests currently being processed, 504 idle workers

Namun, mencoba 265 permintaan simultan masih menghasilkan hasil yang hampir sama dengan sebelumnya

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       25  211 714.7     31    3034
Processing:    17   94  28.6    103     138
Waiting:       17   93  28.5    103     138
Total:         57  306 700.8    138    3071

Percentage of the requests served within a certain time (ms)
  50%    138
  66%    145
  75%    150
  80%    161
  90%    167
  95%   3066
  98%   3068
  99%   3068
 100%   3071 (longest request)

Setelah menjelajahi dokumentasi (dan Stack Exchange) saya bingung untuk pengaturan konfigurasi lebih lanjut untuk mencoba mengatasi kemacetan ini. Apakah ada sesuatu yang saya lewatkan? Haruskah saya mulai mencari jawaban di luar apache? Adakah orang lain yang melihat perilaku ini? Bantuan apa pun akan sangat dihargai.

EDIT:

Sesuai saran Ladadadada, saya berlari melawan apache. Saya mencoba dengan -tt dan -T beberapa kali dan tidak dapat menemukan sesuatu yang luar biasa. Saya kemudian mencoba menjalankan strace -c terhadap semua proses apache yang sedang berjalan, dan mendapatkan ini:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 22.09    0.317836           5     62128      4833 open
 19.91    0.286388           4     65374      1896 lstat
 13.06    0.187854           0    407433           pread
 10.70    0.153862           6     27076           semop
  7.88    0.113343           3     38598           poll
  6.86    0.098694           1    100954     14380 read

(... disingkat)

Jika saya membaca ini dengan benar (dan tahan dengan saya, karena saya tidak sering menggunakan strace) tidak ada panggilan sistem yang dapat menjelaskan jumlah waktu yang dibutuhkan oleh permintaan ini. Sepertinya kemacetan terjadi sebelum permintaan bahkan sampai ke thread pekerja.

EDIT 2:

Seperti yang disarankan beberapa orang, saya menjalankan tes lagi di server web itu sendiri (sebelumnya tes dijalankan dari lokasi internet netral). Hasilnya mengejutkan:

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   11   6.6     12      21
Processing:     5  247 971.0     10    4204
Waiting:        3  245 971.3      7    4204
Total:         16  259 973.3     21    4225

Percentage of the requests served within a certain time (ms)
  50%     21
  66%     23
  75%     24
  80%     24
  90%     26
  95%   4225
  98%   4225
  99%   4225
 100%   4225 (longest request)

Waktu bottom-line mirip dengan tes berbasis internet, tetapi tampaknya secara konsisten menjadi sedikit lebih buruk ketika dijalankan secara lokal. Lebih menarik lagi, profilnya telah berubah secara dramatis. Padahal sebelum sebagian besar waktu permintaan berjalan lama dihabiskan di "terhubung" sekarang hambatan tampaknya dalam pemrosesan atau menunggu. Saya curiga bahwa ini mungkin sebenarnya merupakan masalah terpisah yang sebelumnya ditutupi oleh keterbatasan jaringan.

Menjalankan tes lagi dari komputer lain di jaringan lokal yang sama dengan host Apache, saya melihat hasil yang jauh lebih masuk akal:

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        1    2   0.8      2       4
Processing:    13  118  99.8    205     222
Waiting:       13  118  99.7    204     222
Total:         15  121  99.7    207     225

Percentage of the requests served within a certain time (ms)
  50%    207
  66%    219
  75%    220
  80%    221
  90%    222
  95%    224
  98%    224
  99%    225
 100%    225 (longest request)

Kedua tes ini bersama-sama menimbulkan sejumlah pertanyaan, tetapi secara terpisah dari itu, sekarang ada kasus menarik yang harus dibuat untuk beberapa jenis kemacetan jaringan parah yang terjadi di bawah jumlah beban tertentu. Saya pikir langkah selanjutnya akan menyelidiki lapisan jaringan secara terpisah.

cmckendry
sumber
Opsi untuk dipertimbangkan: CloudFlare, drupal.org/project/boost , CDN, Varnish cache.
ceejayoz
Anda tidak memberi tahu kami apa pun yang dilakukan server ini (dunia nyata) selain melayani permintaan HTTP. Apakah ada database (atau sumber daya umum lainnya yang dapat menderita pertikaian kunci) yang terlibat? Jika masalah terjadi secara tiba-tiba di 256 PERSIS permintaan (OK pada 255) mungkin ada beberapa sumber daya eksternal yang dibanjiri. (Lompatan Anda yang menyajikan laman statis juga tidak normal - lihat jawaban Ladadadada untuk beberapa kiat debug di sana)
voretaq7
ceejayoz: Saya menghargai saran, tetapi pada dasarnya saya percaya bahwa Apache tidak boleh selambat ini. Ada banyak hal yang dapat kita lakukan untuk mengurangi efek dari masalah, tetapi saya lebih suka memperbaikinya atau setidaknya memahaminya.
cmckendry
voretaq7: Saya awalnya berpikir di sepanjang baris yang sama ini, karena permintaan yang khas juga akan melibatkan php / mysql, tetapi masalahnya tetap pada ambang yang sama bahkan ketika menyajikan konten yang sepenuhnya statis.
cmckendry
1
Apakah ini server nyata atau VM? Apakah Anda melakukan tes dari localhost, jaringan lokal atau Internet? Waktu respons minimal dalam kisaran 100 ms menyarankan tes dari Internet. Cobalah untuk menguji dari localhost - mungkin penyedia Anda hanya mencekik Anda.
Tometzky

Jawaban:

4

Apa yang akan saya lakukan dalam situasi ini adalah lari

strace -f -p <PID> -tt -T -s 500 -o trace.txt

pada salah satu proses Apache Anda selama tes ab sampai Anda menangkap salah satu respons lambat. Kemudian lihat-lihat trace.txt.

The -ttdan -Tpilihan memberikan timestamps dari awal dan durasi setiap sistem panggilan untuk membantu mengidentifikasi orang-orang yang lambat.

Anda mungkin menemukan satu panggilan sistem lambat seperti open()atau stat()atau Anda mungkin menemukan panggilan cepat dengan (mungkin beberapa) poll()panggilan langsung setelah itu. Jika Anda menemukan satu yang beroperasi pada file atau koneksi jaringan (kemungkinan besar) melihat ke belakang melalui jejak sampai Anda menemukan file atau koneksi itu menangani. Panggilan sebelumnya pada pegangan yang sama harus memberi Anda gambaran tentang apa yang poll()ditunggu.


Ide bagus melihat -copsi. Apakah Anda memastikan bahwa anak Apache yang Anda lacak melayani setidaknya satu dari permintaan yang lambat selama waktu itu? (Saya bahkan tidak yakin bagaimana Anda akan melakukan ini selain berlari stracesecara bersamaan pada semua anak.)

Sayangnya, stracetidak memberi kami gambaran lengkap tentang apa yang sedang dilakukan program berjalan. Ini hanya melacak panggilan sistem. Banyak yang bisa terjadi di dalam program yang tidak perlu meminta kernel apa pun. Untuk mengetahui apakah ini terjadi, Anda dapat melihat cap waktu pada awal setiap panggilan sistem. Jika Anda melihat kesenjangan yang signifikan, di situlah saatnya. Ini tidak mudah dipahami dan selalu ada celah kecil di antara panggilan sistem.

Karena Anda mengatakan penggunaan CPU tetap rendah, itu mungkin bukan hal yang berlebihan terjadi di antara panggilan sistem tetapi perlu diperiksa.


Melihat lebih dekat pada output dari ab:

Lompatan tiba-tiba di waktu respons (sepertinya tidak ada waktu respons di mana saja antara 150ms dan 3000ms) menunjukkan bahwa ada batas waktu tertentu yang terjadi di suatu tempat yang dipicu di atas sekitar 256 koneksi simultan. Degradasi yang lebih mulus akan terjadi jika Anda kehabisan RAM atau siklus CPU IO normal.

Kedua, abrespon lambat menunjukkan bahwa 3000ms dihabiskan dalam connectfase. Hampir semuanya mengambil sekitar 30 ms tetapi 5% mengambil 3000 ms. Ini menunjukkan bahwa jaringan adalah masalahnya.

Dari mana Anda lari ab? Bisakah Anda mencobanya dari jaringan yang sama dengan mesin Apache?

Untuk lebih banyak data, coba jalankan tcpdumpdi kedua ujung koneksi (sebaiknya dengan ntpmenjalankan di kedua ujung sehingga Anda dapat menyinkronkan kedua penangkapan.) Dan mencari transmisi ulang tcp. Wireshark sangat baik untuk menganalisis pembuangan karena menyoroti pengiriman ulang tcp dalam warna yang berbeda, membuatnya mudah ditemukan.

Mungkin juga layak untuk melihat log dari perangkat jaringan apa pun yang Anda akses. Saya baru-baru ini mengalami masalah dengan salah satu firewall kami di mana ia bisa menangani bandwidth dalam hal kb / s tetapi tidak bisa menangani jumlah paket per detik yang diterimanya. Ini mencapai 140.000 paket per detik. Beberapa matematika cepat saat abdijalankan membuat saya percaya bahwa Anda akan melihat sekitar 13.000 paket per detik (mengabaikan 5% dari permintaan lambat). Mungkin ini adalah hambatan yang telah Anda capai. Fakta bahwa ini terjadi sekitar 256 mungkin murni kebetulan.

Ladadadada
sumber