Hadoop for .NET Developers(十三):实施更复杂的MapReduce作业

来源:互联网 发布:淘宝一千零一夜男主角 编辑:程序博客网 时间:2024/06/06 05:15

在我们的第一个MapReduce练习中,我们使用针对本地开发集群的.NET SDK实现了一个有目的的简单MapReduce作业。 在本练习中,我们将使用相同的SDK实现稍微更复杂的MapReduce作业,但不使用我们的基于Azure的远程群集。

对于本练习,我们将使用ufo_awesome.tsv数据文件中显示的UFO Sightings数据库。 该文件由制表符分隔的数据行组成,包含以下字段:

DateObserved (in YYYYMMDD format)DateReported (in YYYYMMDD format)LocationUFO TypeDurationDescription

在我们的工作中,我们将统计不明飞行物的年份和形状。 在map函数中,我们将简单解析输入行,提取年份和形状。 年将作为关键,在reduce功能中,我们将使用LINQ计算形状的数量,因为LINQ可通过.NET框架提供给我们。 reduce函数的输出的年份将作为键,形状和计数(由制表符分隔)作为值。

开始,我们将像以前一样执行以下步骤。 但是,请注意在第二步中添加Windows Azure Storage 包。 这个软件包使我们能够在Azure中使用HDInsight:

1.启动Visual Studio并打开一个新的C#控制台应用程序项目。

2.使用NuGet将以下软件包添加到项目中:

  • Microsoft .NET Map Reduce API for Hadoop
  • Microsoft ASP.NET Web API
  • Windows Azure Storage

3.如果Program.cs文件尚未打开,请打开它。

4.将以下指令添加到程序中:

using Microsoft.Hadoop;using Microsoft.Hadoop.MapReduce;using Microsoft.Hadoop.WebClient.WebHCatClient;

一切都到位,写一个Mapper类如下:

using Microsoft.Hadoop.MapReduce;using System;using System.Collections.Generic;public class MyUfoMapper : MapperBase {    public override void Map(string inputLine, MapperContext context)    {        // tabs 分隔行        string[] inputValues = inputLine.Split('t');        string dateObserved = inputValues[0].Trim();        string ufoType = inputValues[3].Trim();       //年份 观察       string yearObserved = "unknown";       if (dateObserved.Length >= 4)           yearObserved = dateObserved.Substring(0, 4);        //获取ufo类型       if (String.IsNullOrEmpty(ufoType.Trim())) ufoType = "uknown";       //发送output       context.EmitKeyValue(yearObserved, ufoType);   }}

map函数的逻辑是非常不言自明的。 制表符分隔的输入行在选项卡上进行解析。 DateObserved和UFO Type(shape)字段被访问,解析和清理。 DateObserved字段的年份作为键发出,UFO类型作为值发出。

现在我们将编写一个Reducer类:

using Microsoft.Hadoop.MapReduce;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace MyApp{    public class MyUfoReducer : ReducerCombinerBase    {        public override void Reduce(string key, IEnumerable<string> values, ReducerCombinerContext context)        {            //按类型计数            var query = from v in values                        group v by v into g                        select new                        {                            ufoType = g.Key,                            sightings = g.Count()                        };            //将结果发送到output            foreach (var item in query)            {                context.EmitKeyValue(key, item.ufoType + "t" + item.sightings );            }        }    }}

reduce功能的逻辑更多地涉及到使用LINQ。使用此功能,我们查询UFO类型值的传入集合,按类似值分组,并通过UFO类型提取计数。 (我们可以通过各种各样的方式完成这个任务,但是LINQ可以通过.NET框架提供给我们,我们也可以利用它来使编码功能尽可能简单。)reducer函数然后发出年密钥 和UFO类型并计数值。

通过定义Mapper和Reducer类,我们可以创建一个MapReduce作业。 为此,我们将定义一个配置,连接到Hadoop,并使用我们的配置执行我们的工作,就像我们以前一样。 也就是说,我们与Hadoop的联系看起来有很大的不同:

static void Main(string[] args){            //连接到集群            //Uri myUri = new Uri("http://localhost:50070");            //string userName = "brysmi";            //string hadoopUser = "hadoop";            //string passWord = "my password";            //string storageAccount = "brysmi.blob.core.windows.net";            //string storageKey = "my storage key";            //string container = "mycontainer";            //IHadoop myCluster = Hadoop.Connect(            //     myUri, userName, hadoopUser, passWord,            //     storageAccount, storageKey, container, false            //     );            IHadoop myCluster = Hadoop.Connect();            //配置作业            HadoopJobConfiguration myConfig = new HadoopJobConfiguration();            myConfig.InputPath = "/demo/ufo/in";            myConfig.OutputFolder = "/demo/ufo/out";            //执行作业            MapReduceResult jobResult =myCluster.MapReduceJob.Execute<MyUfoMapper, MyUfoReducer>(myConfig);            //将作业结果写入控制台            int exitCode = jobResult.Info.ExitCode;            string exitStatus = "Failure";            if (exitCode == 0) exitStatus = "Success";            exitStatus = exitCode + " (" + exitStatus + ")";            Console.WriteLine();            Console.Write("Exit Code = " + exitStatus);            Console.Read();}

如果您不清楚在哪里获取连接到Azure群集所需的值,请参阅早期帖子中的设置和数据加载练习。

重要

在我们在Visual Studio中执行我们的工作之前,我们需要做最后一件事:将项目的目标(CPU)平台设置为x64。 默认情况下,Visual Studio将尝试针对x86架构运行程序,这将导致在针对Azure群集中的HDInsight执行时出错:

1.从项目菜单中,选择<项目名称>属性项目。

2.单击“属性”页面左侧的“构建”项目。

3.在页面右上角的“平台”下拉列表中,将值更改为x64

这里写图片描述

现在设置了目标平台,运行应用程序。 作业成功完成后,您可以连接到Azure群集的名称节点或底层存储,以查看输出文件 /demo/ufo/out/part-00000的内容。 在将数据加载到Azure时的早期文章中将介绍如何执行此操作。

原创粉丝点击