URLを取得し、そこからリンクを抽出し、それぞれを特定の深度まで訪問するクローラを構築しています。特定のサイトにパスのツリーを作成します。"オープンファイルが多すぎます"を処理する最善の方法は何ですか?
私は、このクローラのための並列処理を実装方法は、それが次のように見つかったとして、私は、すぐにそれぞれの新しい見つけられたURLにアクセスしてくださいということです。
func main() {
link := "https://example.com"
wg := new(sync.WaitGroup)
wg.Add(1)
q := make(chan string)
go deduplicate(q, wg)
q <- link
wg.Wait()
}
func deduplicate(ch chan string, wg *sync.WaitGroup) {
for link := range ch {
// seen is a global variable that holds all seen URLs
if seen[link] {
wg.Done()
continue
}
seen[link] = true
go crawl(link, ch, wg)
}
}
func crawl(link string, q chan string, wg *sync.WaitGroup) {
// handle the link and create a variable "links" containing the links found inside the page
wg.Add(len(links))
for _, l := range links {
q <- l}
}
}
私は上でそれを実行したときにこれが比較的小さなサイトのために正常に動作しますが、どこにでもたくさんのリンクがある大規模なものですが、私はいくつかのリクエストでこれら2つのエラーの1つ、すなわちsocket: too many open files
とno such host
(ホストは確かにそこにあります)を取得し始めます。
これを処理する最善の方法は何ですか?これらのエラーをチェックして、他のリクエストが完了するまでしばらくの間、実行を一時停止する必要がありますか?または、特定の時間に可能な最大リクエスト数を指定しますか? (正確にコード化する方法がわかりません)
オペレーティングシステムによって制御されるユーザーあたりの開かれたファイルの制限に関連する問題に直面しています。 Linux/Unixを使用している場合は、おそらくulimit -n 4096コマンドを使用して制限を増やすことができます。このコマンドにはしきい値があり、開いているファイルの数を設定することはできません。 ですから、さらにそれを押したい場合は、/ etc/security/limits.confファイルを修正し、ハードとソフトの制限を設定する必要があります。 –
また、enconuterのリンクごとにゴルーチンを開始していますが、それらの多くが特定の時点でゴルーチンの目的を破り、実際にはその処理に時間がかかります。処理を行い、各リンクのために新しいものを開始するのではなく、チャンネルから読み込むために一定数のゴルーチンを試してください。 https://blog.golang.org/pipelines – Topo
か、https://gobyexample.com/worker-poolsのようなパターンをご覧ください。 (あなたの 'WaitGroup'の使用法は非常に奇妙です。各ゴルーチンに1を加えて、各ゴルーチン内から' Done'を延期します)他のものはバグを要求しています) – JimB