把上一次编译后的包解压。
本地启动spark,可以在4040看到sparkUI
spark默认程序名字
调用spark-submit,默认名字Spark shell,$@相当于获取用户输入的模式(比如local)
"${SPARK_HOME}"/bin/spark-submit --class org.apache.spark.repl.Main --name "Spark shell" "$@"
调用了spark-class,传给spark-shell的参数被继承下来了
exec "${SPARK_HOME}"/bin/spark-class org.apache.spark.deploy.SparkSubmit "$@"
加载spark-env,环境参数
. "${SPARK_HOME}"/bin/load-spark-env.sh
import org.apache.spark.{SparkConf, SparkContext}
object Spark02 {
def main(args: Array[String]): Unit = {
val sparkConf=new SparkConf()
//在spark-shell运行的时候再指定,这里的优先级要比在shell里更高,appname可以默认
//shell里有内置
//.setMaster("local[2]").setAppName("Spark02")
val sc =new SparkContext(sparkConf)
//创建rdd方法1,第一个参数是数组,第二个参数是默认切片
// val rdd = sc.parallelize(Array(1,2,3,4,5))
//collect把rdd里所有元素以数组方式返回
// rdd.collect().foreach(println)
//文件数据创建rdd,要保证每个节点下面相同路径有相同文件,返回的是一个字符串的rdd
//第一个参数路径,第二个参数是最小分区数,分区数会影响到最终存储时生成文件的个数
//读本地文件,建议加file声明
//foreach是个action, 遇到action,就是一个job
val rdd = sc.textFile("file:///E:/新建文件夹/ruoze wenjian shiping/asd.txt")
rdd.collect().foreach(println)
//注意top和collect都会内存加载所有数据,很大的数据不能直接collect,返回的是所有数据的数组,不然driver会挂掉,可以用take
rdd.top(3)
//默认升序,第一个参数是函数,第二个参数是排序方法
rdd.sortBy(x=>x)
//存储文件
rdd.saveAsTextFile("file:///E:/新建文件夹/ruoze wenjian shiping/asd.txt")
}
注意,虽然说一个action,一个job但是要注意action算子输入的是不是rdd,如果不是就不算。
比如下面用了两个action,但是只有1个job,因为collect的结果是array。
scala> rdd1.collect().foreach(x=>x)
假如集群有三台机器,三台机器都得有这个文件
scala> sc.textFile("hdfs://hadoop000:9000//g5/asd.txt")
textFile也可以读文件夹和压缩文件
scala> sc.wholeTextFiles("hdfs://hadoop000:9000//g5/asd.txt").collect
wholeTextFiles返回key-value形式,key是文件名,value是它包含的所有内容
默认情况下,文件存储的每个block(hdfs默认128M)都会被创建一个partition。你可以申请更多的partition。要注意,partition数量不要比block更少,不然每个task要处理的数据量会更多,一个文件有可能会被拆成一个很大的和一个很小的文件。
transformations,rdd之间转换相当于作用transformation
rdda ?> rddb map filter
actions 返回一个结果到driver端,可以理解为客户端
transformation不会被立即执行,当action发生才会执行
import java.net.URI
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs.{FileSystem, Path}
import org.apache.spark.{SparkConf, SparkContext}
/**
* 这里我们是要把程序提交到spark上执行,
* 所以读取文件和写文件应当由传入参数指定而不是写死
* 输入:args(0)
* 输出:args(1)
*/
object LogApp {
def main(args: Array[String]): Unit = {
val sparkConf=new SparkConf()
//在spark-shell运行的时候再指定,这里的优先级要比在shell里更高,appname
//shell里有内置
//.setMaster("local[2]").setAppName("Spark02")
val sc =new SparkContext(sparkConf)
//写到hdfs要检测文件是否存在,存在要删掉,不然报错
//val configuration = new Configuration
val uri = new URI("hdfs://192.168.137.190:9000" )
val fileSystem = FileSystem.get(uri,sc.hadoopConfiguration,"hadoop")
if (fileSystem.exists(new Path(args(1)))){
fileSystem.delete(new Path(args(1)),true)
}
//统计每个域名的流量和1
// val lines = sc.textFile("file:///F:/ruozedata_workplace/g5-spark/generatefile")
// lines.map(x=> {
// val temp=x.split("\t")
// //域名前面是hattps//,把后面的截取出来,然后域名后面的用户名以/分割
// //原数据有的流量会多一个-
// //注意流量要转为Long类型,不然字符串是拼接的
// (temp(0).substring(8).split("/")(0),temp(2).replace("-","").toLong)
// }).reduceByKey(_+_).collect().foreach(println)
//统计每个域名流量和工业写法2
val lines = sc.textFile(args(0))
lines.map(x =>{
val temp=x.split("\t")
val domain = temp(0).substring(8).split("/")(0)
//这里考虑到如果流量还有不标准的数据,会报错出问题,这里先给个默认值
var response = 0L
//出错就默认值输出错误咯
try{
response = temp(2).replace("-","").toLong
} catch {
case exception: Exception =>println("......")
}
(domain,response)
}).reduceByKey(_+_).collect().foreach(println)
//访问次数最多的url,排序
//sortBy默认是升序排列
//val lines = sc.textFile(args(0))
lines.map(x=>{
val temp = x.split("\t")
val url = temp(0)
var response = 0L
try{
response=temp(2).replace("-","").toLong
}catch {
case exception: Exception => println("!!!!!")
}
(temp(0),response)
//注意take后面加不了save,因为他的返回值是数组,saveastextfile要输入rdd的算子
//sortby输入是什么类型,输出就是什么类型
}).reduceByKey(_+_).sortBy(_._2,false).saveAsTextFile(args(1))//take(3)//.collect()
//求每个域名下访问次数最多的URL 排序
val ac = lines.map(x=>{
val temp = x.split("\t")
val url = temp(0)
val domain =temp(0).substring(8).split("/")(0)
var response = 0L
try {
response = temp(2).replace("-","").toLong
}catch {
case exception: Exception=>println("fuckfuckfuck")
}
((domain,url),response)
}).reduceByKey(_+_)
//(www.baidu.com,CompactBuffer(((www.baidu.com,https://www.baidu.com/),11)))
val bc = ac.groupBy(_._1._1)//.foreach(println)
var dom = bc.map(x=>{
//注意这里的sortby不是spark的sortby,是scala的,因为输入不是rdd
val top2 = x._2.toList.sortBy(x => x._2).reverse.take(1)
top2
})
dom.foreach(x=>{
println(x)
})
sc.stop()
}
}
注意中文文件报错,要改为英文
生成的jar包会在工程目录下的target文件夹下
将代码放到一个shell文件里,注意\后面不要有空格
class是程序入口的主类,name是程序名字,后面是跑哪个程序
两个路径分别是程序传入的参数,一个是从哪里取,一个是输出到哪里
$SPARK_HOME/bin/spark-submit \
--master local[2] \
--class com.ruozedata.bigdata.core02.LogApp \
--name LogServerApp \
/home/hadoop/data/g5-spark-1.0.jar \
hdfs://hadoop000:9000/g5/generatefile hdfs://hadoop000:9000/g5/
给代码文件加个可执行的权限
chmod +x ....
然后运行即可