├── Hadoop生态 ├── assets │ ├── 1657767090189.png │ ├── 1657779529246.png │ ├── 1657781271931.png │ ├── 1657865386616.png │ ├── 1657871956423.png │ ├── 1657873094885.png │ ├── 1657876970998.png │ ├── 1658122127131.png │ ├── 1658122834445.png │ ├── 1658131281677.png │ ├── 1658131502394.png │ ├── 1658132018864.png │ ├── 1658132110932.png │ ├── 1658136325417.png │ ├── 1658136476325.png │ ├── 1658137105576.png │ ├── 1658137154450.png │ ├── 1658200851074.png │ ├── 1658200889862.png │ ├── 1658207092361.png │ ├── 1658207398851.png │ ├── 1658210426284.png │ ├── 1658211441669.png │ ├── 1658216074225.png │ ├── 1658295144547.png │ ├── 1658298385494.png │ ├── 1658299068573.png │ ├── 1658299681037.png │ ├── 1658382022692.png │ ├── 1658384907909.png │ ├── 1658385384460.png │ ├── 1658820940897.png │ ├── 1658821617982.png │ ├── 1658821646593.png │ ├── 1658823164088.png │ ├── 1658886205864.png │ ├── 1658887440421.png │ ├── 1658901008483.png │ ├── 1658902341763.png │ └── 1672735124222.png ├── 第一章——Hadoop基础.md └── 第二章——Hive.md ├── LICENSE ├── README.md ├── soft ├── README.md └── frpc_0.33.linux_adm64.tgz ├── 准实时数仓项目 ├── README.md └── assets │ └── DAU公式.png ├── 用户画像项目实践 ├── README.md └── assets │ └── 用户画像架构图.png └── 采集与监控平台项目 ├── README.md └── assets ├── 1642557741872.png ├── 1642563394249.png ├── 1642564130136.png ├── 1643860152216.png ├── 1643860621257.png ├── 1643861562371.png ├── 1643862270997.png ├── 1643866651880.png ├── 1643869444450.png ├── 1643869498980.png ├── 1643869508047.png ├── 1643870788661.png ├── 1643873695928.png ├── 1643873897636.png ├── 1643890185710.png ├── 1643890246493.png ├── 1643890458958.png ├── 1643890762076.png ├── 1643890853267.png ├── 1643890899399.png ├── 1643891023827.png ├── 采集架构一.png └── 采集架构二.png /Hadoop生态/assets/1657767090189.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1657767090189.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1657779529246.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1657779529246.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1657781271931.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1657781271931.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1657865386616.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1657865386616.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1657871956423.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1657871956423.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1657873094885.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1657873094885.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1657876970998.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1657876970998.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658122127131.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658122127131.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658122834445.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658122834445.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658131281677.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658131281677.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658131502394.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658131502394.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658132018864.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658132018864.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658132110932.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658132110932.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658136325417.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658136325417.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658136476325.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658136476325.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658137105576.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658137105576.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658137154450.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658137154450.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658200851074.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658200851074.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658200889862.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658200889862.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658207092361.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658207092361.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658207398851.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658207398851.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658210426284.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658210426284.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658211441669.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658211441669.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658216074225.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658216074225.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658295144547.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658295144547.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658298385494.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658298385494.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658299068573.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658299068573.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658299681037.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658299681037.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658382022692.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658382022692.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658384907909.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658384907909.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658385384460.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658385384460.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658820940897.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658820940897.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658821617982.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658821617982.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658821646593.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658821646593.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658823164088.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658823164088.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658886205864.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658886205864.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658887440421.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658887440421.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658901008483.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658901008483.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1658902341763.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1658902341763.png -------------------------------------------------------------------------------- /Hadoop生态/assets/1672735124222.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/Hadoop生态/assets/1672735124222.png -------------------------------------------------------------------------------- /Hadoop生态/第一章——Hadoop基础.md: -------------------------------------------------------------------------------- 1 | # 第一章——Hadoop基础 2 | 3 | ### 一. Hadoop概述 4 | 5 | #### 1.1 为什么要用Hadoop 6 | 7 | 我们生活在数据大爆炸的年代,2020年达到84.5ZB,比预计的61ZB整整多出20+ZB,在疫情时期,数据达到空前爆发式增长,单位换算后在840亿TB以上,也就是全球每人一块1TB硬盘都存储不下。 8 | 9 | > 注:1 Terabyte (TB) = 1024 GB. 1 Petabyte (PB) = 1024 TB. 1 Exabyte (EB) = 1024 PB. 1 Zettabyte (ZB) = 1024 EB 10 | 11 | 一些数据集的大小更是远远超过1TB,也就是数据的存储是一个要解决的问题。同时,硬盘技术也面临一个技术瓶颈,也就是硬盘的传输速度(读数据的速度)。如下表格: 12 | 13 | | 年份 | 硬盘大小 | 传输速率 | 所需时间 | 14 | | ---- | ----------- | -------- | -------- | 15 | | 1990 | 1370MB | 4.4MB/s | 5分钟 | 16 | | 2010 | 1TB(主流) | 100MB/s | 3小时 | 17 | 18 | 可以看到,容量提升了将近千倍,而传输速度才提升了20倍,读完一个硬盘的所需时间相对更长了,读都要这么久更别说写了。 19 | 20 | 对于如何提高读数据的效率,可以将一个数据集存储到多个硬盘里,然后并行读取。如1T数据平均100份存储到100个1TB硬盘上,同时读取,则读取完成整个数据集花不了两分钟,至于剩下的99%容量可以用来存储其它的数据集。 21 | 22 | 但,如果我们要对多个硬盘进行读/写操作时,又有了新的问题需要解决; 23 | 24 | > 硬件故障问题。一旦硬件数量过多,如上述的100个1TB硬盘,那么故障的总数相对1个1TB硬盘就会偏高,为了避免数据丢失,常见的做法就是复制(replication),一旦发生故障则使用另外的副本; 25 | > 26 | > 读取数据的正确性问题。如何把100份数据合并成一个数据集且保证正确性,也是一个非常大的挑战; 27 | 28 | 针对上述问题,Hadoop为我们提供了一个可靠的且可扩展的存储和分析平台,此外,Hadoop还是开源的。具体可参考:https://hadoop.apache.org/docs/r1.0.4/cn/hdfs_design.html 29 | 30 | 31 | 32 | #### 1.2 Hadoop的简要介绍 33 | 34 | Hadoop是Apache基金会旗下一个开源的分布式存储和分析计算平台,使用Java语言开发,具有很好的跨平台性,开源,用户无需了解分布式底层细节即可开发分布式程序,充分使用集群的高速计算和存储。 35 | 36 | 37 | 38 | #### 1.3 谷歌的三篇论文 39 | 40 | ~~~ 41 | - 2003年发表的《GFS》 42 | 基于硬盘不够大、数据存储单份的安全隐患问题,提出了分布式文件系统用于存储的理论思想。 43 | * 解决了如何存储大数据集的问题 44 | 45 | - 2004年发表《MapReduce》 46 | 基于分布式文件系统的计算分析编程框架模型。移动计算而非移动数据,分而治之。 47 | * 解决了如何快速分析大数据集的问题 48 | 49 | - 2006年发表的《BigTable》 50 | 针对传统关系型数据库不适合存储非结构化数据的缺点,提出了另一种适合存储大数据集的解决方案。 51 | ~~~ 52 | 53 | 54 | 55 | #### 1.4 Hadoop的发展历史 56 | 57 | ~~~ 58 | - 起源于Apache Nutch项目(一个网页爬取工具和搜索引擎系统,后来遇到大数据量的存储问题) 59 | - 2003年,谷歌发表《GFS》给了Apache Nutch项目的开发者灵感。 60 | - 2004年,Nutch的开发者开始着手NDFS(Nutch的分布式文件系统)。 61 | - 2005年,谷歌发表一篇介绍MapReduce系统的论文。 62 | - 2006年,开发人员将NDFS和MapReduce移出Nutch项目形成一个子项目,命名Hadoop。 63 | - 2008年,Hadoop已成为Apache的顶级项目。 64 | - 2008年4月,Hadoop打破世界纪录,成为最快排序1TB数据的系统,排序时间为209秒。 65 | - 2009年,Hadoop把1TB数据的排序时间缩短到62秒。 66 | ~~~ 67 | 68 | 69 | 70 | #### 1.5 Hadoop的组成部分 71 | 72 | ~~~ 73 | Hadoop2.0以后的四个模块: 74 | - Hadoop Common: Hadoop模块的通用组件 75 | - Hadoop distributed File System: 分布式文件系统 76 | - Hadoop YARN: 作业调度和资源管理框架 77 | - Hadoop MapReduce: 基于YARN的大型数据集并行计算处理框架 78 | 79 | Hadoop3.0新扩展的两个模块: 80 | - Hadoop Ozone: Hadoop的对象存储机制 81 | - Hadoop Submarine: Hadoop的机器学习引擎 82 | ~~~ 83 | 84 | 85 | 86 | #### 1.6 Hadoop的生态系统 87 | 88 | 2.x版本 89 | 90 | ![1657767090189](assets/1657767090189.png) 91 | 92 | > 在3.x版本中,除了性能方面的提升。在生态,分布式计算框架除了Spark外,Flink也尤为亮眼,且支持更多NameNode,具体参考:https://hadoop.apache.org/docs/r3.0.0/,**本次我们部署的也是22年最新的3.3.1版本** 93 | 94 | 95 | 96 | ### 二. Hadoop集群安装 97 | 98 | #### 2.1 集群规划 99 | 100 | | 集群规划 | 规划 | 101 | | -------------- | ------------------------------------------------------------ | 102 | | 操作系统 | Windows、Mac | 103 | | 虚拟软件 | VMware(windows)、Parallel Desktop(Mac)
或者直接去云厂商开3台centos7.7 | 104 | | 虚拟机 | 主机名:ben01,IP地址192.168.10.101
主机名:ben02,IP地址192.168.10.102
主机名:ben03,IP地址192.168.10.103 | 105 | | 配置 | 主机01:2核,4G,30G
主机02:1核,2G,30G
主机03:1核,2G,30G | 106 | | 软件包上传路径 | /root/softwares | 107 | | 软件包安装路径 | /usr/local | 108 | | JDK | Jdk-8u321-linux-x64.tar.gz | 109 | | Hadoop | hadoop-3.3.1.tar.gz | 110 | | 用户 | root | 111 | 112 | > 上述软件包可通过百度网盘下载: 113 | > 114 | > 链接:https://pan.baidu.com/s/1UZABuNRtoPzjrrc73r26Yw?pwd=d0ni 115 | > 提取码:d0ni 116 | 117 | 118 | 119 | #### 2.2 安装JDK 120 | 121 | > 三台机器都需要做 122 | 123 | 2.2.1 检查是否有内置JDK,如有则卸载 124 | 125 | ~~~shell 126 | [root@ben01 ~]# rpm -qa | grep jdk # 查看是否有 127 | [root@ben01 ~]# rpm -e xxxxxxxx --nodeps # 有则卸载 128 | ~~~ 129 | 130 | 2.2.2 上传jdk1.8到/root/softwares下 131 | 132 | 2.2.3 解压jdk到/usr/local/下 133 | 134 | ~~~shell 135 | [root@ben01 ~]# cd softwares/ 136 | [root@ben01 softwares]# tar -zxvf jdk-8u321-linux-x64.tar.gz -C /usr/local 137 | ~~~ 138 | 139 | 2.2.4 更名jdk 140 | 141 | ~~~shell 142 | [root@ben01 softwares]# cd /usr/local 143 | [root@ben01 local]# mv jdk1.8.0_321/ jdk 144 | ~~~ 145 | 146 | 2.2.5 配置jdk的环境变量:/etc/profile 147 | 148 | ~~~shell 149 | [root@ben01 local]# vi /etc/profile # 在最下面添加如下内容 150 | 151 | #jdk environment 152 | export JAVA_HOME=/usr/local/jdk 153 | export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH 154 | ~~~ 155 | 156 | 2.2.6 使当前窗口生效 157 | 158 | ~~~shell 159 | [root@ben01 local]# source /etc/profile 160 | ~~~ 161 | 162 | 2.2.7 验证jdk换季 163 | 164 | ~~~shell 165 | [root@ben01 local]# java -version 166 | [root@ben01 local]# java 167 | ~~~ 168 | 169 | ![1657779529246](assets/1657779529246.png) 170 | 171 | 172 | 173 | #### 2.3 完全分布式环境需求及安装 174 | 175 | ~~~~ 176 | 1. 三台机器的防火墙必须是关闭的 177 | 2. 确保三台机器的网络配置通畅 178 | 3. 确保/etc/hosts文件配置了IP和hosts的映射关系 179 | 4. 确保配置了三台机器的免密登录认证 180 | 5. 确保所有机器的时间同步 181 | 6. 三台机器JDK和Hadoop的环境变量配置 182 | ~~~~ 183 | 184 | 2.3.1 关闭防火墙 185 | 186 | ~~~shell 187 | [root@ben01 ~]# systemctl stop firewalld 188 | [root@ben01 ~]# systemctl disable firewalld 189 | [root@ben01 ~]# systemctl stop NetworkManager 190 | [root@ben01 ~]# systemctl disable NetworkManager 191 | 192 | # 最好也把selinux关闭,将SELINUXTYPE设置为disabled 193 | [root@ben01 ~]# vi /etc/selinux/config 194 | SELINUXTYPE=disabled 195 | ~~~ 196 | 197 | 2.3.2 静态IP和主机名配置 198 | 199 | > 作者直接开的云厂商的服务 200 | 201 | ~~~shell 202 | # 1.配置静态IP(确保NAT模式) 203 | vi /etc/sysconfig/network-scripts/ifcfg-ens33 204 | 205 | BOOTPROTO=static # dhcp改为static 206 | ............ 207 | ONBOOT=yes # no改为yes 208 | IPADDR=192.168.10.101 # 添加IPADDR属性和ip地址 209 | PREFIX=24 # 添加NETMASK=255.255.255.0 或者 PREFIX=24 210 | GATEWAY=192.168.10.2 # 添加GATEWAY网关 211 | DNS1=114.114.114.114 # 天假DNS1和备份DNS 212 | DNS2=8.8.8.8 213 | 214 | # 2.重启网络服务 215 | systemctl restart network 216 | service network restart 217 | 218 | # 3.修改主机名 219 | hostnamectl set-hostname ben01 # 可以设置成自己的名字 220 | hostname # 即可查看是否设置完成,需要重连才能显示 221 | ~~~ 222 | 223 | 2.3.3 配置/etc/hosts文件 224 | 225 | > 作者是用的云厂商机器,IP有所不同 226 | 227 | ~~~shell 228 | [root@ben01 ~]# vi /etc/hosts 229 | 230 | 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 231 | ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 232 | 233 | # 添加本机的静态IP和本机主机名之间的映射关系 234 | 10.206.0.10 ben01 235 | 10.206.16.4 ben02 236 | 10.206.16.8 ben03 237 | ~~~ 238 | 239 | ![1657781271931](assets/1657781271931.png) 240 | 241 | 2.3.4 免密登录认证 242 | 243 | ~~~shell 244 | # 1.使用rsa加密技术,生成公钥和密钥,一路回车即可,三台机器都需要做 245 | [root@ben01 ~]# cd ~ 246 | [root@ben01 ~]# ssh-keygen -t rsa 247 | 248 | # 2.01免密登录自己和02和03,进入~/.ssh目录下,使用ssh-copy-id命令,需要输入密码 249 | [root@ben01 ~]# cd ~/.ssh 250 | [root@ben01 .ssh]# ssh-copy-id ben01 # 输入密码 251 | [root@ben01 .ssh]# ssh-copy-id ben02 # 输入密码 252 | [root@ben01 .ssh]# ssh-copy-id ben03 # 输入密码 253 | 254 | # 3.进行验证,下面第一次执行时输入yes后,不提示输入密码就对了 255 | [root@ben01 .ssh]# ssh ben02 256 | [root@ben01 ~]# ssh localhost 257 | [root@ben01 ~]# ssh 0.0.0.0 258 | 259 | # 4.同样的,ben02和ben03也需要做对其它两台的免密 260 | ~~~ 261 | 262 | > 如下图 263 | > 264 | > ![1658122127131](assets/1658122127131.png) 265 | 266 | 2.3.5 时间同步 267 | 268 | > 云厂买的则不需要,已经自动同步了 269 | 270 | ~~~shell 271 | # 1.选择集群中的某一台机器作为时间服务器,例如ben01 272 | # 2.保证这台服务器安装了ntp.x86_64 273 | # 3.保证ntpd 服务运行 274 | [root@ben01 ~]# sudo service ntpd start 275 | [root@ben01 ~]# chkcofig ntpd on 276 | 277 | # 4.配置相应文件 278 | [root@ben01 ~]# vi /etc/ntp.conf 279 | # Hosts on local network are less restricted. 280 | # restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap 281 | # 添加集群中的网络段位 282 | restrict 192.168.10.0 mask 255.255.255.0 nomodify notrap 283 | 284 | # Use public servers from the pool.ntp.org project. 285 | # Please consider joining the pool (http://www.pool.ntp.org/join.html). 286 | # server 0.centos.pool.ntp.org iburst 注释掉 287 | # server 1.centos.pool.ntp.org iburst 注释掉 288 | # server 2.centos.pool.ntp.org iburst 注释掉 289 | # server 3.centos.pool.ntp.org iburst 注释掉 290 | servcer 127.127.1.0 -master作为服务器 291 | # 5.其它机器要保证安装ntpdate.x86_64 292 | # 6.其它机器要使用root定义定时器 293 | */1 * * * * /usr/sbin/ntpdate -u ben01 294 | ~~~ 295 | 296 | 2.3.6 Hadoop安装与环境变量配置 297 | 298 | ~~~shell 299 | # 1.上传和解压软件包 300 | [root@ben01 softwares]# tar zxvf hadoop-3.3.1.tar.gz -C /usr/local/ 301 | 302 | # 2.进入local里,给软件改名 303 | [root@ben01 softwares]# cd /usr/local/ 304 | [root@ben01 local]# mv hadoop-3.3.1/ hadoop 305 | 306 | # 3.配置环境变量,再最下面追加 307 | [root@ben01 local]# vi /etc/profile 308 | 309 | ...... 310 | #hadoop environment 311 | export HADOOP_HOME=/usr/local/hadoop 312 | export PATH=$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$PATH 313 | 314 | # 4.刷新环境并验证 315 | [root@ben01 local]# source /etc/profile 316 | [root@ben01 local]# hadoop version 317 | ~~~ 318 | 319 | ![1657865386616](assets/1657865386616.png) 320 | 321 | > 注意,是三台机器都完成了如上的操作 322 | 323 | 324 | 325 | #### 2.4 Hadoop的配置文件 326 | 327 | 2.4.1 概述 328 | 329 | 我们需要通过配置若干配置文件,来实现Hadoop集群的配置信息。需要配置的文件有: 330 | 331 | ~~~ 332 | hadoop-env.sh 333 | yarn-env.sh 334 | core-site.xml 335 | hdfs-site.xml 336 | mapred-site.xml 337 | yarn-site.xml 338 | 339 | 在Hadoop安装完成后,会在$HADOOP_HOME/share路径下,有若干个*-default.xml文件,这些文件中记录了默认的配置信息,同时,在代码中,我们也可以配置Hadoop的配置信息。 340 | 这些位置配置的Hadoop,优先级为:代码设置 > *-site.xml > *-default.xml 341 | ~~~ 342 | 343 | 集群规划: 344 | 345 | | Node | Applications | 346 | | ----- | ------------------------------------------------------------ | 347 | | ben01 | NameNode
DataNode
ResourceManager
NodeManager | 348 | | ben02 | SecondaryNameNode
DataNode
NodeManager | 349 | | ben03 | DataNode
NodeManager | 350 | 351 | 2.4.2 core-site.xml 352 | 353 | ~~~xml 354 | [root@ben01 ~]# cd $HADOOP_HOME/etc/hadoop/ 355 | [root@ben01 hadoop]# vim core-site.xml 356 | 357 | 358 | fs.defaultFS 359 | hdfs://ben01:8020 360 | 361 | 362 | hadoop.tmp.dir 363 | /usr/local/hadoop/tmp 364 | 365 | 366 | ~~~ 367 | 368 | 2.4.3 hdfs-site.xml 369 | 370 | ~~~xml 371 | [root@ben01 hadoop]# vim hdfs-site.xml 372 | 373 | 374 | 375 | dfs.namenode.name.dir 376 | file://${hadoop.tmp.dir}/dfs/name 377 | 378 | 379 | 380 | dfs.datanode.data.dir 381 | file://${hadoop.tmp.dir}/dfs/data 382 | 383 | 384 | 385 | dfs.replication 386 | 3 387 | 388 | 389 | 390 | dfs.blocksize 391 | 134217728 392 | 393 | 395 | 396 | dfs.namenode.secondary.http-address 397 | ben02:50090 398 | 399 | 400 | 401 | dfs.namenode.http-address 402 | ben01:50070 403 | 404 | 405 | ~~~ 406 | 407 | 2.4.4 mapred-site.xml 408 | 409 | ~~~xml 410 | [root@ben01 hadoop]# vim mapred-site.xml 411 | 412 | 413 | 414 | mapreduce.framework.name 415 | yarn 416 | 417 | 418 | 419 | mapreduce.jobhistory.address 420 | ben01:10020 421 | 422 | 423 | 424 | mapreduce.jobhistory.webapp.address 425 | ben01:19888 426 | 427 | 428 | 429 | yarn.app.mapreduce.am.env 430 | HADOOP_MAPRED_HOME=/usr/local/hadoop 431 | 432 | 433 | mapreduce.map.env 434 | HADOOP_MAPRED_HOME=/usr/local/hadoop 435 | 436 | 437 | mapreduce.reduce.env 438 | HADOOP_MAPRED_HOME=/usr/local/hadoop 439 | 440 | 441 | ~~~ 442 | 443 | 2.4.5 yarn-site.xml 444 | 445 | ~~~xml 446 | [root@ben01 hadoop]# vim yarn-site.xml 447 | 448 | 449 | 450 | 451 | 452 | yarn.nodemanager.aux-services 453 | mapreduce_shuffle 454 | 455 | 456 | 457 | yarn.resourcemanager.hostname 458 | ben01 459 | 460 | 461 | 462 | 463 | yarn.nodemanager.aux-services.mapreduce_shuffle.class 464 | org.apache.hadoop.mapred.ShuffleHandler 465 | 466 | 467 | 468 | 469 | yarn.resourcemanager.address 470 | ben01:8032 471 | 472 | 473 | 474 | yarn.resourcemanager.scheduler.address 475 | ben01:8030 476 | 477 | 478 | 479 | yarn.resourcemanager.resource-tracker.address 480 | ben01:8031 481 | 482 | 483 | 484 | yarn.resourcemanager.admin.address 485 | ben01:8033 486 | 487 | 488 | 489 | yarn.resourcemanager.webapp.address 490 | ben01:8088 491 | 492 | 493 | 494 | ~~~ 495 | 496 | 2.4.6 hadoop-env.sh 497 | 498 | ~~~shell 499 | [root@ben01 hadoop]# vi hadoop-env.sh 500 | ...... 501 | # The java implementation to use. By default, this environment 502 | export JAVA_HOME=/usr/local/jdk 503 | ...... 504 | ~~~ 505 | 506 | 2.4.7 yarn-env.sh 507 | 508 | ~~~sh 509 | [root@ben01 hadoop]# vi yarn-env.sh 510 | ......... 511 | # some Java parameters 512 | export JAVA_HOME=/usr/local/jdk 513 | if [ "$JAVA_HOME" != "" ]; then 514 | #echo "run java in $JAVA_HOME" 515 | JAVA_HOME=$JAVA_HOME 516 | fi 517 | ......... 518 | ~~~ 519 | 520 | 2.4.8 workers 521 | 522 | 此文件用于指定datanode守护进程所在的机器点主机名 523 | 524 | ~~~sh 525 | [root@ben01 hadoop]# cat workers 526 | ben01 527 | ben02 528 | ben03 529 | ~~~ 530 | 531 | > **注意**:2.x版本,是添加一个slaves文件,内容与上面一致 532 | 533 | 2.4.9 分发到另外两台节点 534 | 535 | ~~~sh 536 | [root@ben01 etc]# cd /usr/local/ 537 | [root@ben01 local]# scp -r hadoop ben02:$PWD 538 | [root@ben01 local]# scp -r hadoop ben03:$PWD 539 | 540 | # 同步profile到另两台 541 | [root@ben01 local]# scp /etc/profile ben02:/etc 542 | [root@ben01 local]# scp /etc/profile ben03:/etc 543 | ~~~ 544 | 545 | 546 | 547 | #### 2.5 格式化与启动 548 | 549 | 2.5.1 格式化集群 550 | 551 | 1)在ben01机器上运行命令 552 | 553 | ~~~sh 554 | [root@ben01 local]# hdfs namenode -format 555 | ~~~ 556 | 557 | ![1657871956423](assets/1657871956423.png) 558 | 559 | > **用户切换,或权限不足的报错** 560 | > 561 | > ![1657876970998](assets/1657876970998.png) 562 | > 563 | > **原因** 564 | > 565 | > 用户切换,或权限不足 566 | > 567 | > **解决办法** 568 | > 569 | > 将上面的hadoop-env.sh文件,添加如下内容 570 | > 571 | > ~~~sh 572 | > export HDFS_NAMENODE_USER=root 573 | > export HDFS_DATANODE_USER=root 574 | > export HDFS_SECONDARYNAMENODE_USER=root 575 | > export YARN_RESOURCEMANAGER_USER=root 576 | > export YARN_NODEMANAGER_USER=root 577 | > ~~~ 578 | 579 | 2)格式化的相关信息解读 580 | 581 | ~~~sh 582 | --1.生成一个集群唯一标识符:clusterID 583 | --2.生成一个块池唯一标识符:blockPoolID 584 | --3.生成namenode进程管理内容(fsimage)的存储路径: 585 | 默认配置文件属性hadoop.tmp.dir指定的路径下生成dfs/name目录 586 | --4.生成就想fsimage,记录分布式文件系统根路径的元数据 587 | --5.其它信息都可以查看下,比如块的副本数,集群的fsOwner等 588 | ~~~ 589 | 590 | 3)目录里的内容查看 591 | 592 | ![1657871956423](assets/1657873094885.png) 593 | 594 | 2.5.2 启动集群 595 | 596 | 1)启动脚本和关闭脚本介绍 597 | 598 | ~~~sh 599 | 1.启动脚本 600 | -- start-dfs.sh :用于启动hdfs集群的脚本 601 | -- start-yarn.sh :用于启动yarn守护进程 602 | -- start-all.sh :用于启动hdfs和yarn 603 | 2.关闭脚本 604 | -- stop-dfs.sh :用于关闭hdfs集群的脚本 605 | -- stop-yarn.sh :用于关闭yarn守护进程 606 | -- stop-all.sh :用于关闭hdfs和yarn 607 | 3.单个守护进程脚本 608 | -- hadoop-daemons.sh :用于单独启动或关闭的某一个守护进程的脚本 609 | -- hadoop-daemon.sh :用于单独启动或关闭hdfs的某一个守护进程的脚本 610 | reg: 611 | hadoop-daemon.sh [start|stop] [namenode|datanode|secondarynamenode] 612 | 613 | -- yarn-daemons.sh :用于单独启动或关闭hdfs的某一个守护进程的脚本 614 | -- yarn-daemon.sh :用于单独启动或关闭hdfs的某一个守护进程的脚本 615 | reg: 616 | yarn-daemon.sh [start|stop] [resourcemanager|nodemanager] 617 | ~~~ 618 | 619 | 2)启动HDFS 620 | 621 | ~~~sh 622 | [root@ben01 hadoop]# start-dfs.sh 623 | ~~~ 624 | 625 | ![1658131281677](assets/1658131281677.png) 626 | 627 | > **主机间没做免密的报错** 628 | > 629 | > ![1658122834445](assets/1658122834445.png) 630 | 631 | 3)验证,jps查看进程,具体如下 632 | 633 | ~~~sh 634 | [root@ben01 hadoop]# jps 635 | 29411 NameNode 636 | 8233 Jps 637 | 29609 DataNode 638 | 639 | [root@ben02 hadoop]# jps 640 | 19457 Jps 641 | 18914 DataNode 642 | 19127 SecondaryNameNode 643 | 644 | [root@ben03 hadoop]# jps 645 | 19252 Jps 646 | 17960 DataNode 647 | ~~~ 648 | 649 | 4)启动yarn 650 | 651 | ~~~sh 652 | [root@ben01 hadoop]# start-yarn.sh 653 | ~~~ 654 | 655 | > 成功图如下: 656 | > 657 | > ![1658131502394](assets/1658131502394.png) 658 | 659 | jps查看如下 660 | 661 | ~~~sh 662 | [root@ben01 hadoop]# jps 663 | 10352 Jps 664 | 29411 NameNode 665 | 29609 DataNode 666 | 9646 ResourceManager 667 | 9838 NodeManager 668 | 669 | [root@ben02 hadoop]# jps 670 | 18914 DataNode 671 | 31219 NodeManager 672 | 19127 SecondaryNameNode 673 | 31561 Jps 674 | 675 | [root@ben03 ~]# jps 676 | 30023 NodeManager 677 | 17960 DataNode 678 | 31913 Jps 679 | ~~~ 680 | 681 | 5)WebUI查看 682 | 683 | ~~~sh 684 | HDFS: http://1.13.169.142:50070 685 | YARN: http://1.13.169.142:8088 686 | ~~~ 687 | 688 | > 如果是云厂买的注意开放对应端口,效果图如下 689 | > 690 | > ![1658132018864](assets/1658132018864.png) 691 | > 692 | > ![1658132110932](assets/1658132110932.png) 693 | 694 | 致此,恭喜你,hadoop集群已安装完成。 695 | 696 | > 需要关机的话,先stop-all.sh停止服务,开机后再start-all.sh启动 697 | 698 | 699 | 700 | ### 三. HDFS的Shell命令 701 | 702 | 简介 703 | 704 | ~~~sh 705 | HDFS是一个分布式文件系统,我们可以使用一些命令来操作这个分布式文件系统上的文件。 706 | -- 访问HDFS的命令: 707 | hdfs dfs 708 | 709 | -- 小技巧 710 | 1.在命令行中输入hdfs,回车后,就会提示hdfs可以使用哪些明了,其中一个是dfs 711 | 2.在命令行中输入hdfs dfs,回车后,就会提示dfs可以添加哪些常用shell命令 712 | 713 | -- 注意事项 714 | 分布式文件系统的路径在命令行中,要从/开始写,即绝对路径。 715 | ~~~ 716 | 717 | #### 3.1 创建目录 718 | 719 | ~~~sh 720 | [-mkdir [-p] ...] #分布式文件系统上创建目录 -p,多层级创建 721 | 722 | 调用格式:hdfs dfs -mkdir (-p) /目录 723 | 如: 724 | [root@ben01 ~]# hdfs dfs -mkdir /data 725 | [root@ben01 ~]# hdfs dfs -mkdir -p /data/a/b/c 726 | ~~~ 727 | 728 | > 如下图 729 | > 730 | > ![1658136325417](assets/1658136325417.png) 731 | > 732 | > 可以在命令行查看 733 | > 734 | > [root@ben01 ~]# hdfs dfs -ls / 735 | > 736 | > 也可以在UI页面查看 737 | > 738 | > ![1658136476325](assets/1658136476325.png) 739 | 740 | 741 | 742 | #### 3.2 上传命令 743 | 744 | ~~~sh 745 | [-put [-f] [-p] [-l] ... ] # 将本地文件系统的文件上传到分布式文件系统 746 | 747 | 调用格式: hdfs dfs -put /本地文件 /分布式文件系统路径 748 | 注意:直接写/是省略了文件系统的名称hdfs://ip:port 749 | 如: 750 | # 先创建并往文件写内容 751 | [root@ben01 ~]# echo "Hello, ben" > test.txt 752 | [root@ben01 ~]# hdfs dfs -put test.txt /data/ 753 | # 查看上传后的内容 754 | [root@ben01 ~]# hdfs dfs -cat /data/test.txt 755 | ~~~ 756 | 757 | > 效果图如下 758 | > 759 | > ![1658137105576](assets/1658137105576.png) 760 | > 761 | > 同样能在UI页面看到 762 | > 763 | > ![1658137154450](assets/1658137154450.png) 764 | 765 | 766 | 767 | #### 3.3 创建空文件 768 | 769 | ~~~sh 770 | [root@ben01 ~]# hdfs dfs -mkdir /empty 771 | [root@ben01 ~]# hdfs dfs -touchz /empty/emp 772 | ~~~ 773 | 774 | > 效果图如下,大小为0B 775 | > 776 | > ![1658200851074](assets/1658200851074.png) 777 | > 778 | > 注:由于我重启机器了,外网IP有所变化 779 | 780 | 781 | 782 | #### 3.4 向分布式文件系统中的文件里追加内容 783 | 784 | ~~~sh 785 | [root@ben01 ~]# echo "Hello ben" >> e1 786 | [root@ben01 ~]# hdfs dfs -appendToFile e1 /empty/emp 787 | ~~~ 788 | 789 | > 效果图如下,大小为10B 790 | > 791 | > ![1658200889862](assets/1658200889862.png) 792 | 793 | 794 | 795 | #### 3.5 查看指令 796 | 797 | ~~~sh 798 | # 查看分布式文件系统的目录里的内容 799 | [root@ben01 ~]# hdfs dfs -ls / 800 | # 查看分布式文件系统的文件内容 801 | [root@ben01 ~]# hdfs dfs -cat /xxx.txt 802 | # 查看分布式系统的文件内容 803 | [root@ben01 ~]# hdfs dfs -tail /xxx.txt 804 | ~~~ 805 | 806 | 807 | 808 | #### 3.6 下载指令 809 | 810 | ~~~sh 811 | [root@ben01 ~]# hdfs dfs -copyToLocal /empty ./ 812 | ~~~ 813 | 814 | > 效果图![1658207092361](assets/1658207092361.png) 815 | 816 | 817 | 818 | #### 3.7 合并下载 819 | 820 | ~~~sh 821 | # 先创建几个文件 822 | [root@ben01 ~]# echo "Hello ben01" >> file1 823 | [root@ben01 ~]# echo "Hello ben02" >> file2 824 | [root@ben01 ~]# echo "Hello ben03" >> file3 825 | #上传file*文件 826 | [root@ben01 ~]# hdfs dfs -put file* / 827 | 828 | # 合并下载file下的文件到本地file下, 829 | [root@ben01 ~]# hdfs dfs -getmerge /file* ./file 830 | ~~~ 831 | 832 | > 效果图 833 | > 834 | > ![1658207398851](assets/1658207398851.png) 835 | 836 | 837 | 838 | #### 3.8 移动(更名)hdfs中的文件 839 | 840 | ~~~sh 841 | [root@ben01 ~]# hdfs dfs -mv /file1 /empty 842 | ~~~ 843 | 844 | 845 | 846 | #### 3.9 复制hdfs的文件到hdfs的另一个目录 847 | 848 | ~~~sh 849 | [root@ben01 ~]# hdfs dfs -cp /file2 /empty 850 | ~~~ 851 | 852 | 853 | 854 | #### 3.10 删除命令 855 | 856 | ~~~sh 857 | [root@ben01 ~]# hdfs dfs -rm /file* 858 | Deleted /file2 859 | Deleted /file3 860 | 861 | [root@ben01 ~]# hdfs dfs -rmdir /empty/ 862 | # 注:必须是空文件夹 863 | ~~~ 864 | 865 | 866 | 867 | #### 3.11 查看磁盘利用率和文件大小 868 | 869 | ~~~sh 870 | [root@ben01 ~]# hdfs dfs -df -h 871 | Filesystem Size Used Available Use% 872 | hdfs://ben01:8020 147.3 G 255.8 K 127.1 G 0% 873 | 874 | [root@ben01 ~]# hdfs dfs -du -h /data 875 | 0 0 /data/a 876 | 11 33 /data/test.txt 877 | ~~~ 878 | 879 | 880 | 881 | #### 3.12 修改权限 882 | 883 | ~~~sh 884 | [root@ben01 ~]# hdfs dfs -chmod 777 /data 885 | # 页面Permission的drwxr-xr-x刷新后会变为drwxrwxrwx 886 | # 也可以修改Owner和Group 887 | [root@ben01 ~]# hdfs dfs -chown ben:ben /data 888 | # 页面的Owner和Group会从root:supergroup 变为ben:ben 889 | # 再修改回来 890 | [root@ben01 ~]# hdfs dfs -chown root:supergroup /data 891 | ~~~ 892 | 893 | 894 | 895 | #### 3.13 修改文件副本数 896 | 897 | ~~~sh 898 | [root@ben01 ~]# hdfs dfs -setrep 5 /data 899 | Replication 5 set: /data/test.txt 900 | 901 | # 之前data下的test.txt的Replication会从3刷新后变成5 902 | # 再改回来 903 | [root@ben01 ~]# hdfs dfs -setrep 3 /data 904 | Replication 3 set: /data/test.txt 905 | ~~~ 906 | 907 | 908 | 909 | #### 3.14 查看文件的状态 910 | 911 | ~~~sh 912 | [root@ben01 ~]# hdfs dfs -stat %b /data/test.txt 913 | 11 914 | 915 | # 调用格式:hdfs dfs -stat [format] 文件路径 916 | %b: 打印文件大小(目录大小为0) 917 | %n: 打印文件名 918 | %o: 打印block的size 919 | %r: 打印副本数 920 | %y: utc时间 yyyy-MM-dd HH:mm:ss 921 | %Y: 打印自1970年1月1日至今的utc微秒数 922 | %P: 目录打印directory,文件打印regular file 923 | 924 | # 注意: 925 | 1)当使用-stat命令但不指定format时,只打印创建时间,相当于%y 926 | 2)-stat后面只跟目录,%r,%o等打印的都是0,只有文件才有副本和大小 927 | ~~~ 928 | 929 | 930 | 931 | #### 3.15 测试 932 | 933 | ~~~sh 934 | hdfs dfs [generic options] -test -[defsz] 935 | # 参数说明: 936 | -e:文件是否存在,存在返回0 937 | -z:文件是否为空,为空返回0 938 | -d:是否是路径(目录),是返回0 939 | # 如下,存在则返回OK 940 | [root@ben01 ~]# hdfs dfs -test -e /data/test.txt && echo "OK" || echo "NO" 941 | OK 942 | # 已知道没有test111.txt这个文件 943 | [root@ben01 ~]# hdfs dfs -test -e /data/test111.txt && echo "OK" || echo "NO" 944 | NO 945 | ~~~ 946 | 947 | 948 | 949 | ### 四. HDFS块的概念 950 | 951 | #### 4.1 传统型分布式文件系统的缺点 952 | 953 | 现在想象一下这种情况:有四个文件0.5TB的file1,1.2TB的file2,50GB的file3,100GB的file4;有7个服务器,每个服务器上有10个1TB的硬盘。 954 | 955 | ![1658210426284](assets/1658210426284.png) 956 | 957 | 在存储方式上,我们可以将四个文件存储在同一服务器上(当然大于1TB的文件需要切分),那么缺点也暴露了出来: 958 | 959 | 1. 负载不均衡 960 | 961 | ~~~ 962 | 因为文件大小不一致,势必会导致有的节点磁盘的利用率高,有的利用率低 963 | ~~~ 964 | 965 | 2. 网络瓶颈问题 966 | 967 | ~~~ 968 | 一个过大的文件存储在一个节点磁盘上,当并行处理时,每个线程都需要从这个节点磁盘上读取这个文件内容,那么就会出现网络瓶颈问题,不利于分布式的数据处理。 969 | ~~~ 970 | 971 | #### 4.2 HDFS块 972 | 973 | HDFS与其它普通文件系统一样,同样引入了块(Block)的概念,并且块的大小是固定的。块是HDFS系统当中的最小存储单位,在Hadoop2.x中默认大小为128MB。在HDFS上的文件会被拆分成多个块,每个块作为独立的单元进行存储。多个块存放在不同的DataNode上,整个过程中HDFS系统会保证一个块存储在一个数据节点上。另外,如果某个文件大小或最后一个块没有达到128MB,则不会占用整个块空间。 974 | 975 | 以下图为例: 976 | 977 | ![1658211441669](assets/1658211441669.png) 978 | 979 | > 可以看到50G的file3文件会以128MB一个块切分到7台DataNode节点上,每个节点均衡1~2个块 980 | 981 | 982 | 983 | #### 4.3 HDFS块的大小 984 | 985 | HDFS块大小为什么为128MB 986 | 987 | 1. 目的是为了最小化寻址开销时间。 988 | 1. 在I/O开销中,机械硬盘的寻址时间是最耗时的部分,一旦找到第一条记录,剩下的顺序读取效率是非常高的,因此,合适的block大小有助于减少硬盘寻道时间(平衡了硬盘寻道时间、IO时间),提高系统吞吐量。 989 | 2. HDFS寻址开销不仅包括磁盘寻道开销,还包括数据块的定位开销,客户端访问一个文件的流程:名称节点获取组成这个文件的数据块位置列表——>根据位置列表获取到每个数据块的数据节点位置——>数据节点根据数据块信息在本地Linux文件系统中找到对应文件,并返回客户端。 990 | 3. 磁盘的寻址时间为大约5~15ms之间,平均值为10ms,而最小化寻址开销时间普遍认为占1秒的百分之一为最优,那么块的大小就参考1秒的传输速度。 991 | 2. 为了节省内存的使用率 992 | 1. 一个块的元数据大约为150个字节。1亿个块,无论大小,都会占用20G左右的内存。因此块越大,集群相对存储数据就越多。这也暴露了HDFS的一个缺点,不适合存储小文件。 993 | - 不适合小文件的解释,从存储出发:虽然文件不到128M时不能占用整个空间,但是这个块的元数据依然会在内存中占150个字节 994 | - [不适合小文件的解释](),从内存占用出发:假设存储一个块都是占用1M和都是128M,同样存储1PB数据,如果是以1M的小文件存储,占用的内存空间为1PB/1MB×150Byte=150G的内存。如果是以128MB的文件存储,占用空间为1PB/128M×150Byte=1.17G的内存占用。可以看到小文件存储比大文件存储占用更多内存。 995 | 996 | 997 | 998 | #### 4.4 块的相关参数设置 999 | 1000 | ~~~xml 1001 | # 块大小在默认配置文件hdfs-default.xml中,我们可以在hdfs-default.xml中进行重置 1002 | [root@ben01 hadoop]# ll /usr/local/hadoop/etc/hadoop/hdfs-site.xml 1003 | 1004 | dfs.blocksize 1005 | 134217728 1006 | 默认块大小,以字节为单位。可以使用以下后缀(不区分大小写):k,m,g,t,p,e以重新指定大小(例如128k, 512m, 1g等) 1007 | 1008 | 1009 | 1010 | dfs.namenode.fs-limits.min-block-size 1011 | 1048576 1012 | 以字节为单位的最小块大小,由Namenode在创建时强制执行时间。可以防止意外创建带有小块文件降低性能 1013 | 1014 | 1015 | 1016 | dfs.namenode.fs-limits.max-blocks-per-file 1017 | 1048576 1018 | 每个文件的最大块数,由写入时的Namenode执行。这可以防止创建降低性能的最大文件 1019 | 1020 | ~~~ 1021 | 1022 | 1023 | 1024 | #### 4.5 块的存储位置 1025 | 1026 | 在hdfs-site.xml中配置过下面这个属性,这个属性的值就是块在Linux系统上的存储位置 1027 | 1028 | ~~~xml 1029 | 1030 | 1031 | dfs.datanode.data.dir 1032 | file://${hadoop.tmp.dir}/dfs/data 1033 | 1034 | ~~~ 1035 | 1036 | ![1658216074225](assets/1658216074225.png) 1037 | 1038 | 1039 | 1040 | #### 4.6 HDFS的优点 1041 | 1042 | ~~~sh 1043 | 1. 高容错性(硬件故障是常态):数据自动保存多个副本,副本丢失后,会自动恢复。 1044 | 2. 适合大数据集:GB、TB、甚至PB级数据、千万规模以上的文件数量,1000以上节点规模。 1045 | 3. 数据访问:一次性写入,多次读取;保证数据一致性,安全性。 1046 | 4. 构建成本低:可以构建在廉价机器上。 1047 | 5. 多种软硬件平台中的可移植性。 1048 | 6. 高效性:Hadoop能够在节点之间动态的移动数据,并保证各个节点的动态平衡,因此处理速度非常快。 1049 | 7. 高可靠性:Hadoop的存储和处理数据的能力值得人们信赖。 1050 | ~~~ 1051 | 1052 | 1053 | 1054 | #### 4.7 HDFS的缺点 1055 | 1056 | ~~~ 1057 | 1. 不适合做低延迟数据访问: 1058 | HDFS的设计目标是处理大型数据集,高吞吐率。这一点势必以高延迟为代价,因此HDFS不适合处理毫秒级低延迟应用的请求。 1059 | 2. 不适合小文件存取: 1060 | 一个是大量小文件寻址时间浪费以及元数据浪费。 1061 | 3. 不适合并发写入,文件随机修改: 1062 | HDFS上的文件只能拥有一个写着,仅支持append操作,不支持多用户对同一文件的写操作,以及在文件任意位置进行修改。 1063 | ~~~ 1064 | 1065 | 1066 | 1067 | ### 五 HDFS的体系结构 1068 | 1069 | #### 5.1 体系结构解析 1070 | 1071 | ~~~ 1072 | HDFS采用的是master/slaves这种主从的结构模型来管理数据,主要由四个部分组成,分别是Client(客户端)、NameNode(名称节点)、DataNode(数据节点)和SecondaryNameNode。 1073 | 1074 | 一般HDFS集群包括一个NameNode和若干个DataNode。 1075 | 1076 | NameNode是一个中心服务器,负责管理文件系统的命令空间(Namespace),它在内存中维护着命名空间的最新状态,同时对持久性文件(fsimage和edit)进行备份,防止宕机后数据丢失。NameNode还负责管理客户端对文件的访问,如权限验证等。 1077 | 1078 | 集群中的DataNode一般是一个节点运行一个DataNode进程,真正负责管理客户端的读写请求,在NameNode的统一调度下进行数据块的创建、删除和复制等操作。数据块实际上都是保存在DataNode本地的Linux文件系统中。每个DataNode会定期的向NameNode发送数据,报告自己的状态(我们称之为心跳机制)。没有按时发送心跳信息的DataNode会被NameNode标记为“宕机”,不会在给它分配任何I/O请求。 1079 | 1080 | 用户在使用Client进行I/O操作时,依然可以像使用普通文件系统那样,使用文件名去存储和访问文件,只不过在HDFS内部,一个文件会被切分成若干个数据块,并分布存储到若干个DataNode上。 1081 | 1082 | 通过Client访问文件流程如下: 1083 | 客户端把文件名发送给NameNode——>NameNode根据文件名找到对应数据块信息及每个数据块所在DataNode位置——>把这些信息发送给客户端——>客户端直接与DataNode进行通信,获取数据。 1084 | 这种设计的好处在于实现并发访问,大大提高了数据的访问速度。 1085 | 1086 | HDFS集群中只有唯一的NameNode负责所有元数据的管理工作,这种方式保证了DataNode不会脱离NameNode的控制,同时用户数据也永远不会经过NameNode,大大减轻了NameNode的工作负担,使之更方便管理工作。通常在集群中,要选择一套性能较好的机器作为NameNode。当然一台机器可以运行多个DataNode或NameNode和DataNode放在同一机器,只不过实际部署中通常不会这么做。 1087 | ~~~ 1088 | 1089 | ![1658295144547](assets/1658295144547.png) 1090 | 1091 | 1092 | 1093 | #### 5.2 开机启动HDFS的过程 1094 | 1095 | 5.2.1 非第一次启动集群 1096 | 1097 | 我们应该知道,在启动NameNode之前,内存里没有任何有关于元数据的信息的。那么启动集群的过程是怎样的呢?如下: 1098 | 1099 | ~~~ 1100 | 第一步: 1101 | NameNode启动时,会先加载name目录下最近的fsimage文件。 1102 | 将fsimage里保存的元数据加载到内存当中,这样内存里就有之前检查点存储的所有元数据。但还少了从最近一次检查时间点到关闭系统时的部分数据,也就是edit日志文件里存储的数据。 1103 | 1104 | 第二步: 1105 | 加载剩下的edit日志文件 1106 | 将从最近一次检查点到目前为止的所有日志文件加载到内存里,重演一次客户端操作,这样内存里就是最新的文件系统的所有元数据了。 1107 | 1108 | 第三步: 1109 | 进行检查点设置(满足条件会进行) 1110 | namenode会终止之前正在使用的edit文件,创建一个空的edit日志文件。将所有的未合并过的edit日志文件和fsimage文件进行合并,产生一个新的fsimage。 1111 | 1112 | 第四步: 1113 | 处于安全模式下,等待datanode节点的心跳反馈,当收到99.9%的块至少一个副本后,退出安全模式,开始转为正常状态。 1114 | ~~~ 1115 | 1116 | 1117 | 1118 | 5.2.2 非首次启动集群 1119 | 1120 | ![1658298385494](assets/1658298385494.png) 1121 | 1122 | > 作者重启过机器,公网IP有所变化。 1123 | > 1124 | > 首次启动的Loading edits和Saving checkpoint都是空的 1125 | 1126 | 1127 | 1128 | #### 5.3 Secondary NameNode 工作机制 1129 | 1130 | Secondary NameNode 是HDFS集群中的重要组成部分,它可以辅助namenode进行fsimage和editlog的合并工作,减少editlog文件大小,以便缩短下次namenode的重启时间,能尽快退出安全模式。 1131 | 1132 | 两个文件的合并周期,称之为检查点机制(checkpoint),是可以通过hdfs-default.xml配置文件进行修改的: 1133 | 1134 | ~~~xml 1135 | 1136 | dfs.namenode.checkpoint.period 1137 | 3600 1138 | 两次检查点间隔的秒数,默认是1个小时 1139 | 1140 | 1141 | dfs.namenode.checkpoint.txns 1142 | 1000000 1143 | txid执行的次数达到100w次,也执行checkpoint 1144 | 1145 | 1146 | dfs.namenode.checkpoint.check.period 1147 | 60 1148 | 60秒一次检查txid的执行次数 1149 | 1150 | ~~~ 1151 | 1152 | ![1658299068573](assets/1658299068573.png) 1153 | 1154 | 通过上图,可以总结如下: 1155 | 1156 | ~~~ 1157 | 1. SecondaryNameNode请求namenode停止使用正在编辑的editlog文件,namenode会创建新的editlog文件,同时更新seed_tixd文件。 1158 | 2. SecondaryNameNode通过HTTP协议获得namenode上的fsimage和editlog文件。 1159 | 3. SecondaryNameNode将fsimage读进内存当中,并逐步分析editlog文件里的数据,进行合并操作,然后写入新文件fsimage_x.ckpt文件中。 1160 | 4. SecondaryNameNode将新文件fsimage_x.ckpt通过HTTP协议发送回namenode。 1161 | 5. namenode再进行更名操作。 1162 | ~~~ 1163 | 1164 | 1165 | 1166 | ### 六 HDFS的读写流程 1167 | 1168 | #### 6.1 读流程详解 1169 | 1170 | ~~~ 1171 | 读操作: 1172 | - hdfs dfs -get /file2 ./file2 1173 | - hdfs dfs -copyToLocal /file2 ./file2 1174 | - FSDataInputStream fsis = fs.open("/input/a.txt"); 1175 | - fsis.read(byte[] a) 1176 | - fs.copyToLocal(path1,path2) 1177 | ~~~ 1178 | 1179 | ![1658299681037](assets/1658299681037.png) 1180 | 1181 | ~~~ 1182 | 1. 客户端通过调用FileSystem对象的open()方法来打开希望读取的文件,对于HDFS来说,这个对象是DistributedFileSystem,它通过使用远程过程调用(RPC)来调用namenode,以确定文件起始块的位置。 1183 | 1184 | 2. 对于每个块,namenode返回有该块副本的datanode地址,并根据距离客户端的远近来排序。 1185 | 1186 | 3. DistributedFileSystem实例会返回一个FSDataInputStream对象(支持文件定位功能)给客户端以便读取数据,接着客户端对这个输入流调用read() 方法。 1187 | 1188 | 4. FSDataInputStream随即连接距离最近的文件中第一个块所在的datanode,通过对数据流反复调用read()方法,将数据从datanode传输到客户端。 1189 | 1190 | 5. 当读取到块的末端时,FSInputStream关闭与该datanode的连接,然后寻找下一块最佳datanode 1191 | 1192 | 6. 客户端从流中读取数据时,块是按照打开FSInputStream与datanode的新建连接的顺序读取。它也会根据需要询问namenode来检索下一批数据块的datanode位置。一旦客户端完成读取,就对FSInputStream调用close方法。 1193 | 1194 | 注意:在读取数据的时候,如果FSInputStream与datanode通信时遇到错误,会尝试从这个块的最近的datanode读取数据,并且记住那个故障的datanode,保证后续不会反复读取该节点上后续的块。FSInputStream也会通过校验和确认从datanode发来的数据是否完整。如果发现有损坏的块,FSInputStream会从其它的块读取副本,并且将损坏的块通知给namenode。 1195 | ~~~ 1196 | 1197 | 1198 | 1199 | #### 6.2 写流程详解 1200 | 1201 | ~~~ 1202 | 写操作: 1203 | - hdfs dfs -put /file2 ./file2 1204 | - hdfs dfs -copyToLocal /file2 ./file2 1205 | - FSDataOutputStream fsout = fs.create(path); fsout.write(byte[]) 1206 | - fs.copyFromLocal(path1,path2) 1207 | ~~~ 1208 | 1209 | ![1658382022692](assets/1658382022692.png) 1210 | 1211 | ~~~ 1212 | 1. 客户端通过对DistributedFileSystem对象调用create()方法来新建文件 1213 | 1214 | 2. DistributedFileSystem对namenode创建一个RPC调用,在文件系统的命名空间中新建一个文件,此时该文件中还没有相应的数据块。 1215 | 1216 | 3. namenode执行各种不同的检查,以确保这个文件不存在以及客户端有新建该文件的权限。如果检查通过,namenode就会为创建新文件记录一条事务记录(否则,文件创建失败并向客户端跑出一个IOException异常)。DistributedFileSystem向客户端返回一个FSDataOuputStream对象,由此客户端可以写入数据。 1217 | 1218 | 4. 在客户端写入数据时,FSDataOuputStream将它分成一个个的数据包(packet),并写入一个内部队列,这个队列称为“数据队列”(data queue)。DataStreamer线程负责处理数据队列,它的责任是挑选合适存储数据复本的一组datanode,并以此来要去namenode分配新的数据块。这一组datanode将构成一个管道,以默认复本3个为例,所以该管道中有3个节点。DataStreamer将数据包流式传输到管道中第一个datanode,该datanode存储数据包,并将它发送到管道中的第2个datanode。同样,第2个datanode存储该数据包,并发送给管道中的第三个datanode。DataStreamer再将一个个packet流式传到第一个datanode节点后,还会将此packet从数据队列移动到另一个队列 确认队列(ask queue)中。 1219 | 1220 | 5. datanode写入数据成功之后,会为ResponseProcessor线程发送一个写入成功的信息回执,当收到管道中所有的datanode确认信息后,ResponseProcessor线程会将该数据包从确认队列中删除。 1221 | ~~~ 1222 | 1223 | 如果任何datanode在写入期间发生故障,则执行以下操作: 1224 | 1225 | ~~~~ 1226 | 1. 首先关闭管道,把确认队列中的所有数据包添加回数据队列的最前端,以确保故障节点下游的datanode不会漏掉任何一个数据包。 1227 | 1228 | 2. 为存储在另一个正常datanode的当前数据块制定一个新标识,并将该标识传送给namenode,以便故障datanode在恢复后可以删除存储的部分数据块。 1229 | 1230 | 3. 从管道中删除故障datanode,基于两个正常datanode构建一条新管道,余下数据块写入管道中正常的datanode。 1231 | 1232 | 4. namenode注意到块复本不足时,会在一个新的datanode节点上创建一个新的复本。 1233 | 1234 | 注意:一个块被写入期间可能会有多个datanode同时发生故障,但概率非常低。只要写入了。 1235 | dfs.namenode.replication.min的复本数(默认1),写操作就会成功,并且这个块可以在集群中异步复制,直到达到其目标复本数dfs.replication的数量(默认3) 1236 | ~~~~ 1237 | 1238 | 1239 | 1240 | ### 七. Zookeeper的概述 1241 | 1242 | #### 7.1 Zookeeper是什么 1243 | 1244 | 1. Zookeeper是一个分布式应用程序提供的一个分布式开源协调服务框架。是Hadoop和Hbase的重要组件,主要用于解决分布式集群中应用系统的一致性问题。 1245 | 2. 提供了基于Unix系统的目录节点树方式的数据存储。 1246 | 3. 可用于维护和监控存储的数据的变化,通过监控这些数据状态的变化,从而达到基于数据的集群管理 1247 | 4. 提供了一组原语(机器指令),提供Java和C语言的接口。 1248 | 1249 | 1250 | 1251 | #### 7.2 Zookeeper的特点 1252 | 1253 | 1. 一个分布式集群,一个领导者(leader),多个跟随着(follower)。 1254 | 2. 集群中只要有半数以上的节点存活,Zookeeper集群就能正常服务。 1255 | 3. 全局数据一致性:每个server保存一份相同的数据副本,client无论连接到哪个server,数据都是一致的。 1256 | 4. 更新请求按顺序进行:来自同一个client的更新请求按其发送顺序依次执行。 1257 | 5. 数据更新的原子性:一次数据的更新要么成功,要么失败。 1258 | 6. 数据的实用性:在一定时间范围内,client能读到最新数据。 1259 | 1260 | ![1658384907909](assets/1658384907909.png) 1261 | 1262 | 1263 | 1264 | #### 7.3 Zookeeper的数据模型 1265 | 1266 | Zookeeper的数据模型采用的与Unix文件系统类似的层次化的树形结构。我们可以将其理解为一个具有高可用特征的文件系统。这个文件系统中没有文件和目录,而是统一使用“节点”(node)的概念,称之为znode。znode既可以作为保存数据的容器(如同文件),也可以作为保存其它znode的容器(如同目录)。所有的znode构成了一个层次化的命名空间。 1267 | 1268 | ![1658385384460](assets/1658385384460.png) 1269 | 1270 | > - Zookeeper 被设计用来实现协调服务(这类服务通常使用小数据文件),而不是用于大容量数据存储,因此一个znode能存储的数据被限制在1MB以内。 1271 | > - 每个znode都可以通过其路径唯一标识。 1272 | 1273 | 1274 | 1275 | #### 7.4 Zookeeper的应用场景 1276 | 1277 | 1. 统一配置管理 1278 | 2. 统一集群管理 1279 | 3. 服务器节点动态上下线感知 1280 | 4. 软负载均衡 1281 | 5. 分布式锁 1282 | 6. 分布式队列 1283 | 1284 | 1285 | 1286 | ### 八. Zookeeper的安装 1287 | 1288 | #### 8.1 安装与环境变量的配置 1289 | 1290 | ~~~sh 1291 | # 1. 将Zookeeper-3.4.10.tar.gz上传到/root中 1292 | # 2. 解压 1293 | [root@ben01 softwares]# tar -zxvf zookeeper-3.4.10.tar.gz -C /usr/local 1294 | # 3. 更名 1295 | [root@ben01 ~]# cd /usr/local 1296 | [root@ben01 local]# mv zookeeper-3.4.10 zookeeper 1297 | # 4. 配置环境变量 1298 | [root@ben01 local]# vi /etc/profile 1299 | ...... 1300 | #zk environment 1301 | export ZOOKEEPER_HOME=/usr/local/zookeeper 1302 | export PATH=$ZOOKEEPER_HOME/bin:$PATH 1303 | # 5. 使得当前会话生效 1304 | [root@ben01 local]# source /etc/profile 1305 | # 6. 检测是否生效 1306 | # 配置成功后,tab键可补全zk,有zk相关脚本提示即可。 1307 | ~~~ 1308 | 1309 | 1310 | 1311 | #### 8.2 集群模式的配置 1312 | 1313 | 8.2.1 Zookeeper的服务进程布局 1314 | 1315 | ~~~ 1316 | ben01 QuorumPeerMain 1317 | ben02 QuorumPeerMain 1318 | ben03 QuorumPeerMain 1319 | ~~~ 1320 | 1321 | 8.2.2 修改zoo.cfg文件 1322 | 1323 | ~~~sh 1324 | [root@ben01 local]# cd ./zookeeper/conf/ 1325 | [root@ben01 conf]# cp zoo_sample.cfg zoo.cfg 1326 | # 修改存储路径(需要创建)并添加三个服务节点 1327 | [root@ben01 conf]# vim zoo.cfg 1328 | tickTime=2000 # 定义时间单元(单位毫秒),下面的两个值都是tickTime的倍数 1329 | initLimit=10 # follower连接并同步leader的初始化事件 1330 | syncLimit=5 # 心跳机制的时间(正常情况下的请求和应答的时间) 1331 | dataDir=/usr/local/zookeeper/zkData # 修改zk的存储路径,需要创建zkData目录 1332 | clientPort=2181 # 客户端连接服务器的port 1333 | server.1=ben01:2888:3888 # 添加三个服务器节点 1334 | server.2=ben02:2888:3888 1335 | server.3=ben03:2888:3888 1336 | 1337 | # 保存并退出 1338 | [root@ben01 conf]# mkdir ../zkData 1339 | [root@ben01 conf]# ll /usr/local/zookeeper/zkData 1340 | 总用量 0 1341 | 1342 | # 解析Server.id=ip:port1:port2 1343 | id:服务器的id号,对应zkData/myid文件内的数字 1344 | ip:服务器的ip地址 1345 | port1:follower与leader交互的port 1346 | port2:选举期间使用的port 1347 | ~~~ 1348 | 1349 | > ~~~sh 1350 | > [root@ben01 conf]# cat zoo.cfg 1351 | > tickTime=2000 1352 | > initLimit=10 1353 | > syncLimit=5 1354 | > dataDir=/usr/local/zookeeper/zkData 1355 | > clientPort=2181 1356 | > server.1=ben01:2888:3888 1357 | > server.2=ben02:2888:3888 1358 | > server.3=ben03:2888:3888 1359 | > 1360 | > ~~~ 1361 | 1362 | 8.2.3 添加myid 1363 | 1364 | ~~~sh 1365 | # $ZOOKEEPER_HOME/zkData目录下添加myid文件,内容为server的id号 1366 | [root@ben01 zookeeper]# cd /usr/local/zookeeper/zkData 1367 | [root@ben01 zkData]# echo "1" >> myid 1368 | ~~~ 1369 | 1370 | 8.2.4 搭建其它两台server节点的环境 1371 | 1372 | 1)使用scp命令将zk环境复制到ben02、ben03中 1373 | 1374 | ~~~sh 1375 | [root@ben01 zkData]# cd /usr/local/ 1376 | [root@ben01 local]# scp -r zookeeper ben02:/usr/local/ 1377 | [root@ben01 local]# scp -r zookeeper ben03:/usr/local/ 1378 | ~~~ 1379 | 1380 | 2)使用scp命令拷贝/etc/profile到两台机器上 1381 | 1382 | ~~~sh 1383 | [root@ben01 local]# scp /etc/profile ben02:/etc/ 1384 | [root@ben01 local]# scp /etc/profile ben03:/etc/ 1385 | ~~~ 1386 | 1387 | 3)source,并修改ben02的myid文件为2 1388 | 1389 | ~~~sh 1390 | [root@ben02 ~]# source /etc/profile 1391 | [root@ben02 ~]# echo "2" > /usr/local/zookeeper/zkData/myid 1392 | ~~~ 1393 | 1394 | 4)source,并修改ben02的myid文件为3 1395 | 1396 | ~~~sh 1397 | [root@ben03 ~]# source /etc/profile 1398 | [root@ben03 ~]# echo "3" > /usr/local/zookeeper/zkData/myid 1399 | ~~~ 1400 | 1401 | 8.2.5 启动zk 1402 | 1403 | 1)三台机器上都启动zk(防火墙需是关闭状态) 1404 | 1405 | ~~~sh 1406 | [root@ben01 local]# zkServer.sh start 1407 | ZooKeeper JMX enabled by default 1408 | Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg 1409 | Starting zookeeper ... STARTED 1410 | # 此时查看状态提示还没运行起来 1411 | [root@ben01 local]# zkServer.sh status 1412 | ZooKeeper JMX enabled by default 1413 | Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg 1414 | Error contacting service. It is probably not running. 1415 | # 查看jps,已经能看到QuorumPeerMain了,说明启动了,但由于zk是三节点,最低要求有半数以上的节点可用,所以还需启动ben02上的zk 1416 | [root@ben01 local]# jps 1417 | 801 Jps 1418 | 22898 ResourceManager 1419 | 22281 DataNode 1420 | 23100 NodeManager 1421 | 22078 NameNode 1422 | 719 QuorumPeerMain 1423 | 1424 | [root@ben02 ~]# zkServer.sh start 1425 | ZooKeeper JMX enabled by default 1426 | Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg 1427 | Starting zookeeper ... STARTED 1428 | # 可以看到状态是已经成功的 1429 | [root@ben02 ~]# zkServer.sh status 1430 | ZooKeeper JMX enabled by default 1431 | Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg 1432 | Mode: leader 1433 | [root@ben02 ~]# jps 1434 | 21762 NodeManager 1435 | 21330 DataNode 1436 | 2565 Jps 1437 | 1958 QuorumPeerMain 1438 | 21535 SecondaryNameNode 1439 | 1440 | 1441 | [root@ben03 ~]# zkServer.sh start 1442 | ZooKeeper JMX enabled by default 1443 | Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg 1444 | Starting zookeeper ... STARTED 1445 | [root@ben03 ~]# zkServer.sh status 1446 | ZooKeeper JMX enabled by default 1447 | Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg 1448 | Mode: follower 1449 | [root@ben03 ~]# jps 1450 | 19713 Jps 1451 | 21619 DataNode 1452 | 21929 NodeManager 1453 | 2319 QuorumPeerMain 1454 | ~~~ 1455 | 1456 | 2)启动客户端(ben01) 1457 | 1458 | ~~~sh 1459 | [root@ben01 local]# zkCli.sh 1460 | [zk: localhost:2181(CONNECTED) 0] ls 1461 | [zk: localhost:2181(CONNECTED) 1] quit 1462 | # 退出,连到指定的zk机器 1463 | [root@ben01 local]# zkCli.sh -server ben02:2181 1464 | [zk: ben02:2181(CONNECTED) 0] quit 1465 | ~~~ 1466 | 1467 | 1468 | 1469 | ### 九. Zookeeper的shell操作 1470 | 1471 | | 命令 | 描述 | 示例 | 1472 | | ------ | ------------------------------------------------------------ | ----------------------------------------------- | 1473 | | ls | 查看某个目录包含的所有文件 | ls / | 1474 | | ls2 | 查看某个目录包含的所有文件,与ls不同的是它查看到time、version等信息 | ls2 / | 1475 | | create | 修改znode,并需要设置初始内容 | create /test "test"
create -e /test "test" | 1476 | | get | 获取znode的数据 | get /test | 1477 | | set | 修改znode的内容 | set /test "test2" | 1478 | | delete | 删除znode | delete /test | 1479 | | quit | 退出客户端 | | 1480 | | help | 帮助命令 | | 1481 | 1482 | 1483 | 1484 | ### 十. YARN的概述 1485 | 1486 | 为了克服Hadoop 1.x中HDFS和MapReduce存在的各种问题而提出的,针对Hadoop1.x中的MapReduce在扩展性和多框架支持方面的不足,提出了全选的资源管理框架YARN。 1487 | 1488 | Apache YARN是Hadoop集群的资源管理系统,负责为计算程序提供服务器计算资源,相当于一个分布式的操作系统平台,而MapReduce等计算程序则相当于操作系统之上的应用程序。 1489 | 1490 | YARN被引入Hadoop2,最初是为了改善MapReduce的实现,但因其足够的通用性,又支持其他的分布式计算模式,如Spark、Tez等结算框架,逐渐取代原有MapReduce的位置,MapReduce进行了完全重构,发生了根本上的改变,是运行在YARN之上的分布式应用程序。 1491 | 1492 | ![1658820940897](assets/1658820940897.png) 1493 | 1494 | 1495 | 1496 | ### 十一. YARN的架构及组件 1497 | 1498 | #### 11.1 MapReduce 1.x的简介 1499 | 1500 | 第一代Hadoop,由分布式存储系统hdfs和分布式计算框架MapReduce组成,其中,hdfs由一个NameNode和多个DataNode组成,MapReduce由一个JobTracker和多个TaskTracker组成,对应Hadoop版本为Hadoop 1.x和0.21.x,0.22.x。 1501 | 1502 | 1)MapReduce 1 的角色 1503 | 1504 | ~~~ 1505 | -- 1.Client:作业提交发起者 1506 | -- 2.JobTracker:初始化作业,分配作业,与TackTracker通信,协调整个作业。 1507 | -- 3.TaskTracker:保持JobTracker通信,在分配的数据片段上执行MapReduce任务。 1508 | ~~~ 1509 | 1510 | ![1658821617982](assets/1658821617982.png) 1511 | 1512 | 2)MapReduce执行流程 1513 | 1514 | ![1658821646593](assets/1658821646593.png) 1515 | 1516 | > ~~~ 1517 | > 步骤1 提交作业 1518 | > 编写MapReduce程序代码,创建job对象,并进行配置,比如输入和输出路径,压缩格式等,然后通过JobClient来提交作业。 1519 | > 1520 | > 步骤2 作业的初始化 1521 | > 客户提交完成后,JobTracker会将作业加入队列,然后进行调度,默认的调度方法是FIFO调试方法。 1522 | > 1523 | > 步骤3 任务的分配 1524 | > TaskTracker和JobTracker之间的通信与任务的分配是通过心跳机制完成的。 1525 | > TaskTracker会主动向JobTracker询问是否有作业要做,如果自己可以做,那么就会申请到作业任务,这个任务可以是MapTask也可以是ReduceTask。 1526 | > 1527 | > 步骤4 任务的执行 1528 | > 申请到后,TaskTracker会做如下事情: 1529 | > - 1.拷贝代码到本地 1530 | > - 2.拷贝任务的信息到本地 1531 | > - 3.启动JVM运行任务 1532 | > 1533 | > 步骤5 状态与任务的更新 1534 | > 任务在运行过程中,首先会将自己的状态汇报给TaskTracker,然后由TaskTracker汇总给JobTracker。任务进度是通过计数器来实现的。 1535 | > 1536 | > 步骤6 作业的完成 1537 | > JobTracker是在接受到最后一个任务运行完成后,才会将任务标记为成功,此时会做删除中间结果等善后工作。 1538 | > ~~~ 1539 | 1540 | 1541 | 1542 | #### 11.2 YARN的设计思想 1543 | 1544 | YARN的基本思想是将资源管理和作业调度/监控功能划分为单独的守护进程。其思想是拥有一个全局ResourceManager(RM),以及每个应用程序拥有一个ApplicationMaster(AM)。应用程序可以是单个作业,也可以是一组作业 1545 | 1546 | ![1658823164088](assets/1658823164088.png) 1547 | 1548 | 一个ResourceManager和多个NodeManager构成了yarn资源管理框架。他们是yarn启动后长期运行的守护进程,来提供核心服务。 1549 | 1550 | ~~~ 1551 | ResourceManager 是在系统中的所有应用程序之间仲裁资源的最终权威,即管理整个集群上的所有资源分配,内部含有一个Scheduler(资源调度器) 1552 | 1553 | NodeManager 是每台机器的资源管理器,也就是单个节点的管理者,负责启动和监视容器(container)资源使用情况,并向ResourceManager及其Scheduler报告使用情况 1554 | 1555 | Container 是集群上的可用资源,包含cpu、内存、磁盘、网络等 1556 | 1557 | ApplicationMaster(AM) 实际上是框架的特定库,每启动一个应用程序,都会启动一个AM,它的任务是与ResourceManager协商资源,并与NodeManager一起执行和监视任务。 1558 | ~~~ 1559 | 1560 | 扩展)YARN与MapReduce 1的比较 1561 | 1562 | | MapReduce 1 | YARN | 1563 | | ----------- | ----------------------------------------------------- | 1564 | | Jobtracker | Resource manager, application master, timeline server | 1565 | | Tasktracker | Node manager | 1566 | | Slot | Container | 1567 | 1568 | 1569 | 1570 | #### 11.3 YARN的配置 1571 | 1572 | YARN属于Hadoop的一个组件,不需要再单独安装程序,Hadoop中已存在配置文件的设置,本身就是一个集群,有主节点和从节点。 1573 | 1574 | ~~~ 1575 | 注意之间的值不能有空格 1576 | ~~~ 1577 | 1578 | 在mapred-site.xml中的配置如下: 1579 | 1580 | > 无需再配 1581 | 1582 | ~~~xml 1583 | 1584 | 1585 | 1586 | mapreduce.framework.name 1587 | yarn 1588 | 1589 | 1590 | 1591 | mapreduce.jobhistory.address 1592 | ben01:10020 1593 | 1594 | 1595 | 1596 | mapreduce.jobhistory.webapp.address 1597 | ben01:19888 1598 | 1599 | 1600 | 1601 | yarn.app.mapreduce.am.env 1602 | HADOOP_MAPRED_HOME=/usr/local/hadoop 1603 | 1604 | 1605 | mapreduce.map.env 1606 | HADOOP_MAPRED_HOME=/usr/local/hadoop 1607 | 1608 | 1609 | mapreduce.reduce.env 1610 | HADOOP_MAPRED_HOME=/usr/local/hadoop 1611 | 1612 | 1613 | ~~~ 1614 | 1615 | 在yarn-site.xml中的配置如下: 1616 | 1617 | > 无需再配 1618 | 1619 | ~~~xml 1620 | 1621 | 1622 | 1623 | 1624 | 1625 | yarn.nodemanager.aux-services 1626 | mapreduce_shuffle 1627 | 1628 | 1629 | 1630 | yarn.resourcemanager.hostname 1631 | ben01 1632 | 1633 | 1634 | 1635 | yarn.nodemanager.aux-services.mapreduce_shuffle.class 1636 | org.apache.hadoop.mapred.ShuffleHandler 1637 | 1638 | 1639 | 1640 | 1641 | yarn.resourcemanager.address 1642 | ben01:8032 1643 | 1644 | 1645 | 1646 | yarn.resourcemanager.scheduler.address 1647 | ben01:8030 1648 | 1649 | 1650 | 1651 | yarn.resourcemanager.resource-tracker.address 1652 | ben01:8031 1653 | 1654 | 1655 | 1656 | yarn.resourcemanager.admin.address 1657 | ben01:8033 1658 | 1659 | 1660 | 1661 | yarn.resourcemanager.webapp.address 1662 | ben01:8088 1663 | 1664 | 1665 | ~~~ 1666 | 1667 | 1)日志位置 1668 | 1669 | ~~~sh 1670 | jps:当启动进程时出错后的解决步骤 1671 | 1672 | 如果是hdfs上的问题,则查看对应的日志 1673 | less 或 tail -1000 $HADOOP_HOME/logs/hadoop-{user.name}-{jobname}-{hostname}.log 1674 | 如果是yarn则查看 1675 | less 或 tail -1000 $HADOOP_HOME/logs/yarn-{user.name}-{jobname}-{hostname}.log 1676 | ~~~ 1677 | 1678 | 2)历史服务 1679 | 1680 | ~~~sh 1681 | 如果需要查看YARN作业历史,需要打开历史服务: 1682 | # 1.先停止当前YARN进程 1683 | [root@ben01 ~]# jps 1684 | 22898 ResourceManager 1685 | 20324 Jps 1686 | 22281 DataNode 1687 | 23100 NodeManager 1688 | 22078 NameNode 1689 | 719 QuorumPeerMain 1690 | 1691 | [root@ben01 ~]# stop-yarn.sh 1692 | [root@ben01 ~]# jps 1693 | 26176 Jps 1694 | 22281 DataNode 1695 | 22078 NameNode 1696 | 719 QuorumPeerMain 1697 | # 可以看到有关yarn的服务都停了,如Nodemanager、ResourceManager,另外两台机器也可以看到Nodemanager已关闭。 1698 | 1699 | # 2.打开并添加配置 1700 | [root@ben01 ~]# cd /usr/local/hadoop/etc/hadoop/ 1701 | [root@ben01 hadoop]# vim yarn-site.xml 1702 | 1703 | ...... 1704 | 1705 | 1706 | yarn.log-aggregation-enable 1707 | true 1708 | 1709 | 1710 | 1711 | yarn.log-aggregation.retain-seconds 1712 | 640800 1713 | 1714 | 1715 | 1716 | # 3.分发到其它节点 1717 | [root@ben01 hadoop]# scp yarn-site.xml ben02:$PWD 1718 | [root@ben01 hadoop]# scp yarn-site.xml ben03:$PWD 1719 | 1720 | # 4.启动YARN进程 1721 | [root@ben01 hadoop]# start-yarn.sh 1722 | [root@ben01 hadoop]# jps 1723 | 20336 ResourceManager 1724 | 20547 NodeManager 1725 | 22772 Jps 1726 | 22281 DataNode 1727 | 22078 NameNode 1728 | 719 QuorumPeerMain 1729 | 1730 | # 5.开启历史服务 1731 | [root@ben01 hadoop]# mapred --daemon start historyserver 1732 | [root@ben01 hadoop]# jps 1733 | 20336 ResourceManager 1734 | 32672 Jps 1735 | 20547 NodeManager 1736 | 22281 DataNode 1737 | 26381 JobHistoryServer 1738 | 22078 NameNode 1739 | 719 QuorumPeerMain 1740 | # 可以看到JobHistoryServer已经有了 1741 | ~~~ 1742 | 1743 | 1744 | 1745 | ### 阶段关机需要做的操作 1746 | 1747 | ~~~sh 1748 | # 关机前需要关闭的服务,zk(zk需要三台机器都操作)、hadoop、作业任务 1749 | [root@ben01 ~]# zkServer.sh stop 1750 | [root@ben02 ~]# zkServer.sh stop 1751 | [root@ben03 ~]# zkServer.sh stop 1752 | [root@ben01 ~]# mapred --daemon stop historyserver 1753 | [root@ben01 ~]# stop-all.sh 1754 | [root@ben01 ~]# jps 1755 | 32672 Jps 1756 | 1757 | # 开机需要开启的服务 1758 | [root@ben01 ~]# start-all.sh 1759 | # 此时查看三台机器的jps可以看到服务启动的内容 1760 | [root@ben01 ~]# zkServer.sh start 1761 | [root@ben02 ~]# zkServer.sh start 1762 | [root@ben03 ~]# zkServer.sh start 1763 | [root@ben01 ~]# mapred --daemon start historyserver 1764 | [root@ben01 ~]# jps 1765 | 19507 Jps 1766 | 13193 DataNode 1767 | 14012 NodeManager 1768 | 15724 QuorumPeerMain 1769 | 12972 NameNode 1770 | 13821 ResourceManager 1771 | 19343 JobHistoryServer 1772 | ~~~ 1773 | 1774 | 1775 | 1776 | ### 十二. YARN的执行原理 1777 | 1778 | 在MR程序运行时,有五个独立的进程: 1779 | 1780 | ~~~sh 1781 | -- YarnRunner:用于提交作业的客户端程序 1782 | -- ResourceManager:yarn资源管理器,负责协调集群上计算机资源的分配 1783 | -- NodeManager:yarn节点管理器,负责启动和监视集群中机器上的计算容器(container) 1784 | -- Application Master:负责协调运行MapReduce作业的任务,它和任务都在容器中运行,这些容器由资源管理器分配并由节点管理器进行管理。 1785 | -- HDFS:用于共享作业所需文件。 1786 | ~~~ 1787 | 1788 | 整个过程如下图描述: 1789 | 1790 | ![1658887440421](assets/1658887440421.png) 1791 | 1792 | > ~~~sh 1793 | > 1. 调用waitForCompletion方法每秒轮询作业的进度,内部封装了submit()方法,用于创建JobCommiter实例,并且调用其的submitJobInternal方法。提交成功后,如果有状态改变,就会把进度报告到控制台。错误也会报告到控制台。 1794 | > 2. JobCommiter实例会向ResourceManager申请一个新应用ID,用于MapReduce作业ID。这期间JobCommiter也会进行检查输出路径的情况,以及计算输入分片。 1795 | > 3. 如果成功申请到ID,就会将运行作业所需要的资源(包括作业jar文件,配置文件和计算所得的输入分片元数据文件)上传到一个用ID命令目录下HDFS上。此时副本个数是10。 1796 | > 4. 准备工作已做好,再通知ResourceManager调用submitApplication方法提交作业。 1797 | > 5. ResourceManager调用submitApplication方法后,会通知Yarn调度器(Scheduler),调度器分配一个容器,在节点管理器的管理下在容器中启动 application master进程。 1798 | > 6. application master的主类是MRAppMaster,其主要作用是初始化任务,并接受来来自任务的进度和完成报告。 1799 | > 7. 然后从HDFS上接受资源,主要是split。然后为每一个split创建MapTask以及参数指定的ReduceTask,任务ID在此时分配。 1800 | > 8. 然后Application Master会向资源管理器请求容器,首先为MapTask申请容器,然后再为ReduceTask申请容器。(5%) 1801 | > 9. 一旦ResourceManager中的调度器(Scheduler),为Task分配了一个特定节点上的容器,Application Master就会与NodeManager进行通信来启动容器。 1802 | > 10. 运行任务是由YarnChild来执行的,运行任务前,先将资源本地化(jar文件,配置文件,缓存文件) 1803 | > 11. 然后开始运行MapTask或ReduceTask。 1804 | > 12. 当收到最后一个任务已经完成通知后,application master会把作业状态设置为success。然后Job轮询时,知道成功完成,就会通知客户端,并把统计信息输出到控制台。 1805 | > ~~~ 1806 | > 1807 | > 1808 | 1809 | ### 十三. YARN的案例测试 1810 | 1811 | 使用官方提供的 1812 | 1813 | ~~~sh 1814 | # 1.创建一个内容 1815 | [root@ben01 ~]# ls 1816 | e1 empty file file1 file2 file3 softwares test.txt 1817 | [root@ben01 ~]# mkdir input 1818 | [root@ben01 ~]# mv file* input/ 1819 | [root@ben01 ~]# cat input/* 1820 | Hello ben01 1821 | Hello ben02 1822 | Hello ben03 1823 | Hello ben01 1824 | Hello ben02 1825 | Hello ben03 1826 | 1827 | # 2.将文件夹put到hdfs上 1828 | [root@ben01 ~]# hdfs dfs -put input/ / 1829 | [root@ben01 ~]# hdfs dfs -cat /input/* 1830 | 1831 | # 3.官方案例 1832 | [root@ben01 ~]# cd /usr/local/hadoop/share/hadoop/mapreduce 1833 | 1834 | # 4.运行 1835 | [root@ben01 mapreduce]# hadoop jar hadoop-mapreduce-examples-3.3.1.jar wordcount /input /output 1836 | ~~~ 1837 | 1838 | > 输入内容如下: 1839 | > 1840 | > ~~~sh 1841 | > [root@ben01 mapreduce]# hadoop jar hadoop-mapreduce-examples-3.3.1.jar wordcount /input /output 1842 | > 2022-07-27 09:38:32,446 INFO client.DefaultNoHARMFailoverProxyProvider: Connecting to ResourceManager at ben01/10.206.0.10:8032 1843 | > 2022-07-27 09:38:32,917 INFO mapreduce.JobResourceUploader: Disabling Erasure Coding for path: /tmp/hadoop-yarn/staging/root/.staging/job_1658885211305_0002 1844 | > 2022-07-27 09:38:33,181 INFO input.FileInputFormat: Total input files to process : 4 1845 | > 2022-07-27 09:38:33,267 INFO mapreduce.JobSubmitter: number of splits:4 1846 | > 2022-07-27 09:38:33,832 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1658885211305_0002 1847 | > 2022-07-27 09:38:33,832 INFO mapreduce.JobSubmitter: Executing with tokens: [] 1848 | > 2022-07-27 09:38:34,002 INFO conf.Configuration: resource-types.xml not found 1849 | > 2022-07-27 09:38:34,002 INFO resource.ResourceUtils: Unable to find 'resource-types.xml'. 1850 | > 2022-07-27 09:38:34,055 INFO impl.YarnClientImpl: Submitted application application_1658885211305_0002 1851 | > 2022-07-27 09:38:34,086 INFO mapreduce.Job: The url to track the job: http://ben01:8088/proxy/application_1658885211305_0002/ 1852 | > 2022-07-27 09:38:34,087 INFO mapreduce.Job: Running job: job_1658885211305_0002 1853 | > 2022-07-27 09:38:41,181 INFO mapreduce.Job: Job job_1658885211305_0002 running in uber mode : false 1854 | > 2022-07-27 09:38:41,182 INFO mapreduce.Job: map 0% reduce 0% 1855 | > 2022-07-27 09:38:52,312 INFO mapreduce.Job: map 25% reduce 0% 1856 | > 2022-07-27 09:38:53,322 INFO mapreduce.Job: map 100% reduce 0% 1857 | > 2022-07-27 09:38:57,359 INFO mapreduce.Job: map 100% reduce 100% 1858 | > 2022-07-27 09:38:57,375 INFO mapreduce.Job: Job job_1658885211305_0002 completed successfully 1859 | > 2022-07-27 09:38:57,459 INFO mapreduce.Job: Counters: 54 1860 | > File System Counters 1861 | > FILE: Number of bytes read=126 1862 | > FILE: Number of bytes written=1363365 1863 | > FILE: Number of read operations=0 1864 | > FILE: Number of large read operations=0 1865 | > FILE: Number of write operations=0 1866 | > HDFS: Number of bytes read=447 1867 | > HDFS: Number of bytes written=32 1868 | > HDFS: Number of read operations=17 1869 | > HDFS: Number of large read operations=0 1870 | > HDFS: Number of write operations=2 1871 | > HDFS: Number of bytes read erasure-coded=0 1872 | > Job Counters 1873 | > Launched map tasks=4 1874 | > Launched reduce tasks=1 1875 | > Data-local map tasks=4 1876 | > Total time spent by all maps in occupied slots (ms)=40246 1877 | > Total time spent by all reduces in occupied slots (ms)=2673 1878 | > Total time spent by all map tasks (ms)=40246 1879 | > Total time spent by all reduce tasks (ms)=2673 1880 | > Total vcore-milliseconds taken by all map tasks=40246 1881 | > Total vcore-milliseconds taken by all reduce tasks=2673 1882 | > Total megabyte-milliseconds taken by all map tasks=41211904 1883 | > Total megabyte-milliseconds taken by all reduce tasks=2737152 1884 | > Map-Reduce Framework 1885 | > Map input records=6 1886 | > Map output records=12 1887 | > Map output bytes=120 1888 | > Map output materialized bytes=144 1889 | > Input split bytes=375 1890 | > Combine input records=12 1891 | > Combine output records=10 1892 | > Reduce input groups=4 1893 | > Reduce shuffle bytes=144 1894 | > Reduce input records=10 1895 | > Reduce output records=4 1896 | > Spilled Records=20 1897 | > Shuffled Maps =4 1898 | > Failed Shuffles=0 1899 | > Merged Map outputs=4 1900 | > GC time elapsed (ms)=1627 1901 | > CPU time spent (ms)=2840 1902 | > Physical memory (bytes) snapshot=1411006464 1903 | > Virtual memory (bytes) snapshot=13943873536 1904 | > Total committed heap usage (bytes)=1187512320 1905 | > Peak Map Physical memory (bytes)=309903360 1906 | > Peak Map Virtual memory (bytes)=2796343296 1907 | > Peak Reduce Physical memory (bytes)=201601024 1908 | > Peak Reduce Virtual memory (bytes)=2792300544 1909 | > Shuffle Errors 1910 | > BAD_ID=0 1911 | > CONNECTION=0 1912 | > IO_ERROR=0 1913 | > WRONG_LENGTH=0 1914 | > WRONG_MAP=0 1915 | > WRONG_REDUCE=0 1916 | > File Input Format Counters 1917 | > Bytes Read=72 1918 | > File Output Format Counters 1919 | > Bytes Written=32 1920 | > ~~~ 1921 | > 1922 | > 1923 | 1924 | 1925 | 1926 | ### 十五. YARN的Web UI查看 1927 | 1928 | 外网加上8088端口访问 1929 | 1930 | ![1658886205864](assets/1658886205864.png) 1931 | 1932 | 1933 | 1934 | **Hadoop基础部分已完成🎉🎉🎉** -------------------------------------------------------------------------------- /Hadoop生态/第二章——Hive.md: -------------------------------------------------------------------------------- 1 | # 第二章——Hive 2 | 3 | ### 一. Hive开篇 4 | 5 | #### 1.1 hive简介 6 | 7 | ##### 1.1.1 hive出现的原因 8 | 9 | 视频网站每天产生海量的结构化日志数据,为了对这些数据进行管理,且因机器学习的需求,产生了hive这门技术,并继续发展成为一个成功的Apache项目。 10 | 11 | 12 | 13 | ##### 1.1.2 什么是hive 14 | 15 | hive是构建在Hadoop上的数据仓库工具(框架),可以将结构化的数据文件映射成一张数据表,并可以使用类sql的方式来对这样的数据文件进行读、写以及管理(包括元数据)。这套HIVE SQL简称HQL。hive的执行引擎可以是MR、Spark以及Tez。 16 | 17 | 如果执行引擎是MapReduce的话,hive会将HQL翻译成MR进行数据的计算。用户可以使用命令行工具或JDBC驱动程序来连接到hive。 18 | 19 | 20 | 21 | ##### 1.1.3 为什么使用hive 22 | 23 | 因为直接使用MapReduce需要面临以下问题: 24 | 25 | - 人员学习成本高 26 | - 项目周期要求太短 27 | - MapReduce实现复杂查询逻辑开发难度大 28 | 29 | 30 | 31 | ##### 1.1.4 hive的优缺点 32 | 33 | 1)hive的优点 34 | 35 | - 学习成本低 36 | - 提供类SQL查询语法HQL(简单、容易上手),避免直接写MapReduce(适合java语音不好的,sql熟练的人) 37 | - 可扩展性好 38 | - 为超大数据集设计了计算/扩展能力(MR作为计算引擎,HDFS作为而存储系统),Hive可以自由的扩展集群的规模,一般情况下不需要重启服务。 39 | - 适合做离线分析处理(OLAP) 40 | - Hive的执行延迟比较高,因此Hive常用于数据分析,对实时性要求不高的场合。 41 | - 延展性好 42 | - Hive支持用户自定义函数,用户可以根据自己的需求来实现自己的函数。 43 | - 良好的容错性 44 | - 某个数据节点出现问题HQL仍可完成执行。 45 | - 统计管理 46 | - 提供了统一的元数据管理 47 | 48 | 2)hive的缺点 49 | 50 | - hive的HQL表达能力有限 51 | - 迭代式算法无法表达,比如PageRank(网页排名) 52 | - 数据挖掘方面,比如KMeans(k均值聚类算法) 53 | - hive的效率比较低 54 | - hive自动生成的MapReduce作业,通常情况下不够智能化 55 | - hive调优比较苦难,粒度较粗 56 | 57 | 58 | 59 | #### 1.2 Hive架构和原理 60 | 61 | ##### 1.2.1 hive的架构简介 62 | 63 | ![1658901008483](assets/1658901008483.png) 64 | 65 | 从上图可以看出,Hive的体系结构分位以下几部分: 66 | 67 | ~~~ 68 | 1. 用户连接接口 69 | CLI:指Shell命令行。 70 | JDBC/ODBC:指Hive的java实现,与传统数据库JDBC类似。 71 | WebUI:指可通过浏览器访问Hive。 72 | 2. Thrift Server: 73 | hive的可选组件,是一个软件框架服务,允许客户端使用包括Java、C++、Ruby和其它多种语言,通过编程的方式远程访问Hive。 74 | 3. Meta Store 75 | Hive将元数据存储在数据库中,如mysql、derby。hive中的元数据包括(表名、表所属的数据库表名、表的拥有者、列/分区字段、表的类型(是否是外部表)、表的数据所在目录等) 76 | 4. 驱动器(Driver) 77 | - 解析器(SQLParser): 78 | 将HQL字符串转换成抽象语法树AST,这一步一般都用第三方工具库完成,比如antlr;对AST进行语法分析,比如表是否存在、字段是否存在、SQL语义是否有误。 79 | - 编译器(Compiler): 80 | 对hql语句进行词法、语法、语义的编译(需要跟元数据关联),编译完成后会生成一个执行计划。hive上就是编译成MapReduce的job。 81 | - 优化器(Optimizer): 82 | 将执行计划进行优化,减少不必要的列、使用分区、使用索引等,优化job。 83 | - 执行器(Executer): 84 | 将优化后的执行计划提交给hadoop的yarn上执行。提交job。 85 | 5.hadoop 86 | Jobtracker是hadoop1.x中的组件,它的功能相当于:Resourcemanager+AppMaster 87 | TaskTracker相当于:Nodemanager+yarnchild 88 | 89 | Hive的数据存储在HDFS中,大部分的插叙、计算由MapReduce完成 90 | ~~~ 91 | 92 | 注意: 93 | 94 | ~~~~ 95 | - 包含*的全表查询,比如select * from table 不会生成MapReduce任务 96 | - 包含*的limit查询,比如select * from table limit 10 不会生成MapReduce任务 97 | ~~~~ 98 | 99 | 100 | 101 | ##### 1.2.2 hive的工作原理 102 | 103 | ![1658902341763](assets/1658902341763.png) 104 | 105 | ~~~ 106 | 1. 用户提交查询等任务给Driver。(可以选择CLI/JDBC/Web UI) 107 | 2. 驱动程序将Hql发送编译器,检查语法和生成查询计划。 108 | 3. 编译器Compiler根据用户任务去MetaStore中获取需要的Hive的元数据信息。 109 | 4. 编译器Compiler得到元数据信息,对任务进行编译,先将HiveQL转换为抽象语法树,然后抽象语法树转换成查询块,将查询块转化为逻辑的查询计划,重写逻辑查询计划,将逻辑计划转化为物理的计划(MapReduce),最后选择最佳的策略。 110 | 5. 将最终的计划提交给Driver。到此为止,查询解析和编译完成。 111 | 6. Driver将计划Plan转交给ExecutionEngine去执行。 112 | 7.1 在内部,执行作业的过程是一个MapReduce工作。执行引擎发送作业给JobTracker,在名称节点并把它分配作业到TaskTracker,这是在数据节点。在这里,查询执行MapReduce工作。 113 | 7.2 与此同时,执行时的执行引擎可以通过MetaStore执行元数据操作。 114 | 8. 执行引擎接收来自数据节点的结果。 115 | 9. 执行引擎发送这些结果值给驱动程序。 116 | 10. 驱动程序将结果发送给Hive接口。 117 | ~~~ 118 | 119 | 120 | 121 | ##### 1.2.3 Hive和Hadoop的关系 122 | 123 | ~~~ 124 | - hive本身没有多少功能,hive相当于在hadoop上包了一个壳子,就是对hadoop进行了一次封装。 125 | - hive的存储是基于hdfs/hbase的,hive的计算是基于mapreduce。 126 | 参考下图: 127 | ~~~ 128 | 129 | ![1672735124222](assets/1672735124222.png) 130 | 131 | 132 | 133 | #### 1.3 hive与传统数据库的区别 134 | 135 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 ben.guo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Practical-projects-of-BigData-and-AI 2 | 3 | 4 | 5 | ## 学习路径: 6 | 7 | - Hadoop生态——对应项目《采集与监控平台》 8 | - Hadoop基础 9 | 10 | -------------------------------------------------------------------------------- /soft/README.md: -------------------------------------------------------------------------------- 1 | # README 2 | 3 | 这个软件包只有部分文件,请到百度云下载链接:https://pan.baidu.com/s/1UZABuNRtoPzjrrc73r26Yw 4 | 提取码:d0ni 5 | 6 | 有需要补充的可以发邮箱给我909336740@qq.com 7 | 8 | -------------------------------------------------------------------------------- /soft/frpc_0.33.linux_adm64.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/soft/frpc_0.33.linux_adm64.tgz -------------------------------------------------------------------------------- /准实时数仓项目/README.md: -------------------------------------------------------------------------------- 1 | # README 2 | 3 | 准实时数仓项目 4 | 5 | ### 一.项目背景 6 | 7 | #### 1.简介 8 | 9 | **WAHT:**基于数据采集与监控。其中用户行为数据、内容数据、业务数据收集到HDFS。我们着重普及事件分析、漏斗分析、留存分析在用户模型分析在用户模型分析中最常见的3个分析模型。 10 | 11 | **WHY:**搭建数仓的最终目的是为了使得数据更为高效的令其产生价值。数据仓库的手段不一,但最终目的是一致的。 12 | 13 | **HOW:**如经典模型:DAU[日常活跃用户统计:Daily Active User]预测未来一段时间的日活跃用户,根据活跃用户可以指定策略等。如生鲜市场备货等,更有效的减少损耗,提高资源利用率。 14 | 15 | #### 2.行为分析模型 16 | 17 | 在分析模型中经常会出现两个名词:指标和维度。 18 | 19 | - 指标:具体的数值。新闻浏览量、新闻点击量。指标一般都要结合维度才能产生更大的价值。 20 | - 维度:看数据的角度,描述一个事物本身具备的特征或属性。在数据分析领域,维度通常用来描述分析指标(如上面的新闻分成实事、娱乐的维度,亦或者分为国内、国外的维度)。 21 | 22 | #### 2.1.事件分析 23 | 24 | 用来追踪用户行为的。在行为日志中有个event:AppClick 25 | 26 | - 所谓事件分析,就是基于事件的指标统计。 27 | 28 | - 最近一周哪个渠道的新增用户最多,以及变化趋势。 29 | 30 | > 其中“最近一周”和“哪个渠道”都是维度,“新增用户”量和“变化趋势”则是指标 31 | 32 | - 每天每个地域的活跃用户数。 33 | 34 | #### 2.2.留存分析 35 | 36 | **WHAT:**一种用来分析用户参与情况/活跃程度的分析模型,考察进行初始行为的用户中,有多少人会进行后续行为。 37 | 38 | > 在互联网行业里,通常我们会通过拉新把客户引过来,但是经过一段时间可能就会有一部分客户逐渐流失了。那些留下来的人或者是经常回访我们公司网站 / App 的人就称为留存。 39 | 40 | **WHY:**用来衡量产品对用户价值高低的重要方法。 41 | 42 | > 如某个社交产品改进了新注册用户的引导留存,期待改善用户注册后的参与程度,这样用留存分析就可以验证改进的效果。亦或者是判断某项产品改动是否奏效,如新增了一个邀请好友的功能,观察是否有人因新增功能而多使用产品几个月。 43 | 44 | 特点与价值 45 | 46 | - 留存率是判断产品价值最重要的标准,揭示了产品保留用户的能力 47 | - 宏观上把握用户生命周期长度以及定位产品可改善至之处 48 | 49 | #### 2.3.漏斗分析 50 | 51 | **WHAT:**一套流程式数据分析,它能够科学反映用户行为状态以及从起点到终点各阶段用户转化率情况的重要分析模型。 52 | 53 | > 漏斗的步骤、漏斗的时间范围、漏斗的窗口期。 54 | > 55 | > 漏斗分析模型已经广泛应用于流量监控、产品目标转化等日常数据运营与数据分析的工作中。例如在一款产品服务平台中,直播用户从激活APP开始到花费,一般的用户购物路径为激活APP、注册账号、进入直播间、互动行为、礼物花费五大阶段,漏斗能够展现出各个阶段的转化率,通过漏斗各环节相关数据的比较,能够直观地发现和说明问题所在,从而找到优化方向。 56 | 57 | 特点与价值 58 | 59 | - 企业可以监控用户在各个层级的转化情况,聚焦用户选购全流程中最有效转化路径;同时找到可优化的短板,提升用户体验。 60 | - 多维度切分与呈现用户转化情况,成单瓶颈无处遁形。 61 | - 不同属性的用户群体漏斗比较,从差异角度窥视优化思路。 62 | 63 | #### 2.3.1.DAU预测 64 | 65 | 日活跃用户数量。 66 | 67 | > 一般用于反映网站、互联网应用等运营情况。结合MAU(月活跃用户数量)一起使用,用来衡量服务的用户粘性以及服务的衰退周期。 68 | 69 | ![DAU公式](assets/DAU公式.png) 70 | 71 | > $$ 72 | > A_N:表示第N日的新增用户\\ 73 | > R_i:第i天的留存率 74 | > \sum_{i=1}^N=A_{N-i}*R_i:第N-i天的新增和第i天的留存率乘积之和 75 | > $$ 76 | > 77 | > 整个公式:`当天的日活`=`当天的新增用户`+`之前每天新增用户到当日的用户之和` 78 | 79 | ### 二.项目需求 80 | 81 | #### 1.数据 82 | 83 | #### 1.1.数据表 84 | 85 | | 数据库 | 数据表 | 描述 | 86 | | -------- | ------------ | --------------------------- | 87 | | ods_news | news | 原始行为数据 | 88 | | ods_news | news_parquet | 原始数据,json转换为parquet | 89 | | ods_news | news_article | 通过HTTP请求过来的内容日志 | 90 | | ods_news | ad_info | 从MySQL过来的广告信息 | 91 | | ods_news | meta | 从MySQL过来的元信息 | 92 | 93 | #### 1.2.行为数据解释 94 | 95 | -------------------------------------------------------------------------------- /准实时数仓项目/assets/DAU公式.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/准实时数仓项目/assets/DAU公式.png -------------------------------------------------------------------------------- /用户画像项目实践/README.md: -------------------------------------------------------------------------------- 1 | # README 2 | 3 | # 用户画像 4 | 5 | ### 一.项目背景 6 | 7 | > 你将掌握的技术:标签存储、中文分词、标签向量化、企业工程实施、向量搜索,以解决企业人群圈定、相似用户搜索。 8 | > 9 | > **WHAT:**用户画像是指根据用户的属性、用户偏好、生活习惯、用户行为等信息而抽象出来的标签化用户模型。 通俗说就是给用户打标签,而标签是通过对用户信息分析而来的高度精炼的特征标识。 10 | > 11 | > **WHY:**电商领域中,有上百万的商品和用户,哪些商品应该推送给哪些客户,这就要知道商品画像和用户画像,与之一一对应就能推送到有效的商品促成购买。 12 | > 13 | > ​ 商品画像往往可以在商家上架时要求商家添加各种属性,而且他们也很乐意这么做,但是让用户一开始就填自己的画像显然不现实,一是非常麻烦二是用户需求会一直变,今天想要这个明天就想要那个了。 14 | > 15 | > ​ 而这个项目就是为了解决这一大痛点,利用用户的看的内容建设画像,并随时更新,且基于用户之间相似性去推荐商品。 16 | > 17 | > **HOW:** 如何得到不同用户的画像(或物品的画像),基于TF-IDF和Word2Vec技术,把用户看的内容分类分向量,以此来得到用户的画像,且计算用户之间的相似性。 18 | 19 | #### 1.介绍 20 | 21 | 想要做用户画像必须以数据仓库作为基础(数据仓库-OLAP引擎)。一般在电商平台或者头条等会有广告投放业务,我们需要将广告展示给不同的用户,不同用户一定是对不同广告感兴趣的,如何才能给到用户想看的?我们需要不停的给用户贴标签(根据用户行为将他/她感兴趣的记录下来)。标签在用户画像里是给机器看的(向量)。 22 | 23 | > 标签包含基本属性、行为等,每个标签也要有排名之分,因为有时候用户是不小心点了那个内容,而有时候看一个内容看了很久。 24 | 25 | #### 2.OLAP对比OTIP 26 | 27 | OLTP(Online Transcation Processing, 联机式事务处理): Java开发,强调对事务的管理,如几个业务之间的一致性等。 28 | 29 | OLAP(Online Analytical Processing, 联机式分析处理): 数据分析,强调分析数据以得出业务价值,增删改查会比较多。 30 | 31 | #### 3.画像&向量(标签) 32 | 33 | 这里的标签同时也指向量 34 | 35 | > 基础标签:性别、年龄、手机号码等 36 | > 37 | > 高级标签:收入、浏览喜好(如游戏的王者荣耀、欧洲足球等) 38 | 39 | **向量:**(也称为欧几里得*向量*、几何*向量*、矢量),指具有大小(magnitude)和方向的量。它可以形象化地表示为带箭头的线段。可以简单理解为它就代表这个用户的画像信息,以**数组**的形式。 40 | 41 | > **数组:**有一维数组[12, 52, 11],也有这样的多维数组 42 | > 43 | > [52, 0.2] 44 | > 45 | > [-0.123, 2] 46 | 47 | **HOW:**如何构建用户画像(标签/向量) 48 | 49 | 1. 对原始数据进行基础ETL就可以得出标签 50 | 51 | 2. 物品打标签,然后获取用户在这些标签上的历史行为 52 | 53 | 3. 利用算法把词变成向量 54 | 55 | > TF-IDF、Word2Vec等 56 | 57 | 4. 把标签存储起来 58 | 59 | > BitMap。 60 | > 61 | > **WHAT:**位图或者说基于位的隐射,用bit位来标记某个元素对应的Value,而key即是该元素,即要表达{1, 2, 4, 6}只需要这么存即可 62 | > 63 | > | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 64 | > | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | 65 | > | 7 | "6" | 5 | "4" | 3 | "2" | "1" | 0 | 66 | > 67 | > **而这仅仅是1 bit**,如何查找等更多细节参考https://www.cnblogs.com/cjsblog/p/11613708.html 68 | > 69 | > **WHY:**在20亿个随机数中找出某个数,判断它是否在其中。那么量就是20亿个int,int占4个字节,1字节=8位(1 byte=8 bit)。 70 | > 71 | > ​ 即=20亿×4/1024/1024≈7.6G。 72 | > 73 | > ​ 而用BitMap则=2000000000/8/1024/1024/1024)≈0.233G。 74 | 75 | #### 4.表 76 | 77 | ##### 4.1涉及的表 78 | 79 | | 项目 | 数据库 | 表 | 描述 | 本项目是否使用 | 80 | | ---- | -------- | ------------ | ------------- | -------------- | 81 | | 采集 | ods_news | news | 行为数据 | 否 | 82 | | 采集 | ods_news | news_article | 内容数据 | 是 | 83 | | 采集 | ods_news | news_parquet | 行为数据 | 否 | 84 | | 采集 | ods_news | meta | mysql元信息 | 否 | 85 | | 采集 | ods_news | ad_info | mysql广告信息 | 否 | 86 | | dw | ods_news | user | 用户表 | 是 | 87 | | dw | ods_news | event | 行为时间表 | 是 | 88 | | dw | dwb_news | rsu | 留存率加速表 | 否 | 89 | 90 | > 目前数仓有的表 91 | 92 | ##### 4.2人群圈定、相似用户搜索 93 | 94 | ### 二.架构 95 | 96 | #### 1.架构图 97 | 98 | ![用户画像架构图](assets/用户画像架构图.png) 99 | 100 | 从HDFS中提取用户和文章的信息,并开放出API接口供调用。 101 | 102 | > 以下内容后续会展开。 103 | > 104 | > 注(1) Hive、Hadoop、Presto:数仓存储数据的,也是HDFS。 105 | > 106 | > 注(2) Log:用户的行为数据。 107 | > 108 | > 注(3) Symbolize features:拿到象征/统计类的标签(通过SQL获取,如近期点击次数)。 109 | > 110 | > 注(4) Base features:拿到基础的标签(通过SQL获取,如性别)。 111 | > 112 | > 注(5) BitMap:利用位图,提取特征里的内容。 113 | > 114 | > 注(6) ClickHouse:存储标签的库。 115 | > 116 | > User content:用户浏览的内容。 117 | > 118 | > 注(7) User content features:利用Spark的技术结合用户浏览内容和关键词,拿到用户的内容相关的特征。 119 | > 120 | > 注(8) Content:相关文章。 121 | > 122 | > Spark:包含Spark MLlib,spark MLlib 是spark中可以扩展的机器学习库,它有一系列的机器学习算法和实用程序组成。包括分类、回归、聚类、协同过滤等。 123 | > 124 | > 注(9) HanLP:用以提取实体词技术(非标点符号等)。 125 | > 126 | > 注(10) word:提取到的实体词(非标点符号等)。 127 | > 128 | > 注(11) TF-IDF:用以提取关键字的技术。 129 | > 130 | > 注(12) Key Words:提取到关键字(代表某个文章的关键字)。 131 | > 132 | > 注(13) Word2Vec:用以出标签向量的技术。 133 | > 134 | > 注(14) Word embedding:提取到标签向量。 135 | > 136 | > 注(15) User content embedding:标签向量结合用户内容特征,形成用户的画像,即不同的用户都喜欢哪些文章哪些关键信息。 137 | > 138 | > 注(16) milvus:存到快速的向量搜索引擎。 139 | > 140 | > 注(17) Springboot:写个代码打通查询的接口。 141 | > 142 | > 注(18) 开放API:提供查询接口。 143 | 144 | 145 | 146 | #### 2.算法 147 | 148 | ~~~python 149 | Word2vec: 获取词向量 150 | navie bayes: 文本分类 151 | TF-IDF: 关键字提取 152 | HanLP/JieBa:中文分词工具 153 | ~~~ 154 | 155 | 156 | 157 | ### 三.部署实施 158 | 159 | #### 1.Base feature 160 | 161 | ​ 从用户行为日志中提取的数据(ods_news.event_ro和ods_news.user_ro):[性别、年龄、电话归属地、邮箱、手机号码],通过spark sql将其最终写入到clickhouse 162 | 163 | ​ 我们的数据是直接写入到ClickHouse中的,所以hdfs中并没有数据产生。如果想要使用presto或者hive这样的工具查询数据是没有的,只能通过clickhouse。所以我们应该在保存到clickhouse的同时也想hdfs存放一份数据,通过两种做法,如1.通过spark sql向clickhouse写的时候同时保存一份到hdfs;2.通过presto直接执行相同的逻辑。这里我们使用的第一种方法。 164 | 165 | -------------------------------------------------------------------------------- /用户画像项目实践/assets/用户画像架构图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/用户画像项目实践/assets/用户画像架构图.png -------------------------------------------------------------------------------- /采集与监控平台项目/README.md: -------------------------------------------------------------------------------- 1 | # README 2 | 3 | # 采集与监控平台-头条新闻资讯类APP 4 | 5 | ### 一. 项目背景 6 | 7 | #### 1. 简介 8 | 9 | **WHAT:**学习大数据课程,首先要知道数据从何而来(产生)。 10 | 11 | **WHY:**针对不同场景和不同类型的数据应该使用什么样的技术去收集,当有了数据之后才能在这些数据集上探索利用它们,从中挖掘价值。我们还要对数据采集过程的重要指标进行监控,当数据采集发生故障时我们能够及时收到报警,同时当我们遇到性能问题时,通过监控系统我们能更有针对性的优化采集流程。 12 | 13 | #### 2. 基本概念 14 | 15 | 讨论一件事情一般要有上下文的限定,这里我们限定我们的讨论范围是做C端产品(比如`头条`、`快手`、`微信`、`美团`等移动端可以下载的APP)公司的日志。这些公司不仅有APP,可能还有自己的网站,小程序等,这些应用产生的日志都在我们的讨论范围之内。 16 | 17 | #### 2.1.行为日志 18 | 19 | **WHAT:**我们先引入第一个概念`用户行为日志`,用户行为日志是指用户和应用之间进行交互时,由应用本身记录下来的具有一定格式的文本数据,这个文本数据就是用户行为日志。 20 | 21 | **HOW:**比如当我们在手机上打开美团,此时美团APP就会在后台生成一条日志,记录这个设备进行了启动操作,比如 22 | 23 | ~~~ 24 | { 25 | "client_time": 1587523571, 26 | "event_name": "StartAPP", 27 | "properties": { 28 | "os": "android", 29 | "imei": "868034031518269", 30 | "model": "HUAWEI MT7-L09", 31 | "wifi": true 32 | ... 33 | }, 34 | ... 35 | } 36 | ~~~ 37 | 38 | 这条json数据就是一条行为数据了,不同的应用会有自己的格式定义,但是核心思想不变,就是要记录一个用户什么时间在什么位置做了什么样的操作。上面说的是APP日志,还有网站、小程序等需要和用户交互的都可以产生此类日志。因为这些数据都由客户端应用上报的,我们也叫客户端日志。 39 | 40 | #### 2.2. 内容日志 41 | 42 | 不同的公司根据其业务场景不同,会有不同的`内容日志`,比如头条是做资讯的,那么每条新闻咨询就是一条内容日志,包含了文本信息和图片信息。淘宝是做电商的,每条商品信息就是一条内容日志,这些日志也可以用一个json描述出来。这些日志的来源可能是UGC(用户产生的内容),也可能是PGC(专业生产内容的团队)。 43 | 44 | #### 2.3. 业务日志 45 | 46 | **WHAT:**这里的`业务日志`是指由公司服务端业务系统产生的数据,这样数据往往存储在服务端的数据库中,内容日志也往往存储在服务端的数据库中,但是和内容日志不同的是,业务日志是应用逻辑的支撑,我们叫业务日志,在服务端看来就是数据库中的表。这里的数据库可能是关系型也可能是非关系型。 47 | 48 | > 我们在互联网大数据领域研究的数据,基本就是上述三种类型的数据。 49 | 50 | #### 2.4. 元数据 51 | 52 | **WHAT:**元数据用来`描述数据`的数据。如,我们再MySQL创建了一张表,我们创建这张表的同时MySQL会记录下我们创建的表的名字,创建的列的字段信息(列名、数据类型等),索引信息等,这些信息就叫做这张表的元信息,它不是表中的数据,而是描述这些数据用的,这些信息存储在MySQL的`information_shcema`库中。只要是描述数据而用的,都可以叫元数据。 53 | 54 | #### 3. 场景 55 | 56 | 在企业中我们要构建数据平台,第一步先要设计我们的数据采集系统,先把数据从各个源头收集过来。此项目我们以信息流产品类型的企业数据来讲解如何构建数据数据采集及监控系统。对于信息流产品,如`今日头条`、`抖音`、`快手`等都是信息流产品,有的除了图文还有视频,本项目以图文信息流产品为例。 57 | 58 | 59 | 60 | ### 二. 项目需求 61 | 62 | #### 1. 数据源 63 | 64 | 在项目背景中我们已经知道,需要采集的是信息流产品的数据信息。在这里我们限定我们需要采集的数据是新闻资讯类的产品,类似头条。需要收集的日志如下: 65 | 66 | - 用户行为数据。包含用户启动APP,各页面的浏览、点击、分享、收藏广告的点击等行为日志,这些日志会在`客户端埋点`,将数据通过HTTP请求发送到我们设计的数据接口。 67 | 68 | > 如何埋点,写一段Android或IOS代码,监听用户在页面的操作,并按照一定的数据格式记录下俩,之后发送HTTP请求即可。可以自己写代码,也可以选择开源的埋点SDK,比如`sa[sensors data]`,`argo`等。有了客户端发过来的数据,那么我们再设计HTTP数据接口就能让这些数据实时发送到接口中。 69 | 70 | - 资讯数据,这些数据有专门的数据公司提供,一般会有两种方式让我们获取数据。 71 | 72 | - 第一种,拉模式,他们提供HTTP接口,我们通过接口拉取数据。 73 | 74 | > 一般选这种,方便可控。 75 | 76 | - 第二种,推模式,我们提供HTTP接口给他们,他们往接口推数据。 77 | 78 | 数据会先被服务端拉取(前面说的第一种模式),供线上业务使用,如果数据部分需要这部分数据,服务端可以选择在拉取到数据后给数据部分推一份过去。数据端也可以主动去对应的业务库拉数据。在这里我们选择提供HTTP接口,服务端先去拉数据,再把数据推给我们。 79 | 80 | - 业务数据,由于服务端业务表非常多,我们只抽取广告信息表的数据做案例,此表在MySQL中,存储着每条广告的基本信息和对应的广告主。需要我们同步此表的数据到HDFS中。 81 | 82 | #### 2. 目标 83 | 84 | - 数据采集到HDFS。 85 | 86 | > 针对现有的三种数据源设计数据收集方案,将数据采集到HDFS中,建立相对应的Hive表,以供后续进行数据的联合分析。 87 | 88 | - 数据时间自适应。 89 | 90 | > 用户行为和内容数据落到HDFS上均自动按天进行分目录,分目录的时间应当以每条`日志中的时间字段`为准。不能以当下时间为准,这样保证数据有延迟时,每条日志依然归属到其本身对应的时间日期中,业务数据直接全量同步。 91 | 92 | - 数据自校验。 93 | 94 | > 数据落地后,简历Hive外部表,并通过Azkaban调度Shell作业,自动检测当日数据目录是否已存在,并自动添加分区。 95 | > 96 | > Hive是读时模式,即便当日数据目录不存在,一样可以成功添加分区,这里之所以要检测目录是为了后续项目做准备。 97 | 98 | - 监控告警。 99 | 100 | > 基于`Prometheus`、`Grafana`搭建监控系统,监控采集流量的重要指标,需要监控的指标有HTTP数据接口的`QPS`、`99延时`、Flume的`channel填充量`、`发送Event速度`。当指标异常是发出报警,我们选择奖报警消息发送到钉钉或企业微信。 101 | 102 | #### 3. 二次开发 103 | 104 | ##### 3.1. Azkaban Alert 二次开发 105 | 106 | 需要对Azkaban的`报警进行二次开发`,使其支持将调度失败的信息发送至我们自有的报警中心,在这里我们直接开发使其支持将失败消息发送至钉钉。 107 | 108 | ##### 3.2. Flume Interceptor 二次开发 109 | 110 | 因为我们的行为数据是经过BASE64编码的(下方架构会有说明),但落地到HDFS时如果我们需要直接用日志中的某个字段值作为我们HDFS上的目录划分,就必须先对BASE64进行编码,然后取出字段值放到Flume的头信息中,在Sink端配置使用。 111 | 112 | 113 | 114 | ### 三. 架构及阐述——核心 115 | 116 | - 采集`架构一`采用LVS+Nginx(OpenResty)+Lua+Flume+Sqoop+Hadoop+Hive+Azkaban+SpringBoot 117 | - 采集`架构二`采用LVS+Nginx(OpenResty)+Lua+Kafka+Sqoop+DataX+Hadoop+Hive+Azkaban+SpringBoot 118 | - 整体监控架构采用`Prometheus`+`Grafana`+`IM`方案 119 | - 本项目中的组件监控`ngingx-lua-prometheus`+`flume-expoter`+`Prometheus`+`Grafana`+`Supervisor`+`IM` 120 | - 元数据管理及实施数据接收`FRP(Ngrok)`+`Supervisor`+`Metaserver`+`qfapp` 121 | 122 | #### 1. 架构图 123 | 124 | 设计两个架构图,架构一不涉及`Kafka`、`Spark`、`Flink`。架构二作为参考架构。后面讲完`Kafka`、`Spark`、`Flink`等组件后由大家自己思考 125 | 126 | ![采集架构一](assets/采集架构一.png) 127 | 128 | > 数据采集与监控架构一,也是我们这次实战使用的架构,架构阐述在三.1.3架构阐述会进行阐述 129 | 130 | ![采集架构二](assets/采集架构二.png) 131 | 132 | > 数据采集与监控架构二 133 | 134 | #### 1.2. 项目组件 135 | 136 | 本项目中我们的操作系统信息如下: 137 | 138 | ~~~ 139 | * CentOS Linux release 7.6.1810 (Core) # 操作系统选择Centos7即可 140 | * JDK 1.8 141 | ~~~ 142 | 143 | 144 | 145 | | 编号 | 组件 | 基础课 | 版本 | 备注 | 146 | | ---- | ---------- | ------ | -------- | ------------------------------ | 147 | | 1 | OpenResty | | 1.15.8.3 | based on the nginx 1.15.8 core | 148 | | 2 | Flume | | 1.7.0 | | 149 | | 3 | Sqoop | | 1.4.7 | | 150 | | 4 | DataX | | 3.0 | | 151 | | 5 | LVS | | | | 152 | | 6 | Prometheus | | 2.17.1 | | 153 | | 7 | Grafana | | 6.7.3 | | 154 | | 8 | Hadoop | | 2.7.6 | | 155 | | 9 | Hive | | 2.1.1 | | 156 | | 10 | Azkaban | | 3.82.0 | | 157 | | 11 | SpringBoot | | 2.2.0 | | 158 | 159 | #### 1.3. 架构阐述 160 | 161 | 本阶段的项目使用上图的架构一进行实施,接下来是对其设计进行阐述,会简单讲解其中的基本概念和在架构中的作用,后续在实施时会进行具体讲解。 162 | 163 | ##### 1.3.1. 客户端日志收集 164 | 165 | 之前讲到我们要开发一个HTTP服务,接收客户端上报给来的用户行为日志(HTTP请求),除此之外还要将数据落到磁盘上,这样数据就从客户端保存到服务器的磁盘上,也就是下图的部分: 166 | 167 | ![1642557741872](assets/1642557741872.png) 168 | 169 | 从图中可以看到,我们通过开源的SDK进行埋点(可自行研发)将APP、网页(H5)等客户端的用户日志,通过HTTP请求发送到Nginx集群,这里有几点需求说明: 170 | 171 | - 可以看到通过HTTP发送的数据并非直接的明文数据,而是做了`base64`编码,对于`base64`编码 172 | 173 | - 第一,其并非加密算法,而是一种编码方式,所以并不能保证数据的安全,如果想要加密数据可以使用对称加密或非对称加密算法,但这样也就涉及解密,这一过程需要耗费大量计算资源,尤其是海量数据的情况下。现在基本APP数据上报都是`base64`编码,有的APP会使用https相对更安全些。 174 | - 第二,客户端并不会在用户每次产生行为数据就立刻上报,而是有两个条件控制`时间`和`日志条数`,比如`30s, 100条`这两个条件任何一个达到才触发请求,请求数据时为了减少网络流量我们会将这些数据压缩为二进制,然后转换为`base64`后传输。 175 | 176 | - 使用Nginx作为HTTP接口服务,Nginx是一个高性能的web服务器,在环境搭建中也会做一个Nginx的文档。请求通过Nginx的Access日志直接落盘。 177 | 178 | - Nginx可以线性扩展,以应对高并发请求,一般来讲,一台`4C8G的机器`,可以承受`8000-11000的QPS`。多台Nginx我们通过`lvs`来做负载均衡或者云缠上提供的`slb`服务,lvs是为了将流量合理的分配给多台Nginx,分配算法一般是Round Robin(RR)轮询算法,Least Connections(LC)最小连接调度。 179 | 180 | > lvs:整体相比Nginx/HAProxy要更稳定,转发效率也更高。将请求(流量)合理分配给服务器(这里指Nginx),其包含十种调度算法和三种工作模式,供使用者选择。其中常用且容易理解的就是“加权最小连接调度”,在调度新连接时尽可能使服务器的已建立连接数和其权值成比例。 181 | > 182 | > slb:商业的(花钱搞定一切),解决lvs的一些痛点,如:跨vlan通讯问题、DDOS攻击防御功能、性能部署扩容等。当然这些也可以在lvs的基础上搞,只是花时间而且没有人兜底。`兜底`≈出问题有人背锅。 183 | 184 | - 对于落盘后的数据我们可以通过Flume监听磁盘数据目录,实时收集数据发送到hdfs指定的目录上。我们会做一个定时任务切分Nginx Access日志到指定的磁盘数据目录。Flume监听这个数据目录中的文件,发送完一个文件就删除一个文件。 185 | 186 | ##### 1.3.2. 新闻&业务数据收集 187 | 188 | ![1642563394249](assets/1642563394249.png) 189 | 190 | 前面讲到,新闻资讯服务端先拉专门数据公司的数据,再通过推的方式给我们,我们可以通过`Flume Http Source`提供HTTP接口给服务端,让他们把数据推给我们,之后直接投递到hdfs上。我们的业务数据在MySQL(RDB关系型数据库)中,只收集广告数据表中的数据,这个数据通过Sqoop或者DataX也可以直接收集,相关MySQL连接信息后面会给出。 191 | 192 | ##### 1.3.3. 元数据&调度 193 | 194 | ![1642564130136](assets/1642564130136.png) 195 | 196 | 从图中可以看出,我们的数据经过`Flume、Sqoop`发送到hdfs,通过Azkaban调度建立HIVE分区表,注意此表中是json数据,再调度一个json数据转换的宽表,之后我们会有一个MR根据`元数`据信息和我们的数据信息结合做一个数据校验控制。 197 | 198 | > 元数据(Metadata):又称中介数据、中继数据,为描述数据的数据(data about data),主要是描述数据属性(property)的信息,用来支持如指示存储位置、历史数据、资源查找、文件记录等功能。 199 | > 200 | > 这里可以简单理解为对于我们埋点数据json中的字段进行管理,如json中有哪些字段,字段都是什么类型等。实际开发过程中,每埋一个点,都需要在埋点数据管理平台(上图中的web),提交一个申请,比如我要增加一个点击新闻的埋点,这个埋点需要添加什么字段,是什么类型等都要写清楚,经过审核后,客户端伙伴才会开发埋点。这样我们上报的json数据才会有这个字段。 201 | > 202 | > 不用关注埋点数据管理平台如何实现,了解其作用即可。 203 | 204 | 这样通过元数据和我们上报的数据可以做一个检验,过滤掉客户端再实际操作过程中出现的错误数据,同时对于埋点,我们通过和元数据结合,也可以做到快速下线数据。在本项目中,我们会把元数据也同步到HIVE表,通过SQL Join的方式去做数据校验,而不是写MR。DophonScheduler也是作业流调度系统。 205 | 206 | ### 四.部署实施 207 | 208 | #### 4.1. 数据格式 209 | 210 | ##### 4.1.1. 行为数据格式 211 | 212 | 之前我们说过,对于用户行为数据的Scheme我们是有埋点平台的,通过元数据管理控制,在这里我们为了简化,不再去开发元数据管理的WEB平台,而是直接给出元数据的表结构信息,这个表在MySQL中。我们通过已经埋过的点的数据结构,只要开发好HTTP接口,将客户端上报数据的地址,指向开发好的HTTP接口地址,就可以实时收到用户行为数据。 213 | 214 | - 配置客户端上报数据的地址,这里的地址就是开发好的HTPP接口地址,使用方式如下 215 | 216 | ~~~shell 217 | # 例如我们开发好HTTP接口地址为 http://xxx.xxx.xxx/data/v1, 我们需要执行如下命令,将我们开发好的地址配置到管理中心,只要有数据发送到我们的接口中,我们可以在request_body中获取到发送的base64编码数据,在后面的部署中会详细说明 218 | curl -X POST \ 219 | http://meta.frp.qfbigdata.com:8112/ \ 220 | -F data_url=http://xxx.xxx.xxx/data/v1 221 | ~~~ 222 | 223 | 224 | 225 | - 上报数据格式 226 | 227 | ~~~json 228 | # 原始base64 229 | eyJjb25ldG50Ijp7ImRpc3RpbmN0X2lkIjoiNjkyNDA3MiIsInByb3BlcnRpZXMiOnsibW9kZWwiOiJIUlktQUwwMGEiLCJuZXR3b3JrX3R5cGUiOiJXSUZJIiwiaXNfY2hhcmdpbmciOiIyIiwiYXBwX3ZlcnNpb24iOiI0LjQuNSIsImVsZW1lbnRfbmFtZSI6IuaIkeeahOmSseWMhemhtSIsImVsZW1lbnRfcGFnZSI6IummlumhtSIsImNhcnJpZXIiOiLkuK3lm73np7vliqgiLCJvcyI6ImFuZHJvaWQiLCJpbWVpIjoiOTM4ZDczMWY0MTg3NGRhMCIsImJhdHRlcnlfbGV2ZWwiOiI2OSIsInNjcmVlbl93aWR0aCI6IjEwODAiLCJkZXZpY2VfaWQiOiJlZDcxZDdkZi0yZjVjLTY2ZDMtY2JmYi01M2Y1NWJjNzg5OTkiLCJjbGllbnRfdGltZSI6IjIwMjAtMDQtMjUwNzo1OTo1MCIsImlwIjoiMTIxLjU2Ljc5LjQiLCJ3aWZpIjoiMSIsIm1hbnVmYWN0dXJlciI6IkhVQVdFSSIsInNjcmVlbl9oZWlnaHQiOiIyMzQwIn0sImV2ZW50IjoiQXBwQ2xpY2sifSwicHJvamVjdCI6Im5ld3MiLCJjdGltZSI6IjE1ODc3NzU3NDUifQo= 230 | # decode之后的json 231 | { 232 | "conetnt": { 233 | "distinct_id": "6924072", # 用户ID 234 | "properties": { 235 | "model": "HRY-AL00a", #机型 236 | "network_type": "WIFI", #用户网络类型 237 | "is_charging": "2", #是否充电中 238 | "app_version": "4.4.5", #app版本 239 | "element_name": "我的钱包页", #元素名称 240 | "element_page": "首页", #元素所在页面 241 | "carrier": "中国移动", #运营商 242 | "os": "android", #操作系统 243 | "imei": "938d731f41874da0", #手机IMEI号 244 | "battery_level": "69", #手机电量 245 | "screen_width": "1080", #屏幕宽度 246 | "device_id": "ed71d7df-2f5c-66d3-cbfb-53f55bc78999", #设备ID 247 | "client_time": "2020-04-25 07:59:50",#客户端上报此条日志时间 248 | "ip": "121.56.79.4", #客户端IP地址 249 | "manufacturer": "HUAWEI", #制造商 250 | "screen_height": "2340", #屏幕高度 251 | "client_time":"1587771745000" # 客户端上报日志时间 252 | }, 253 | "event": "AppClick" # 事件名称 254 | }, 255 | "project": "news", #产品名称 256 | "ctime": "1587775745000" #服务器接收到日志时间 257 | } 258 | ~~~ 259 | 260 | ##### 4.1.2. 业务数据格式 261 | 262 | 业务数据在MySQL中共两张表,一张是行为数据的元数据表,一张表是广告信息表,结构信息如下 263 | 264 | ~~~sql 265 | -- 元信息表,已经过简化 266 | CREATE TABLE `meta` ( 267 | `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID,主键', 268 | `field` varchar(50) NOT NULL DEFAULT '' COMMENT '字段名称', 269 | `filed_type` varchar(20) NOT NULL DEFAULT '' COMMENT '字段类型', 270 | `field_desc` varchar(255) DEFAULT NULL COMMENT '字段说明', 271 | `app_version` varchar(10) NOT NULL DEFAULT '' COMMENT '上线版本号', 272 | `status` tinyint(4) DEFAULT '0' COMMENT '字段状态,0 下线 1 上线', 273 | `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 274 | `update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 275 | PRIMARY KEY (`id`) 276 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4; 277 | -- 广告信息表,已经过简化 278 | CREATE TABLE `ad_info` ( 279 | `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID,主键', 280 | `ad_id` int(11) DEFAULT NULL COMMENT '广告ID', 281 | `advertiser_id` int(11) DEFAULT NULL COMMENT '广告商ID,一个广告商会投放多个广告', 282 | `advertiser_name` varchar(255) DEFAULT NULL COMMENT '广告商名称', 283 | `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 284 | `update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 285 | PRIMARY KEY (`id`) 286 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 287 | 288 | ~~~ 289 | 290 | ##### 4.1.3. 新闻资讯数据格式 291 | 292 | 新闻资讯数据服务端会通过我们提供的`Flume HTTP Source`推给我们,格式如下 293 | 294 | ~~~json 295 | { 296 | "article_id": 487186016, # 文章ID,新闻的唯一标识 297 | "type_name": " 科技", #新闻类型 298 | "pub_time": "2020-04-20 19:45:36.919", # 新闻发布时间 299 | "title": "小米10pro 30w无线充电对比华为40w有线充电", # 新闻标题 300 | "content": "

之前做了一个小米10pro 30w无线充电对比华为40w有线充电,米10pro无线充电充满只需要55分钟。 这次oppoACE2,看了其他媒体测试的40w快充,前半小时还比不上米10pro,总时间才快了5分钟。然而一 个40w,一个30w,一个4000毫安,一个4500毫安。。。这40w真的阳痿

", # 新闻内容html格式 301 | "source_name": "今日头条移动端-数码", # 新闻来源 302 | "tags": "pro,充电,小时,测试,充满,比不上,需要" # 内容标签 303 | } 304 | ~~~ 305 | 306 | #### 4.2. 采集架构实施 307 | 308 | ##### 4.2.1. LVS负载均衡 309 | 310 | 对于负载均衡LVS的环境,因为这部分的内容偏运维,并不是我们大数据课程要掌握的内容,所以在这里我们不搭建这个环节,大家只要知晓工程中我们在高并发场景下,可以使用LVS做负载均衡就可以了。 311 | 312 | > 例如:我们用一天机器作为数据收集的机器,但是单台的机器性能是有限的,比如4C8G单台机器只能抗住我们`10000 QPS`,但我们的流量高峰有`15000 QPS`,那我们再加一台机器就可以了。但是这两台机器如何同一对外提供服务呢,我们的目的简单来讲有两点,第一,对外是一个IP提供服务。第二,两台机器要相对均衡分配,每天机器都分到`7500 QPS`。那LVS就可以实现我们的目的,那我们再说一个LVS最简单的流量调度算法,Round Robin Scheduling (RR)轮询算法,就是一次把请求分配给RS(real server),就是我们的两台机器。LVS有8种调度算法,来满足不同场景的需求,在大数据这门课程中,并不需要我们掌握。另外对于负载均衡(SLB),LVS只是负载均衡的一种实现方式,不要片面的认为LVS就是SLB。 313 | 314 | ##### 4.2.2. Nginx & Lua 数据埋点接口 315 | 316 | > 写在前面的话:我们在本节中使用Lua,并没用使用Lua直接写入Kafka的模型,因为当前Kafka我们还没有学习,这里通过Lua写access日志,对于写Kafka的模式对应前文的架构图而,等学完Kafka后,我们将采用写Kafka的方式 317 | 318 | 前文框架阐述中我们已经说过,将使用Nginx作为数据采集的HTTP服务,词小节我们会对Nginx及其部署做说明。在LVS小节中我们说过并不搭建LVS环境,因此将直接使用单台Nginx构建我们的数据采集接口。以下是引用[官网]([Welcome to NGINX Wiki! | NGINX](https://www.nginx.com/resources/wiki/))对Nginx的描述 319 | 320 | > NGINX is a free, open-source, high-performance HTTP server and reverse proxy, as well as an 321 | > IMAP/POP3 proxy server. NGINX is known for its high performance, stability, rich feature set, simple 322 | > configuration, and low resource consumption. 323 | 324 | 我们私用时并没有使用官方的原生Nginx,而是使用[OpenResty](https://openresty.org/cn/),它是就Nginx和LuaJit开发的开源软件,可以让我们在Nginx中直接嵌入Lua代码,使我们可以更加灵活的操控数据。对于Lua在本届中,我们也不会单独讲解,在后面搭建环境时,你可以从代码中看到Lua在其中起到的作用就足够了。 325 | 326 | OpenResty安装(**实操**) 327 | 328 | > 使用的是4C8G的虚拟机7.6版本,我在腾讯云开的 329 | 330 | 1. 选择yum安装方式,yum默认会安装openresty源的最新版本,当前版本是1.19.9.1 331 | 332 | ~~~shell 333 | sudo yum install -y yum-utils 334 | # 添加openresty yum 源 335 | sudo yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo 336 | # 安装openresty 337 | sudo yum install -y openresty 338 | ~~~ 339 | 340 | > 使用open+tab键看是否补全,或`whereis openresty`查看是否安装到/usr/bin/下。 341 | > 342 | > ![1643860152216](assets/1643860152216.png) 343 | > 344 | > 如果是root用户,可以不用sudo,如果非root用户且具有sudo权限,并准备用root权限创建应用,就用sudo。如果责备用个人用户创建,请确保具有相关目录的权限,这里我们使用sudo的权限。 345 | 346 | 2. yum方式安装后,安装目录在/usr/local/openresty 同时可执行文件在/usr/bin/openresty, 它只是一个软链接如果你的/usr/bin 目录不在系统PATH中,是无法直接执行 openresty 命令的。你需要把/usr/bin 添加到系统环境变量PATH中,[关于OpenResty RPM包的更多介绍](https://openresty.org/cn/rpm-packages.html),如果指定安装也是可以的,查看源中可用的版本,之后指定一个版本安装即可,这里我们使用默认最新版本 347 | 348 | ~~~shell 349 | # 查看可用版本 350 | sudo yum list openresty --showduplicates 351 | ~~~ 352 | 353 | 354 | 355 | 3. 为我们的采集服务创建一个OpenResty应用,其实就是创建一个目录,应用相关配置文件都放在这个目录里,方便管理。 356 | 357 | ~~~shell 358 | # 创建相关目录 359 | sudo mkdir -p /opt/app/collect-app/ 360 | sudo mkdir -p /opt/app/collect-app/conf/ 361 | sudo mkdir -p /opt/app/collect-app/logs/ 362 | sudo mkdir -p /opt/app/collect-app/conf/vhost/ 363 | sudo cp /usr/local/openresty/nginx/conf/mime.types /opt/app/collect-app/conf/ 364 | ~~~ 365 | 366 | > conf目录存储主配置文件 367 | > 368 | > logs存储程序运行过程中的日志,用户行为日志 369 | > 370 | > vhost放nginx的副配置文件 371 | > 372 | > ![1643860621257](assets/1643860621257.png) 373 | 374 | 4. 编写nginx配置文件,cd到/opt/app/collect-app/conf/ 目录下,vi/vim命名nginx.conf添加如下内容 375 | 376 | ~~~shell 377 | # nginx.conf 378 | # nginx 用户和组 379 | user root root; 380 | # work进程数, 381 | worker_processes 4; 382 | # 错误日志路径,和日志级别 383 | error_log logs/nginx_error.log error; 384 | # nginx pid文件 385 | pid logs/nginx.pid; 386 | # 单个worker最大打开的文件描述符个数 387 | worker_rlimit_nofile 65535; 388 | events 389 | { 390 | #使用epoll模型 391 | use epoll; 392 | # 单个worker进程允许的最多连接数 393 | worker_connections 65535; 394 | } 395 | http 396 | { 397 | include mime.types; 398 | default_type application/octet-stream; 399 | gzip on; 400 | gzip_min_length 1k; 401 | gzip_buffers 4 16k; 402 | gzip_http_version 1.0; 403 | gzip_comp_level 2; 404 | gzip_types text/plain application/x-javascript text/css application/xml; 405 | gzip_vary on; 406 | underscores_in_headers on; 407 | log_format main 408 | '$remote_addr - $remote_user [$time_local] ' 409 | '$request_length ' 410 | '"$request" $status $bytes_sent $body_bytes_sent ' 411 | '"$http_referer" "$http_user_agent" ' 412 | '"$gzip_ratio" "$request_time" ' 413 | '"$upstream_addr" "$upstream_status" "$upstream_response_time"'; 414 | # 定义我们数据采集的 access 日志格式 415 | log_format collect-app '$cad'; 416 | open_log_file_cache max=1000 inactive=60s; 417 | keepalive_timeout 0; 418 | client_max_body_size 20m; 419 | include /opt/app/collect-app/conf/vhost/*.conf; 420 | } 421 | ~~~ 422 | 423 | 424 | 425 | 5. cd到/opt/app/collect-app/conf/vhost/下,编写我们的APP的nginx配置,命名为collect-app.conf。这里说明一下,企业工程中我们一般会把多个应用配置和nginx主配置文件分开,然后在主配置文件中通过include命令包含我们的应用配置,在上方配置最后一行你可以看到include命令。这样做的目的是方便我们管理配置。 426 | 427 | ~~~shell 428 | #collect-app.conf 429 | server { 430 | listen 8802 default_server; 431 | 432 | # lua_need_request_body on; 433 | client_max_body_size 5M; 434 | client_body_buffer_size 5M; 435 | location /data/v1 { 436 | set $cad ''; 437 | content_by_lua_block { 438 | -- cjson模块 439 | local cjson = require "cjson" 440 | -- 读取请求体信息 441 | ngx.req.read_body() 442 | -- 请求体信息存放到 body_data变量中 443 | local body_data = ngx.req.get_body_data() 444 | -- 如果请求体为空,返回错误 445 | if body_data == nil then 446 | ngx.say([[{"code":500,"msg":"req body nil"}]]) 447 | return 448 | end 449 | -- 定义当前时间 450 | local current_time = ngx.now()*1000 451 | -- 请求的URL project参数中获取其值 452 | local project = ngx.var.arg_project 453 | -- 定义一个字典,存放有当前服务为日志增加的信息,如ctime表示接受到请求的时间,ip地址等 454 | local data={} 455 | data["project"] = project 456 | data["ctime"] = current_time 457 | if ngx.var.http_x_forwarded_for == nil then 458 | data["ip"] = ngx.var.remote_addr; 459 | else 460 | data["ip"] = ngx.var.http_x_forwarded_for 461 | end 462 | -- 将增加的信息编码为json 463 | local meta = cjson.encode(data) 464 | -- 将编码的json信息做base64 和 body_data拼接 465 | local res = ngx.encode_base64(meta) .. "-" .. ngx.unescape_uri(body_data) 466 | -- 将数据赋值给我们定义的nginx变量cad中,我们定义的log_format就使用这个变量的值 467 | ngx.var.cad = res 468 | ngx.say([[{"code":200,"msg":"ok"}]]) 469 | } 470 | access_log logs/collect-app.access.log collect-app; 471 | } 472 | } 473 | ~~~ 474 | 475 | > 上面的`ccess_log logs/collect-app.access.log collect-app`指定的是相对位置,下面我们再指定前缀 476 | 477 | 6. 将上述第4,5步中的配置文件,放到对应的目录下后,执行以下命令测试配置文件是否正确,并启动服务 478 | 479 | ~~~shell 480 | # 测试配置文件格式是否正确,-p指定上面需要的前缀 481 | sudo openresty -p /opt/app/collect-app/ -t 482 | # 后台启动 483 | sudo openresty -p /opt/app/collect-app/ 484 | #如果没有任何输出,代表我们已经成功启动nginx,后面讲解报警服务时,我们会用supervisor来管理nginx服务。 485 | # 执行下面命令,可以查看到我们的nginx的进程 486 | ps axu|grep nginx|grep -v grep 487 | # 也可以通过我们监听的端口号查看到nginx master 488 | netstat -antp |grep 8802 489 | ~~~ 490 | 491 | > ![1643861562371](assets/1643861562371.png) 492 | 493 | 7. Nginx启动后,安装我们的配置,已经在`8802`端口监听请求了,我们数据服务配置的路径是/data/v1,同时我们会解析请求中url的参数project的参数值。接下来我们就测试一下我们接口是否能正常接收数据。我们再来认识一下我们的接口。首先,我们的服务监听`8802`端口,请求的路径是/data/v1,如果客户端有数据请求过来,我们会解析HTTP请求`request_body`中的数据,接收到数据之后和我们自己定义的数据做拼接,日志写入到`collect-app.access.log`文件中,返回给客户端`{"code":200,"msg":"ok"}`。如果一个客户请求的`request_body`为空,我们将在日志中记录空行,返回客户端`{"code":500,"msg":"req body nil"}`。我们接下来通过测试验证我们的接口是否正常。 494 | 495 | ~~~shell 496 | # 发送一个带request_body的请求,值可以是任意值。 project参数的值,我们定成news,因为我们是新闻的行为数据 497 | curl localhost:8802/data/v1?project=news -d test_data 498 | # > return: {"code":200,"msg":"ok"} 499 | 500 | # 查看我们记录到的日志 501 | tail -n 1 /opt/app/collect-app/logs/collect-app.access.log 502 | # > return: eyJjdGltZSI6MTY0Mzg2MTc3ODg3NiwicHJvamVjdCI6Im5ld3MiLCJpcCI6IjEyNy4wLjAuMSJ9-test_data 503 | #可以看到我们的数据通过我们定义的"-"做了分隔,第一部分是我们base64后的自定义信息,每个人看到的可能是不一样的,第二部分是刚才HTTP请求体的数据test_data。这些在collect-app.conf文件里local res行定义了 504 | 505 | # 我们之前说过客户端发过来的数据也是做了base64的,我们也模拟一下 506 | echo "test_data"|base64 |xargs -I {} curl localhost:8802/data/v1?project=news -d {} 507 | # > return: {"code":200,"msg":"ok"} 508 | tail -n 1 /opt/app/collect-app/logs/collect-app.access.log 509 | # > return: eyJjdGltZSI6MTY0Mzg2MjA0ODAwNiwicHJvamVjdCI6Im5ld3MiLCJpcCI6IjEyNy4wLjAuMSJ9-dGVzdF9kYXRhCg== 510 | 511 | # 可以看到,我们得到了两部分base64数据,他们中间依然以"-"分隔,我们解析出来这两部分数据,验证结果 512 | # 第一部分 513 | echo "eyJjdGltZSI6MTY0Mzg2MjA0ODAwNiwicHJvamVjdCI6Im5ld3MiLCJpcCI6IjEyNy4wLjAuMSJ9"|base64 -d 514 | # > return: {"ctime":1643862048006,"project":"news","ip":"127.0.0.1"} 515 | # 可以看到,解出来的是我们在nginx lua中自定义的json信息。 516 | # 第二部分 517 | echo "dGVzdF9kYXRhCg=="|base64 -d 518 | # > return test_data 519 | # 可以看到解析出来是我们的reqest_body中的数据 520 | 521 | # 我们再发送一个不带 request_body 的数据 522 | curl localhost:8802/data/v1?project=news 523 | # > return {"code":500,"msg":"req body nil"} 524 | # 可以看到,如果客户端不带请求体发送请求,我们会给客户端返回错误信息 525 | ~~~ 526 | 527 | > ![1643862270997](assets/1643862270997.png) 528 | 529 | 8. 配置接口到管理中心。经过上述步骤,我们的接口就开发完毕了。接下来需要把我们的接口配置到管理中心,这样就可以接收到真实客户端上报的数据了。但由于大家的机器是内网,所以需要先把本机的服务端口,通过内网穿透暴露公网地址,之后配置这个公网地址到管理中心,管理中心通过这个公网给你地址发送数据。这部分内容仅仅是为了让你能够实时的接收到数据,按照下面的方法执行就可以了 530 | 531 | ~~~shell 532 | # 下载frp 客户端,这个frp是我们自己编译的,已经修改了源码中的默认地址,并做了相关优化,你下载完直接用即可 533 | mkdir -p /opt/soft/frp/ 534 | cd /opt/soft/frp/ 535 | wget https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/main/soft/frpc_0.33.linux_adm64.tgz 536 | # 可能需要改名 537 | mv frpc_0.33.linux_adm64.tgz\?raw\=true frpc_0.33.linux_adm64.tgz 538 | 539 | tar -xvzf frpc_0.33.linux_adm64.tgz 540 | /opt/soft/frp/frpc http --sd name -l 8802 -s frp.qfbigdata.com:7001 -u name # 这两个name替换成自己的名字拼音就可以 8802是我们nginx配置的监听端口,注意,name一定要改 541 | ~~~ 542 | 543 | > ![1643866651880](assets/1643866651880.png) 544 | > 545 | > ![1643869444450](assets/1643869444450.png) 546 | > 547 | > 这个打开后不能停,不小心停了再打开 548 | 549 | ~~~shell 550 | #运行上述命令后,会看到如上图日志 551 | # 只需要将我们开发的接口主机地址,替换为上述红色圈子中的http连接地址即可,比如上图: 552 | # 我们开发的接口地址是:localhost:8802/data/v1?project=news 553 | # 替换后的地址是(注意非https) http://name.frp.frp.qfbigdata.com:8002/data/v1?project=news 554 | # 同样可以测试一下新地址是否正常,注意name替换为自己写的名字拼音全拼 555 | curl http://name.frp.qfbigdata.com:8002/data/v1?project=news -d test_data 556 | #> 返回结果{"code":200,"data":true} 557 | ~~~ 558 | 559 | > 新打开一个窗口 560 | > 561 | > ![1643869498980](assets/1643869498980.png) 562 | 563 | ~~~shell 564 | # 接下来把次地址通过命令,配置到管理中心,你只需要把下方命令中 data_url=后面的地址替换成你的地址, name参数的值换成刚刚改的名字 565 | curl -X POST \ 566 | http://meta.frp.qfbigdata.com:8112/api/v1/meta/register \ 567 | -F data_url=http://name.frp.qfbigdata.com:8002/data/v1?project=news \ 568 | -F type=1 \ 569 | -F name=name 570 | # 请求成功后会有如下图返回值 571 | ~~~ 572 | 573 | > ![1643869508047](assets/1643869508047.png) 574 | > 575 | > 这时候内网穿透已经完成了 576 | 577 | ~~~shell 578 | # 如果一切OK,可以去看我们的access日志了,会发现数据正在实时写入到日志文件 579 | tail -f /opt/app/collect-app/logs/collect-app.access.log 580 | 581 | # 最后注意,你的frp启动后,如果想要一直接收数据,是不能停止的,一旦停止,就接收不到数据了,再启动就又可以接收到了 582 | ~~~ 583 | 584 | > 文件一直在增大 585 | > 586 | > ![1643870788661](assets/1643870788661.png) 587 | > 588 | > [数据管理中心代码](http://qianfeng.qfjava.cn:8087/bigdata/dmc), 这个是GoLang开发的,有兴趣可以看一下 589 | 590 | ##### 4.2.3. Flume行为数据收集 591 | 592 | 我们的日志已经实时的写入到文件了,为了能够通过Hadoop分析这些数据,我们首先要做的就是将数据投递到HDFS上。我们很容易想到Flume就是帮我们做这个事情的。我们需要思考,使用Flume时,`source channel sink`应该如何选择。 593 | 594 | 1. 首先对于`sink` 因为我们要将数据投递到HDFS上,毋庸置疑我们选择`hdfs sink`。 595 | 2. 对于`channel`, 我们有多种选择,如果速度是第一优先级,同时允许数据再Flume挂掉后有丢失,我们可以选择`Memory Channel`,如果不允许数据丢失,我们可以选择其他可以持久化数据的Channel,比如`File Channel,Kafka Channel` 。对于生成环境中,不同的公司根据其业务会有不同的选择,比如对于用户行为日志,偶尔的丢失数据是可以接受的,因为丢失的数据相对于总体的数据可用忽略不计,也不会因为少量的数据丢失而影响到分析结果,而数据采集的速度和性能我们是比较关注的,因此我们会选择`Memory Channel`。当然很多些企业也会选择`File Channel`,这是个仁者见仁智者见智的事情,`Kafka Channel`我们还没有学习Kakfa,这里先不提。 596 | 3. 对于`Source`,因为我们的数据是` access `日志文件,因此我们的Source可以选择`Spooling Directory Source` 和 `Exec Source` 。 我们为什么不使用`Exec Source`,请[参看官网对其解释](https://flume.apache.org/FlumeUserGuide.html#exec-source), 我们使用Spooling Directory Source,先要对我们的access日志做切分处理。接下来我们就开始自己写脚本,切分日志。 597 | 598 | 先来看一个现象,我们把名字改了 599 | 600 | ![1643873695928](assets/1643873695928.png) 601 | 602 | 可以看到改了名字后依然在变大,这说明nginx监控到的数据依然在往这里面放,因为nginx追踪的并不是文件名,而是inode唯一标识。即使移动文件也依然在增长。 603 | 604 | ![1643873897636](assets/1643873897636.png) 605 | 606 | 如果想做切分,但数据还是会往相同的inode里写入,所以还需要做一些操作,怎么让它停止对文件的追踪开发新的文件写新的日志,如下操作 607 | 608 | ![1643890246493](assets/1643890246493.png) 609 | 610 | `kill -USR1 2095`kill 掉掉这个id,让nginx产生一个新的文件 611 | 612 | ![1643890458958](assets/1643890458958.png) 613 | 614 | 可以看到旧的abc.log不再增加 615 | 616 | > 注意,这里我重启了机器,所以文件变小了。重启机器只需要跑这两个命令即可`openresty -p /opt/app/collect-app/`,`/opt/soft/frp/frpc http --sd name -l 8802 -s frp.qfbigdata.com:7001 -u name`注意name要改成之前改的名字 617 | 618 | 接下来定时执行我们的切分脚本,根据数据量级和对数据实时性的要求,选择切分周期,这里我们选择1分钟切分一次。 619 | 620 | ~~~shell 621 | # 先创建我们切分后的数据目录 622 | mkdir -p /opt/app/collect-app/logs/data/ 623 | # 建立一个目录用来存放我们以后的脚本文件 624 | mkdir -p /opt/scripts/ 625 | ~~~ 626 | 627 | cd到/opt/scripts/下,创建split-access-log.sh脚本文件,并添加如下内容 628 | 629 | ~~~shell 630 | #!/bin/sh 631 | # filename: split-access-log.sh 632 | # desc: 此脚本用于切割Nginx Access日志到指定的目录下,供Flume采集使用 633 | # date: 2020-04-28 634 | 635 | # 帮助 636 | usage() { 637 | echo "Usage:" 638 | echo " split-access-log.sh [-f log_file] [-d data_dir] [-p pid_file]" 639 | echo "Description:" 640 | echo " log_file: nginx access file absolute path" 641 | echo " data_dir: split data dir" 642 | echo " pid_file: nginx pid file absolute path" 643 | echo "Warning: if no parmas, use default value" 644 | exit -1 645 | } 646 | default(){ 647 | echo "user default value:" 648 | echo " log_file=/opt/app/collect-app/logs/collect-app.access.log" 649 | echo " data_dir=/opt/app/collect-app/logs/data/" 650 | echo " pid_file=/opt/app/collect-app/logs/nginx.pid" 651 | # 我们的access日志文件 652 | log_file="/opt/app/collect-app/logs/collect-app.access.log" 653 | # 切分后文件所放置的目录 654 | data_dir="/opt/app/collect-app/logs/data/" 655 | # Nginx pid 文件 656 | pid_file="/opt/app/collect-app/logs/nginx.pid" 657 | } 658 | 659 | while getopts 'f:d:p:h' OPT; do 660 | case $OPT in 661 | f) log_file="$OPTARG";; 662 | d) data_dir="$OPTARG";; 663 | p) pid_file="$OPTARG";; 664 | h) usage;; 665 | ?) usage;; 666 | *) usage;; 667 | esac 668 | done 669 | 670 | # 当没有参数传入时 671 | if [ $# -eq 0 ];then 672 | default 673 | fi 674 | 675 | # 重命名access, 注意mv 的过程日志是不会丢失的,因为nginx是以inode来表示数据文件的,而不是文件名,这里mv的操作不会改变inode 676 | if [ ! "${log_file}" ] || [ ! "${data_dir}" ] || [ ! ${pid_file} ]; then 677 | echo "some parmas is empty,please user " 678 | exit -1 679 | fi 680 | # 切分之前,先判断日志文件是否有数据,如果有数据再切分,防止切分出来很多空文件 681 | line=`tail -n 1 ${log_file}` 682 | if [ ! "$line" ];then 683 | echo "Warning: access log file no data, do not split!" 684 | exit 0 685 | fi 686 | mv ${log_file} ${data_dir}collect-app.access.$(date +"%s").log 687 | # 向nginx 发送 USR1信号,让其重新打开一个新的日志文件 688 | kill -USR1 `cat ${pid_file}` 689 | echo "finish!" 690 | ~~~ 691 | 692 | > ![1643890762076](assets/1643890762076.png) 693 | > 694 | > 测试下效果 695 | > 696 | > ~~~shell 697 | > sh split-access-log.sh 698 | > ~~~ 699 | > 700 | > ![1643890899399](assets/1643890899399.png) 701 | > 702 | > 可以看到上面的红框内容已经变小,被切分到下面的红框内了。 703 | 704 | ~~~shell 705 | # 建立一个目录用来存放我们以后的脚本执行过程中产生的日志 706 | mkdir -p /opt/scripts/logs 707 | # 写个crontab定时执行文件,一分钟切一次 708 | echo "*/1 * * * * sh /opt/scripts/split-access-log.sh >> /opt/scripts/logs/split-access-log.log 2>&1 " > /opt/scripts/collect-app-log.cron 709 | # 添加到定时任务,执行下面命令,linux其实是将你的定时脚本中的内容写到了 /var/spool/cron/root 文件中,这个root就是当前的用户名,因为我这边是以root执行的 710 | crontab /opt/scripts/collect-app-log.cron 711 | # 查看生成的定时任务 712 | crontab -l 713 | # 1分钟后可以查看我们脚本的执行日志 714 | more /opt/scripts/logs/split-access-log.log 715 | ~~~ 716 | 717 | > ![1643891023827](assets/1643891023827.png) 718 | > 719 | > 可以看到红框内的log已经变成0了,因为到一分钟了。 720 | 721 | 至此我们切分日志的工作就做完了,接下来我们要做就是编写Flume的配置文件,将数据投递到HDFS上了,根据我们前文对于`Source,Channel,Sink` 的选择,在/opt/scripts/下创建collect-app-agent.conf,并添加配置内容 722 | 723 | ~~~shell 724 | # filename: collect-app-agent.conf 725 | # 定义一个名字为 a1001 的agent 726 | # 定义channel 727 | a1001.channels = ch-1 728 | # 定义source 729 | a1001.sources = src-1 730 | # 定义sink 731 | a1001.sinks = k1 732 | 733 | # sink 接到 channel 上 734 | a1001.sinks.k1.channel = ch-1 735 | # source 接到 channel 上 736 | a1001.sources.src-1.channels = ch-1 737 | a1001.sources.src-1.type = spooldir 738 | # 数据文件目录 739 | a1001.sources.src-1.spoolDir = /opt/app/collect-app/logs/data/ 740 | # 正则匹配我们需要的数据文件 741 | a1001.sources.src-1.includePattern = ^collect-app.*.log 742 | # 如果想在header信息中加入你传输的文件的文件名,设置下面参数为true,同时设置文件header的key,我们这里设置成fileName,之后你就可以在sink端通过 %{fileName}, 取出header中的fileName变量中的值,这个值就是文件名 743 | # a1001.sources.src-1.basenameHeader = true 744 | # a1001.sources.src-1.basenameHeaderKey = fileName 745 | 746 | # 积累多少个event后,一起发到channel, 这个值在生成环境中我们需要根据数据量配置batchSize大的下,通常来讲们的batchSize越大,吞吐就高,但是也要受到 channel 的capacity,transactionCapacity的限制,不能大于channel的transactionCapacity值。 关于这三个参数的区别及说明参看 [官方wiki](https://cwiki.apache.org/confluence/display/FLUME/BatchSize%2C+ChannelCapacity+and+ChannelTransactionCapacity+Properties) 747 | a1001.sources.src-1.batchSize = 100 748 | 749 | a1001.sinks.k1.type = hdfs 750 | a1001.sinks.k1.hdfs.path = hdfs://qianfeng01:8020/sources/news/%Y%m%d 751 | a1001.sinks.k1.hdfs.filePrefix = news-%Y%m%d_%H 752 | a1001.sinks.k1.hdfs.fileSuffix = .gz 753 | a1001.sinks.k1.hdfs.codeC = gzip 754 | a1001.sinks.k1.hdfs.useLocalTimeStamp = true 755 | a1001.sinks.k1.hdfs.writeFormat = Text 756 | a1001.sinks.k1.hdfs.fileType = CompressedStream 757 | # 禁用安装event条数来滚动生成文件 758 | a1001.sinks.k1.hdfs.rollCount = 0 759 | # 如果一个文件达到10M滚动 760 | a1001.sinks.k1.hdfs.rollSize = 10485760 761 | # 5分钟滚动生成新文件,和文件大小的滚动一起,那个先达到,执行那个 762 | a1001.sinks.k1.hdfs.rollInterval = 600 763 | # 参加上边连接官网说明,理论上batchSize 越大,吞吐越高。 但是HDFS Sink 调用 Hadoop RPC(包括 open、flush、close ..)超时会抛出异常,如果发生在 flush 数据阶段,部分 event 可能已写入 HDFS,事务回滚后当前 BatchSize 的 event 还会再次写入造成数据重复。 batchSize越大可能重复的数据就越多. 同时batchSize值,不能大于channel的transactionCapacity值 764 | a1001.sinks.k1.hdfs.batchSize = 100 765 | # 每个HDFS SINK 开启多少线程来写文件 766 | a1001.sinks.k1.hdfs.threadsPoolSize = 10 767 | # 如果一个文件超过多长时间没有写入,就自动关闭文件,时间单位是秒 768 | a1001.sinks.k1.hdfs.idleTimeout = 60 769 | 770 | a1001.channels.ch-1.type = memory 771 | a1001.channels.ch-1.capacity = 10000 772 | a1001.channels.ch-1.transactionCapacity = 100 773 | ~~~ 774 | 775 | 编写一个脚本启动Flume Agent 开始采集数据,在/opt/scripts/下创建start-flume-agent.sh 776 | 777 | ~~~shell 778 | #!/bin/sh 779 | # filename: start-flume-agent.sh 780 | # desc: 启动采集数据的flume agent,agent 名字为 a1001 781 | # date: 2020-04-28 782 | # 请写你安装的FLUME的路径 783 | FLUME_HOME=/opt/local/flume 784 | 785 | ${FLUME_HOME}/bin/flume-ng agent -c ${FLUME_HOME}/conf -f /opt/scripts/conf/collect-app-agent.conf -n a1001 -Dflume.root.logger=INFO,console -Dflume.monitoring.type=http -Dflume.monitoring.port=31001 786 | ~~~ 787 | 788 | 启动 789 | 790 | ~~~shell 791 | # 依然把你的脚本放到你之前创建的 /opt/scripts/ 目录下 792 | # 直接执行,程序运行在前台 793 | sh /opt/scripts/start-flume-agent.sh 794 | # 可以后台执行 795 | nohup sh /opt/scripts/start-flume-agent.sh >> /opt/scripts/a1001-flume-agent.log 2>&1 & 796 | # 终止进程 797 | ps axu|grep flume|grep collect-app-agent.conf|gawk '{print $2}'|xargs -n1 kill -15 798 | ~~~ 799 | 800 | 801 | 802 | 803 | 804 | -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1642557741872.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1642557741872.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1642563394249.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1642563394249.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1642564130136.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1642564130136.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1643860152216.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1643860152216.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1643860621257.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1643860621257.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1643861562371.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1643861562371.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1643862270997.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1643862270997.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1643866651880.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1643866651880.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1643869444450.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1643869444450.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1643869498980.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1643869498980.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1643869508047.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1643869508047.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1643870788661.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1643870788661.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1643873695928.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1643873695928.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1643873897636.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1643873897636.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1643890185710.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1643890185710.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1643890246493.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1643890246493.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1643890458958.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1643890458958.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1643890762076.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1643890762076.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1643890853267.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1643890853267.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1643890899399.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1643890899399.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/1643891023827.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/1643891023827.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/采集架构一.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/采集架构一.png -------------------------------------------------------------------------------- /采集与监控平台项目/assets/采集架构二.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ben1234560/Practical-projects-of-BigData-and-AI/65c5a4bdb9f0ff2a57b1be3116924e9aad5beeda/采集与监控平台项目/assets/采集架构二.png --------------------------------------------------------------------------------