Tôi đang điều hành một trang web có lưu lượng truy cập tương đối thấp, trải nghiệm lượng khách truy cập tăng đột biến mỗi tuần một lần sau khi cập nhật trang web. Trong thời gian tăng đột biến này, hiệu suất trang web cực kỳ kém so với phần còn lại của tuần. Tải thực tế trên các máy chủ vẫn rất thấp, đáng tin cậy dưới 10% CPU và dưới 30% RAM (phần cứng nên hoàn toàn quá mức cho những gì chúng ta thực sự đang làm), nhưng vì một số lý do, Apache dường như không thể đối phó với số lượng của các yêu cầu. Chúng tôi đang chạy apache 2.2.3 trên RHEL 5.7, kernel 2.6.18-274.7.1.el5, x86_64.
Cố gắng tái tạo hành vi này trong giờ nghỉ với ab, tôi thấy hiệu suất giảm đáng kể khi vượt quá 256 người dùng. Chạy thử nghiệm với trường hợp sử dụng nhỏ nhất có thể mà tôi có thể đưa ra (tệp văn bản tĩnh được truy xuất, tổng cộng 223 byte) hiệu suất luôn bình thường với 245 yêu cầu đồng thời:
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)
Nhưng ngay sau khi tôi bắt đầu lên tới 265 yêu cầu đồng thời, một tập hợp con trong số chúng bắt đầu mất một lượng thời gian vô lý để hoàn thành:
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)
Những kết quả này rất nhất quán trên nhiều lần chạy. Vì có lưu lượng truy cập khác đi vào ô đó, tôi không chắc chắn chính xác nơi bị cắt cứng, nếu có, nhưng dường như nó gần đến mức đáng ngờ là 256.
Đương nhiên, tôi cho rằng điều này là do giới hạn luồng trong prefork gây ra, vì vậy tôi đã tiếp tục và điều chỉnh cấu hình để tăng gấp đôi số lượng luồng có sẵn và để ngăn nhóm luồng phát triển và co lại không cần thiết:
<IfModule prefork.c>
StartServers 512
MinSpareServers 512
MaxSpareServers 512
ServerLimit 512
MaxClients 512
MaxRequestsPerChild 5000
</IfModule>
mod_status xác nhận rằng tôi hiện đang chạy với 512 luồng có sẵn
8 requests currently being processed, 504 idle workers
Tuy nhiên, cố gắng 265 yêu cầu đồng thời vẫn mang lại kết quả gần như giống hệt với trước đây
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)
Sau khi quét tài liệu (và Stack Exchange), tôi không biết các cài đặt cấu hình tiếp theo để cố gắng giải quyết nút thắt này. Có cái gì tôi đang thiếu? Tôi có nên bắt đầu tìm kiếm câu trả lời bên ngoài apache? Có ai khác nhìn thấy hành vi này? Mọi sự trợ giúp sẽ rất được trân trọng.
BIÊN TẬP:
Theo lời khuyên của Ladadadada, tôi đã chạy chống lại apache. Tôi đã thử với -tt và -T một vài lần và không thể tìm thấy điều gì khác thường. Sau đó tôi đã thử chạy strace -c chống lại tất cả các quy trình apache hiện đang chạy và nhận được điều này:
% 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
(... rút gọn)
Nếu tôi đang đọc quyền này (và đồng ý với tôi, vì tôi không thường xuyên sử dụng strace) thì không có cuộc gọi hệ thống nào có thể chiếm thời lượng mà các yêu cầu này đang thực hiện. Có vẻ như nút cổ chai đang xảy ra trước khi các yêu cầu thậm chí đến các luồng công nhân.
EDIT 2:
Như nhiều người đề xuất, tôi đã chạy thử nghiệm lại trên chính máy chủ web (trước đây thử nghiệm đã được chạy từ một địa điểm internet trung tính). Kết quả thật đáng ngạc nhiên:
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)
Thời gian cuối cùng tương tự như thử nghiệm dựa trên internet, nhưng dường như luôn tệ hơn một chút khi chạy cục bộ. Thú vị hơn, hồ sơ đã thay đổi đáng kể. Trong khi trước khi phần lớn thời gian của các yêu cầu chạy dài được sử dụng để "kết nối" thì bây giờ nút cổ chai dường như đang trong quá trình xử lý hoặc chờ đợi. Tôi còn nghi ngờ rằng đây thực sự có thể là một vấn đề riêng biệt mà trước đây đã bị che giấu bởi các giới hạn mạng.
Chạy thử nghiệm lại từ một máy khác trên cùng mạng cục bộ với máy chủ Apache, tôi thấy kết quả hợp lý hơn nhiều:
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)
Hai bài kiểm tra này cùng nhau đưa ra một số câu hỏi, nhưng riêng từ đó, giờ đây đã có một trường hợp hấp dẫn được thực hiện cho một số loại tắc nghẽn mạng nghiêm trọng xảy ra trong một lượng tải nhất định. Tôi nghĩ rằng các bước tiếp theo sẽ điều tra lớp mạng riêng biệt.