概述

\\

Node.js是一套JavaScript框架,其核心诉求在于利用非阻塞I/O以及异步式事件驱动处理模型实现服务器端应用程序的高性能运行。

\\

当客户需要处理规模庞大且复杂性较高的数据时,Node.js能够提供一套以原生方式支持JSON数据结构的运行时环境。Python及Ruby等编程语言都拥有面向JSON数据的优秀支持能力,但Node.js在处理包含列表及数组的结构时显得尤为得心应手。Node.js还提供一套高性能且具备可扩展能力的备用方案,能够以原生方式将JSON数据作为对象加以处理。目前大家已经可以获得专门针对Node.js的AWS SDK(http://aws.amazon.com/sdkfornodejs),其允许我们将Node.js应用程序与AWS服务加以紧密整合。

\\

在今天的文章中,大家将了解到如何在Amazon Elastic MapReduce(简称Amazon EMR)当中安装Node.js、如何构建一款Node.js应用程序并将其与Hadoop Streaming并发处理架构相整合、外加如何在AWS之上部署并运行我们的Node.js MapReduce应用程序。要了解更多与Amazon EMR以及Hive项目相关之细节信息,请大家点击此处查看专题教程。

\\

本文假定大家已经熟知与Hadoop、Hive以及Amazon EMR相关的专业知识。

\\

用例

\\

在本文当中,我们将使用来自Twitter的数据,这部分数据中包含由推文、转发、回复以及直发信息所构成的复杂信息体系。每个文件中都包含有单一Twitter事务数据块,我们需要将其内容写入至Amazon Simple Storage Service(简称Amazon S3)并随时加以读取。我们希望针对Hive的实际需求对数据进行转换,旨在对转发率、每秒推文数量以及每用户直发信息数量等指标进行汇总。

\\

样本输入数据

\\

我们的数据表现出一套由大量Twitter用户所构成的复杂交互图谱,其中包括推文转发与回复内容,如下图所示:

\\

\\

为了进行数据发现,我们可以利用Hive配合JsonSerde(可参看http://aws.amazon.com/articles/2854)对数据进行调查。不过由于这套图谱非常复杂而且存在自我指涉,因此大部分Hive JsonSerde无法将这部分数据显示为表格。能够在Node.js中进行数据处理,我们能够更轻松地利用简单语法实现数据图谱导航。

\\

安装Node.js

\\

我们可以利用以下bootstrap操作将Node.js安装在Amazon EMR集群当中:

\\

\---bootstrap-actions Path=s3://github-emr-bootstrap-actions/node/install-nodejs.sh,Name=InstallNode.js

\\

(如果大家此前从未接触过bootstrap操作,请点击此处查阅Amazon EMR提供的说明文档。)

\\

编写MapReduce代码

\\

现在Node.js已经被安装在Amazon EMR集群之上,而Hadoop Streaming也得到正确配置,接下来我们需要运行自己的Node.js应用程序以完成映射与归约操作。利用Hadoop Streaming处理架构,我们能够为流任务指定所需要使用的映射与归约代码。

\\

与其它Hadoop Streaming兼容语言一样,我们必须从Amazon S3数据存储或者HDFS文件系统当中利用标准输入(即stdin)方式实现数据读取。在Node.js当中,stdin能够利用处理全局对象的方式获得可访问能力(参见http://nodejs.org/api/process.html)。这就使我们得以访问多种控制机制,进而通过管理输入与输出数据流对数据进行读取与写入,例如process.stdin与process.stdout。

\\

我们的MapReduce程度必须执行五项主要函数以实现从Hadoop Streaming以及输出结果中读取数据。

\\

配置标准输入

\\

在默认情况下,process.stdin输入通道会处于暂停状态,且不触发任何事件。在将其启用之前,我们必须首先配置所需的字符集编码。对于非多字节字符集而言,我们可以使用UTF-8。因此,我们映射或者归约方案的主体流程应该从这里开始:

\\

\process.stdin.setEncoding('utf8'); 

\\

或者,我们也可以使用UTF-16实现多字节支持。在此之后,我们必须启用stdin对事件进行恢复以及触发:

\\

\process.stdin.resume(); 

\\

处理来自STDIN的输入内容

\\

当我们的Node.js应用程序使用该stdin.data事件时,process.stdin通道会就此发出通知——stdin.data事件会在一定数量的数据可用于读取时被触发。我们的Node.js应用程序必须对这部分数据进行缓存处理以备后续使用,因为事件所提供的每一个数据块可能都仅仅属于标准输入内容中全部可用数据的一小部分。由于我们此前通过配置让Hadoop Streaming使用非分割式FileInputFormat,因此我们会在单一映射器中获取到完整的JSON数据,并能够将该文件作为整体加以处理。有鉴于此,我们可以通过以下代码将数据块缓存于data事件当中:

\\

\var line = ‘’;\// fires on every block of data read from stdin\process.stdin.on('data', function(chunk) {\    // chunk and emit on newline\    lines = chunk.split(\"\\")\     \    if (lines.length \u0026gt; 0) {\        // append the first chunk to the existing buffer\        line += lines[0]\         \        if (lines.length \u0026gt; 1) {\            // emit the current buffer\            emitter.emit(lineEvent,line);\ \            // go through the rest of the lines and emit them, buffering the last\            for (i=1;i\u0026lt;lines.length; i++) {\                if (i\u0026lt;lines.length) {\                    emitter.emit(lineEvent,lines[i]);\                } else {\                    line = lines[i];\                }\            }\        }\    }\});

\\

上述操作会将全部数据块附加至行变量处,并在每一次发现新的换行符时触发“lineReady”事件。

\\

处理完整的stdin数据

\\

在全部来自stdin的数据被读取完成后,该流程将触发stdin.end事件。我们已经将全部数据收集到行缓冲区当中,这样我们只需要利用以下代码刷新最后一行数据:

\\

\// fires when stdin is completed being read\process.stdin.on('end', function() {\    emitter.emit(lineEvent,line);\});

\\

每当新的内容行准备就绪时,我们都将利用以下代码将其排序至一个JSON对象当中:

\\

\try {\    obj = JSON.parse(line);\} catch (err) {\    process.stderr.write('Error Processing Line ' + line + '\');\    process.stderr.write(err);\    return;\}

\\

我们可以选择把复杂的JSON数据简化为普通输出结果,以供Hive JsonSerde进行加载,或者选择生成CSV或者XML数据来代替。

\\

以Hadoop兼容格式写入数据

\\

对于某些特定的MapReduce操作类型,我们需要确保其归约器能够获取到归属于特定类型的全部数据。为了实现这一目标,我们必须指定一个键值,并保证Hadoop在调用该归约器之前会首先对输出结果进行分类。在进行文本内容处理时,我们会利用由\\t标签开头的字符串来表示这个值。

\\

要执行存储或者移除方面的数据写入操作,我们需要利用process.stdout.write()向stdout实施写入。

\\

制作可执行文件

\\

Amazon EMR利用命令行语法调用的方式运行映射器与归约器,例如“./mapper.js”。因此,我们需要确保我们所构建的Node.js模块能够通过命令行实现调用。为达成这一目标,我们在映射器或者归约器文件的开头处添加一条标准“shebang”命令,这样它就能调用Node.js并运行脚本内容:

\\

\#!/usr/bin/env node 

\\

接下来,大家可以通过命令行调用的方式测试自己的映射器代码了(以下示例假定代码位于名为Mapper.js的文件当中):

\\

\./mapper.js \u0026lt; input-file-path 

\\

部署与运行

\\

在编写了自己的映射器与归约器之后,接下来我们将其传输至Amazon S3当中,而后利用Amazon EMR针对部分输入数据运行MapReduce。

\\

以下示例讲解了如何利用Amazon EMR命令行执行各个步骤(参见http://aws.amazon.com/developertools/2264),不过大家也可以在Amazon EMR控制台(参见console.aws.amazon.com/elasticmapreduce)或者Amazon EMR API(参见http://docs.aws.amazon.com/ElasticMapReduce/latest/API/Welcome.html?r=8857)中利用命令实现同样的效果。我们将展示如何以自动方式利用AWS命令行工具运行该应用程序,但大家完全可以使用AWS Web Console或者AWS Data Pipeline完成同样的工作。我们可以使用--create-cluster命令启动一套新的Amazon EMR集群,同时利用以下代码启动该集群并捃行我们的Node.js bootstrap操作:

\\

\aws emr create-cluster --ami-version 3.3.1 --enable-debugging --visible-to-all-users\ --name MyNodeJsMapReduceCluster --instance-groups  InstanceCount=2,InstanceGroupType=CORE,InstanceType=m3.xlarge \InstanceCount=1,InstanceGroupType=MASTER,InstanceType=m3.xlarge --\no-auto-terminate --enable-debugging --log-uri s3:///logs --\bootstrap-actions Path=s3://github-emr-bootstrap-\actions/node/install-nodejs.sh,Name=InstallNode.js --ec2-attributes \KeyName=\u0026lt;my key pair\u0026gt; 

\\

这样我们就创建了一套始终启用的集群,其中包含配备3.3.1 AMI、双核心节点以及一个主节点,全部采用m3.xlarge实例类型。以上代码同时为指定存储桶设定了调试与日志记录机制,并通过bootstrap操作完成了Node.js的启动时安装。除此之外,代码中还使用了Amazon EC2密钥对,从而将SSH安全机制引入该Hadoop集群。

\\

接下来,我们将添加Hadoop Streaming流程,旨在处理自己的输入数据。在以下代码中,大家需要把\u0026lt;my cluster ID\u0026gt;替换为自己的实际集群ID:

\\

\aws emr add-steps --cluster-id \u0026lt;my cluster ID\u0026gt; \--steps Name=NodeJSStreamProcess,Type=Streaming

\\

我们通过创建一套文件系统参考(利用—files参数)添加自己的映射器与归约器JavaScript文件,而后将该基础文件名通过-mapper与-reducer进行引用:

\\

\Args=--files,\"s3://\u0026lt;path to mapper\u0026gt;/mapper.js\\,s3://\u0026lt;path to \reducer\u0026gt;/reducer.js\

如何将Node.js Streaming MapReduce引入Amazon EMR相关推荐

  1. 不再为 Node.js 模块自动引入 Polyfills

    在早期,webpack 的目的是为了让大多数的 Node.js 模块运行在浏览器中,但如今模块的格局已经发生了变化,现在许多模块主要是为前端而编写.webpack <= 4 的版本中提供了许多 ...

  2. node.js使用手册_权威的Node.js手册

    node.js使用手册 Note: you can get a PDF, ePub, or Mobi version of this handbook for easier reference, or ...

  3. Node.js 系列:构建原生 Node.js 应用

    原生 Node.js 应用 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境 Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效 Nod ...

  4. 了不起的Node.js: 将JavaScript进行到底

    了不起的Node.js: 将JavaScript进行到底(Web开发首选,实时,跨多服务器,高并发) Guillermo Rauch 编 赵静 译 ISBN 978-7-121-21769-2 201 ...

  5. 了不起的Node.js: 将JavaScript进行到底(Web开发首选,实时,跨多服务器,高并发)...

    了不起的Node.js: 将JavaScript进行到底(Web开发首选,实时,跨多服务器,高并发) Guillermo Rauch 编   赵静 译 ISBN 978-7-121-21769-2 2 ...

  6. 2021了,真的不要再说 Node.js 是一门编程语言了

    Node.js 全栈基础 1. Node.js 光速入门 1.1 Node.js 概述 Node.js 是什么 Node.js 不是一门编程语言,它是一个执行 JavaScript 代码的工具.工具是 ...

  7. JavaScript教程9 - Node.js

    Node.js 安装Node.js https://nodejs.org/ npm npm其实是Node.js的包管理工具(package manager). 命令行模式 执行node hello.j ...

  8. Node.js开发入门—语音合成示例

    出于项目需要,搞了一个语音合成(TTS)的小示例,使用的是OKVoice. 我想在PC上测试,OKVoice的快速接入API可以实现我的目的,文档在这里:http://dev.okvoice.com/ ...

  9. 45天带你玩转Node(第一天)初探Node.js

    45天带你玩转Node 粉丝要求博主系统的写一篇关于Node.js的学习资料,但其实我们的Node.js知识点并不少,所以博主为大家搭建了一个专栏,为了方便大家系统的学习Node.js,大家记得订阅哦 ...

最新文章

  1. 今年1篇Science,2篇NBT,2篇MP,1篇PNAS等11篇文章,遗传发育所白洋组在植物微生物组取得系列进展!
  2. 运维监控系统——Zabbix简介
  3. php判断单选框是否被选中,jquery怎么判断radio是否选中
  4. python修改文件内容最后一行_关于python:如何修改文件的最后一行?
  5. 自动装箱自动拆箱java,自动装箱?拆箱?==问题?详解java面试常见的一个问题...
  6. java自适应table_Java 设置Word中的表格自适应的3种方式
  7. 推荐系统--矩阵分解(4)
  8. ES6学习(十一)—Class 的基本语法和继承
  9. 使用VS开发基于Oracle程序的严重问题
  10. 科技文献检索与计算机应用试卷,科技文献检索试卷
  11. 智慧路灯解决方案-最新全套文件
  12. 3dmax渲染计算机内存不足怎么办,3DMax渲染 提示内存不足怎么办
  13. 计算机网络思维导图图片
  14. 都2022年了 究竟什么叫旗舰手机?
  15. makefile编写知识小结
  16. 计算机考研复试面试常问问题 数据库篇
  17. eas报错日记_eas日志收集方式
  18. 【洛谷 P5550】 Chino的数列【矩阵乘法】
  19. 简单易用,基于js或vue项目实现一次批量文件下载功能
  20. 产品经理的常见面试问题

热门文章

  1. JSON与MAP之间的转换
  2. oracle 网络访问配置tnsnames.ora文件的路径
  3. Exception in thread main java.lang.NoClassDefFoundError解决了
  4. 【剑指offer】5.二叉树的镜像和打印
  5. 北京市强化电信用户信息安全保护
  6. 【Rayeager PX2分享】OpenCV入门之图像显示
  7. Linux 命令(14)—— df 命令
  8. n 个骰子点数和及各自出现的概率
  9. 当子查询内存在ORDER BY 字句时查询会报错
  10. 【bzoj3174】[Tjoi2013]拯救小矮人 贪心+dp