tag:blogger.com,1999:blog-12100799824395100082024-10-05T06:16:02.670+09:00q-v-pAnonymoushttp://www.blogger.com/profile/14765828692647479269[email protected]Blogger10125tag:blogger.com,1999:blog-1210079982439510008.post-60847018763041552332014-10-05T18:10:00.002+09:002014-10-05T18:10:54.649+09:00vagrant packageのvmware_fusionプロバイダ対応はよ調査期間Gの啓示に従いこの辺の記事を読んでもよくわからなかった:<br /> <br /> <ul> <li><a href="http://momijiame.tumblr.com/post/65429388802/vagrant-box">Vagrantで作った仮想マシンからBoxファイルを作り直す</a></li> <li><a href="http://d.hatena.ne.jp/KoshianX/20131219/1387414427">Vagrant: Debian Wheezyのbase boxを作成する</a></li> </ul> <br /> のでおとなしく<a href="https://docs.vagrantup.com/v2/cli/package.html">本家サイトのドキュメントを見に行った</a>らそもそもpackageコマンドはVirtualBoxしかプロバイダとして想定してないとかふざけたことが書いてあった。VMware Fusionプロバイダのユーザはプラグインのライセンス料支払ってんのに無償プラグイン使ってるユーザより待遇が悪いってどういうことなのHashiCorp.<br /> <br /> 仕方がないのでこのページ <a href="http://blog.jameskyle.org/2013/05/zsh-script-to-create-vmware-fusion-5-vagrant-box/">Zsh Script to Create VMware Fusion 5 Vagrant Box</a>&nbsp;を眺めつつ早い話しが<br /> <br /> <ul> <li><span style="font-family: inherit;">.vmxf, .nvram, .vmsd, .vmx, .vmdk</span></li> <li><span style="font-family: inherit;">{"provider":"vmware_fusion"} と記述された metadata.json</span></li> </ul> <div> が .box っていう拡張子を持ったtar玉にまとめられてればいいということを知ったので手作業でさっさと片付けるなどした。Linuxで使っているときによくお世話になるVMware関連のコマンド群はMacOSXでは /Applications/VMWare Fusion.app/Contents/Library/ の下に転がっているので vmware-vdiskmanager を使ってデフラグ、シュリンクしてあげればOK. できたtar玉は普通に vagrant box add で登録できる。</div> Anonymoushttp://www.blogger.com/profile/14765828692647479269[email protected]0tag:blogger.com,1999:blog-1210079982439510008.post-32022891806788047952014-03-21T21:31:00.002+09:002014-03-21T21:31:09.315+09:00Clipper Cardの罠・終幕すっかり確認するのを忘れてましたが10ドル払い戻しされてました。払い戻しされる1週間くらい前にそれまでやり取りしてたところとは違う部署の担当者から「お前のカードに1ドルキャッシュバックすっから後で確認しろや」的なメールが来てて何で10分の1になってんねん!って突っ込みのメールを送るとかしてたんですが、先方の単純なミスだったようで最終的にはちゃんと戻ってまいりました。<br /> <br /> 今度は西海岸に行く2週間前くらいにValue Addするようにしよう。これと比べると日本のSuicaとかは遥か先を行ってるよね。Anonymoushttp://www.blogger.com/profile/14765828692647479269[email protected]0tag:blogger.com,1999:blog-1210079982439510008.post-28780481127979738762014-03-21T21:18:00.000+09:002014-03-21T21:44:54.990+09:00Cloudera Manager 5でNFSを有効にしてみる<div style="clear: both; text-align: left;"> 分散ファイルシステムにアクセスする口としてのNFSはクライアントが分散環境の恩恵を受けることができない(NFSクライアントからのサーバコールが1箇所に集約されるので簡単にボトルネックになる)のでそんなにメリットはないんだけど、HDFSの中身を適当にのぞいて回るくらいの用途ならそれなりに便利ではあるので動作確認がてらCloudera Manager 5でHDFS NFS Gatewayを有効にする手順を確認してみます。</div> <div style="clear: both; text-align: left;"> <br /></div> <div style="clear: both; text-align: left;"> まずサービスの一覧からHDFSを選択します:</div> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQnSX4z9-KT-IUdyEOyVA8-mAgfk-d8Fq0rTDDAAzHmFFWKC-caUeJDoSRf6ErEaSpcf77m3Ft703Xdu8d4r-CpTBw2kCgGB6QBtlo-LN9PV6ifChu-J6RImyJoAGXpFSG0CqTyEdM3lw/s3200/cloudera-quickstart-vm-5_0_0b2-vmware-00.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQnSX4z9-KT-IUdyEOyVA8-mAgfk-d8Fq0rTDDAAzHmFFWKC-caUeJDoSRf6ErEaSpcf77m3Ft703Xdu8d4r-CpTBw2kCgGB6QBtlo-LN9PV6ifChu-J6RImyJoAGXpFSG0CqTyEdM3lw/s3200/cloudera-quickstart-vm-5_0_0b2-vmware-00.png" height="344" width="640" /></a></div> <br /> <div class="separator" style="clear: both; text-align: left;"> HDFSサービス画面からインスタンスのタブを選択します:</div> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9f554wT44j2TUXNkK4kkASjtV1ejpPbLnyFWOtI0soLCSsWz4_YHpwSKgwFdaM-d7yCqdLCrmMZ3HqVIFDDANp_kmUrIC7Vv6h4-ssWEHlM8UMf_AK8h53Yhlh3MSpFpsHoHWbUYsgjs/s3200/cloudera-quickstart-vm-5_0_0b2-vmware-01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9f554wT44j2TUXNkK4kkASjtV1ejpPbLnyFWOtI0soLCSsWz4_YHpwSKgwFdaM-d7yCqdLCrmMZ3HqVIFDDANp_kmUrIC7Vv6h4-ssWEHlM8UMf_AK8h53Yhlh3MSpFpsHoHWbUYsgjs/s3200/cloudera-quickstart-vm-5_0_0b2-vmware-01.png" height="346" width="640" /></a></div> <br /> <div class="separator" style="clear: both; text-align: left;"> ここで "Add" ボタンをクリックしてロールの追加を行ないます:</div> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzBb6UbCvxiPCyWhqUKJohGdW4ToYbNWogei_b-Y0BSfoxPSWtsqHG2uyqPxSWgy9R-ZwoQ6vyn69nyabBpfd08k0SHWMCdCijcN9kOCEKXtR59KqVhy_YUs2ChL-UCgA39lYzPpo88A4/s3200/cloudera-quickstart-vm-5_0_0b2-vmware-02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzBb6UbCvxiPCyWhqUKJohGdW4ToYbNWogei_b-Y0BSfoxPSWtsqHG2uyqPxSWgy9R-ZwoQ6vyn69nyabBpfd08k0SHWMCdCijcN9kOCEKXtR59KqVhy_YUs2ChL-UCgA39lYzPpo88A4/s3200/cloudera-quickstart-vm-5_0_0b2-vmware-02.png" height="340" width="640" /></a></div> <br /> NFS Gatewayを選択します:<br /> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOjsJCP7uJgo0Hdk09W0GAdQKcdBWi3s_uUxoRoRR2k5NAxNNjyPlTaqH4t7FaKP3IZ2IDs1oMzKkIKdUgmKdThi9exW-meGjC7EoZPUwkqvh5cFytvfl-6qGD9G3SXotOzs5KvhoMTpA/s3200/cloudera-quickstart-vm-5_0_0b2-vmware-03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOjsJCP7uJgo0Hdk09W0GAdQKcdBWi3s_uUxoRoRR2k5NAxNNjyPlTaqH4t7FaKP3IZ2IDs1oMzKkIKdUgmKdThi9exW-meGjC7EoZPUwkqvh5cFytvfl-6qGD9G3SXotOzs5KvhoMTpA/s3200/cloudera-quickstart-vm-5_0_0b2-vmware-03.png" height="326" width="640" /></a></div> <br /> Quickstart VMなのでロールを配置するホストに選択肢はありません:<br /> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkycWfIlZpavPOJmouobe-mGcNXoY7c-MoFzQ_Wj1DUcgzDFslsNmSjpBjk2zALwVaxTgC7YNdq76cRUPhQZPm78NlCOU0xrshdCMxukcynTT2zJhl_NndoTfcVWLDxgnpehyzh9R_upc/s3200/cloudera-quickstart-vm-5_0_0b2-vmware-04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkycWfIlZpavPOJmouobe-mGcNXoY7c-MoFzQ_Wj1DUcgzDFslsNmSjpBjk2zALwVaxTgC7YNdq76cRUPhQZPm78NlCOU0xrshdCMxukcynTT2zJhl_NndoTfcVWLDxgnpehyzh9R_upc/s3200/cloudera-quickstart-vm-5_0_0b2-vmware-04.png" height="338" width="640" /></a></div> <div class="separator" style="clear: both; text-align: left;"> <br /></div> <div class="separator" style="clear: both; text-align: left;"> NFS Gatewayが追加されました:</div> <br /> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjz1D1ZTDpHFKQ8pVB57aYJHTV9AJgmv7z6N7LHAC7gyCWrfa_FEYL3ouIRAT7XL4H95KRksiVafA8H7oBxTol5-ZakbhFPuBvZPsmpWutoXVGhKZnzEw5V4Oj-mnW6usqK4FFsZwd26VA/s3200/cloudera-quickstart-vm-5_0_0b2-vmware-05.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjz1D1ZTDpHFKQ8pVB57aYJHTV9AJgmv7z6N7LHAC7gyCWrfa_FEYL3ouIRAT7XL4H95KRksiVafA8H7oBxTol5-ZakbhFPuBvZPsmpWutoXVGhKZnzEw5V4Oj-mnW6usqK4FFsZwd26VA/s3200/cloudera-quickstart-vm-5_0_0b2-vmware-05.png" height="340" width="640" /></a></div> <div class="separator" style="clear: both; text-align: center;"> <br /></div> <div class="separator" style="clear: both; text-align: left;"> 状態が "Stopped" になっているので nfsgateway にチェックを入れて Actions for Selected から開始してやればOKです。これだけでHDFSの / がまるっとexportされます:</div> <br /> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLDz7FT7n4XIvkkpuyvZqYbuaC-R3YZR87jPM9avmFvi5JDgYfqAUK5wL0B6A44AYZjBxkH9kzBaowjUTbUiwXozbgFCL3KtMV2zrFlUv4CYfawktqvKVXzAAW-YFqSSQB9UxLrv9eGRY/s3200/cloudera-quickstart-vm-5_0_0b2-vmware-06.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLDz7FT7n4XIvkkpuyvZqYbuaC-R3YZR87jPM9avmFvi5JDgYfqAUK5wL0B6A44AYZjBxkH9kzBaowjUTbUiwXozbgFCL3KtMV2zrFlUv4CYfawktqvKVXzAAW-YFqSSQB9UxLrv9eGRY/s3200/cloudera-quickstart-vm-5_0_0b2-vmware-06.png" height="340" width="640" /></a></div> <div class="separator" style="clear: both; text-align: center;"> <br /></div> <div class="separator" style="clear: both; text-align: left;"> Hueで見えてるのとNFSマウントしてファインダから見てるのが同じだということが確認できますね:</div> <br /> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVafga1qxMREZ-KbJNEMLB9CtuhbClAN7h6F_cx5LQEq1Qnl16vaa_U2LD4lc7A8GEQqynIyHYTAStn4DNCtPWdfv_3_1njb2skeel6bHnlBu3MTWu_uoAwIRWZwW1V8eHITjr_TEkf-Y/s3200/cloudera-quickstart-vm-5_0_0b2-vmware-07.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVafga1qxMREZ-KbJNEMLB9CtuhbClAN7h6F_cx5LQEq1Qnl16vaa_U2LD4lc7A8GEQqynIyHYTAStn4DNCtPWdfv_3_1njb2skeel6bHnlBu3MTWu_uoAwIRWZwW1V8eHITjr_TEkf-Y/s3200/cloudera-quickstart-vm-5_0_0b2-vmware-07.png" height="404" width="640" /></a></div> <div class="separator" style="clear: both; text-align: center;"> <br /></div> <div class="separator" style="clear: both; text-align: left;"> ドラッグ&ドロップでHDFSにファイルを放り込んでみようと思ったんですがユーザIDの対応関係が適当だったんで書き込めませんでした。これはセキュリティ的に正しい姿ですね。</div> <br /> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPrhnst_te7rKyAHYKE9MBNXO3lgd878q_kDFAqkqUL4Z9ugtFu_jtUsumQbkIE6nwDvzFdbQmtIYtg5IKB3WA_kGZExuZVVyLK_ntJ4_etd1gXc6iO2WBL4k3Z2O9Lt2f3DY842iLOcc/s3200/cloudera-quickstart-vm-5_0_0b2-vmware-08.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPrhnst_te7rKyAHYKE9MBNXO3lgd878q_kDFAqkqUL4Z9ugtFu_jtUsumQbkIE6nwDvzFdbQmtIYtg5IKB3WA_kGZExuZVVyLK_ntJ4_etd1gXc6iO2WBL4k3Z2O9Lt2f3DY842iLOcc/s3200/cloudera-quickstart-vm-5_0_0b2-vmware-08.png" height="212" width="640" /></a></div> <div class="separator" style="clear: both; text-align: center;"> <br /></div> <div class="separator" style="clear: both; text-align: left;"> 別のLinuxホストにHDFSに書き込む権限を持つユーザと同じユーザID, グループIDを持つユーザを作成してNFS Gateway経由でアクセスしたら問題なく書き込むことができました。</div> <div class="separator" style="clear: both; text-align: left;"> <br /></div> <div class="separator" style="clear: both; text-align: left;"> 今回はCloudera Manager 5を利用して取り敢えず試してみただけのお知らせでした。@kernel023のブログ記事&nbsp;<a href="http://linux.wwing.net/WordPress/?p=603">CDH5ベータ1のNFSv3ゲートウェイを試してみました</a>&nbsp;と比較してみるとコマンドラインを一切書いてないのに気付くと思います。コマンドプロンプトとかシェルが嫌いな人には絶賛Cloudera Managerをお勧めします。そうでない人も使うべきというか、これなしで大規模クラスタの運用管理ってムリですよね実際...</div> <br /> <div> <br /></div> Anonymoushttp://www.blogger.com/profile/14765828692647479269[email protected]0tag:blogger.com,1999:blog-1210079982439510008.post-27229485695775768122014-02-16T05:07:00.001+09:002014-02-16T05:07:47.352+09:00続・Clipper Cardの罠続き。ここしばらく西海岸行く予定ないんだけど、って連絡したらサポートの中の人から2つのオプションが提示された:<br /> <br /> <br /> <ul> <li>次に西海岸に行く機会があったら1週間前くらいに連絡くれればカードに取り込めるようにしてあげる</li> </ul> <div> <ul> <li>いまアカウントに設定されているカード情報が支払いに使ったのと同じカードだったら払い戻ししてあげる</li> </ul> <div> <br /></div> </div> <div> ここは迷わず払い戻しを選択。ただし手続きして承認されて払い戻しされるまでに30日くらい掛かるよ、って念を押された。戻ってくるなら何でもいいので一月くらい待ちますわ。そっちこそリファンド、忘れんなよw</div> Anonymoushttp://www.blogger.com/profile/14765828692647479269[email protected]0tag:blogger.com,1999:blog-1210079982439510008.post-77226449310980279472014-02-13T00:31:00.000+09:002014-02-13T00:32:20.715+09:00Clipper Cardの罠一部ですこぶる便利だと評判のClipper Cardですが割としょーもない落とし穴があるので自分のために記録しておきます。<br /> <br /> <br /> <ul> <li>ウェブサイトでチャージしてもシステムに反映されるまでに3〜5日を要する</li> </ul> <div> <ul> <li>システムに反映された金額をカードに取り込むにはカードリーダにかざさなきゃダメ</li> </ul> </div> <div> <ul> <li>ウェブサイトでチャージしたおカネは半年以内にカードに取り込まないと失効する</li> </ul> <div> <br /></div> </div> <div> 去年 San Francisco 〜 Palo Alto 〜 San Jose 辺りをうろうろしていたときにすこぶる便利に使っていたんだけど、そろそろ残高心もとなくなってきたからチャージしとこうと思ってチャージしたのが帰国の2日くらい前。そのまま帰国して経費精算するのに乗車履歴見てたらチャージした筈の金額が取り込まれてなくて、システムに反映されるまでにタイムラグがあるのを知ってまぁいいかと思って放って置いて、先月 San Francisco 行ったときに使ったら(=カードリーダにかざしたら)チャージされると思っていたのに実は失効していたという罠。</div> <div> <br /></div> <div> 履歴調べて失効した分を再度カードに取り込めるようにしてくれる、ってサポートから連絡きたけどここ半年以内に西海岸行く予定ないんだよなぁ... どーすべw</div> Anonymoushttp://www.blogger.com/profile/14765828692647479269[email protected]0tag:blogger.com,1999:blog-1210079982439510008.post-66247505416507425582014-01-18T20:10:00.000+09:002014-01-18T20:10:38.052+09:00Java 7 Update 51 on MacOSX 10.9.1<div class="separator" style="clear: both; text-align: left;"> Java7 Update 51が来てたので早速インストールしておいたんだけど:</div> <div class="separator" style="clear: both; text-align: center;"> <br /></div> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjx_f3pSwYUz780RAHdZzlaXuBrn8VuV_yi30Jj5K7OFyZR2KhczBWHYdGhDWB5bv0EEftY_mouat_Lb-X42fPLnsHeBIx-RQQOjZjGGx8nQbvsx8_-ZWQJxIqHc9u26SjJly5lUsrQGuo/s1600/Java_Control_Panel_and_Java_Control_Panel_and_Skype_and_HipChat_-_Freebit_and_Timeline_and_Skype.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjx_f3pSwYUz780RAHdZzlaXuBrn8VuV_yi30Jj5K7OFyZR2KhczBWHYdGhDWB5bv0EEftY_mouat_Lb-X42fPLnsHeBIx-RQQOjZjGGx8nQbvsx8_-ZWQJxIqHc9u26SjJly5lUsrQGuo/s1600/Java_Control_Panel_and_Java_Control_Panel_and_Skype_and_HipChat_-_Freebit_and_Timeline_and_Skype.png" height="640" width="620" /></a></div> <br /> shellから確認するとJava 7 Update 45のままなのはどうしてなの?<br /> <br /> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXVOjEI0Dp5XqpAVEkNQ6co9zcHmFfrIlvycIWrB-gqcrBnLzMQok_fjXoiGy-_VD-RAHZPgHskXJl7siZI-nTK5hAgUigib7aBE_TFq4kH03Jcjpjc8O-hhLMePk0jtUGU1hc-KvBG2g/s1600/Terminal_%E2%80%94_zsh_%E2%80%94_80%C3%9724.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXVOjEI0Dp5XqpAVEkNQ6co9zcHmFfrIlvycIWrB-gqcrBnLzMQok_fjXoiGy-_VD-RAHZPgHskXJl7siZI-nTK5hAgUigib7aBE_TFq4kH03Jcjpjc8O-hhLMePk0jtUGU1hc-KvBG2g/s1600/Terminal_%E2%80%94_zsh_%E2%80%94_80%C3%9724.png" height="443" width="640" /></a></div> <br />Anonymoushttp://www.blogger.com/profile/14765828692647479269[email protected]0tag:blogger.com,1999:blog-1210079982439510008.post-75474480082423360862014-01-13T16:30:00.000+09:002014-01-13T16:31:06.337+09:002つのTwitterSource.javaCDH 4.5に含まれるFlume-NGにはTwitterからデータを取得するためのTwitterSourceクラスが含まれるようになっています。これがCDH 4.5にTwitter4Jが同梱されるようになった理由。実際こんな感じでjarファイルが転がっているのが見て取れます。<br /> <br /> <div style="background-color: whitesmoke; border-radius: 10px; border-style: solid; border-width: 0px; padding: 5px 5px 5px 5px; width: 620px;"> <pre><code>% cd /opt/cloudera/parcels/CDH-4.5.0-1.cdh4.5.0.p0.30/lib/flume-ng/lib % ls -lF twitter* -rwxr-xr-x 1 root root 283752 Nov 21 11:07 twitter4j-core-3.0.3.jar* -rwxr-xr-x 1 root root 27690 Nov 21 11:07 twitter4j-media-support-3.0.3.jar* -rwxr-xr-x 1 root root 56262 Nov 21 11:07 twitter4j-stream-3.0.3.jar*</code></pre> </div> <br /> これだけで終わってもいいのですが折角なので混乱を招くのではないかと思うTwitterSource.javaについて書いておきます。<br /> <br /> <h3> 世の中には2つのTwitterSource.javaがある</h3> <div> <ul> <li><a href="https://github.com/cloudera/cdh-twitter-example">https://github.com/cloudera/cdh-twitter-example</a>&nbsp;で提供されるもの</li> <li>Flume-NGの機能として提供されるもの</li> <ul> <li>CDH 4.5に入っているのはこれ。CDH 5にも入るハズ</li> </ul> </ul> <h3> </h3> <h3> cdh-twitter-example版</h3> </div> <div> <ul> <li>com.cloudera.flume.source.TwitterSource</li> <li>TwitterのSample APIを叩く</li> <ul> <li>指定されたキーワードを含むものが取得できる</li> </ul> <li>フォーマットはいじらずに後段に流す</li> </ul> <div> コードからコメント抜いてくるとこう書いてある:</div> </div> <div> <br /></div> <div style="background-color: whitesmoke; border-radius: 10px; border-style: solid; border-width: 0px; padding: 5px 5px 5px 5px; width: 600px;"> <pre><code>/** * A Flume Source, which pulls data from Twitter's streaming API. Currently, * this only supports pulling from the sample API, and only gets new status * updates. */</code></pre> </div> <h3> <span style="font-size: 15px;"><span style="font-family: inherit;"><br /></span></span></h3> <h3> <span style="font-size: 15px;"><span style="font-family: inherit;">Flume-NG版</span></span></h3> <div> <ul> <li><span style="font-size: 15px;">org.apache.flume.source.twitter.TwitterSource</span></li> <li><span style="font-size: 15px;">TwitterのStreaming APIを叩く</span></li> <ul> <li><span style="font-size: 15px;">Firehoseで取得できるものの1%がサンプリングされるらしい</span></li> </ul> <li><span style="font-size: 15px;">Avroフォーマットにして後段に流す</span></li> </ul> <div> <span style="font-size: 15px;">コードからコメント抜いてくるとこう書いてある:</span></div> </div> <pre><code> </code></pre> <div style="background-color: whitesmoke; border-radius: 10px; border-style: solid; border-width: 0px; padding: 5px 5px 5px 5px; width: 620px;"> <pre><code>/** * Demo Flume source that connects via Streaming API to the 1% sample twitter * firehose, continously downloads tweets, converts them to Avro format and * sends Avro events to a downstream Flume sink. * * Requires the consumer and access tokens and secrets of a Twitter developer * account */</code></pre> </div> <h3> <code><span style="font-family: inherit;"><br /></span></code></h3> <h3> <code><span style="font-family: inherit;">まとめ</span></code></h3> <div> <span style="font-family: inherit;">早い話がClouderaが作ったTwitterSource便利だからApache Software Foundationに寄贈してFlume-NGに取り込まれたけどちょっと機能が変わってますね、ということでした。</span></div> Anonymoushttp://www.blogger.com/profile/14765828692647479269[email protected]0tag:blogger.com,1999:blog-1210079982439510008.post-48731226882028764312014-01-12T02:07:00.001+09:002014-01-12T02:08:08.947+09:00CDH 4.5に移行したらFlume agentが動かなくなった年末年始の休みでアップグレードしようと思ってたのが作業できてなかったので、忘れないうちにと思って3連休の初日にCloudera Manager 4.8&nbsp;+ CDH 4.5の環境に移行してみた。移行作業自体は何の問題も無く終わったんだけど新しくしてから全サービス起動して問題ないか見て回ってたら不審な点に気付いてしまった:<br /> <br /> <blockquote class="tr_bq"> <span style="font-size: large;">Flumeからデータが流れてきてないw</span></blockquote> <br /> いやこれ本番環境とかだったら全然笑えない事態だけど。Cloudera Managerからログを調べてみたらagentがエラー吐いてた:<br /> <br /> <div style="background-color: whitesmoke; border-radius: 10px; border-style: solid; border-width: 0px; padding: 5px 5px 5px 5px; width: 1100px;"> <pre><code>Unable to start EventDrivenSourceRunner: { source:com.cloudera.flume.source.TwitterSource{name:Twitter,state:IDLE} } - Exception follows. java.lang.NoSuchMethodError: twitter4j.FilterQuery.setIncludeEntities(Z)Ltwitter4j/FilterQuery; at com.cloudera.flume.source.TwitterSource.start(TwitterSource.java:141) at org.apache.flume.source.EventDrivenSourceRunner.start(EventDrivenSourceRunner.java:44) at org.apache.flume.lifecycle.LifecycleSupervisor$MonitorRunnable.run(LifecycleSupervisor.java:251) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441) at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317) at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(ScheduledThreadPoolExecutor.java:98) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodic(ScheduledThreadPoolExecutor.java:180) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:204) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:662)</code></pre> </div> <br /> Twitter4Jのところで存在しないメソッドを呼び出すとかアホなことしてる。これ原因は判ってしまえば簡単で、CDH 4.5に入っているTwitter4JのバージョンとFlume agentが使っているTwitter4Jのバージョンが違うのが問題だった。以前のCDHにはTwitter4Jは含まれてなかったのでFlume agentのjarに入れてあったんだけどCDH 4.5側のTwitter4Jを先に見付けてしまって誤動作するという昔懐かしいDLL HELLみたいな状況が起きてた。<br /> <br /> 判ってしまえば対処も簡単でCDH 4.5用にpomを書き換えてFlume agentをビルドし直してデプロイ、サービス再起動で問題なくデータが流れ始めた。<br /> <br /> fork元の&nbsp;<a href="https://github.com/cloudera/cdh-twitter-example">cloudera/cdh-twitter-example</a>&nbsp;に差分が来てたのでそれらを&nbsp;<a href="https://github.com/kmizumar/cdh-twitter-example/commit/7871a13574613e79fff5e0e7853f2c39356c80b1">kmizumar/cdh-twitter-example</a>&nbsp;に取り込んだだけ。<br /> <br /> どうしてCDH 4.5にTwitter4Jが入っているのか、は気が向いたら書きます。Anonymoushttp://www.blogger.com/profile/14765828692647479269[email protected]1tag:blogger.com,1999:blog-1210079982439510008.post-78050747602073063062013-12-10T00:59:00.000+09:002013-12-13T00:02:14.943+09:00cdh-twitter-exampleで遊ぶ<div style="font-family: Meiryo; text-indent: 18px;"> この記事はHadoop Advent Calendar 2013, 13日目のエントリです。ブログなんざ書いたことないので勝手が良く分かりませんが@sudabonさん@kernel023さんのお前も何か書けやコラという圧力に負けてBloggerにページを用意してみました。<br /> <br /> Hadoopの利用目的としてデータの分析に取り組んでいる、もしくはこれから取り組もうとしているユーザは多いのではないかと思います。中でもログ分析と並んでソーシャルメディアの分析は各社が積極的に取り組もうとしているテーマであり、私が勝手にTwitter分析3部作と呼んでいる以下のブログを読まれた方も多いのではないでしょうか:<br /> <ol style="font-family: Times; text-indent: 0px;"> <li><a href="http://blog.cloudera.com/blog/2012/09/analyzing-twitter-data-with-hadoop/"><span style="font-family: Trebuchet MS, sans-serif;">http://blog.cloudera.com/blog/2012/09/analyzing-twitter-data-with-hadoop/</span></a></li> <li><a href="http://blog.cloudera.com/blog/2012/10/analyzing-twitter-data-with-hadoop-part-2-gathering-data-with-flume/"><span style="font-family: Trebuchet MS, sans-serif;">http://blog.cloudera.com/blog/2012/10/analyzing-twitter-data-with-hadoop-part-2-gathering-data-with-flume/</span></a></li> <li><span style="font-family: Trebuchet MS, sans-serif;"><a href="http://blog.cloudera.com/blog/2012/11/analyzing-twitter-data-with-hadoop-part-3-querying-semi-structured-data-with-hive/">http://blog.cloudera.com/blog/2012/11/analyzing-twitter-data-with-hadoop-part-3-querying-semi-structured-data-with-hive/</a></span></li> </ol> まだ読まれていない方のためにざっくりと説明しますと、Flumeを利用してTwitterからデータをぶっこ抜いてきてHDFSに流し込んでやれば、あとはHiveにJSON SerDeを組み込むだけでSQLでTwitterを分析する準備ができちゃいます、ということが紹介されてます。</div> <div style="font-family: Meiryo; text-indent: 18px;"> <br /> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdh6j3h1jUgV9Q-x8ka0zR-oBQNy2iPrytNLvy6GhNaoUQzB121MIHJtjzTr4PsvVqa-yk_9gL_uLdvVtd5BROkKFZehTQ0ZHdKc6I9Ok6yh0o6fJ2hlxd-lvb1xq8Zl-mgfQt-WKSVAY/s1600/datapipeline-original.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdh6j3h1jUgV9Q-x8ka0zR-oBQNy2iPrytNLvy6GhNaoUQzB121MIHJtjzTr4PsvVqa-yk_9gL_uLdvVtd5BROkKFZehTQ0ZHdKc6I9Ok6yh0o6fJ2hlxd-lvb1xq8Zl-mgfQt-WKSVAY/s1600/datapipeline-original.png" /></a><br /> <br /> 前置きが長くなりましたがこのエントリでは上の図のTwitter分析用のデータパイプラインに細工してデータを流し込む先としてHBaseを追加してみたり、HBaseに書き込まれたデータについてインデックスを作成して全文検索が出来るようにする方法を紹介してみたいと思います。せっかちな方のためにどんな技術トピックが関係するかを先に列記しておくとFlume Interceptor, Flume flow multiplexer, Flume HBaseSink, Lily HBase NRT Indexer Service, Cloudera Search (SolrCloud)といったものになります。ここから先はTwitter分析3部作のブログは読んでいる、もしくは同等の内容を知っているものとして話を進めます。Twitter分析3部作のオリジナルのコードはGithubの以下のリポジトリに置かれています:</div> <div style="text-indent: 18px;"> <br /> <ul> <li><a href="https://github.com/cloudera/cdh-twitter-example"><span style="font-family: Trebuchet MS, sans-serif;">https://github.com/cloudera/cdh-twitter-example</span></a></li> </ul> </div> <div style="font-family: Meiryo; text-indent: 18px;"> これを勝手にforkしていじくったものをGithubの以下のリポジトリに置いています。興味がある人はのぞいてみてください。</div> <div> <br /> <ul> <li><a href="https://github.com/kmizumar/cdh-twitter-example"><span style="font-family: Trebuchet MS, sans-serif;">https://github.com/kmizumar/cdh-twitter-example</span></a></li> </ul> <br /> <div style="font-family: Meiryo;"> <br /></div> <h2> <span style="font-family: Meiryo;"><span style="font-size: large;">InterceptorでFlume eventをネコババする</span></span></h2> <div style="font-family: Meiryo;"> 先に見たデータパイプラインにある「カスタム作成のFlume Source」の正体はcom.cloudera.flume.source.TwitterSourceクラスです。このクラスは設定ファイルで指定されたキーワードで検索したtweetをJSONフォーマットで出力してきます。<span style="text-indent: 18px;">1イベントについて1つのJSONレコードが含まれています。以下は例です:</span></div> <br /> <div style="background-color: whitesmoke; border-radius: 10px; border-style: solid; border-width: 0px; padding: 5px 5px 5px 5px; width: 580px;"> <pre><code>{"filter_level":"medium","contributors":null,"text":"In the past, our team at Bing Ads has applied big data insight to ad copy strategy in the travel and financial servi\u2026http://t.co/A3A5xRJE8b","geo":null,"retweeted":false,"in_reply_to_screen_name":null,"possibly_sensitive":false,"truncated":false,"lang":"en","entities":{"symbols":[],"urls":[{"expanded_url":"http://lnkd.in/bipZAX3","indices":[117,139],"display_url":"lnkd.in/bipZAX3","url":"http://t.co/A3A5xRJE8b"}],"hashtags":[],"user_mentions":[]},"in_reply_to_status_id_str":null,"id":390880848465375232,"source":"&lt;a href=\"http://www.linkedin.com/\" rel=\"nofollow\"&gt;LinkedIn&lt;\/a&gt;","in_reply_to_user_id_str":null,"favorited":false,"in_reply_to_status_id":null,"retweet_count":0,"created_at":"Thu Oct 17 16:43:51 +0000 2013","in_reply_to_user_id":null,"favorite_count":0,"id_str":"390880848465375232","place":null,"user":{"location":"Raleigh, NC","default_profile":true,"statuses_count":3010,"profile_background_tile":false,"lang":"en","profile_link_color":"0084B4","id":474950294,"following":null,"favourites_count":0,"protected":false,"profile_text_color":"333333","description":null,"verified":false,"contributors_enabled":false,"profile_sidebar_border_color":"C0DEED","name":"Dan Damato","profile_background_color":"C0DEED","created_at":"Thu Jan 26 14:35:17 +0000 2012","default_profile_image":false,"followers_count":139,"profile_image_url_https":"https://si0.twimg.com/profile_images/1785237335/images_normal.jpg","geo_enabled":false,"profile_background_image_url":"http://abs.twimg.com/images/themes/theme1/bg.png","profile_background_image_url_https":"https://abs.twimg.com/images/themes/theme1/bg.png","follow_request_sent":null,"url":null,"utc_offset":null,"time_zone":null,"notifications":null,"profile_use_background_image":true,"friends_count":389,"profile_sidebar_fill_color":"DDEEF6","screen_name":"onlinesalesnut","id_str":"474950294","profile_image_url":"http://a0.twimg.com/profile_images/1785237335/images_normal.jpg","listed_count":1,"is_translator":false},"coordinates":null} </code></pre> </div> <br /> <div style="font-family: Meiryo; text-indent: 18px;"> JSONレコード1つをHBaseの1カラムに格納してもいいのですが、ここではtweetの中から取り敢えず興味のある</div> <div style="font-family: Meiryo; text-indent: 18px;"> </div> <ol> <li><span style="font-family: Verdana, sans-serif;">id : tweetを一意に識別する識別子(だと予想)</span></li> <li><span style="font-family: Verdana, sans-serif;">text : tweetの本文</span></li> <li><span style="font-family: Verdana, sans-serif;">user.screen_name : twitterユーザのアカウント(例:kmizumar)</span></li> <li><span style="font-family: Verdana, sans-serif;">user.name : twitterユーザのフルネーム(例:Kiyoshi Mizumaru)</span></li> </ol> <br /> <span style="font-family: Meiryo; text-indent: 18px;">だけを抽出してそれぞれHBaseのtid, text, screen, userというカラムに格納することにします。</span>&nbsp;<span style="font-family: Meiryo; text-indent: 18px;">これを実現するためにはJSONレコードをパースして興味のある名前と値のペアだけを抜き出すという処理が必要になりますが、このためにTwitterSourceクラスを改造することは得策ではありません。Flumeには任意のSourceにくっつけてそのSourceへ入力されてくるイベントを横取りして好きなようにイベントに細工を施すことのできるInterceptorが用意されてますのでこれを使います。</span><span style="font-family: Meiryo; text-indent: 18px;">TwitterSourceにくっつけて上記の処理を行わせるために作成したものがcom.cloudera.flume.interceptor.TwitterInterceptorクラスです:</span><br /> <br /> <ul> <li><span style="font-family: Meiryo; text-indent: 18px;"><a href="https://github.com/kmizumar/cdh-twitter-example/blob/master/flume-sources/src/main/java/com/cloudera/flume/interceptor/TwitterInterceptor.java">https://github.com/kmizumar/cdh-twitter-example/blob/master/flume-sources/src/main/java/com/cloudera/flume/interceptor/TwitterInterceptor.java</a></span></li> </ul> <br /> <h3> private byte[] readJsonStream(InputStream)メソッド</h3> <div style="text-indent: 18px;"> <div style="font-family: Meiryo;"> JSONレコードをパースして”id”, “text”, “user.name”, “user.screen_name”に該当する値だけを抜き出します。抜き出した値を使用して<br /> <br /> <div style="background-color: whitesmoke; border-radius: 10px; border-style: solid; border-width: 0px; padding: 5px 5px 5px 5px; width: 1000px;"> <pre><code>____ID____:&lt;idの値&gt;____TEXT____:&lt;textの値&gt;____USER____:&lt;user.nameの値&gt;____SCREEN____:&lt;user.screen_nameの値&gt;</code></pre> </div> <br /> という内容を持つbyte[]を組み立てて返します。パーサーはcom.google.gson.stream.JsonReaderクラスを利用しています。&nbsp;</div> <h3> </h3> <h3> <br />pubic Event intercept(Event)メソッド</h3> <div> <span style="font-family: Verdana, sans-serif;">イベントをひとつ受け取ったら</span></div> <div> </div> <ol> <li><span style="font-family: Verdana, sans-serif;">元のイベントのヘッダをコピーしたものに <span style="background-color: #eeeeee;">SINKTYPE → HBASE</span> というデータを追加</span></li> <li><span style="font-family: Verdana, sans-serif;">上記ヘッダとreadJsonStreamから戻ってきた内容をボディに持つ新しいイベントを作成</span></li> </ol> <span style="font-family: Verdana, sans-serif;">して返します。ここではイベントのボディを完全に別の物にすり替えています。</span><br /> <br /> <h3> </h3> <h3> <span style="font-family: Verdana, sans-serif;"><span style="font-size: small;"><br />public List&lt;Event&gt; intercept(List&lt;Event&gt;)メソッド</span></span></h3> <div> <span style="font-family: Verdana, sans-serif;">イベントのリストを受け取ります。リストに含まれているイベントそれぞれについて</span></div> <div> <ol> <li><span style="font-family: Verdana, sans-serif;">元のイベントのヘッダに <span style="background-color: #eeeeee;">SINKTYPE → HDFS</span> というデータを追加する</span></li> <li><span style="font-family: Verdana, sans-serif;">Event intercept(Event)メソッドを呼び出して <span style="background-color: #eeeeee;">SINKTYPE → HBASE</span> の新しいイベントを取得する</span></li> </ol> <span style="font-family: Verdana, sans-serif;">という処理を行いHDFS用とHBase用の2つのイベントを作成してリストに入れて返します。入力されてきたイベントのリストはHDFS用とHBase用のイベントを含む倍の長さのイベントのリストになって出力されることになります。</span></div> <div> <br /></div> <div> <span style="font-family: Verdana, sans-serif;"><br /></span></div> <div> <div style="-webkit-text-stroke-width: 0px; color: black; font-family: Meiryo; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;"> </div> </div> <br /> <h2 style="-webkit-text-stroke-width: 0px; color: black; font-family: Times; font-style: normal; font-variant: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;"> <span style="font-family: Meiryo;"><span style="font-size: large;">仕方がないのでTwitterSourceを改造する</span></span></h2> <div> <span style="font-family: Meiryo;">ここまでで作成したTwitterInterceptorを使うことで、</span><span style="font-family: Meiryo;">TwitterSourceに流れてくるイベントを横取りしてHDFS向けに従来通りのJSONレコードを保持するevent、HBASE向けにJSONレコードから欲しいところだけ抜き出した内容を保持するevent、の2つのeventを吐き出すことができるようになるはずです。はずです、と書いたのには理由があって実はオリジナルのTwitterSourceクラスの実装では期待した結果が得られません。これはTwitterSourceクラスの中で使用しているStatusListenerクラスのインスタンスがJSONレコードをラップするイベントオブジェクトを作成したら、イベントオブジェクト1つを引数にして後段のチャネルに流しているのが原因です。これではTwitterInterceptorクラスのEvent intercept(Event)メソッドしか呼ばれないためイベントを捨てるか(nullを返す)、イベントを改変して返すか、そのまま返すか、しかできることがありません。現在のTwitterInterceptorの実装ではすべてのイベントがHBase用に置き換えられて出てくるだけで、いずれにしてもこのままでは今回やろうとしている「1つのイベントを受け取って2つのイベントを返す」ということはできないのでチャネルに流す前にイベントオブジェクトをList&lt;Event&gt;に突っ込んでチャネルにはリストを流すように変更してしまいます。もっと上手い方法はありそうですがQuick and Dirty Hackでここは乗り切ることにします。</span><br /> <br /> <ul> <li><span style="font-family: Meiryo;"><a href="https://github.com/kmizumar/cdh-twitter-example/commit/840fb2279b11437d850027b5feeb880b215cb2a9#diff-c3d9e77e0883358123b3a4fb832b2d87">https://github.com/kmizumar/cdh-twitter-example/commit/840fb2279b11437d850027b5feeb880b215cb2a9#diff-c3d9e77e0883358123b3a4fb832b2d87</a></span></li> </ul> <br /> <div style="background-color: whitesmoke; border-radius: 10px; border-style: solid; border-width: 0px; padding: 5px 5px 5px 5px; width: 1000px;"> <pre><code> diff --git a/flume-sources/src/main/java/com/cloudera/flume/source/TwitterSource.java b/flume-sources/src/main/java/com/ index 53c2f60..0305702 100644 --- a/flume-sources/src/main/java/com/cloudera/flume/source/TwitterSource.java +++ b/flume-sources/src/main/java/com/cloudera/flume/source/TwitterSource.java @@ -18,7 +18,9 @@ package com.cloudera.flume.source; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.apache.flume.Context; @@ -110,8 +112,8 @@ public class TwitterSource extends AbstractSource headers.put("timestamp", String.valueOf(status.getCreatedAt().getTime())); Event event = EventBuilder.withBody( DataObjectFactory.getRawJSON(status).getBytes(), headers); - - channel.processEvent(event); + List&lt;event&gt; events = Arrays.asList(event); + channel.processEventBatch(events); } // This listener will ignore everything except for new tweets </code></pre> </div> </div> </div> </div> <br /> <div style="-webkit-text-stroke-width: 0px; color: black; font-family: Times; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 18px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;"> </div> <br /> <h2 style="-webkit-text-stroke-width: 0px; color: black; font-family: Times; font-style: normal; font-variant: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;"> <span style="font-family: Meiryo;"><span style="font-size: large;">Flow multiplexerでFlume eventを撃ち分ける</span></span></h2> <div> <div style="font-family: Meiryo; text-indent: 18px;"> Flumeのデータフローを組み立てます。登場するのはsourceとしてTwitterからデータを入力するものが1つ、sinkとしてHDFSへ流し込むのとHBaseへ流し込むものが2つ、そしてそれぞれのsinkに対応するchannelが2つです。flume.confからポイントとなる部分だけ抜粋します。TwitterAgentという名前でエージェントを作成しています。 </div> <br /> <div style="background-color: whitesmoke; border-radius: 10px; border-style: solid; border-width: 0px; padding: 5px 5px 5px 5px; width: 1000px;"> <pre><code>TwitterAgent.sources = Twitter TwitterAgent.channels = MemChannel MemChannel2 TwitterAgent.sinks = HDFS HBASE TwitterAgent.sources.Twitter.type = com.cloudera.flume.source.TwitterSource TwitterAgent.sources.Twitter.channels = MemChannel MemChannel2 </code></pre> </div> <br /> <div style="font-family: Meiryo; text-indent: 18px;"> 続いてこのTwitterAgentにインターセプターを設定します。インターセプターの型を指定する<code>*.type</code>プロパティにはインターセプターのクラス名ではなくインターセプターのビルダークラスを指定しなければならないのに気付くまでかなり時間をムダに費やしたのは秘密です。 </div> <br /> <div style="background-color: whitesmoke; border-radius: 10px; border-style: solid; border-width: 0px; padding: 5px 5px 5px 5px; width: 1000px;"> <pre><code>TwitterAgent.sources.Twitter.interceptors = TwitterInterceptor TwitterAgent.sources.Twitter.interceptors.TwitterInterceptor.type = com.cloudera.flume.interceptor.TwitterInterceptor$Builder </code></pre> </div> <br /> <div style="font-family: Meiryo; text-indent: 18px;"> これでTwitterSourceが取得してきたイベントはTwitterInterceptorを経由してからチャネルに流れ出るようになります。どのイベントをどのチャネルに流し込むかを選択するにはsourceにマルチプレクサを設定して、イベントのどのヘッダを見て、その内容に応じてどのチャネルに流し込んで欲しいかを指定します。ここではSINKTYPEヘッダの内容を見てそれが"HDFS"だったらMemChannelへ、"HBASE"だったらMemChannel2へ流し込むようにしています。いまのTwitterInterceptorの実装ではSINKTYPEがHDFSかHBASEのどちらかしか出力してきませんが、将来的に他のタイプのものを出力するようにしたときにHBase側に流れても正しく扱えないのでデフォルトをHDFS側のMemChannelに倒しています(HDFSなら任意のJSONレコードをそのまま格納できるので)。 </div> <br /> <div style="background-color: whitesmoke; border-radius: 10px; border-style: solid; border-width: 0px; padding: 5px 5px 5px 5px; width: 1000px;"> <pre><code>TwitterAgent.sources.Twitter.selector.type = multiplexing TwitterAgent.sources.Twitter.selector.header = SINKTYPE TwitterAgent.sources.Twitter.selector.mapping.HDFS = MemChannel TwitterAgent.sources.Twitter.selector.mapping.HBASE = MemChannel2 TwitterAgent.sources.Twitter.selector.default = MemChannel </code></pre> </div> <div class="separator" style="clear: both; text-align: center;"> <br /></div> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHIa-7UkPGrn6HLi64AgBOkR4jgCuyHZvBC6g-AVu0VuD81fxcuGmb3jbVFPurO_un7mjrE1VsdauT35TVmt8hRzSjsqJgtfTtKscgGoUYuDSRemJw1tRoKqe0V9xUouIqFtLYjh-xVB0/s1600/eventflow.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHIa-7UkPGrn6HLi64AgBOkR4jgCuyHZvBC6g-AVu0VuD81fxcuGmb3jbVFPurO_un7mjrE1VsdauT35TVmt8hRzSjsqJgtfTtKscgGoUYuDSRemJw1tRoKqe0V9xUouIqFtLYjh-xVB0/s1600/eventflow.png" /></a></div> <br /> <h2 style="text-indent: 0px;"> <span style="font-family: Meiryo;"><span style="font-size: large;">HBaseSinkでHBaseにデータを流し込む</span></span></h2> <div style="font-family: Meiryo; text-indent: 18px;"> MemChannel側の設定はTwitter分析3部作のブログと変わらずHdfsSinkに接続してHDFSに書き込んでいるだけなので説明は省略します。MemChannel2側のチャネルにはHBaseSinkを接続してデータをHBaseに流し込むことにします。 </div> <br /> <div style="background-color: whitesmoke; border-radius: 10px; border-style: solid; border-width: 0px; padding: 5px 5px 5px 5px; width: 1000px;"> <pre><code>TwitterAgent.sinks.HBASE.channel = MemChannel2 TwitterAgent.sinks.HBASE.type = hbase TwitterAgent.sinks.HBASE.table = tweets_hbase TwitterAgent.sinks.HBASE.columnFamily = cf1 TwitterAgent.sinks.HBASE.batchSize = 1000 TwitterAgent.sinks.HBASE.serializer = org.apache.flume.sink.hbase.RegexHbaseEventSerializer TwitterAgent.sinks.HBASE.serializer.regex = ^____ID____:(.*)____TEXT____:(.*)____USER____:(.*)____SCREEN____:(.*)$ TwitterAgent.sinks.HBASE.serializer.colNames = tid,text,user,screen </code></pre> </div> <br /> <div style="font-family: Meiryo; text-indent: 18px;"> ここでは次のことを指定しています: <br /> <ol> <li><span style="font-family: Verdana, sans-serif;">書き込む先のHBaseテーブルの名前をtweets_hbase</span></li> <li><span style="font-family: Verdana, sans-serif;">カラムファミリ名をcf1</span></li> <li><span style="font-family: Verdana, sans-serif;">RegexHbaseEventSerializerを使ってイベントボディからデータを取り出す(ここ正しくはデシリアライザじゃないのかなぁ... 名前)</span></li> <li><span style="font-family: Verdana, sans-serif;">データを取り出すための正規表現パターン</span></li> <li><span style="font-family: Verdana, sans-serif;">マッチしたデータをHBaseテーブルのどのカラムに書き込むか</span></li> </ol> ここまでの内容に合わせてHBaseにテーブルを作成しておきます。 </div> <br /> <br /> <div style="background-color: whitesmoke; border-radius: 10px; border-style: solid; border-width: 0px; padding: 5px 5px 5px 5px; width: 580px;"> <pre><code>% hbase shell hbase(main):001:0&gt; create 'tweets_hbase', 'cf1' </code></pre> </div> <br /> <div style="font-family: Meiryo; text-indent: 18px;"> ここまでの構成が問題なくできていればFlume agentを立ち上げることでTwitterからデータの取り込みが開始されてHDFS, HBaseの双方にデータが書き込まれて行きます。画面はHueのHBaseブラウザでtweets_hbaseテーブルを表示してみたところです。指定したcf1:screen, cf1:tid, cf1:text, cf1:userカラムにそれぞれ値が格納されている様子がわかります: </div> <br /> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoLxTNp0qYQgUZOJd7j0gukhMwKBg6-LblQZiUVKsRLSnKZXZR0-TrXKti18EbBG2gyJmLelsuNU0HJrbGplWwBSlm0FwZh_70C2IsBl_ECovigm5DpTo8OpdcWRzZ8I0g__ls5O91n5k/s1600/hue-hbase-browser.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoLxTNp0qYQgUZOJd7j0gukhMwKBg6-LblQZiUVKsRLSnKZXZR0-TrXKti18EbBG2gyJmLelsuNU0HJrbGplWwBSlm0FwZh_70C2IsBl_ECovigm5DpTo8OpdcWRzZ8I0g__ls5O91n5k/s1600/hue-hbase-browser.png" /></a> </div> <br /> <div> <h2 style="text-indent: 0px;"> <span style="font-family: Meiryo;"><span style="font-size: large;">Lily HBase NRT Indexer Serviceでインデックス作成</span></span></h2> <div style="font-family: Meiryo; text-indent: 18px;"> そろそろ飽きてきたころだと思いますがここまでくればもう少しです。まずはインデックスを作成したいHBaseのテーブルでレプリケーションが有効になっていることが要求されますのでこれを片付けておきます: </div> </div> </div> <br /> <div style="background-color: whitesmoke; border-radius: 10px; border-style: solid; border-width: 0px; padding: 5px 5px 5px 5px; width: 700px;"> <pre><code>% hbase shell hbase(main):001:0&gt; disable 'tweets_hbase' hbase(main):002:0&gt; alter 'tweets_hbase', {NAME =&gt; 'cf1', REPLICATION_SCOPE =&gt; 1} hbase(main):003:0&gt; enable 'tweets_hbase' </code></pre> </div> <br /> <div style="font-family: Meiryo; text-indent: 18px;"> 立て続けにmorphlines.confを設定します。後ほど作成するSolrコレクション hbase-collection1に対してインデックスを登録していくこと、HBaseテーブルのどのカラムを持ってきてSolrスキーマのどのフィールドに割り当てるか、を指定しています。この例ではcf1:textカラムの値がSolrスキーマのtextフィールドとして出力されることになります。 </div> <br /> <div style="background-color: whitesmoke; border-radius: 10px; border-style: solid; border-width: 0px; padding: 5px 5px 5px 5px; width: 1000px;"> <pre><code> SOLR_LOCATOR : { # Name of solr collection collection : hbase-collection1 # ZooKeeper ensemble zkHost : "$ZK_HOST" } morphlines : [ { id : morphline importCommands : ["com.cloudera.**", "com.ngdata.**"] commands : [ { extractHBaseCells { mappings : [ { inputColumn : "cf1:tid" outputField : "tid" type : string source : value } { inputColumn : "cf1:text" outputField : "text" type : string source : value } { inputColumn : "cf1:user" outputField : "user" type : string source : value } { inputColumn : "cf1:screen" outputField : "screen" type : string source : value } ] } } { logDebug { format : "output record: {}", args : ["@{}"] } } ] } ] </code></pre> </div> <br /> <div style="font-family: Meiryo; text-indent: 18px;"> Solrのコレクションを作ります。スキーマ定義は上記のmorphlines.confに合わせて書き換えたものをGithubに置いてますのでこれを利用してSolrCloudにインスタンスディレクトリの作成とコレクションの作成を行います。下の例ではコレクションの作成時にshardの数を4と指定していますが利用しているSolrCloudのノード数に合わせて適宜変更する必要があるので注意してください。Solrスキーマの詳細について知りたいときはWebサイトや専門の書籍を参照してください。深遠なる検索システムの世界が貴方を待っています。 </div> <br /> <div style="background-color: whitesmoke; border-radius: 10px; border-style: solid; border-width: 0px; padding: 5px 5px 5px 5px; width: 580px;"> <pre><code>% solrctl instancedir --create hbase-collection1 hbase-collection1 % solrctl collection --create hbase-collection1 -s 4 </code></pre> </div> <br /> <div style="font-family: Meiryo; text-indent: 18px;"> 最後にインデクサの設定ファイルを作成します。この設定ファイルではインデクサがどのHBaseテーブルを読みに行って、どのmorphlines.confの設定に従って動作するべきなのかを指定します。Githubにmorphline-hbase-mapper.xmlという名前で置いてあるサンプルの内容を以下に示します。ここでtweets_hbaseテーブルをインデックスの作成対象として指示しています。パラメータmorphlineFileの値がフルパスで指定されていないのはCloudera Managerの管理下にあるSolrCloudを利用しているときの設定の仕方になります。 </div> <br /> <div style="background-color: whitesmoke; border-radius: 10px; border-style: solid; border-width: 0px; padding: 5px 5px 5px 5px; width: 1000px;"> <pre><code>&lt;?xml version="1.0"?&gt; &lt;indexer table="tweets_hbase" mapper="com.ngdata.hbaseindexer.morphline.MorphlineResultToSolrMapper"&gt; &lt;!-- The relative or absolute path on the local file system to the morphline configuration file. --&gt; &lt;!-- Use relative path "morphlines.conf" for morphlines managed by Cloudera Manager --&gt; &lt;param name="morphlineFile" value="morphlines.conf"/&gt; &lt;!-- &lt;param name="morphlineFile" value="/etc/hbase-solr/conf/morphlines.conf"/&gt; --&gt; &lt;!-- The optional morphlineId identifies a morphline if there are multiple morphlines in morphlines.conf --&gt; &lt;!-- &lt;param name="morphlineId" value="morphline1"/&gt; --&gt; &lt;/indexer&gt; </code></pre> </div> <br /> <div style="font-family: Meiryo; text-indent: 18px;"> 準備がすべて整ったところでインデクサを登録します。動作しているLily HBase NRT Indexer Serviceに対して設定ファイルの登録を行い、正しく登録されていることを確認できたらすべての作業は終了です。登録に用いるhbase-indexer add-indexerコマンドの実行例を以下に示します。ZooKeeperアンサンブルの指定は利用している環境に合わせて適宜変更してください。 </div> <br /> <div style="background-color: whitesmoke; border-radius: 10px; border-style: solid; border-width: 0px; padding: 5px 5px 5px 5px; width: 580x;"> <pre><code>% hbase-indexer add-indexer -n myindexer \ --indexer-conf morphline-hbase-mapper.xml \ -cp solr.zk=nn1.demo.dev,nn2.demo.dev,ms3.demo.dev/solr \ -cp solr.collection=hbase-collection1 -z nn1.demo.dev </code></pre> </div> <br /> <div style="font-family: Meiryo; text-indent: 18px;"> インデクサの一覧を見るにはhbase-indexer list-indexersコマンドを使用します。設定ファイルに間違いがあるときは一番下に表示されるProcessesの項目に実行中のプロセスが1個もなくてshard数分のプロセスがfailしているという状態になりますので注意して見てください: </div> <br /> <div style="background-color: whitesmoke; border-radius: 10px; border-style: solid; border-width: 0px; padding: 5px 5px 5px 5px; width: 580x;"> <pre><code>% hbase-indexer list-indexers -z nn1.demo.dev Number of indexes: 1 myindexer + Lifecycle state: ACTIVE + Incremental indexing state: SUBSCRIBE_AND_CONSUME + Batch indexing state: INACTIVE + SEP subscription ID: Indexer_myindexer + SEP subscription timestamp: 2013-12-03T03:38:40.206+09:00 + Connection type: solr + Connection params: + solr.collection = hbase-collection1 + solr.zk = nn1.demo.dev,nn2.demo.dev,ms3.demo.dev/solr + Indexer config: 645 bytes, use -dump to see content + Batch index config: (none) + Default batch index config: (none) + Processes + 4 running processes + 0 failed processes </code></pre> </div> <br /> <div style="font-family: Meiryo; text-indent: 18px;"> CDH4.4 + Cloudera Manager 4.7の組み合わせではCloudera SearchとCloudera Managerの統合がそんなに進んでいないのでSolrCloudの構成状況やドキュメントの登録状況を確認するためにはSolr Admin Console画面を参照します。CollectionのStatistics画面で時間が経つにつれて登録されているドキュメントの数(= tweets_hbaseテーブルに格納されたtweetの数)がどんどん増えて行く様子が見て取れます。またHueのSearch AppでCollection Managerからhbase-collection1を登録して適当なキーワードを投げたりして遊んでみてください。 </div> <br /> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrsGe1py6IcENIa0zs77CDH0hnkQryQYR9QLZaHZG00RFwr4Zt9vbh-eNLnzp3nzUuz6UmTs1kSQqsnF31tlk0dXuKXP_kuUnYQmR6MjUhr7OeN45Rdf6O-rsebNcEMNJsVQG33g6EqoM/s1600/solr-admin-graph.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrsGe1py6IcENIa0zs77CDH0hnkQryQYR9QLZaHZG00RFwr4Zt9vbh-eNLnzp3nzUuz6UmTs1kSQqsnF31tlk0dXuKXP_kuUnYQmR6MjUhr7OeN45Rdf6O-rsebNcEMNJsVQG33g6EqoM/s1600/solr-admin-graph.png" /></a></div> <br /> <div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCJYqVzWSR5gjCWVml9-Jc36n1FH7VO5VG5PsibapuscMUTARl1MscugvF394Q2U2l5ER5PC3smD4fGgXsvuhtx2MUB5Xlmtgyxldie_6C_NNusJgRzldNNTAWGjHqe7FqF9y8mKbt7WM/s1600/solr-admin-collection.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCJYqVzWSR5gjCWVml9-Jc36n1FH7VO5VG5PsibapuscMUTARl1MscugvF394Q2U2l5ER5PC3smD4fGgXsvuhtx2MUB5Xlmtgyxldie_6C_NNusJgRzldNNTAWGjHqe7FqF9y8mKbt7WM/s1600/solr-admin-collection.png" /></a></div> <br /> <div> <h2> <span style="font-family: Meiryo;"><span style="font-size: large;">おわりに</span></span></h2> <div style="font-family: Meiryo; text-indent: 18px;"> 駆け足でTwitterSourceからデータを横取りしてHBaseに放り込み全文検索用のインデックスを張るところまでを眺めてみました。Flumeからしかデータを書き込まないのであればFlume Morphline Solr Sinkを利用してインデックス作成とデータ書き込みを同時にやってのけるという芸当も実際には可能です。興味のある人は是非挑戦してみてください。 </div> <br /> <div style="font-family: Meiryo; text-indent: 18px;"> Hadoop Advent Calendar 2013, 14日目はs-wool@githubさんです。おたのしみに。 </div> </div> Anonymoushttp://www.blogger.com/profile/14765828692647479269[email protected]0tag:blogger.com,1999:blog-1210079982439510008.post-25074554952457077132013-12-08T00:51:00.001+09:002013-12-08T03:02:27.120+09:00投稿テスト<div class="separator" style="clear: both; text-align: center;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH1sum6L5tu74jkSvRkAf_pS8pz5OoMHKX7g_hoVdgcRwrNr76al9o7yN9nSNuwZhIS2xWTTy6xEDyWAPZwusp43ulXIT1A8UcD9EeBULvXlU_yPglvsaqoH1DZtEKfm6LJdXcpdBlmaE/s1600/skitch.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH1sum6L5tu74jkSvRkAf_pS8pz5OoMHKX7g_hoVdgcRwrNr76al9o7yN9nSNuwZhIS2xWTTy6xEDyWAPZwusp43ulXIT1A8UcD9EeBULvXlU_yPglvsaqoH1DZtEKfm6LJdXcpdBlmaE/s640/skitch.png" width="521" /></a></div> <br /> <div> <br /></div> Anonymoushttp://www.blogger.com/profile/14765828692647479269[email protected]0