2012-06-19 40 views
5

Tôi đang làm việc trên một dịch vụ mới để chạy QA cho nhiều thuộc tính web của công ty chúng tôi và đã gặp sự cố đồng thời về mạng thú vị. Để tăng hiệu suất, tôi đang sử dụng TPL để tạo HttpWebRequests dựa trên một bộ sưu tập lớn các url để chúng có thể chạy song song; tuy nhiên, tôi dường như không thể tìm ra nơi nút cổ chai đang trong quá trình này.Các vấn đề về hiệu suất yêu cầu web đồng thời

quan sát của tôi cho đến nay:

  • tôi có thể nhận được một tối đa khoảng 25-30 đề song song qua TPL
  • CPU không bao giờ phá vỡ 5-6% cho các dịch vụ (chạy trên 1-4 lõi, có và không có H/T)
  • Sử dụng NIC không bao giờ ngắt 2-3%
  • Lưu lượng truy cập mạng dường như không bị ảnh hưởng (người dùng khác không phàn nàn, kiểm tra tốc độ chạy cùng lúc don ' t hiển thị nhiều ảnh hưởng)
  • Tốc độ không thay đổi nhiều giữa chạy trên mạng văn phòng của chúng tôi (15Mbps) hoặc trung tâm dữ liệu của chúng tôi (100 Mbps)
  • Tôi nhận được một chút hiệu suất bằng cách tải xuống từ nhiều máy chủ cùng một lúc thay vì nhiều trang từ một máy chủ.

điểm đau có thể xảy ra:

  • CPU (số lượng lõi hoặc đề phần cứng)
  • NIC
  • Max phép số HttpWebRequests đồng thời
  • LAN
  • WAN
  • Router/Bộ chuyển đổi/Cân bằng tải

Vì vậy, câu hỏi là:

Rõ ràng hiện nay là cách để tải về toàn bộ Internet chỉ trong vài phút, nhưng tôi quan tâm để biết nơi mà các nút cổ chai là trong một kịch bản như thế này và những gì, nếu bất cứ điều gì, có thể được thực hiện để vượt qua nó.

Lưu ý phụ, chúng tôi hiện đang sử dụng dịch vụ của bên thứ ba để thu thập dữ liệu, nhưng chúng tôi bị giới hạn bởi một số cách và muốn linh hoạt hơn. Một cái gì đó về nước sốt bí mật của công ty hoặc poison on the tip of the arrow ... :)

+0

Bạn có thể đăng một vài chi tiết về mã của mình không? Tôi đang chạy trình thu thập thông tin với 100 luồng song song không có vấn đề gì. Tôi đang trên .NET 4 và máy chủ không có gì nhiều. Tôi đang sử dụng NCrawler trong phần phụ trợ. –

+0

Mã thực sự rất đơn giản. Tôi sử dụng Parallel.ForEach để lặp qua một tập hợp các URL (chuỗi). Hành động tạo ra một HttpWebRequest và sau đó đổ kết quả vào một ConcurrentBag. BTW, NCrawler có vẻ thú vị; Tôi sẽ kiểm tra. Cảm ơn vì tiền hỗ trợ. –

+0

Có giới hạn về số lượng HttpWebRequest đồng thời cho cùng một máy chủ IIRC –

Trả lời

7

tôi rất nghi ngờ một trong những điều sau đây là nguyên nhân:

  1. Bạn đang chạy vào giới hạn kết nối mặc định. Kiểm tra giá trị của ServicePointManager.DefaultConnectionLimit. Tôi khuyên bạn nên đặt giá trị đó thành giá trị thực tế vô hạn chẳng hạn như 1000.
  2. TPL không bắt đầu bằng nhiều chủ đề cần thiết để bão hòa mạng. Lưu ý rằng các máy chủ web từ xa có thể có một lượng lớn độ trễ. Trong khi chờ đợi, luồng của bạn không được tải trên mạng.

TPL không đảm bảo cho bạn mức độ song song tối thiểu (DOP). Đó là một điều đáng tiếc bởi vì đôi khi bạn thực sự cần phải kiểm soát mức độ song song chính xác khi làm việc với IO.

Tôi khuyên bạn nên bắt đầu thủ công một số chuỗi cố định để thực hiện IO của bạn vì đó là cách duy nhất để đảm bảo DOP cụ thể. Bạn cần phải thử nghiệm với giá trị chính xác. Nó có thể nằm trong khoảng từ 50 đến 500. Bạn có thể giảm kích thước ngăn xếp mặc định của các chủ đề của bạn để tiết kiệm bộ nhớ với nhiều chuỗi.

+0

Cảm ơn bạn đã biết các mẹo. Tuy nhiên, điều tôi thích về TPL là nó dễ dàng cho phép một bản dựng đơn lẻ hoạt động trên nhiều máy khác nhau mà không cần phải viết nhiều mã để quản lý các chuỗi phần cứng số. –

+3

@SteveKonves điều này là đúng nhưng nó chỉ áp dụng cho công việc liên kết CPU. Mã của bạn có vẻ như nó sẽ bị ràng buộc mạng. TPL sẽ chủ động xâm nhập và quản lý tài nguyên của bạn. – usr

+1

điểm đầu tiên của usr là gần như chắc chắn là trường hợp. Bất kể bạn quản lý các chủ đề của mình như thế nào, bạn sẽ phải chú ý đến DefaultConnectionLimit. – MNGwinn

1

Có thể bạn đang nhấn giới hạn kết nối TCP hoặc không xử lý kết nối đúng cách, trong mọi trường hợp, hãy thử sử dụng một cái gì đó như JMeter để xem thông lượng HTTP đồng thời tối đa mà bạn có thể nhận được.

1

Mã thực sự rất đơn giản. Tôi sử dụng Parallel.ForEach để lặp qua một tập hợp các URL (chuỗi). Hành động tạo ra một HttpWebRequest và sau đó kết xuất các kết quả vào một ConcurrentBag. BTW, NCrawler có vẻ là thú vị; Tôi sẽ kiểm tra. Cảm ơn vì tiền hỗ trợ.

Bởi vì với Parallel.ForEach không thể kiểm soát số lượng chủ đề, sau đó tôi đề nghị ít nhất chuyển sang số ThreadPool.

Bạn có thể sử dụng QueueUserWorkItem để phân bổ công việc cho đến khi bộ sưu tập tác vụ của bạn được đẩy hoàn toàn vào chuỗi công việc hoặc cho đến khi phương thức trả về false (không còn chủ đề nào trong nhóm).

Với ThreadPool bạn có thể kiểm soát số lượng chủ đề tối đa được phân bổ với SetMaxThreads.

+1

Tại sao bạn đề xuất sử dụng 'ThreadPool' trực tiếp nếu bạn có thể sử dụng' Task's? Họ thuận tiện hơn nhiều. Và tôi không nghĩ rằng số lượng tối đa của các chủ đề trong hồ bơi thread là một vấn đề ở đây, nó thường đủ lớn. – svick

+0

Tôi không biết. Tôi đoán tôi đang sử dụng để sử dụng ThreadPool. –

Các vấn đề liên quan