誤爆日記

quick and dirty prototype

クローラが重くなったときの原因特定・対処について

クローラが重いときに、何が原因か特定して対処する手順です。(クロールするサイトに迷惑をかけないように注意です)

curlボトルネックを調査する

http://akuwano.hatenablog.jp/entry/20120503/1335994486

問題の切り分けに利用します。

# cat <<'EOF' >/tmp/curl_env.txt
url_effective\t\t: %{url_effective}\n
http_code\t\t: %{http_code}\n
http_connect\t\t: %{http_connect}\n
time_total\t\t: %{time_total}\n
time_namelookup\t\t: %{time_namelookup}\n
time_connect\t\t: %{time_connect}\n
time_appconnect\t\t: %{time_appconnect}\n
time_pretransfer\t\t: %{time_pretransfer}\n
time_redirect\t\t: %{time_redirect}\n
time_starttransfer\t\t: %{time_starttransfer}\n
size_download\t\t: %{size_download}\n
size_upload\t\t: %{size_upload}\n
size_header\t\t: %{size_header}\n
size_request\t\t: %{size_request}\n
speed_download\t\t: %{speed_download}\n
speed_upload\t\t: %{speed_upload}
EOF
 # curl -o /dev/null https://xxxxxx -w @/tmp/curl_env.txt -s
 url_effective           : https://xxxxxx
 http_code               : 200
 http_connect            : 000
 time_total              : 10.599
 time_namelookup         : 0.002
 time_connect            : 0.003
 time_appconnect         : 0.102
 time_pretransfer                : 0.102
 time_redirect           : 0.000
 time_starttransfer              : 10.497
 size_download           : 171989
 size_upload             : 0
 size_header             : 513
 size_request            : 191
 speed_download          : 16227.000
 speed_upload            : 0.000

time_namelookup(名前解決の問題)

開始から名前解決が完了したときまでの時間(秒)。
ここが重い場合、名前解決に問題がありそうです。

time_connect・time_appconnect(curlの問題)

開始からリモートホストへの SSL/SSH/etc 接続/ハンドシェイク完了までの時間です(秒)(7.19.0 以降)
ここが重い場合、curlバージョンが低いのが問題になっているかもしれません。

time_starttransfer(対象サイトのクローラ対策)

開始から最初のバイトが転送されるまでの時間(秒)です。
time_pretransfer に加えてサーバが結果を算出するのに要した時間も含まれます。

この場合、クロールしたいサイトがクローラ対策をしている可能性が高いです。
(サイトがブラウザで表示するときも重い場合は、単にそのサイトが重いだけで対処しようがないので、ご注意下さい)

対処

名前解決が重い

/etc/resolv.confの設定変更

・/etc/resolv.confに「options single-request-reopen」を追加する(CentOS6)
CentOS6 (RedHat6) 名前解決に時間がかかる。 - medamaの日記
CentOS6で名前解決に時間がかかるとき at softelメモ

curlの問題

curlバージョンアップ

curlで150ms損していた話

バージョンによってlibcurlのバグで重くなることがあるようなので、バージョンアップさせます。
Bug 1130239 - Difference in curl performance between RHEL6 and RHEL7
https://bugzilla.redhat.com/show_bug.cgi?id=1130239

クローラ対策への対処

リクエストヘッダを見直す

ブラウザでクロールしたいサイトにアクセスしたときのリクエストヘッダに合わせてみます。
下記使うとテストがしやすいです。
chrome.google.com

リクエストヘッダの確認は、chromeデベロッパーツール等を利用します。
Chromeデベロッパー・ツールを使ってヘッダー情報を確認する | FAIRWAY Engineer {Blog}

早くなったリクエストヘッダを使い、クロールを行うようにします。

リダイレクトされてないか

また、リダイレクトされていないかもチェックして下さい。
リダイレクトされているようであれば、リダイレクトされないURLを探してみて下さい。(http→httpsにリダイレクトされている・存在しないURLのためリダイレクトされる等)

サーバを変えてためす

アクセスが多い場合、アクセスしてきたIPやドメイン単位にレスポンスを重くしている場合があります。
その場合、プロキシサーバなどを介してアクセスする等の対処を行います。

ちょっとクロールする程度であれば、下記サイトの無料プロキシを使うのもいいかもです。(コロコロ変わるので、定期的に取得するには難しいかもです)
無料プロキシリスト

定期的にまとまったアクセスを行うのであれば、下記対策が必要だと思われます。

・複数台のプロキシサーバを契約して対象サイトに分散してアクセスする
 5分で作るPROXYサーバー

・アクセス数が多くプロキシが台数固定だとすぐ重くなってしまう場合、AWSなどでipを自動切換えしてクロールする
 Amazon EC2 を使った無限IPアドレスの作り方 - ぼくはまちちゃん!(Hatena)
 リクエスト時に複数IP分散や自動IP変更をする方法