JAZUG 3周年のセッションでも少ししゃべらしてもらったのですが、あまり時間もなく、ブログでフォローしようと思いつつ時間がたってしまいましたが、少しブログでもまとめておこうかと思います。
.NET SDK For Hadoop
C#で、M/Rを書くための.NET向け SDKがCodePlexから配布されています。
ライブラリ自身は、NuGetから取得できるので、ここから何かダウンロードする必要はありませんが、ドキュメントは参考になるかと思います、
実行方法など
プログラムを紹介する前に、実行方法について。以下の3種類の実行方法があります。
- ローカル実行
- ローカルのHDInsightによる実行
- Azure上のHDInsightによる実行
1.はStreamingUnitクラスによるお手軽実行です。ローカルのHadoop環境すら不要なので、とりあえず動かしてみたり、挙動を確認したりするのに適しています。 2.は、前記事で説明したローカル環境にインストールしたHadoopで実行、3.はAzure上に構築したHadoop環境での実行になります。
サンプル
ここでは、簡単なM/RとしてWordカウントサンプルを作成し、StreamingUnitクラスによる実行を紹介します。
準備
まずは、VSでコンソールプロジェクトを作成します。後に補足しますが、単独実行可能なようにexeのプロジェクトです。
NuGetコンソールから、Hadoopクライアントライブラリをインストールします。Hive等は使わなければインストールしなくても構わないでしょう。
install-package Microsoft.Hadoop.MapReduce install-package Microsoft.Hadoop.Hive install-package Microsoft.Hadoop.WebClient install-package Microsoft.Hadoop.Avro
Mapper
Mapperは、MapperBaseクラスを継承し、Mapメソッドをオーバーライドします。ビッグデータ(笑)が適宜分割されて投げられますので、ここではライン毎にワード分割をし、それらをキーバリュー形式でコンテキストオブジェクトに設定します。ここでは、キーをワード、バリューには適当に、"1"を設定しておきます。
public class Mapper : MapperBase { private readonly char[] _delimiterChars = { ' ', ',', '.', ':', ';', '\'', '\t' }; public override void Map(string inputLine, MapperContext context) { var words = inputLine.Split(_delimiterChars); foreach (var word in words) { if (!string.IsNullOrEmpty(word)) { context.EmitKeyValue(word, "1"); } } } }
Reducer
後処理となるReducerは、ReducerCombineBaseクラスを継承し、Reduceメソッドをオーボーライドします。キーとバリューが渡されます。Mapperでは、ワードカウント毎に、"1"を足していたので、その数を数えればワードをカウントできるということです。ワードをキーに、カウント数をバリューに設定します。
public class Reducer : ReducerCombinerBase { public override void Reduce(string key, IEnumerable<string> values, ReducerCombinerContext context) { context.EmitKeyValue(key, values.Count().ToString()); } }
ローカル実行
StreamingUnitクラスに、Mapper、Reducerを指定し、Executeメソッドを呼び出します。引数は、ワードカウントするファイルを一行ずつ読み込んだ配列です。
string name = @"hoge.txt"; StreamingUnitOutput outputData = StreamingUnit.Execute<Mapper, Reducer>(File.ReadAllLines(name)); foreach (var r in outputData.Result) { Console.WriteLine(r); } Console.WriteLine("Hit any key."); Console.ReadLine();
結果はStreamingUnitOutputオブジェクトが返ってくるので、とりあえず表示さしてみるとよいでしょう。
まとめ
StreamingUnit クラスを使うとお手軽に実行して、デバッグできたりするのでGJですね。