3

プロキシ経由で多くのページをダウンロードする必要があります。マルチスレッド Web クローラーを構築するためのベスト プラクティスは何ですか?

Parallel.For\Foreach で十分ですか、それとも負荷の高い CPU タスクに適していますか?

次のコードについてどう思いますか?

var multyProxy = new MultyProxy();

   multyProxy.LoadProxyList();


   Task[] taskArray = new Task[1000];

        for(int i = 0; i < taskArray.Length; i++)
        {
            taskArray[i] = new Task( (obj) =>
                {                                                             
                       multyProxy.GetPage((string)obj);
                },

            (object)"http://google.com"
            );
            taskArray[i].Start();
        }


   Task.WaitAll(taskArray);

それは恐ろしく働いています。それは非常に遅く、その理由はわかりません。

このコードもうまく機能していません。

 System.Threading.Tasks.Parallel.For(0,1000, new System.Threading.Tasks.ParallelOptions(){MaxDegreeOfParallelism=30},loop =>
            {
                 multyProxy.GetPage("http://google.com");
            }
            );

まあ、私は何か間違ったことをしていると思います。

スクリプトを開始すると、ネットワークは 2% ~ 4% しか使用されません。

4

3 に答える 3

8

基本的に、IO バウンド タスクのために CPU バウンド スレッドを使い果たしています。操作を並列化していても、主に CPU バウンド操作を目的とした ThreadPool スレッドを本質的に使い果たしています。

基本的に、データをダウンロードして IO 完了ポートを使用するように変更するには、非同期パターンを使用する必要があります。WebRequest を使用している場合は、BeginGetResponse() および EndGetResponse() メソッドを使用します。

これを行うには、Reactive Extensions を参照することをお勧めします。

IEnumerable<string> urls = ... get your urls here...;
var results = from url in urls.ToObservable()
             let req = WebRequest.Create(url)
             from rsp in Observable.FromAsyncPattern<WebResponse>(
                  req.BeginGetResponse, req.EndGetResponse)()
             select ExtractResponse(rsp);

ExtractResponse は、おそらく StreamReader.ReadToEnd を使用して文字列の結果を取得するだけです。

.Retry 演算子を使用することもできます。これにより、接続の問題などが発生した場合に簡単に数回再試行できます...

于 2012-05-21T15:56:57.143 に答える
1

これをメイン メソッドの先頭に追加します。

System.Net.ServicePointManager.DefaultConnectionLimit = 100;

したがって、少量の同時接続に制限されることはありません。

于 2012-05-21T15:51:30.763 に答える
0

これは、多くの接続を使用する場合に役立ちます (app.config または web.config に追加します)。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.net>
    <connectionManagement>
      <add address="*" maxconnection="50"/>
    </connectionManagement>
  </system.net>
</configuration>

50 ではなく同時接続数を設定する

詳細については、http://msdn.microsoft.com/en-us/library/fb6y0fyc.aspxを参照してください。

于 2012-05-21T15:50:06.400 に答える