誤爆日記

quick and dirty prototype

複数のCSVをDB登録するライブラリを作っている

複数のCSV/TSVファイルをテーブルに登録(Insert)するライブラリを作っています。
ありがちなテーブル登録の前処理と後処理も入れてます。(ごった煮ライブラリになってきている...)

仕事でこういうことする機会多く、いちいち作るのもめんどくさいのでライブラリにしてみようと思って作っています。

github.com

作業ログ

  • 2018/09/16:だいたい動くようになる
  • 2018/09/17:

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

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

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変更をする方法

GoFパターン写経

個人開発の作業開始時にエンジンかけるため・毎日コード書く習慣を促進させるためにGoFパターンの写経しています。
こういうやり方もあるのね、と自分の引き出しを増やす意味でやっています。

量があって、まだ全部やれてないので順次追加していきます。


GoF Builderパターンのサンプル

GoF Commandパターン

GoF Bridgeパターン

GoF Compositeパターン

GoF Decoratorパターン

GoF Flyweightパターン

GoF Interpreterパターン

GoF Mediatorパターン

GoF Stateパターン

GoF Strategyパターン

GoF Facadeパターン

GoF Proxyパターン

GoF ChainOfReposibillityパターン

curl_multiを使った並列リクエストライブラリを作った

参考

下記記事を参考につくりました。
curl_multiでHTTP並行リクエストを行うサンプル - Qiita

ライブラリを使うメリット

下記2点です。

■コードすっきり
・libcurl7.20以上での実行が前提(curl_multi_execを実行するときにdo-whileを除外)
・クラス化してメソッドを処理ごとに区分け

■実行しやすい
・簡易的に使う場合は、リクエストしたいURLをライブラリに渡すだけ
・リクエストごとにcurlのオプションを指定可能です

ライブラリ

github.com
libディレクトリ内のrapidFire.phpを読み込んで利用して下さい。

2018年1月の振り返り

2018年1月にやったこと

リポジトリ3つ作った。
ほぼVueとTypescriptの扱いに慣れようと四苦八苦してた感じです。

typescriptで作った入力バリデーション

observerモデルを使って作ったので、observerモデルの理解も深まった。(と思う)
github.com

vue+typescriptで作ったはてなホッテントリクローン

vueとtypescriptで何か作ろうと思ってやったやつ。動かすだけで精一杯だった。
github.com

vue+Firevaseで作った食費管理ログ

firebaseを使ってみたくて作ったやつ。認証もDBもfirebaseに任せられるので、クライアントの実装だけでアプリを作れる。
でもリアルタイムデータベースの扱いは、実際運用まで持っていこうと思うとまだまだよくわかってない事が多いと思う。。。
github.com

Gist

自分の開発スタイルとして、gistで簡単に実装して形になってきたらリポジトリで開発していくようにしてます。
その方が全体を見渡しながら開発を進めやすい / アウトプットを短期間で出しやすくなるので、頓挫せず続きやすいからです。

作ってたコード片としては、下記です。

2018年2月にやること

PHPフレームワークを自作するのがひとつと、chrome拡張を1つリリースしたいと思ってます。
あとは引き続きVue+Typescriptでクライアントアプリを作るのは続けていきます。

  • phpフレームワークを作る
    • ルータ
    • ORM
    • テンプレートエンジン
  • chrome拡張を作る
    • twitterいいねシークレットツールを作る
  • Vue+Typescriptでクライアントアプリ作る