Chúng tôi có một API được triển khai bằng ServiceStack được lưu trữ trong IIS. Trong khi thực hiện kiểm tra tải API, chúng tôi đã phát hiện ra rằng thời gian phản hồi là tốt nhưng chúng sẽ xuống cấp nhanh chóng ngay khi chúng tôi đạt khoảng 3.500 người dùng đồng thời trên mỗi máy chủ. Chúng tôi có hai máy chủ và khi đánh chúng với 7.000 người dùng, thời gian phản hồi trung bình ở mức dưới 500ms cho tất cả các điểm cuối. Các hộp nằm phía sau một bộ cân bằng tải để chúng tôi nhận được 3.500 đồng quy trên mỗi máy chủ. Tuy nhiên, ngay khi chúng tôi tăng số lượng người dùng đồng thời, chúng tôi sẽ thấy thời gian phản hồi tăng đáng kể. Việc tăng số người dùng đồng thời lên 5.000 trên mỗi máy chủ cho chúng ta thời gian phản hồi trung bình trên mỗi điểm cuối khoảng 7 giây.
Bộ nhớ và CPU trên các máy chủ khá thấp, cả trong khi thời gian đáp ứng đều tốt và khi nào chúng bị hỏng. Ở mức cao nhất với 10.000 người dùng đồng thời, CPU trung bình chỉ dưới 50% và RAM chiếm khoảng 3-4 GB trong số 16. Điều này khiến chúng tôi nghĩ rằng chúng tôi đang đạt một số giới hạn ở đâu đó. Ảnh chụp màn hình bên dưới cho thấy một số bộ đếm chính trong perfmon trong quá trình thử tải với tổng số 10.000 người dùng đồng thời. Bộ đếm được tô sáng là yêu cầu / giây. Ở bên phải của ảnh chụp màn hình, bạn có thể thấy các yêu cầu trên biểu đồ thứ hai trở nên thực sự thất thường. Đây là chỉ số chính cho thời gian đáp ứng chậm. Ngay khi chúng tôi thấy mẫu này, chúng tôi nhận thấy thời gian phản hồi chậm trong thử nghiệm tải.
Làm thế nào để chúng tôi đi về khắc phục sự cố hiệu suất này? Chúng tôi đang cố gắng xác định xem đây là vấn đề mã hóa hay vấn đề cấu hình. Có bất kỳ cài đặt nào trong web.config hoặc IIS có thể giải thích hành vi này không? Nhóm ứng dụng đang chạy .NET v4.0 và phiên bản IIS là 7.5. Thay đổi duy nhất chúng tôi đã thực hiện từ cài đặt mặc định là cập nhật giá trị Độ dài hàng đợi của nhóm ứng dụng từ 1.000 đến 5.000. Chúng tôi cũng đã thêm các cài đặt cấu hình sau vào tệp Aspnet.config:
<system.web>
<applicationPool
maxConcurrentRequestsPerCPU="5000"
maxConcurrentThreadsPerCPU="0"
requestQueueLimit="5000" />
</system.web>
Thêm chi tiết:
Mục đích của API là kết hợp dữ liệu từ nhiều nguồn bên ngoài khác nhau và trả về dưới dạng JSON. Hiện tại nó đang sử dụng triển khai bộ đệm InMemory để lưu trữ các cuộc gọi bên ngoài riêng lẻ ở lớp dữ liệu. Yêu cầu đầu tiên đối với tài nguyên sẽ tìm nạp tất cả dữ liệu cần thiết và mọi yêu cầu tiếp theo cho cùng một tài nguyên sẽ nhận được kết quả từ bộ đệm. Chúng tôi có một 'người chạy bộ đệm' được triển khai như một quá trình nền để cập nhật thông tin trong bộ đệm theo các khoảng thời gian nhất định. Chúng tôi đã thêm khóa xung quanh mã lấy dữ liệu từ các tài nguyên bên ngoài. Chúng tôi cũng đã triển khai các dịch vụ để lấy dữ liệu từ các nguồn bên ngoài theo cách không đồng bộ để điểm cuối chỉ nên chậm như cuộc gọi bên ngoài chậm nhất (tất nhiên trừ khi chúng tôi có dữ liệu trong bộ đệm). Điều này được thực hiện bằng cách sử dụng lớp System.Threading.T task.Task.Chúng ta có thể đạt được một giới hạn về số lượng chủ đề có sẵn cho quá trình không?