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

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

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

DateObserved (in YYYYMMDD format)
DateReported (in YYYYMMDD format)
Location
UFO Type
Duration
Description

在我们的工作中,我们将统计不明飞行物的年份和形状。 在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时的早期文章中将介绍如何执行此操作。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值