senna-feed01=# explain analyze select * from fetchdata_tmp where crawl_ready = 't';
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
Seq Scan on fetchdata_tmp (cost=0.00..2028.91 rows=24450 width=176) (actual time=0.015..117.897 rows=24450 loops=1)
Filter: (crawl_ready = true)
Total runtime: 131.433 ms
(3 rows)
senna-feed01=# explain analyze select * from fetchdata_tmp where crawl_ready2 = 1;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using fetchdata_tmp_crawl_ready2_idx on fetchdata_tmp (cost=0.00..1043.72 rows=288 width=176) (actual time=0.134..0.134 rows=0 loops=1)
Index Cond: (crawl_ready2 = 1)
Total runtime: 0.222 ms
(3 rows)
コメント
ただいまの実装されている仕様としては
- イベント型
- クローラー1プロセスで約6000~12000 urls/hを取得。
- フーレムワークとしてはどんなタイプのクローラーでも実装できる感じ。
xango-blog (ブログ検索用データ収集)
- RSS/Atomフィードを定期的にチェック+インデックス
- Postgresバックエンド
- robots.txt 対応
- RSS/Atom自動発見
問題点
- 数時間おきに何故か落ちる。静かに。エラー無しで。なんでじゃあ
- sf.livedoor.comと同じように、フィードを取りに行く前にユーザーがフィードの長さより多い数の記事を書くとインデックス漏れが起きる
- 関係ないコンテンツをいっぱい取ってきてる。
今まず何故落ちるのかを考察中・・・
今さっきようやくポェに頼らない、HTTP Fetcherフレームワーク書きました。あんまりevent drivenではないけれども、非同期でソケットに読み書きできる感じで、DNSをローカルにキャッシュしたり。
こちらの課題としては
- 30X のリダイレクトに対応してない
- DNS応答が非同期ではない
- 現存のxango-blogとの結合部分が全然違う。
・・・という感じです。
現在xango.razil.jpのDBを使いつつ、おいらのマシンからガンガンアクセスしてます。これで落ちなければDebianが悪い、ということで・・・
なんでポェが落ちるのか詳細を追って行ったところ、どうもPerl内部のバグっぽい感じが・・・。一応わけわかめなのでMLに投稿してみたりしました。
誰も返信してくれなさそうな予感のMLスレはここ
http://aspn
メソッドコールがうまく行ってないのですよねぇ。これでコアファイルでも落としてくれればなんとかデバッグのしようもあるんですが、残念ながらコアファイルはナシです。
ホップ数はエントリ毎のプライオリティで決定されていて、プライオリティはリンクもとのプライオリティx係数で決めてます。これでプライオリティが0だったら取得そのものを行いません
で、今この係数が0.1。つまり100 - 10 - 1 - 0と4ホップくらいは可能なわけなんですが・・・
3ホップくらいは妥当なんじゃないかなぁ、とは思うんですよ。
あとはなんかHTMLをパースしてから追加するリンクをもっとスマートにコントロールするとかかなぁ。今は結構とりあえず足してる、って感じもあるので。
極端な話、当初は大手有名blogサイトを網羅できればかなりサービスとしてイケてる感が見えて来ると思うのです。
ですから、ホスト間リンクは係数を小さく、ホスト内リンクは係数を大きくするのが良いと思います。
つまりそれってサーバー側でソケットを切っちゃったとかかなぁ・・・
正直ポェのほうが後々楽だからポェにしたほうがいいと思うんだけどなぁ・・・
まぁともかく。そのカラムを見て、どっちを優先するか見るべし。もしAtomとRSSと両方ある場合はRSSのほうはクロールしないようにしちゃったほうがよろし。
http://blog
のソースを見てみると、上のほうに<link>タグが4つくらいあるでしょ?そこのapplication/rdf+xmlとかatom+xmlみたいなヤツがRSS/Atomですよね。
で、これで過去記事に行くと
http://blog
とかいうURIになるんだけれども、同じAtom+RSSにリンクするんですなぁ。
まぁ、一般的にはブログ(N):RSS(1)+Atom(1)になるんですが。
この先どんなフィード方式が出てくるかわからないし、一応一般化しておかないといけないなぁ、と。
普通にクロールしてる分にはたいした問題ではないのだけど、メンテする時に激しく遅いです。vacuumしても、vacuumしても、遅い。ぐほ。
やっぱり分散化するのがスジだぽ
ちょっとどう使うかまだよく考えてないんですが、あったら便利なような気が。
atomやrssからデータを拾ってくるのはあくまでblog_baseが入ってるものだけにして(=信用できるデータ)、残りのis_blog = trueだけどblog_base = NULLのヤツは後でそれを抽出できるようにheuristicsを変更するって感じでいいかな・・・
あと、ふと思ったんだけどxango-blogのほう、dev.razil.jpからソース降ろしときます。
xango-blogのソースは非公開が良いですね。
http://dev
トップは直したー
というわけでis_seedカラムを足して、重要なシードと認識したURIはどんな状況でもクロールするようにしてみた。
あと、どこかに「プロセス終了しますた」フラグをセットしてないところがあるんだけど、それでフラグがクリアされない少量のURIを定期的に拾ってクロール可能に戻すコードも入れたです。
・・・どうりで全然こねぇなぁ、と思ってたのですよ・・・
対応するコード作成中・・・
ちなみに現在シードは他のURIに飲み込まれてしまって1時間に一回取得にいけるかどうか。(これでもその他フィードから一日10万件くらいは拾ってこれそう・・・)
ついでにxango-blogのほうでメモリを使いすぎるので(HTTPレスポンスが丸ごとメモリ内にあるので、changes.xmlとかでかいファイルだとやたらとスペースを食う)そこらへんを柔軟にカスタマイズできるように設定項目とかも増やします。
あとメモリの問題だが、こっちはどうもHTTP fetch能力が、それ以降の処理能力を上まると起こるっぽいこと発見。ということは現在「稼働中」のジョブ数を常に把握してるのがグッドっぽい。
これからXML::LibXMLで自分で書き直します・・・しくしく。
あとRSSとかはcreatorフィールドがない事が多いのを忘れてた。not null設定を取り払ったら結構また取り込める件数がのびましたよ。
ちきしょー
え〜ん・・・
今ってdescriptionの内容しか入ってないんじゃなかったっけ?
http://xango
マイナスポイントは、若干プライオリティによるページ取得の順番が乱れるのと、バッファする分メモリを食うって事かな。
ところでxangoフレームワークのほうはそろそろCPANにあげちゃってもいいかな・・・?
どうも一個遅いプロセスがあるとそれにひっぱられてるような気がする・・・なんでだろう。皆独立したプロセスなんだけどなぁ。
とりあえず結合試験はまだ。
暇があれば今夜中に全部結合してやってみますよ。
アイデア:キャッシュを使う。先にcanonicalizeして、配列ではなくハッシュで保存等。
crawl_ready というboolean型のカラムにどうやってもインデックスが使われないのでなんでだろう、なんでだろうと試行錯誤していたところ、じゃあこれがbooleanじゃなくてintegerだったらどうなるんだろう?と思ってやったみた:
senna-feed01=# explain analyze select * from fetchdata_tmp where crawl_ready = 't';
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
Seq Scan on fetchdata_tmp (cost=0.00..2028.91 rows=24450 width=176) (actual time=0.015..117.897 rows=24450 loops=1)
Filter: (crawl_ready = true)
Total runtime: 131.433 ms
(3 rows)
senna-feed01=# explain analyze select * from fetchdata_tmp where crawl_ready2 = 1;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using fetchdata_tmp_crawl_ready2_idx on fetchdata_tmp (cost=0.00..1043.72 rows=288 width=176) (actual time=0.134..0.134 rows=0 loops=1)
Index Cond: (crawl_ready2 = 1)
Total runtime: 0.222 ms
(3 rows)
senna-feed01=#
なんじゃこりゃああああ!!!!!
これを非同期でやるべきなのか・・・?
軽くログを取ってみると44個のURIを登録するのに14秒かかってる。これってもっと秒殺できるべきなんじゃないのかなぁ。
これがある程度の大きいリストならいいけれども、処理するURIのリストが短く、かつ処理がqueue_aheadが始まる前に終わらない場合は同じURIを延々と処理し続けるハメになる事が有る。
一番簡単な回避方法は「ただいま処理中です」フラグを付ける事なのだけれども、これがまた小さいwriteが多発するので格段に効率が落ちる。
現在まだ処理中のURIがある間にqueue_aheadをする場合はLIMIT %d OFFSET %dを使うかなぁ。これももちろん完璧ではないけど、歩い程度は防げるのではないかと。
RSSのDateフィールドってなんであんなヘンチクリンなんだろう?といつも思います。だから、偽モノDateを作る気持がなんとなく分かる。
7.2あたりのときに経験したビックリパターンはintegerで"where hoge = 1"が何かの理由でseq scanだったのに、"where hoge between 1 and 1"にするとindex scanになったやつです。GAさん本当にお願いしますよ。
8でもSELECTで/* HINT */こういうヒントが使えるんだったら使うといいかもよ。
between 1 and 1ってすげーですな!それは思いつかないよ・・・
とりあえず、explainで正しいmultiple index作って、SET LOCAL seq_scan = 'off'するとある程度期待通りの動きしてくれてるっぽいっすわ
/* HINT */ってポスグレでも使えるのか・・・
なんでわからないかというと、MySQLにINSERTできない。とりあえずINSERT処理を待っているコンテンツが・・・20万件あるので、結構多いんじゃなかろうかと。
あと何故かdoblogを取ってなかった事に気づく。おかしいなぁ。
06/13 23:49 - 821,684
06/14 00:01 - 828,619
00:09 - 832,900
00:20 - 837,407
00:35 - 842,381
01:02 - 850,065
01:30 - 859,168
02:00 - 866,967
02:33 - 876,782
08:18 - 974,290
09:19 - 989,152
09:31 - 992,234
10:00 - 997,824
10:30 - 1,005,309
11:49 - 1,017,144
12:10 - 1,022,670
12:31 - 1,026,352
キ(゚∀゚)ター
キ(゚Д゚)タ?
(゚Д゚)モヘー
>>102
なかなかデフォルト検索にしてもらえなくて悲しいですよ。とっくに実用段階に入ってるのに。
今日はちょっと軟調だった(゚Д゚)ディスカ?