Hiệu suất Apache giảm đáng kể trên ~ 256 yêu cầu đồng thời


14

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.


Các tùy chọn để xem xét: CloudFlare, drupal.org/project/boost , CDN, Varnish cache.
ceejayoz

Bạn không cho chúng tôi biết bất cứ điều gì về những gì máy chủ này đang làm (thế giới thực) bên cạnh việc phục vụ các yêu cầu HTTP. Có một cơ sở dữ liệu (hoặc một số tài nguyên phổ biến khác có thể bị tranh chấp khóa) liên quan không? Nếu sự cố xảy ra đột ngột ở CHÍNH XÁC 256 yêu cầu (OK ở 255), có thể một số tài nguyên bên ngoài đang bị ngập. (Nhảy của bạn phục vụ một trang tĩnh chắc chắn là không bình thường quá - xem câu trả lời Ladadadada cho một số lời khuyên gỡ lỗi có)
voretaq7

ceejayoz: Tôi đánh giá cao các đề xuất, nhưng về cơ bản tôi tin rằng Apache không nên chậm như vậy. Có rất nhiều điều chúng ta có thể làm để giảm thiểu ảnh hưởng của vấn đề, nhưng tôi muốn sửa chữa hoặc ít nhất là hiểu nó.
cmckendry

voretaq7: Ban đầu tôi đã suy nghĩ theo cùng một dòng, vì một yêu cầu thông thường cũng liên quan đến php / mysql, nhưng vấn đề vẫn tồn tại ở cùng một ngưỡng ngay cả khi phục vụ nội dung hoàn toàn tĩnh.
cmckendry

1
Đây là máy chủ thật hay máy ảo? Bạn có làm bài kiểm tra của mình từ localhost, mạng cục bộ hoặc Internet không? Thời gian đáp ứng tối thiểu trong phạm vi 100ms đề xuất các thử nghiệm từ Internet. Hãy thử kiểm tra từ localhost - có thể nhà cung cấp của bạn đang điều chỉnh bạn.
Tometzky

Câu trả lời:


4

Những gì tôi sẽ làm trong tình huống này là chạy

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

trên một trong các quy trình Apache của bạn trong quá trình kiểm tra ab cho đến khi bạn nắm bắt được một trong những phản hồi chậm. Sau đó có một cái nhìn qua trace.txt.

Các tùy chọn -tt-Tcung cấp cho bạn dấu thời gian bắt đầu và thời lượng của mỗi cuộc gọi hệ thống để giúp xác định các cuộc gọi chậm.

Bạn có thể tìm thấy một cuộc gọi hệ thống chậm duy nhất như open()hoặc stat()hoặc bạn có thể tìm thấy một cuộc gọi nhanh với (có thể nhiều poll()cuộc gọi ) ngay sau cuộc gọi đó. Nếu bạn tìm thấy một cái đang hoạt động trên một tệp hoặc kết nối mạng (rất có thể) hãy nhìn về phía sau qua dấu vết cho đến khi bạn tìm thấy tệp hoặc kết nối đó xử lý. Các cuộc gọi trước đó trên cùng một xử lý sẽ cung cấp cho bạn một ý tưởng về những gì poll()đang chờ đợi.


Ý tưởng tốt nhìn vào các -ctùy chọn. Bạn có đảm bảo rằng đứa trẻ Apache mà bạn đang theo dõi đã phục vụ ít nhất một trong những yêu cầu chậm trong thời gian đó không? (Tôi thậm chí không chắc chắn làm thế nào bạn sẽ làm điều này ngoài việc chạy straceđồng thời trên tất cả trẻ em.)

Thật không may, stracekhông cho chúng ta bức tranh hoàn chỉnh về những gì một chương trình đang làm. Nó chỉ theo dõi các cuộc gọi hệ thống. Rất nhiều điều có thể xảy ra trong một chương trình không yêu cầu kernel cho bất cứ điều gì. Để tìm hiểu xem điều này có xảy ra không, bạn có thể xem dấu thời gian bắt đầu của mỗi cuộc gọi hệ thống. Nếu bạn thấy những khoảng trống đáng kể, đó là thời gian sẽ đến. Điều này không dễ dàng có thể truy cập được và luôn có những khoảng trống nhỏ giữa các cuộc gọi hệ thống.

Vì bạn nói rằng việc sử dụng CPU vẫn ở mức thấp, có lẽ không gì quá đáng xảy ra giữa các cuộc gọi hệ thống nhưng nó đáng để kiểm tra.


Nhìn kỹ hơn vào đầu ra từ ab:

Việc nhảy đột ngột trong thời gian phản hồi (có vẻ như không có thời gian phản hồi ở bất kỳ đâu trong khoảng 150ms đến 3000ms) cho thấy rằng có một khoảng thời gian chờ cụ thể xảy ra ở đâu đó được kích hoạt ở trên khoảng 256 kết nối đồng thời. Một sự xuống cấp mượt mà hơn sẽ được dự kiến ​​nếu bạn hết RAM hoặc CPU quay vòng IO bình thường.

Thứ hai, abphản ứng chậm cho thấy 3000ms đã được sử dụng trong connectpha. Gần như tất cả trong số họ mất khoảng 30ms nhưng 5% mất 3000ms. Điều này cho thấy rằng mạng là vấn đề.

Bạn đang chạy abđi đâu Bạn có thể thử nó từ cùng một mạng với máy Apache không?

Để biết thêm dữ liệu, hãy thử chạy tcpdumpở cả hai đầu của kết nối (tốt nhất là ntpchạy ở cả hai đầu để bạn có thể đồng bộ hóa hai ảnh chụp lên.) Và tìm kiếm bất kỳ truyền lại tcp nào. Wireshark đặc biệt tốt để phân tích các bãi rác vì nó làm nổi bật việc truyền lại tcp bằng một màu khác, giúp chúng dễ dàng tìm thấy.

Cũng có thể đáng để xem nhật ký của bất kỳ thiết bị mạng nào bạn có quyền truy cập. Gần đây tôi đã gặp phải một vấn đề với một trong các tường lửa của chúng tôi, nơi nó có thể xử lý băng thông theo kb / s nhưng nó không thể xử lý số lượng gói mỗi giây mà nó nhận được. Nó đứng đầu với 140.000 gói mỗi giây. Một số phép toán nhanh trên đường abchạy của bạn khiến tôi tin rằng bạn sẽ thấy khoảng 13.000 gói mỗi giây (bỏ qua 5% yêu cầu chậm). Có thể đây là nút cổ chai bạn đã đạt được. Việc điều này xảy ra vào khoảng 256 có thể hoàn toàn là một sự trùng hợp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.