IOT架构探索(一) Spark+Mosquitto实现MQTT消息的接收及大数据处理

0.整体思路

Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎。Spark使用Scala语言进行实现,它是一种面向对象、函数式编程语言,能够像操作本地集合对象一样轻松地操作分布式数据集,具有运行速度快、易用性好、通用性强以及随处运行等特点,适合大多数批处理工作,并已成为大数据时代企业大数据处理优选技术。

在物联网时代,越来越多的设备将通过互联网连接到公有云或私有云,实时上报设备的状态和业务数据,产生海量规模的原始数据。对大数据的实时处理,Spark是这一场景下的行家里手。但针对于海量的设备连接及与设备的通信并非Spark的强项。因此我们需要寻找其他中间件产品解决这些问题。由于设备采用的通信协议种类繁多(MQTT、CoAP 、HTTP、XMPP、SoAP),因此我们目前聚焦于应用最为广泛的MQTT协议的方案设计。

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(Publish/Subscribe)模式的轻量级通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布,目前最新版本为v3.1.1。MQTT最大的优点在于可以以极少的代码和有限的带宽,为远程设备提供实时可靠的消息服务。做为一种低开销、低带宽占用的即时通讯协议,MQTT在物联网、小型设备、移动应用等方面有广泛的应用。
 

MQTT的消息代理(MQTT Broker)很多,经过对开源产品的调研,Mosquitto从成熟度和性能上都十分出色,因此我们选择Mosquitto作为本方案的MQTT代理。

现在既然选定了通信协议,那就要面对Spark如何订阅并处理MQTT消息的问题。很遗憾,原生的Spark并不支持将MQTT作为数据的数据输入流。但是,Apache上有一个专门针对Spark等大数据中间件研发扩展/插件的项目Apache Bahir提供了对于MQTT的支撑。至此我们便形成了Spark+Bahir+Mosquitto的整体设计思路。

 

 

1.安装Spark

在Apache Spark官网下载Spark(如果你不想单独安装Hadoop,则请下载已嵌入Hadoop组件的版本):

http://spark.apache.org/downloads.html

 

设置环境变量

HADOOP_HOME=d:\spark-2.1.1-bin-hadoop2.7

PATH=%PATH%;%HADOOP_HOME%\bin

以Administrator用户启动cmd命令窗口,执行命令:

spark-shell

即可启动spark交互窗口

 

查看web管理界面 

http://127.0.0.1:4040/jobs/

2.安装Mosquitto

在以下网址下载mosquitto,并根据引导安装

https://mosquitto.org/download/

 

3.安装MQTT客户端工具-mqttfx

如果初次接触MQTT,并希望能够通过一个专业的MQTT客户端发送消息给Mosquitto,mqttfx是你最好的选择。关于mqttfx的使用,请查阅网上相关文档,在此不再赘述。

官网地址:http://www.mqttfx.org/

下载地址:http://www.jensd.de/apps/mqttfx/

4.测试mosquitto可用性

a)启动mqttfx

b)在mqttfx中,创建配置文件,截图如下:

c)基于刚创建的配置文件连接Mosquitto

d)监听名称为“news”(这个可随意)的Topics

 

e)发送消息

f)查看接收结果

如果走到这一步,恭喜你的Mosquitto工作正常,可以继续深入探索Spark的部分了。

 

5.开发演示程序

一提到Spark,用过的人都知道总要拿单词统计这一经典案例说事儿,这里也要用这个例子做做文章。以下示例在Spark代码库中的代码JavaNetworkWordCount.java的基础上做了修改,使其能够支持接收并处理MQTT消息。

pom.xml依赖

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>io.suntrap</groupId>
	<artifactId>mqtt_test</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>mqtt_test</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<!-- https://mvnrepository.com/artifact/org.apache.spark/spark-streaming -->
		<dependency>
			<groupId>org.apache.spark</groupId>
			<artifactId>spark-streaming_2.12</artifactId>
			<version>2.4.3</version>
			<scope>provided</scope>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.apache.bahir/spark-streaming-mqtt -->
		<dependency>
			<groupId>org.apache.bahir</groupId>
			<artifactId>spark-streaming-mqtt_2.11</artifactId>
			<version>2.3.3</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
</project>

 

package io.suntrap.spark.mqtt.test;

import java.util.Arrays;
import java.util.regex.Pattern;

import scala.Tuple2;

import org.apache.spark.SparkConf;
import org.apache.spark.streaming.Durations;
import org.apache.spark.streaming.api.java.JavaDStream;
import org.apache.spark.streaming.api.java.JavaPairDStream;
import org.apache.spark.streaming.api.java.JavaReceiverInputDStream;
import org.apache.spark.streaming.api.java.JavaStreamingContext;
import org.apache.spark.streaming.mqtt.*;

public class JavaNetworkWordCount {
	 private static final Pattern SPACE = Pattern.compile(" ");

	  public static void main(String[] args) throws Exception {
		  
		String brokerUrl="tcp://127.0.0.1:1883";
		String topic="news";
		
	    SparkConf sparkConf = new SparkConf().setAppName("JavaNetworkWordCount").setMaster("local[2]");
	    JavaStreamingContext ssc = new JavaStreamingContext(sparkConf, Durations.seconds(1));
	    JavaReceiverInputDStream<String> lines = MQTTUtils.createStream(ssc, brokerUrl, topic);
	    JavaDStream<String> words = lines.flatMap(x -> Arrays.asList(SPACE.split(x)).iterator());
	    JavaPairDStream<String, Integer> wordCounts = words.mapToPair(s -> new Tuple2<>(s, 1))
	        .reduceByKey((i1, i2) -> i1 + i2);
	    wordCounts.print();
	    ssc.start();
	    ssc.awaitTermination();
	  }
}

 

6.运行并测试

 

在mqttfx上再次发送前面报文,演示程序侧将显示报文中各单词的统计结果:

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值