基本配置: http://www.cnblogs.com/huligong1234/p/4136331.html https://www.cnblogs.com/huligong1234/p/4137133.html 浏览器查看 浏览器打开 http://ubuntu-V01:50070/,会看到hdfs管理页面 浏览器打开 http://ubuntu-V01:8088/,会看到hadoop进程管理页面 浏览器打开 http://ubuntu-v01:8088/cluster 查看cluster情况 day06问题总结: 1/运行mr程序出错 connecting to resoucemanager retrying …. retrying ….. 原因是没有启动yarn或者启动失败 sudo date -s “2018-1-21 09:00:00” 2/初始化工作目录结构 hdfs namenode -format 只是初始化了namenode的工作目录 而datanode的工作目录是在datanode启动后自己初始化的 3/datanode不被namenode识别的问题 namenode在format初始化的时候会形成两个标识: blockPoolId: clusterId: 新的datanode加入时,会获取这两个标识作为自己工作目录中的标识 一旦namenode重新format后,namenode的身份标识已变,而datanode如果依然 持有原来的id,就不会被namenode识别 4/datanode下线后多久看到效果 datanode不是一下线就会被namenode认定为下线的,有一个超时时间 5/关于副本数量的问题 副本数由客户端的参数dfs.replication决定(优先级: conf.set > 自定义配置文件 > jar包中的hdfs-default.xml) _hadoop-dfs.jar > hdfs-site.xml > 代码中的 configuration(执行顺序,后来执行的会覆盖后面执行的。)_
Day07开始我们开始 4.1关于服务器HDFS内部的工作原理开始进行 研究 探讨。
离线计算机系统-目录 [课程大纲(HDFS详解).................................................................................................... 2](#_Toc439077207)
- HDFS前言…………………………………………………………………………………………………….. 3
- HDFS的概念和特性…………………………………………………………………………………………. 3
- HDFS的shell(命令行客户端)操作……………………………………………………………………….. 4
3.1 HDFS命令行客户端使用…………………………………………………………………………… 4 3.2命令行客户端支持的命令参数…………………………………………………………………… 4 3.2 常用命令参数介绍………………………………………………………………………………….. 5
4.1 概述:…………………………………………………………………………………………………. 8 4.2 HDFS写数据流程…………………………………………………………………………………….. 9 4.2.1 概述……………………………………………………………………………………………. 9 4.2.2 详细步骤图…………………………………………………………………………………… 9 4.2.3 详细步骤解析……………………………………………………………………………….. 9 4.3. HDFS读数据流程………………………………………………………………………………….. 10 4.3.1 概述………………………………………………………………………………………….. 10 4.3.2 详细步骤图:……………………………………………………………………………… 10 4.3.3 详细步骤解析……………………………………………………………………………… 10
5.1 概述…………………………………………………………………………………………………… 11 5.2元数据管理………………………………………………………………………………………….. 11 5.2.1 元数据存储机制…………………………………………………………………………… 11 5.2.2 元数据手动查看…………………………………………………………………………… 11 5.2.3 元数据的checkpoint……………………………………………………………………… 12
6.1 概述…………………………………………………………………………………………………… 13 6.2 观察验证DATANODE功能………………………………………………………………………. 13
7.1 搭建开发环境………………………………………………………………………………………. 13 7.2 获取api中的客户端对象……………………………………………………………………….. 14 7.3 DistributedFileSystem实例对象所具备的方法………………………………………………. 14 7.4 HDFS客户端操作数据代码示例:……………………………………………………………… 15 7.4.1 文件的增删改查…………………………………………………………………………… 15 7.4.2 通过流的方式访问hdfs…………………………………………………………………. 18
课程大纲(HDFS详解)
Hadoop HDFS
分布式文件系统DFS简介
HDFS的系统组成介绍
HDFS的组成部分详解
副本存放策略及路由规则
命令行接口
Java接口
客户端与HDFS的数据流讲解
学习目标: 掌握hdfs的shell操作 掌握hdfs的java api操作 理解hdfs的工作原理
******HDFS基本概念篇******
1. HDFS前言
- 设计思想
分而治之:将大文件、大批量文件,分布式存放在大量服务器上,以便于采取分而治之的方式对海量数据进行运算分析;
- 在大数据系统中作用:
为各类分布式运算框架(如:mapreduce,spark,tez,……)提供数据存储服务
- 重点概念:文件切块,副本存放,元数据
2. HDFS的概念和特性
首先,它是一个文件系统,用于存储文件,通过统一的命名空间——目录树来定位文件 其次,它是分布式的,由很多服务器联合起来实现其功能,集群中的服务器有各自的角色; 重要特性如下:
HDFS中的文件在物理上是分块存储(**block**),块的大小可以通过配置参数( dfs.blocksize)来规定,默认大小在x版本中是128M,老版本中是64M
HDFS文件系统会给客户端提供一个统一的抽象目录树,客户端通过路径来访问文件,形如:hdfs://namenode:port/dir-a/dir-b/dir-c/file.data
- 目录结构及文件分块信息(**元数据)**的管理由namenode节点承担
——namenode是HDFS集群主节点,负责维护整个hdfs文件系统的目录树,以及每一个路径(文件)所对应的block块信息(block的id,及所在的datanode服务器)
- 文件的各个block的存储管理由datanode节点承担
---- datanode是HDFS集群从节点,每一个block都可以在多个datanode上存储多个副本(副本数量也可以通过参数设置dfs.replication)
HDFS是设计成适应一次写入,多次读出的场景,且不支持文件的修改
_(__注:适合用来做数据分析,并不适合用来做网盘应用,因为,不便修改,延迟大,网络开销大,成本太高)_
******HDFS基本操作篇******
3. HDFS的shell(命令行客户端)操作
3.1 HDFS命令行客户端使用
HDFS提供shell命令行客户端,使用方法如下:
3.2 命令行客户端支持的命令参数
\[-appendToFile <localsrc> ... <dst>\] \[-cat \[-ignoreCrc\] <src> ...\] \[-checksum <src> ...\] \[-chgrp \[-R\] GROUP PATH...\] \[-chmod \[-R\] <MODE\[,MODE\]... | OCTALMODE> PATH...\] \[-chown \[-R\] \[OWNER\]\[:\[GROUP\]\] PATH...\] \[-copyFromLocal \[-f\] \[-p\] <localsrc> ... <dst>\] \[-copyToLocal \[-p\] \[-ignoreCrc\] \[-crc\] <src> ... <localdst>\] \[-count \[-q\] <path> ...\] \[-cp \[-f\] \[-p\] <src> ... <dst>\] \[-createSnapshot <snapshotDir> \[<snapshotName>\]\] \[-deleteSnapshot <snapshotDir> <snapshotName>\] \[-df \[-h\] \[<path> ...\]\] \[-du \[-s\] \[-h\] <path> ...\] \[-expunge\] \[-get \[-p\] \[-ignoreCrc\] \[-crc\] <src> ... <localdst>\] \[-getfacl \[-R\] <path>\] \[-getmerge \[-nl\] <src> <localdst>\] \[-help \[cmd ...\]\] \[-ls \[-d\] \[-h\] \[-R\] \[<path> ...\]\] \[-mkdir \[-p\] <path> ...\] \[-moveFromLocal <localsrc> ... <dst>\] \[-moveToLocal <src> <localdst>\] \[-mv <src> ... <dst>\] \[-put \[-f\] \[-p\] <localsrc> ... <dst>\] \[-renameSnapshot <snapshotDir> <oldName> <newName>\] \[-rm \[-f\] \[-r|-R\] \[-skipTrash\] <src> ...\] \[-rmdir \[--ignore-fail-on-non-empty\] <dir> ...\] \[-setfacl \[-R\] \[{-b|-k} {-m|-x <acl\_spec>} <path>\]|\[--set <acl\_spec> <path>\]\] \[-setrep \[-R\] \[-w\] <rep> <path> ...\] \[-stat \[format\] <path> ...\] \[-tail \[-f\] <file>\] \[-test -\[defsz\] <path>\] \[-text \[-ignoreCrc\] <src> ...\] \[-touchz <path> ...\] \[-usage \[cmd ...\]\]
3.2 常用命令参数介绍
注意: hdfs fs -du -s -h hdfs://aclear1:9000/* //是从这里面uri去访问的资源!全称是这样的!
-help 功能:输出这个命令参数手册
-ls 功能:显示目录信息 _示例: hadoop fs -ls hdfs://hadoop-server01:9000/_ _备注:这些参数中,所有的hdfs__路径都可以简写_ _—>hadoop fs -ls /_ _等同于上一条命令的效果_
-mkdir 功能:在hdfs**上创建目录** _示例:hadoop fs -mkdir -p /aaa/bbb/cc/dd_
-moveFromLocal 功能:从本地剪切粘贴到hdfs _示例:hadoop fs - moveFromLocal /home/hadoop/a.txt /aaa/bbb/cc/dd_ -moveToLocal 功能:从hdfs**剪切粘贴到本地** _示例:hadoop fs - moveToLocal /aaa/bbb/cc/dd /home/hadoop/a.txt_
—appendToFile 功能:追加一个文件到已经存在的文件末尾 _示例:hadoop fs -appendToFile ./hello.txt hdfs://hadoop-server01:9000/hello.txt_ _可以简写为:_ _Hadoop fs -appendToFile ./hello.txt /hello.txt_
-cat 功能:显示文件内容 _示例:hadoop fs -cat /hello.txt_ //Hadoop fs -cat /hello.txt | more //就会出现可以翻页的more. -tail 功能:显示一个文件的末尾 _示例:hadoop fs -tail /weblog/access_log.1_ -text 功能:以字符形式打印一个文件的内容 _示例:hadoop fs -text /weblog/access_log.1_
-chgrp //**改组 -chmod //**该权限 -chown //**改组 和 该用户! 功能:linux**文件系统中的用法一样,对文件所属权限 _示例:_ _hadoop fs -chmod 666 /hello.txt_ _hadoop fs -chown someuser:somegrp /hello.txt //someuser用户(但是不回去检查是否存在!) somegrp__组_
-copyFromLocal 功能:从本地文件系统中拷贝文件到hdfs**路径去 _示例:hadoop fs -copyFromLocal ./jdk.tar.gz /aaa/_ -copyToLocal 功能:从hdfs**拷贝到本地 _示例:hadoop fs -copyToLocal /aaa/jdk.tar.gz_
-cp 功能:从hdfs**的一个路径拷贝hdfs**的另一个路径 _示例: hadoop fs -cp /aaa/jdk.tar.gz /bbb/jdk.tar.gz.2_ -mv 功能:在hdfs**目录中移动文件** _示例: hadoop fs -mv /aaa/jdk.tar.gz /_
-get 功能:等同于copyToLocal**,就是从hdfs**下载文件到本地 示例:hadoop fs -get /aaa/jdk.tar.gz -getmerge 功能:合并下载多个文件 //**注意是合并成一个文件了,txt 等* _示例:比如hdfs的目录 /aaa/__下有多个文件:log.1, log.2,log.3,…_ hadoop fs -getmerge /aaa/log. ./log.sum
-put 功能:等同于copyFromLocal _示例:hadoop fs -put /aaa/jdk.tar.gz /bbb/jdk.tar.gz.2_
-rm 功能:删除文件或文件夹 _示例:hadoop fs -rm -r /aaa/bbb/_ -rmdir 功能:删除空目录 _示例:hadoop fs -rmdir /aaa/bbb/ccc_
-df 功能:统计文件系统的可用空间信息 _示例:hadoop fs -df -h /_ -du 功能:统计文件夹的大小信息 _示例:_ _hadoop fs -du -s -h /aaa/*_
-count 功能:统计一个指定目录下的文件节点数量 _示例:hadoop fs -count /aaa/_
-setrep 功能:设置hdfs**中文件的副本数量** _示例:hadoop fs -setrep 3 /aaa/jdk.tar.gz_ 但是注意: 中间只开启了DataNode三个机器——_<__这里设置的副本数只是记录在namenode__的元数据中,是否真的会有这么多副本,还得看datanode__的数量!现在只有三个,当有三个以上的datanode__节点的时候,会自动从namenode_ _元数据当中知道有十个,当然就会在新建的datanode__中添加此结点。="">_
******HDFS原理篇******
4. hdfs的工作机制
_(工作机制的学习主要是为加深对分布式系统的理解,以及增强遇到各种问题时的分析解决能力,形成一定的集群运维能力)_ _注:很多不是真正理解hadoop技术体系的人会常常觉得HDFS可用于网盘类应用,但实际并非如此。要想将技术准确用在恰当的地方,必须对技术有深刻的理解_
4.1 概述
- HDFS集群分为两大角色:NameNode、DataNode
- NameNode负责管理整个文件系统的元数据
- DataNode 负责管理用户的文件数据块
- 文件会按照固定的大小(blocksize)切成若干块后分布式存储在若干台datanode上
- 每一个文件块可以有多个副本,并存放在不同的datanode上
- Datanode会定期向Namenode汇报自身所保存的文件block信息,而namenode则会负责保持文件的副本数量
- HDFS的内部工作机制对客户端保持透明,客户端请求访问HDFS都是通过向namenode申请来进行
4.2 HDFS写数据流程
4.2.1 概述
客户端要向HDFS写数据,首先要跟namenode通信以确认可以写文件并获得接收文件block的datanode,然后,客户端按顺序将文件逐个block传递给相应datanode,并由接收到block的datanode负责向其他datanode复制block的副本
4.2.2 详细步骤图
4.2.3 详细步骤解析
1、根namenode通信请求上传文件,namenode检查目标文件是否已存在,父目录是否存在 2、namenode返回是否可以上传 3、client请求第一个 block该传输到哪些datanode服务器上 4、namenode返回3个datanode服务器ABC 5、client请求3台dn中的一台A上传数据(本质上是一个RPC调用,建立pipeline),A收到请求会继续调用B,然后B调用C,将真个pipeline建立完成,逐级返回客户端 6、client开始往A上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以packet为单位,A收到一个packet就会传给B,B传给C;A每传一个packet会放入一个应答队列等待应答 7、当一个block传输完成之后,client再次请求namenode上传第二个block的服务器。
4.3. HDFS读数据流程
4.3.1 概述
客户端将要读取的文件路径发送给namenode,namenode获取文件的元信息(主要是block的存放位置信息)返回给客户端,客户端根据返回的信息找到相应datanode逐个获取文件的block并在客户端本地进行数据追加合并从而获得整个文件
4.3.2 详细步骤图
4.3.3 详细步骤解析
1、跟namenode通信查询元数据,找到文件块所在的datanode服务器 2、挑选一台datanode(就近原则,然后随机)服务器,请求建立socket流 3、datanode开始发送数据(从磁盘里面读取数据放入流,以packet为单位来做校验) 4、客户端以packet为单位接收,现在本地缓存,然后写入目标文件
5. NAMENODE工作机制
学习目标:理解namenode的工作机制尤其是元数据管理机制,以增强对HDFS工作原理的理解,及培养hadoop集群运营中“性能调优”、“namenode”故障问题的分析解决能力 _问题场景:_ _1、集群启动后,可以查看文件,但是上传文件时报错,打开web页面可看到namenode正处于safemode状态,怎么处理?_ _2、Namenode服务器的磁盘故障导致namenode宕机,如何挽救集群及数据?_ _3、Namenode是否可以有多个?namenode内存要配置多大?namenode跟集群数据存储能力有关系吗?_ _4、文件的blocksize究竟调大好还是调小好?_ _……_ _诸如此类问题的回答,都需要基于对namenode自身的工作原理的深刻理解_
5.1 NAMENODE职责
NAMENODE职责: 负责客户端请求的响应 元数据的管理(查询,修改)
5.2 元数据管理
namenode对数据的管理采用了三种存储形式: 内存元数据(NameSystem) 磁盘元数据镜像文件 数据操作日志文件(可通过日志运算出元数据)
5.2.1 元数据存储机制
A、内存中有一份完整的元数据(内存meta data) B、磁盘有一个“准完整”的元数据镜像(fsimage)文件(在namenode的工作目录中) C、用于衔接内存metadata和持久化元数据镜像fsimage之间的操作日志(edits**文件**)_注:当客户端对hdfs中的文件进行新增或者修改操作,操作记录首先被记入edits日志文件中,当客户端操作成功后,相应的元数据会更新到内存meta.data中_
5.2.2 元数据手动查看
可以通过hdfs的一个工具来查看edits中的信息 bin/hdfs oev -i edits -o edits.xmlbin/hdfs oiv -i fsimage_0000000000000000087 -p XML -o fsimage.xml
5.2.3 元数据的checkpoint
每隔一段时间,会由secondary namenode将namenode上积累的所有edits和一个最新的fsimage下载到本地,并加载到内存进行merge(这个过程称为checkpoint)
checkpoint的详细过程
checkpoint操作的触发条件配置参数
dfs.namenode.checkpoint.check.period=60 #检查触发条件是否满足的频率,60秒 dfs.namenode.checkpoint.dir=file://${hadoop.tmp.dir}/dfs/namesecondary #以上两个参数做checkpoint操作时,secondary namenode的本地工作目录 dfs.namenode.checkpoint.edits.dir=${dfs.namenode.checkpoint.dir} dfs.namenode.checkpoint.max-retries=3 #最大重试次数 dfs.namenode.checkpoint.period=3600 #两次checkpoint之间的时间间隔3600秒 dfs.namenode.checkpoint.txns=1000000 #两次checkpoint之间最大的操作记录
checkpoint的附带作用
namenode和secondary namenode的工作目录存储结构完全相同,所以,当namenode故障退出需要重新恢复时,可以从secondary namenode的工作目录中将fsimage拷贝到namenode的工作目录,以恢复namenode的元数据
6. DATANODE的工作机制
_问题场景:_ _1、集群容量不够,怎么扩容?_ _2、如果有一些datanode宕机,该怎么办?_ _3、datanode明明已启动,但是集群中的可用datanode列表中就是没有,怎么办?_ _以上这类问题的解答,有赖于对datanode__工作机制的深刻理解_
6.1 概述
1、Datanode工作职责: 存储管理用户的文件块数据 定期向namenode汇报自身所持有的block信息(通过心跳信息上报) (这点很重要,因为,当集群中发生某些block副本失效时,集群如何恢复block初始副本数量的问题)
2、Datanode掉线判断时限参数 datanode进程死亡或者网络故障造成datanode无法与namenode通信,namenode不会立即把该节点判定为死亡,要经过一段时间,这段时间暂称作超时时长。HDFS默认的超时时长为10分钟+30秒。如果定义超时时间为timeout,则超时时长的计算公式为: timeout = 2 heartbeat.recheck.interval + 10 dfs.heartbeat.interval。 而默认的heartbeat.recheck.interval 大小为5分钟,dfs.heartbeat.interval默认为3秒。 需要注意的是hdfs-site.xml 配置文件中的heartbeat.recheck.interval的单位为毫秒,dfs.heartbeat.interval的单位为秒。所以,举个例子,如果heartbeat.recheck.interval设置为5000(毫秒),dfs.heartbeat.interval设置为3(秒,默认),则总的超时时间为40秒。
6.2 观察验证DATANODE功能
上传一个文件,观察文件的block具体的物理存放情况: 在每一台datanode机器上的这个目录中能找到文件的切块: /home/hadoop/app/hadoop-2.4.1/tmp/dfs/data/current/BP-193442119-192.168.2.120-1432457733977/current/finalized 更新当前目录为: /home/hadoop/hdpdata/dfs/data/current/BP-1525464751-192.168.78.201-1515703290610/current/finalized/subdir0/subdir0
******HDFS应用开发篇******
hdfs dfsadmin -report //注意这里进行shell中的集群状态的打印。 大数据list hashmap<不常用>;常常是在 iterator当中 进行迭代取值(或者在hashmap的数据池当中进行获取),这样大数据 方便拿到数据! HDFS加上MR在上层跑应用程序的框架来说,我们需要进行MR在HDFS中调用一小片的数据!
7. HDFS的java操作
_hdfs在生产应用中主要是客户端的开发,其核心步骤是从hdfs提供的api中构造一个HDFS的访问客户端对象,然后通过该客户端对象操作(增删改查)HDFS__上的文件_
7.1 搭建开发环境
1、引入依赖
_注:如需手动引入jar包,hdfs的jar包——hadoop的安装目录的share__下_ 2、window下开发的说明 建议在linux下进行hadoop应用的开发,不会存在兼容性问题。如在window上做客户端应用开发,需要设置以下环境:
- 在windows的某个目录下解压一个hadoop的安装包
- 将安装包下的lib和bin目录用对应windows版本平台编译的本地库替换
- 在window系统中配置HADOOP_HOME指向你解压的安装包
- 在windows系统的path变量中加入hadoop的bin目录
7.2 获取api中的客户端对象
在java中操作hdfs,首先要获得一个客户端实例
Configuration conf = new Configuration() FileSystem fs = FileSystem.get(conf)
而我们的操作目标是HDFS,所以获取到的fs对象应该是DistributedFileSystem的实例; get方法是从何处判断具体实例化那种客户端类呢? ——从conf**中的一个参数 fs.defaultFS**的配置值判断; 如果我们的代码中没有指定fs.defaultFS,并且工程classpath下也没有给定相应的配置,conf中的默认值就来自于hadoop的jar包中的core-default.xml,默认值为: file:///,则获取的将不是一个DistributedFileSystem的实例,而是一个本地文件系统的客户端对象
7.3 DistributedFileSystem实例对象所具备的方法
7.4 HDFS客户端操作数据代码示例:
7.4.1 文件的增删改查
public class HdfsClient { FileSystem fs = null; @Before public void init() throws Exception { // 构造一个配置参数对象,设置一个参数:我们要访问的hdfs的URI // 从而FileSystem.get()方法就知道应该是去构造一个访问hdfs文件系统的客户端,以及hdfs的访问地址 // new Configuration();的时候,它就会去加载jar包中的hdfs-default.xml // 然后再加载classpath下的hdfs-site.xml Configuration conf = new Configuration(); conf.set(“fs.defaultFS”, “hdfs://hdp-node01:9000”); / 参数优先级: 1、客户端代码中设置的值 2、classpath下的用户自定义配置文件 3、然后是服务器的默认配置 / conf.set(“dfs.replication”, “3”); // 获取一个hdfs的访问客户端,根据参数,这个实例应该是DistributedFileSystem的实例 // fs = FileSystem.get(conf); // 如果这样去获取,那conf里面就可以不要配”fs.defaultFS”参数,而且,这个客户端的身份标识已经是hadoop用户 fs = FileSystem.get(new URI(“hdfs://hdp-node01:9000”), conf, “hadoop”); } / 往hdfs上传文件 @throws Exception / @Test public void testAddFileToHdfs() throws Exception { // 要上传的文件所在的本地路径 Path src = new Path(“g:/redis-recommend.zip”); // 要上传到hdfs的目标路径 Path dst = new Path(“/aaa”); fs.copyFromLocalFile(src, dst); fs.close(); } / 从hdfs中复制文件到本地文件系统 @throws IOException @throws IllegalArgumentException */ @Test public void testDownloadFileToLocal() throws IllegalArgumentException, IOException { fs.copyToLocalFile(new Path(“/jdk-7u65-linux-i586.tar.gz”), new Path(“d:/“)); fs.close(); } @Test public void testMkdirAndDeleteAndRename() throws IllegalArgumentException, IOException { // 创建目录 fs.mkdirs(new Path(“/a1/b1/c1”)); // 删除文件夹 ,如果是非空文件夹,参数2必须给值true fs.delete(new Path(“/aaa”), true); // 重命名文件或文件夹 fs.rename(new Path(“/a1”), new Path(“/a2”)); } / 查看目录信息,只显示文件 @throws IOException @throws IllegalArgumentException @throws FileNotFoundException / @Test public void testListFiles() throws FileNotFoundException, IllegalArgumentException, IOException { // 思考:为什么返回迭代器,而不是List之类的容器 RemoteIterator
7.4.2 通过流的方式访问hdfs
_/_ _*_ _相对那些封装好的方法而言的更底层一些的操作方式_ _*_ _上层那些mapreduce spark等运算框架,去hdfs中获取数据的时候,就是调的这种底层的__api_ _ * @author_ _ _ _ /_ _public class StreamAccess {_ _ FileSystem fs = null;_ _ @Before_ _ public void init() throws Exception {_ _ Configuration conf = new Configuration();_ _ fs = FileSystem.get(new URI(“hdfs://hdp-node01:9000”), conf, “hadoop”);_ _ }_ _ /_ _*_ _通过流的方式上传文件到hdfs_ _ * @throws Exception_ _ */_ _ @Test_ _ public void testUpload() throws Exception {_ _ FSDataOutputStream outputStream = fs.create(new Path(“/angelababy.love”), true);_ _ FileInputStream inputStream = new FileInputStream(“c:/angelababy.love”);_ _ IOUtils.copy(inputStream, outputStream);_ _ }_ _ @Test_ _ public void testDownLoadFileToLocal() throws IllegalArgumentException, IOException{_ _ //先获取一个文件的输入流----针对hdfs上的_ _ FSDataInputStream in = fs.open(new Path(“/jdk-7u65-linux-i586.tar.gz”));_ _ //再构造一个文件的输出流----针对本地的_ _ FileOutputStream out = new FileOutputStream(new File(“c:/jdk.tar.gz”));_ _ //再将输入流中数据传输到输出流_ _ IOUtils.copyBytes(in, out, 4096);_ _ }_ _ /_ _ * hdfs支持随机定位进行文件读取,而且可以方便地读取指定长度_ _*_ _用于上层分布式运算框架并发处理数据_ _ * @throws IllegalArgumentException_ _ * @throws IOException_ _ */_ _ @Test_ _ public void testRandomAccess() throws IllegalArgumentException, IOException{_ _ //先获取一个文件的输入流----针对hdfs上的_ _ FSDataInputStream in = fs.open(new Path(“/iloveyou.txt”));_ _ //可以将流的起始偏移量进行自定义_ _ in.seek(22);_ _ //再构造一个文件的输出流----针对本地的_ _ FileOutputStream out = new FileOutputStream(new File(“c:/iloveyou.line.2.txt”));_ _ IOUtils.copyBytes(in,out,19L,true);_ _ }_ _ /_ _*_ _显示hdfs上文件的内容_ _* @throws IOException_ _* @throws IllegalArgumentException_ _ */_ _ @Test_ _ public void testCat() throws IllegalArgumentException, IOException{_ _ FSDataInputStream in = fs.open(new Path(“/iloveyou.txt”));_ _ IOUtils.copyBytes(in, System.out, 1024);_ _ }_ _}_
7.4.3 场景编程
在mapreduce 、spark等运算框架中,有一个核心思想就是将运算移往数据,或者说,就是要在并发计算中尽可能让运算本地化,这就需要获取数据所在位置的信息并进行相应范围读取 以下模拟实现:获取一个文件的所有block位置信息,然后读取指定block中的内容
_ @Test_ _ public void testCat() throws IllegalArgumentException, IOException{_ _ FSDataInputStream in = fs.open(new Path(“/weblog/input/access.log.10”));_ _ //拿到文件信息_ _ FileStatus[] listStatus = fs.listStatus(new Path(“/weblog/input/access.log.10”));_ _ //获取这个文件的所有block的信息_ _ BlockLocation[] fileBlockLocations = fs.getFileBlockLocations(listStatus[0], 0L, listStatus[0].getLen());_ _ //第一个block的长度_ _ long length = fileBlockLocations[0].getLength();_ _ //第一个block的起始偏移量_ _ long offset = fileBlockLocations[0].getOffset();_ _ System.out.println(length);_ _ System.out.println(offset);_ _ //获取第一个block__写入输出流_ _// IOUtils.copyBytes(in, System.out, (int)length);_ _ byte[] b = new byte[4096];_ _ FileOutputStream os = new FileOutputStream(new File(“d:/block0”));_ _ while(in.read(offset, b, 0, 4096)!=-1){_ _ os.write(b);_ _ offset += 4096;_ _ if(offset>=length) return;_ _ };_ _ os.flush();_ _ os.close();_ _ in.close();_ _ }_
//注意:其实在client //只需要导入 hadooop-common.jar //还有对应的 Hadoopjars-common-lib对应上方 jar包的依赖也是需要的! //《Hadoop 技术内幕》可以看一下,研究源代码!-自己打断点这样学习源码更加省力一点。 //注意 源码调试可以看一下:视频day07-06 第一个视频!已经跳过 原理:1.写一个java定时收集数据的程序,进行shell脚本的定时数据的手机、 Timer、线程池、scheduler、code?进行java定时 或者利用服务器进行定时启动-à天 小时 时间段,每隔多少小时,linux文档当中启动服务器进行采集数据—> 2.然后 copyFromLocal() 放入hdfs当中,每一个小时进行一次的数据分析! 有需求/挑战 就是有市场—>数据的采集也是有相应的api文档进行开发的! 首先过滤(上传到一个地方检查是否合法),然后 上传hdfs !要进行改名! 脚本因为没有对应的代码规范、编译检错。所以需要我们自己对于这种开发进行 代码模板规范 看懂老师相应的代码就好!慢慢的一点点看 去开发! 模板:先export 再定义一些 固定文件目录常量 编写代码
8. 案例1:开发shell采集脚本
8.1需求说明
点击流日志每天都10T,在业务应用服务器上,需要准实时上传至数据仓库(Hadoop HDFS)上
8.2需求分析
一般上传文件都是在凌晨24点操作,由于很多种类的业务数据都要在晚上进行传输,为了减轻服务器的压力,避开高峰期。 如果需要伪实时的上传,则采用定时上传的方式
8.3技术分析
HDFS SHELL: hadoop fs –put xxxx.tar /data 还可以使用 Java Api 满足上传一个文件,不能满足定时、周期性传入。 定时调度器: Linux crontab crontab -e /5 * $home/bin/command.sh //五分钟执行一次 系统会自动执行脚本,每5分钟一次,执行时判断文件是否符合上传规则,符合则上传
8.4实现流程
8.4.1日志产生程序
日志产生程序将日志生成后,产生一个一个的文件,使用滚动模式创建文件名。 日志生成的逻辑由业务系统决定,比如在log4j配置文件中配置生成规则,如:当xxxx.log 等于10G时,滚动生成新日志
_log4j.logger.msg=info,msg_ _log4j.appender.msg=cn.maoxiangyi.MyRollingFileAppender_ _log4j.appender.msg.layout=org.apache.log4j.PatternLayout_ _log4j.appender.msg.layout.ConversionPattern=%m%n_ _log4j.appender.msg.datePattern=’.’yyyy-MM-dd_ _log4j.appender.msg.Threshold=info_ _log4j.appender.msg.append=true_ _log4j.appender.msg.encoding=UTF-8_ _log4j.appender.msg.MaxBackupIndex=100_ _log4j.appender.msg.MaxFileSize=10GB_ _log4j.appender.msg.File=/home/hadoop/logs/log/access.log_
细节:
- 如果日志文件后缀是1\\2\\3等数字,该文件满足需求可以上传的话。把该文件移动到准备上传的工作区间。
- 工作区间有文件之后,可以使用hadoop put命令将文件上传。
阶段问题:
- 待上传文件的工作区间的文件,在上传完成之后,是否需要删除掉。
8.4.2伪代码
使用ls命令读取指定路径下的所有文件信息, ls | while read line //判断line这个文件名称是否符合规则 if line=access.log. ( 将文件移动到待上传的工作区间 ) //批量上传工作区间的文件 hadoop fs –put xxx *脚本写完之后,配置linux定时任务,每5分钟运行一次。
8.5代码实现
代码第一版本,实现基本的上传功能和定时调度功能 代码第二版本:增强版V2(基本能用,还是不够健全)
8.6效果展示及操作步骤
1、日志收集文件收集数据,并将数据保存起来,效果如下: 2、上传程序通过crontab定时调度 3、程序运行时产生的临时文件 4、Hadoo hdfs上的效果 作业:第七节都要自己敲一遍! 然而第八节 这个是企业里面实实在在就是这样写的!所以自己最好实实在在敲一遍!
9. 案例2:开发JAVA采集程序
9.1 需求
从外部购买数据,数据提供方会实时将数据推送到6台FTP服务器上,我方部署6台接口采集机来对接采集数据,并上传到HDFS中 提供商在FTP上生成数据的规则是以小时为单位建立文件夹(2016-03-11-10),每分钟生成一个文件(00.dat,01.data,02.dat,……..) 提供方不提供数据备份,推送到FTP服务器的数据如果丢失,不再重新提供,且FTP服务器磁盘空间有限,最多存储最近10小时内的数据 由于每一个文件比较小,只有150M左右,因此,我方在上传到HDFS过程中,需要将15分钟时段的数据合并成一个文件上传到HDFS 为了区分数据丢失的责任,我方在下载数据时最好进行校验
9.2 设计分析
Kotlin