0

私は C# で書かれた Webcrawles を持っており、マルチスレッドを使用しています。今のところ、1分あたり約1000リンクをダウンロードして解析できますが、ex. 3 つのインスタンスが同時に 1 つのインスタンスごとに 1000 リンク/分に到達できるため、3000 リンク/分になります。1 つのインスタンスは、最大 2% の CPU、100MB の RAM、および 1% のネットワーク速度を使用します。利用可能なリソース (CPU、RAM、ネットワーク) がある場合、1 つのインスタンスが 3000 リンク/分以上に達する可能性があるのでしょうか?

私のコードの構造:

ThreadSafeFileBuffer<string> successWriter = new ThreadSafeFileBuffer<string>("ok.txt");
IEnumerable<string> lines = File.ReadLines("urls.txt");
var options = new ParallelOptions
                                            {
                                                CancellationToken = _cts.Token,
                                                MaxDegreeOfParallelism = 500
                                            };

Parallel.ForEach(lines, options, (line, loopState, idx) =>
                                                {
var crawler = new Crawler(line);
var result = crawler.Go(); //download,parse
successWriter.AddResult(result);
}

私はWindows 7、CPU i7、16GB RAM、SSDディスクを持っています

4

6 に答える 6

3

URL のリストでを使用する際の問題Parallel.ForEachは、これらのリストに同じサイトからの多数の URL が含まれていることが多く、同じサイトへの複数の同時要求が発生することです。一部のサイトはそれに眉をひそめ、あなたをブロックしたり、人為的な遅延を挿入したりします.

1 分あたり 1,000 リクエストは、1 秒あたり 16 または 17 リクエストになります。問題の大部分は DNS 解決であり、驚くほど長い時間がかかることがあります。さらに、既定の .NET では、ServicePointManager特定のサイトでの同時要求は 2 つに制限されています。それ以上をサポートする場合は、ServicePointManager.DefaultConnectionLimitプロパティを変更する必要があります。

何百ものスレッドを追加したくないことは間違いありません。私は一度それをしました。痛いです。必要なのは、非同期リクエストを非常に迅速に作成できる少数のスレッドです。私のテストでは、 HttpRequest.BeginGetResponseが非同期になる前に多くの同期作業を行うため、1 つのスレッドが 1 秒あたり 15 を超えるリクエストを維持できないことが示されています。ドキュメントに記載されているように:

BeginGetResponse メソッドでは、このメソッドが非同期になる前に、いくつかの同期セットアップ タスク (DNS 解決、プロキシ検出、TCP ソケット接続など) を完了する必要があります。

DNS クライアント キャッシュのサイズを増やしたり、別のマシンにローカル DNS キャッシュを用意したりすることで、多少は高速化できますが、そこで達成できることには限界があります。

どれだけクロールしているかわかりません。多くのことをしている場合は、robots.txt ファイルを考慮し、特定のサイトにアクセスする頻度を制限し、ダウンロードする URL の種類を制限する丁寧さポリシーを実装する必要があります (MP3 や .クローラーがブロックされるのを防ぐために、クローラーはコアで、たまたまウェブページをダウンロードするポライトネスポリシーエンフォーサーになります。

しばらく前にこのことについて書き始めましたが、結局終わりませんでした (他のプロジェクトが優先されました)。最初の投稿とスレッド内の他の投稿へのリンクについては、http://blog.mischel.com/2011/12/13/writing-a-web-crawler-introduction/を参照してください。http://blog.mischel.com/2011/12/26/writing-a-web-crawler-queue-management-part-1/も参照してください。もう一度やり直したいと思っていたのですが、2 年近く経った今でもまだできていません。

また、プロキシの問題、URL フィルタリングの問題 (ここここ)、奇妙なリダイレクト完全に非同期ではない非同期呼び出しにも遭遇します。

于 2013-10-21T22:08:00.330 に答える
1

これらのスレッドはすべて待機に時間を費やすため、これ以上のスレッドは必要ありません。Web 応答を待っているスレッドをブロックしない非同期プログラムが必要です。

スレッドの問題は、スレッドのスタックに必要なメモリと、スレッドが OS スレッド スケジューラ用に作成する作業のために、かなり高価なリソースであることです。あなたのプログラムでは、このスケジューラはスレッドを切り替え続け、すべてのスレッドが順番に待機できるようにします。しかし、彼らは何の役にも立ちません。

于 2013-10-21T12:45:34.203 に答える
0

実際には、1 分あたりのリンク数は、同時に実行されるクローラー スレッドの数に正比例します。

あなたの最初のケースでは; あたり n スレッドの 3 つのプロセスがあります。(合計 3n スレッド)

1 つのプロセスで 3n スレッドを実行してみてください。

実際、これはオペレーティング システムと CPU にも依存します。古いバージョンの Windows (XP など) は、異なる CPU コアでの並列マルチスレッドをサポートしていないためです。

于 2013-10-21T12:39:26.457 に答える
0

はい、そうです。ボトルネックがどこにあるかを見つけて、パフォーマンスを改善します。

編集:

Parallel.ForEach を使用している場合は、ParallelOptionsパラメーターを使用してオーバーロードを試すことができます。MaxDegreeOfParallelism プロパティを設定すると役立つ場合があります。

于 2013-10-21T12:24:20.357 に答える
0

TPL との並列処理は、Web クローラーにとって不適切な設計です。Parallel.ForEach() ループは、時間のかかる計算を並行して実行し、ほとんど何もしない数千の要求を並行して実行しないように設計されているため、一連の要求 (5 ~ 50) のみを開始します。必要なデータを取得するには、非常に大量 (10000 以上) のリクエストを並行して実行できる必要があります。その鍵となるのは非同期操作です。

Crawler-Lib Framework の Crawler Engine を開発しました。これはワークフロー対応のクローラーであり、あらゆる種類の要求や必要な処理を実行するように簡単に拡張できます。すぐに高いスループットが得られるように設計されています。

エンジンは次のとおりです。 http://www.crawler-lib.net/crawler-lib-engine

Crawler-Lib エンジンがどのように機能するかを示すいくつかの Youtube ビデオを次に示します: http://www.youtube.com/user/CrawlerLib

このプロジェクトがオープンソースではないことは知っていますが、無料版があります。

于 2013-12-28T09:04:34.073 に答える
0

Web クローラーでは、ほとんどの時間を Web 要求の待機に費やします。したがって、I/O をブロックしている場合、プログラムは全速力で処理されません。プログラムがアイドル状態でコールバックを待機している場合も、非同期 IO は役に立ちません。メインアプリにスレッドを追加して並列処理するだけでよいようです。

ただし、コードを投稿していないため、わかりにくいです。

于 2013-10-21T12:35:22.573 に答える