主要考察的是广播变量的使用:

1、将要广播的数据 IP 规则数据存放在HDFS上,(广播出去的内容一旦广播出去产就不能改变了,如果需要实时改变的规则,可以将规则放到Redis中)

2、在Spark中转成RDD,然后收集到Driver端,

3、把 IP 规则数据广播到Executor中。Driver端广播变量的引用是怎样跑到 Executor中的呢?  Task在Driver端生成的,广播变量的引用是伴随着Task被发送到Executor中的,广播变量的引用也被发送到Executor中,恰好指向HDFS

4、Executor执行分配到的 Task时,从Executor中获取 IP 规则数据做计算。

package com.rz.spark.base

import java.sql.{Connection, DriverManager, PreparedStatement}

import org.apache.spark.broadcast.Broadcast
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext} object IpLocation2 {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName(this.getClass.getSimpleName).setMaster("local[2]")
val sc = new SparkContext(conf) // 取到HDFS中的 ip规则
val rulesLine: RDD[String] = sc.textFile(args()) // 整理ip规则数据
val ipRulesRDD: RDD[(Long, Long, String)] = rulesLine.map(line => {
val fields = line.split("[|]")
val startNum = fields().toLong
val endNum = fields().toLong
val province = fields()
(startNum, endNum, province)
})
// 将分散在多个Executor中的部分IP规则数据收集到Driver端
val rulesInDriver: Array[(Long, Long, String)] = ipRulesRDD.collect() // 将Driver端的数据广播到Executor中
// 调用sc上的广播方法
// 广播变量的引用(还在Driver端中)
val broadcastRef: Broadcast[Array[(Long, Long, String)]] = sc.broadcast(rulesInDriver) // 创建RDD,读取访问日志
val accessLines: RDD[String] = sc.textFile(args()) // 整理数据
val provinceAndOne: RDD[(String, Int)] = accessLines.map(log => {
// 将log日志的第一行进行切分
val fields = log.split("[|]")
val ip = fields()
// 将ip转换成10进制
val ipNum = MyUtils.ip2Long(ip)
// 进行二分法查找,通过Driver端的引用获取到Executor中的广播变量
// (该函数中的代码是在Executor中被调用执行的,通过广播变量的引用,就可以拿到当前Executor中的广播的ip二人规则)
// Driver端广播变量的引用是怎样跑到 Executor中的呢?
// Task在Driver端生成的,广播变量的引用是伴随着Task被发送到Executor中的,广播变量的引用也被发送到Executor中,恰好指向HDFS
val rulesInExecutor: Array[(Long, Long, String)] = broadcastRef.value
// 查找
var province = "末知"
val index = MyUtils.binarySearch(rulesInExecutor, ipNum)
if (index != -) {
province = rulesInExecutor(index)._3
}
(province, )
})
// 聚合
val reduced: RDD[(String, Int)] = provinceAndOne.reduceByKey(_+_)
// 将结果打印
// val result = reduced.collect()
// println(result.toBuffer) // 将结果写入到MySQL中
// 一次拿一个分区的每一条数据
reduced.foreachPartition(it=>{
val conn: Connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/bigdata?characterEncoding=utf-8","root","root")
val pstm: PreparedStatement = conn.prepareStatement("insert into access_log values(?,?)") it.foreach(tp=>{
pstm.setString(, tp._1)
pstm.setInt(,tp._2)
pstm.executeUpdate()
})
pstm.close()
conn.close()
}) sc.stop()
}
}

工具类

package com.rz.spark.base

import java.sql
import java.sql.{DriverManager, PreparedStatement} import scala.io.{BufferedSource, Source} object MyUtils { def ip2Long(ip: String): Long = {
val fragments = ip.split("[.]")
var ipNum = 0L
for (i <- until fragments.length){
ipNum = fragments(i).toLong | ipNum << 8L
}
ipNum
} def readRules(path: String): Array[(Long, Long, String)] = {
//读取ip规则
val bf: BufferedSource = Source.fromFile(path)
val lines: Iterator[String] = bf.getLines()
//对ip规则进行整理,并放入到内存
val rules: Array[(Long, Long, String)] = lines.map(line => {
val fileds = line.split("[|]")
val startNum = fileds().toLong
val endNum = fileds().toLong
val province = fileds()
(startNum, endNum, province)
}).toArray
rules
} def binarySearch(lines: Array[(Long, Long, String)], ip: Long) : Int = {
var low =
var high = lines.length -
while (low <= high) {
val middle = (low + high) /
if ((ip >= lines(middle)._1) && (ip <= lines(middle)._2))
return middle
if (ip < lines(middle)._1)
high = middle -
else {
low = middle +
}
}
-
} def data2MySQL(it: Iterator[(String, Int)]): Unit = {
//一个迭代器代表一个分区,分区中有多条数据
//先获得一个JDBC连接
val conn: sql.Connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/bigdata?characterEncoding=UTF-8", "root", "")
//将数据通过Connection写入到数据库
val pstm: PreparedStatement = conn.prepareStatement("INSERT INTO access_log VALUES (?, ?)")
//将分区中的数据一条一条写入到MySQL中
it.foreach(tp => {
pstm.setString(, tp._1)
pstm.setInt(, tp._2)
pstm.executeUpdate()
})
//将分区中的数据全部写完之后,在关闭连接
if(pstm != null) {
pstm.close()
}
if (conn != null) {
conn.close()
}
}
}

pom文件

<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<scala.version>2.11.</scala.version>
<spark.version>2.2.</spark.version>
<hadoop.version>2.6.</hadoop.version>
<encoding>UTF-</encoding>
</properties> <dependencies>
<!-- 导入scala的依赖 -->
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
</dependency> <!-- 导入spark的依赖 -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.</artifactId>
<version>${spark.version}</version>
</dependency> <!-- 指定hadoop-client API的版本 -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>${hadoop.version}</version>
</dependency> </dependencies> <build>
<pluginManagement>
<plugins>
<!-- 编译scala的插件 -->
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.2.</version>
</plugin>
<!-- 编译java的插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<executions>
<execution>
<id>scala-compile-first</id>
<phase>process-resources</phase>
<goals>
<goal>add-source</goal>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>scala-test-compile</id>
<phase>process-test-resources</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin> <!-- 打jar插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

最新文章

  1. Java中六大时间类的使用和区别
  2. 在ionic/cordova中使用百度地图插件
  3. 为opencv贡献代码
  4. python数字图像处理(3):图像像素的访问与裁剪
  5. Oracle-记录学习
  6. Java 7 中 NIO.2 的使用——第二节 元数据文件的属性
  7. 我来说说MVC过滤器
  8. C#类方法声明where的用法
  9. iOS纯代码工程手动快速适配
  10. js、jQuery实现2048小游戏
  11. Python——Web.py詳解
  12. Dynamics CRM 日常使用JS整理(二)
  13. Vue/Egg大型项目开发(一)搭建项目
  14. Coursera, Deep Learning 1, Neural Networks and Deep Learning - week2, Neural Networks Basics
  15. ElasticSearch入门简介
  16. 使用thinkphp框架实现Excel导入数据库
  17. DSO windowed optimization 代码 (1)
  18. #7 //[CQOI2014]和谐矩阵
  19. 推荐一个 .Net Core 的 Redis 库
  20. 代码:PC HTML——图片列表

热门文章

  1. python 三行代码实现快速排序
  2. django博客项目1.环境搭建
  3. Springboot入门-配置异常页面
  4. HDU1158:Employment Planning(线性dp)
  5. python安装virtualenv
  6. 【算法题12 解码方法decode way】
  7. Hadoop的分布式架构改进与应用
  8. 安卓ios app自动化测试用例模板
  9. js验证真实姓名
  10. spring和spirngmvc整合