2010-12-07 7 views
9

C#을 사용하여 웹 페이지를 다운로드 할 수있는 속도를 측정하는 응용 프로그램을 작성하고 있습니다. 고유 한 도메인 이름 목록을 제공 한 다음 X 개의 스레드를 생성하고 도메인 목록이 소비 될 때까지 HTTPWebRequests를 수행합니다. 문제는 얼마나 많은 스레드를 사용하든, 초당 약 3 페이지 만 얻는다는 것입니다.HttpWebRequest의 동시 처리 제한

System.Net.ServicePointManager.DefaultConnectionLimit는 2이지만 도메인 당 연결 수와 관련이 있다는 인상을 받았습니다. 목록의 각 도메인은 고유하므로 문제가되지 않아야합니다.

그런 다음 WebResponse가 닫힐 때까지 GetResponse() 메서드가 다른 모든 프로세스의 액세스를 차단한다는 것을 알았습니다. http://www.codeproject.com/KB/IP/Crawler.aspx#WebRequest 웹을 통해이 클레임을 뒷받침하는 다른 정보를 찾지 못했습니다. 그러나 HTTP 요청을 구현했습니다. 소켓, 그리고 상당한 속도 (4 배에서 6 배)를 느꼈습니다.

내 질문 : HttpWebRequest 객체의 작동 방식을 정확히 아는 사람이 있습니까? 위에 언급 한 것 외에 다른 해결 방법이 있습니까? 아니면 C#으로 작성된 고속 웹 크롤러의 예가 있습니까?

+0

도메인 당 연결 제한을 구성 할 수 있지만 기본적으로 연결 제한은 전역입니다. https://msdn.microsoft.com/en-us/library/fb6y0fyc.aspx – Todd

답변

8

BeginGetResponse()와 같은 비동기 메서드를 사용해 보셨나요?

.net 4.0을 사용하는 경우이 코드를 사용해보십시오. 기본적으로 나는 특정 사이트에 1,000 요청하기 위해 작업을 사용하여 (나는 내 ​​dev에 컴퓨터에 응용 프로그램의 부하 테스트를 수행하려면이 옵션을 사용하고 내 애플을 연속으로 빠르게 이러한 요청보고 있기 때문에 나는 다음과 같은 한계를 참조)

public partial class Form1 : Form 
    { 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     for (int i = 0; i < 1000; i++) 
     { 
     var webRequest = WebRequest.Create(textBox1.Text); 
     webRequest.GetReponseAsync().ContinueWith(t => 
     { 
      if (t.Exception == null) 
      { 
      using (var sr = new StreamReader(t.Result.GetResponseStream())) 
      { 
       string str = sr.ReadToEnd(); 
      } 
      } 
      else 
      System.Diagnostics.Debug.WriteLine(t.Exception.InnerException.Message); 
     }); 
     } 
    } 
    } 

    public static class WebRequestExtensions 
    { 
    public static Task<WebResponse> GetReponseAsync(this WebRequest request) 
    { 
     return Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null); 
    } 
    } 

여기 작업 부하가 I/O 경계이므로 작업을 완료하기위한 스레드를 생성 할 필요가 없으며 실제로 성능이 저하 될 수 있습니다. WebClient 클래스에서 Async 메서드를 사용하면 I/O 완료 포트를 사용하므로 성능이 향상되고 리소스가 부족해집니다.

3

차단하지 않고 비동기 인 BeginGetResponse 방법을 사용해야합니다.

I/O 바인딩 비동기를 처리 할 때 I/O 작업을 수행하기 위해 스레드를 생성하기 때문에 하드웨어 (이 경우 네트워크 카드)가 응답하기를 기다리지 만 해당 스레드는 여전히 차단됩니다. 기본 BeginGetResponse를 사용하면 해당 스레드가 네트워크 카드에 대기열을 올려 놓고 더 많은 작업을 수행 할 수있게됩니다. 하드웨어가 완료되면 사용자에게 알려주고 콜백이 호출됩니다.

1

내가 BeginGetResponse 방법은 완전히 비동기가 아닙니다 싶습니다 : (MSDN에서)

BeginGetResponse 방법

를 완료하는 데 몇 가지 동기 설치 작업이 필요합니다 (DNS 확인, 프록시 탐지 및 TCP 소켓 연결).이 메서드가 비동기가되기 전에. 결과적으로 사용자 인터페이스 (UI) 스레드에서이 메서드를 호출하면 안됩니다. 일반적으로 몇 초가 걸릴 수 있기 때문입니다.