大数据各个工具随笔

# 基本配置

```shell
#目录结构:
bin:二进制的客户端命令
etc:存放配置文件
etc/conf
lib:存放jar包的目录
sbin:存放管理类的脚本启动服务
share:hadoop所有的jar包

#查看主机名
hostname
#临时修改主机名
hostname hadoop
#永久修改主机名
vi /etc/sysconfig/network

#查看主机ip
ifconfig -a

#静态IP配置
setup编辑网卡

vi /etc/sysconfig/network-scripts/ifcfg-eth0或eth1
service network restart 重启网络服务

#配置映射关系
vi /etc/hosts
#时钟同步
ntpdate us.pool.ntp.org # 此命令即可和时钟服务器进行同步
crontab -e # 设置定时任务

#查看防火墙规则
vim /etc/sysconfig/iptables
#关闭防火墙:
service iptables stop
#永久关闭:
chkconfig iptables off
#重启防火墙
systemctl restart firewalld
#关闭深层防火墙selinux需重启liunx
vim /etc/selinux/config # 打开配置文件
SELINUX = enforcing 更改为 SELINUX = disabled

#ssh免密登录
ssh-keygen -t rsa # 使用非对称加密生成公钥和私钥
ssh-copy-id 主机名 #分发公钥
测试
ssh 主机名

#下载rz并全自动安装
yum -y install lrzsz

#下载文件
sz 默认下载地址

#创建普通用户
useradd 普通用户名
passwd 普通用户密码
visudo:会打开一个文件,该文件中可以配置让普通用户越权执行命令
hpsk ALL=(root) NOPASSWD: ALL
su -普通用户名/root #切换用户
或用exit

#修改目录用户
chown -R root:root export

chown -R 用户名:用户名 目录名

#授权
chmod 755 ./*.sh
#加执行权限
chomd +x 文件名

tar -zxvf 文件名 -C 路径 #解压到指定目录
Unzip 文件名 -d 路径 #解压到指定目录
scp -r 文件名 用户名@主机名:$PWD #发送到同级目录
scp -r 文件名 用户名@主机名:/export/servers #发送到指定目录

mv 原名 重命名 #重命名
mv 文件名 路径 #移动


#查看日志
tail -100f logs/kafka.log

#修改环境变量:
vi /etc/profile
#立即生效:
source /etc/profile

#创建软连接
ln -s 【目标目录】 【软链接地址】
#删除链接
rm -rf 【软链接地址】
#修改链接
ln -snf 【新目标目录】 【软链接地址】

#添加到启动列表
chkconfig redis on
验证:chkconfig --list

kill -9 进程号 强制终止进程

#解决进程杀不掉
cd /tmp查看hsperfdata_开头的目录 rm -rf 删除下边文件号

#查看路由表
netstat -rn
#远程登录
telnet 主机名

df-h 查看资源占用情况

top 查看实时更新进程
ps -lA 查看所有进程
pstree -P 以树状形式显示进程,并显示进程号
kill -9 -1 杀死所有进程
ps -aux 查看所有进程包括后台进程只显示自己的进程号(PID)
ps -ef 查询系统中所有运行的进程可以显示每个进程的父进程号(PPID)
ps aux|grep tomact 解释:以管道形式搜索
```

```shell
#netstat命令各个参数说明如下:

-t : 指明显示TCP端口
-u : 指明显示UDP端口
  -l : 仅显示监听套接字(所谓套接字就是使应用程序能够读写与收发通讯协议(protocol)与资料的程序)
  -p : 显示进程标识符和程序名称,每一个套接字/端口都属于一个程序。
  -n : 不进行DNS轮询,显示IP(可以加速操作)
即可显示当前服务器上所有端口及进程服务,于grep结合可查看某个具体端口及服务情况

netstat -ntlp //查看当前所有tcp端口·
netstat – tnl 可以看到处于监听状态的 TCP 端口和连接
netstat -ntulp |grep 80 //查看所有80端口使用情况·
netstat -an | grep 3306 //查看所有3306端口使用情况·
netstat -atunlp | grep 10000

#查看一台服务器上面哪些服务及端口
netstat -lanp
#查看一个服务有几个端口。比如要查看mysqld
ps -ef |grep mysqld
#查看某一端口的连接数量,比如3306端口
netstat -pnt |grep :3306 |wc
#查看某一端口的连接客户端IP 比如3306端口
netstat -anp |grep 3306

netstat -an 查看网络端口 lsof -i :port,使用lsof -i :port就能看见所指定端口运行的程序,同时还有当前连接。 nmap 端口扫描netstat -nupl (UDP类型的端口)netstat -ntpl (TCP类型的端口)netstat -anp 显示系统端口使用情况
```

```shell
#1-手动添加一块硬盘:详细过程参考图片
注意该虚拟硬盘所在的物理硬盘剩余空间至少大于15GB
#2-创建分区
fdisk -l 确认出现/dev/sdb该硬盘设备
fdisk /dev/sdb 对sdb硬盘进行分区
p 查看当前硬盘的分区信息
n 创建新分区
p 分区类型为主分区
1 分区号为1
回车 硬盘起始位置,默认为0
回车 硬盘结束位置,默认为最大值
p 查看当前硬盘的分区信息
w 保存并退出
mkfs -t ext4 /dev/sdb1 格式化硬盘分区

#3-挂载目录
创建挂载目录:
mkdir /export/users
手动临时挂载:
mount /dev/sdb1 /export/users
验证是否挂载成功:
df -h
永久挂载,开机自动加载:
echo "/dev/sdb1 /export/users ext4 defaults 0 0" >> /etc/fstab
```

## java

rpm -qa | grep java 查看是否已经安装了jdk
rpm -e --nodeps 软件的名称 将软件进行卸载

修改环境变量:
vi /etc/profile
立即生效:

source /etc/profile

## mysql

一、rpm安装包安装

```shell
#1.查看系统自带的mysql的rpm包
rpm -qa | grep mysql
删除自带安装包
rpm -e mysql-libs-5.1.73-8.el6_8.x86_64 --nodeps
#2.安装mysql的rpm包
rpm -ivh *.rpm

rpm -ivh MySQL-client-5.6.25-1.el6.x86_64.rpm
#3.启动mysql的服务

启动脚本: service mysql start
关闭脚本: service mysql stop
重启:service mysqld restart

#4.查看mysql初始化密码
cat /root/.mysql_secret

#5.登录mysql,root用户默认没有密码
mysql -u root -p+密码

#6.在mysql中修改自己的密码
set password = password('密码');

#7.远程登录mysql的权限登录mysql后输入如下命令
grant all privileges on *.* to 'root'@'%' identified by '123456' with grant option;
flush privileges;

#8.设置mysql的开机启动
chkconfig --add mysqld
chkconfig mysqld on

#9.查询列表:
chkconfig
#10.卸载

rpm -qa | grep -i mysql#查看所有mysql的安装包

卸载所有mysql的安装包

rpm -e --nodeps MySQL-server-5.6.25-1.el6.x86_64

MySQL-client-5.6.25-1.el6.x86_64

MySQL-devel-5.6.25-1.el6.x86_64

MySQL-shared-compat-5.6.25-1.el6.x86_64

MySQL-embedded-5.6.25-1.el6.x86_64

MySQL-test-5.6.25-1.el6.x86_64

MySQL-shared-5.6.25-1.el6.x86_64

#查看是否卸载干净
rpm -qa | grep -i mysql

#查看哪里还有mysql的文件夹
whereis mysql

删除所有关于mysql的配置以及文件夹即可

删掉 rm -rf /usr/lib64/mysql

删掉 rm -rf /usr/my.cnf

删掉 rm -rf /root/.mysql_secret

删掉 rm -rf /var/lib/mysql
```

二、在线安装(5.1.73)

```shell
#1.在线安装mysql相关的软件包
yum install mysql mysql-server mysql-devel
#2.启动mysql的服务
/etc/init.d/mysqld start
#3.通过mysql安装自带脚本进行设置
/usr/bin/mysql_secure_installation
#4.进入mysql的客户端然后进行授权
grant all privileges on *.* to 'root'@'%' identified by '123456' with grant option;
flush privileges;
#5.设置开机自启
chkconfig --add mysqld
chkconfig mysqld on


```

三、在线安装(5.7)

```shell
一、安装MySQL:root用户操作
#1、检查是否安装
yum list installed | grep mysql
卸载:
yum -y remove mysql-server
yum -y remove mysql
yum -y remove mysql-libs
#2、安装依赖
yum install libaio
#3、配置MySQL的yum源
下载yum源的rpm包
wget http://repo.mysql.com/mysql57-community-release-el6.rpm
安装yum源的rpm包
yum -y localinstall mysql57-community-release-el6.rpm
查看是否安装成功
yum repolist enabled | grep "mysql.*-community.*"
查看可用的MySQL版本
yum repolist all | grep mysql
#4、安装MySQL
yum -y install mysql-community-server
查看安装位置:
whereis mysql
#5、启动MySQL:
如果安装过MySQL:
rm -rf /var/lib/mysql/ib*
清空数据目录:
rm -rf /var/lib/mysql/*
初始化:
mysqld --initialize --user=mysql
查看临时密码:
more /var/log/mysqld.log | grep 'temporary password'
启动MySQL服务
service mysqld start
设置开机自启动
chkconfig mysqld on
#6、登录MySQL:
mysql -uroot -p
回车输入临时密码
#7、修改登录密码
set password for 'root'@'localhost'=password('123456');
#8、授权允许从其他机器登录
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456' WITH GRANT OPTION;
FLUSH PRIVILEGES;
#9、设置UTF-8编码
vim /etc/my.cnf
[mysqld]
character_set_server = utf8
[mysql]
default-character-set = utf8
查看:SHOW VARIABLES LIKE 'character%';
```

## git

1.下载地址:https://git-scm.com/download

## nginx

```shell
./nginx 启动
./nginx -s stop 停止 ./nginx -s reload 重启 修改完配置文件,必须重新启动才会生效
./nginx -t 检查配置文件的合法性
```
1) 安装依赖环境: 由于nginx为C语言开发, 需要C语言依赖环境

```
yum install -y gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel
./configure
```

2.上传解压安装包

```
使用rz上传即可, 上传到 /export/software目录下
tar -zxvf nginx-1.8.0.tar.gz
cd nginx-1.8.0
```

3.设置编译参数

```
--prefix=/export/servers/nginx
--pid-path=/export/data/nginx/nginx.pid
--lock-path=/export/data/nginx.lock
--error-log-path=/export/logs/nginx/error.log
--http-log-path=/export/logs/nginx/access.log
--with-http_gzip_static_module
--http-client-body-temp-path=/export/data/nginx/client
--http-proxy-temp-path=/export/data/nginx/proxy
--http-fastcgi-temp-path=/export/data/nginx/fastcgi
--http-uwsgi-temp-path=/export/data/nginx/uwsgi
--http-scgi-temp-path=/export/data/nginx/scgi
解释:
--prefix=/export/servers/nginx 代表将nginx安装到哪个目录中

--pid-path=/export/data/nginx/nginx.pid nginx的pid文件存放的位置 待会需要创建这个目录nginx

--error-log-path=/export/logs/nginx/error.log nginx错误日志存放的文件目录

--http-log-path=/export/logs/nginx/access.log nginx的访问日志
```

4.编译安装

```
先创建数据和日志存放的文件夹
mkdir -p /export/data/nginx
mkdir -p /export/logs/nginx
进行编译和安装
cd /export/software/nginx-1.8.0 # 切换nginx根目录
make # 编译
make install # 安装, 安装后在 /export/servers/nginx
```

5.# 启动nginx

```
cd /export/servers/nginx/sbin
./nginx # 启动nginx

查看nginx启动进程
ps -ef | grep nginx


注意:执行./nginx启动nginx,这里可以-c指定加载的nginx配置文件,如下:
./nginx -c /export/servers/nginx/conf/nginx.conf
如果不指定-c,nginx在启动时默认加载conf/nginx.conf文件,此文件的地址也可以在编译安装nginx时指定./configure的参数(--conf-path= 指向配置文件(nginx.conf))


停止nginx:
快速停止:
cd /export/servers/nginx/sbin
./nginx -s stop
此方式相当于先查出nginx进程id再使用kill命令强制杀掉进程。

完整停止(推荐使用):
cd /usr/local/nginx/sbin
./nginx -s quit
此方式停止步骤是待nginx进程处理任务完毕进行停止。

重启nginx :
先停止再启动(建议使用):
对nginx进行重启相当于先停止nginx再启动nginx,即先执行停止命令再执行启动命令。
如下:
./nginx -s quit
./nginx

重新加载配置文件:
当nginx的配置文件nginx.conf修改后,要想让配置生效需要重启nginx,使用-s reload不用先停止nginx再启动nginx即可将配置信息在nginx中生效,如下:
./nginx -s reload
```

6.使用nginx

```
修改配置文件: conf/ nginx.conf文件
```

7.安装测试

![](jiqun-images/1561523111292.png)**发布网站到服务器中**

```
访问路径: http://ip地址
注意: 上面这个访问路径,表示已经访问到了,html目录的下, 默认访问到html的目录的index页面
```

![](jiqun-images/1561534105434.png)

```
另一种方式:我们可以将页面复制到nginx的目录下,然后访问

- 使用此种方式, 需要修改nginx的配置文件:nginx.conf
- 修改完配置文件后: 需要重新加载一下配置文件: ./nginx -s reload
```

![](jiqun-images/1543584639422.png)

```
访问路径: http://ip地址/页面名称
注意: 这个路径, 默认访问到了配置文件中 root后面设置的路径下, 默认访问的index页面
```

![](jiqun-images/wps77FB.tmp.jpg)

但是我们可以发现这样,通过IP地址可以访问。但是IP其实相对来讲是很难记住的,我们通常会通过域名去访问一个网站。

```
1. 上传网站到142服务器上 : /export/servers/nginx
2. 网站的解压 tar -zxvf dest.tar.gz
3. 修改的nginx的配置(参考他的html网站如何部署)nginx.conf
sz nginx.conf 将这个文件下载到windows桌面
修改nginx.conf 文件 root dest;
4. 重新上传到conf目录中
5. 重新启动 进入nginx下sbin目录下 ./nginx -s reload
http://192.168.72.142/
```

![](jiqun-images/1561532453847.png)

**网站访问的过程**

![](jiqun-images/1547688376994.png)

**修改hosts文件**

```shell
进入电脑C:WindowsSystem32driversetc下查找一个hosts文件

192.168.72.142 www.jx.com # 如果使用的是公开的比较有名的域名, 可能会导致访问不到, 建议使用ie浏览器尝试, 或者换一个自定义域名

打开浏览器访问:http://www.jx.com
```

**配置nginx的反向代理, 实现网站发布(重点)**

![](jiqun-images/1539338764382.png)

```
这个过程被称为是反向代理, 原来浏览器直接请求tomcat, 获得内容, 现在由nginx作为代理, 请求目标地址, 并将目标地址的数据返回给浏览器
```

![](jiqun-images/1561537956102.png)

如何配置呢.

- 1) 修改配置文件: conf/ nginx.conf文件, 添加如下内容
- 提示: 可以直接打开配置文件, 拉到最下面, 在最后一个没有被注释的大括号前书写

```
pstream tomcat1 {
server 192.168.72.141:8080;
server 192.168.72.142:8080;
server 192.168.72.143:8080;
}

server {
listen 80;
server_name localhost;

location / {
proxy_pass http://tomcat1;
index index.html index.htm;
}
}
```

![](jiqun-images/1561538248369.png)

**负载均衡**

```
负载均衡是由多台服务器以对称的方式组成一个服务器集合,每台服务器都具有等价的地位,都可以单独对外提供服务而无须其他服务器的辅助。

通过某种负载分担技术,将外部发送来的请求均匀分配到对称结构中的某一台服务器上,而接收到请求的服务器独立地回应客户的请求。均衡负载能够平均分配客户请求到服务器列阵,借此提供快速获取重要数据,解决**大量并发访问**服务问题。 (廉价的)
```

**nginx的负载均衡**

```
我们可以在nginx上配置多台服务器, 当大量并发访问的时候, 我们通过nginx将这些并发请求根据一定的规则平均分派到多台服务器, 提高服务器高可用
```

![](jiqun-images/1543589410708.png)

**如何在nginx中配置负载均衡(重点)**

![](jiqun-images/1561537769951.png)

1) 修改配置文件

```shell
upstream tomcat1 {
server 192.168.72.141:8080;
server 192.168.72.142:8080;
server 192.168.72.143:8080;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://tomcat1;
index index.html index.htm;

}
}

********** 上述代码是原始内容, 只需要更改upsteam中的server即可

#第一种方案: 配置多台server, nginx就会自动进行负载均衡, 将并发请求平均分配给这两个服务器
upstream tomcat1 {
server 192.168.72.141:8080;
server 192.168.72.142:8080;
server 192.168.72.143:8080;

}
#第二种方案: 可以根据服务器的实际情况调整服务器权重。权重越高分配的请求越多,权重越低,请求越少。默认是都是1
upstream tomcat1 {
server 192.168.72.141:8080 weight=3;
server 192.168.72.142:8080 weight=1;
server 192.168.72.143:8080 weight=6;

}
#例如设置为2, 表示第二个服务器所能承受比第一台两倍的并发请求, 此时, nginx就会权重分配, 如果有6个并发请求, 第二台会承受4个请求, 而第一台只会承受2个请求

注意:
1. 三台服务器中的tomcat必须保证可以正常访问
2. nginx的配置文件修改后, 一定要重新加载nginx : ./nginx -s reload
```

关于高可用的搭建可以参考此地址: http://blog.51cto.com/superpcm/2095395

## redis

添加到启动列表
chkconfig redis on
验证:chkconfig --list

service redis start
启动
service redis stop
停止
service redis restart
重启
service redis status
查看状态
1.下载redis安装包

wget http://download.redis.io/releases/redis-4.0.2.tar.gz

解压:tar -zxvf redis-4.0.2.tar.gz -C ../servers

2.安装编译环境

```
yum -y install gcc gcc-c++ libstdc++-devel tcl -y
```

3.编译并进行安装redis

```
cd /export/servers/redis-src/
make MALLOC=libc
make PREFIX=/export/servers/redis install
```

4.在指定的位置创建一个redis的配置文件

mkdir -p /export/servers/redis/conf
cd /export/servers/redis/conf
vi redis_6379.conf

配置文件内容:

```shell
bind 192.168.72.142 绑定的ip
protected-mode yes
port 6379 端口号 tcp-backlog 511
timeout 0 #客户端闲置多少秒后,断开连接
tcp-keepalive 300
daemonize yes #是否作为守护进程运行
supervised no
pidfile /export/data/redis/6379/redis_6379.pid pid文件位置
loglevel notice 日志级别
logfile "/export/data/redis/6379/log.log" 日志文件的位置(出错查看日志)
databases 16 #设置数据库的数量,默认连接的数据库是0,可以通过select N来连接不同的数据库
always-show-logo yes
save 900 1 表示900s内如果有1条是写入命令,就触发产生一次快照
save 300 10 表示300s内如果有10条是写入命令,就触发产生一次快照
save 60 10000 表示60s内如果有10000条是写入命令,就触发产生一次快照
stop-writes-on-bgsave-error yes 如果持久化出错,主进程是否停止写入
rdbcompression yes 是否压缩
rdbchecksum yes 导入时是否检查
dbfilename dump.rdb rdb文件名称
dir /export/data/redis/6379/ 数据保存目录
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
slave-lazy-flush no
appendonly yes 是否开启aof
appendfilename "appendonly.aof" 文件名称
appendfsync everysec 同步方式[always everysec no]
no-appendfsync-on-rewrite no aof重写期间是否同步
auto-aof-rewrite-percentage 100 重写触发配置
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes 加载aof时如果有错如何处理
aof-use-rdb-preamble no
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes 文件重写策略
```

4.启动redis的服务

```
mkdir -p /export/data/redis/6379/
cd /export/servers/redis/bin/
./redis-server ../conf/redis_6379.conf
```

5.客户端连接

cd /export/servers/redis/bin/
./redis-cli -h 192.168.72.142
以下命令为检测命令:
输入: ping 返回 pong 表示成功

客户端退出:
第一种:强制退出 Ctrl+c
第二种: quit

## sorl

1. solr的下载

途径1: 官网网址: http://lucene.apache.org/ 与Lucene的官网是一个

途径2: 下载历史版本的网址: http://archive.apache.org/dist/lucene/solr/

## zookeeper

```shell
1.上传解压安装包

2.在conf目录下修改zoo_sample.cfg 文件
修改dataDir=/export/data/zk
在底部添加

server.1=node01:2887:3887

server.2=node02:2887:3887
server.3=node03:2887:3887

(zookeeper客户端连接端口:2181;2887:服务器间通信的端口

3887:选举的端口)
3.将配置好的zookeeper发送到其他主机

4.分别输入以下命令,配置myid

node01:执行的命令
mkdir -p /export/data/zk
echo "1" > /export/data/zk/myid //将1字符串写入myid这个文件中,文件位置和文件名不可以修改
cat /export/data/zk/myid //此命令用于查看此文件有没有正确写入 1

node02:执行的命令
mkdir -p /export/data/zk
echo "2" > /export/data/zk/myid
cat /export/data/zk/myid //此命令用于查看此文件有没有正确写入 2

node03:执行的命令
mkdir -p /export/data/zk
echo "3" > /export/data/zk/myid
cat /export/data/zk/myid //此命令用于查看此文件有没有正确写入 3
```

sbin/zkServer.sh start 启动

sbin/zkServer.sh status 查看状态

sbin/zkServer.sh restart 重启

sbin/zkServer.sh stop 停止

## ELK

**Elasticsearch 安装部署**

```shell
1创建用户
创建一个es专门的用户(必须),因为es不能用root用户启动
#使用root用户在三台机器执行以下命令
useradd es
mkdir -p /export/servers/es
mkdir -p /export/data/es
mkdir -p /export/logs/es
chown -R es /export/servers/es
chown -R es /export/data/es
chown -R es /export/logs/es
passwd es

2为es用户添加sudo权限
三台机器使用root用户执行visudo然后为es用户添加权限
visudo
es ALL=(ALL) ALL

关闭我们的xshll的所有的会话,重新连接,一定要记得使用es的用户来连接我们的linux服务器

第一台服务器切换到es用户下,下载安装包
su es
cd ~
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.0.0.tar.gz
tar -zxvf elasticsearch-6.0.0.tar.gz -C /export/servers/es/
4 第一台服务器修改配置文件
cd /export/servers/es/elasticsearch-6.0.0/config
rm elasticsearch.yml
vi elasticsearch.yml
# 集群名字
cluster.name: myes
# # 集群中当前的节点
node.name: node01
# # 数据目录
path.data: /export/data/es
# # 日志目录
path.logs: /export/logs/es
# # 当前主机的ip地址
network.host: 192.168.52.100
http.port: 9200
# # 集群上的节点信息
discovery.zen.ping.unicast.hosts: ["node01","node02","node03"]
# # linux安装es的一个bug解决的配置
bootstrap.system_call_filter: false
bootstrap.memory_lock: false
# # 是否支持跨域
http.cors.enabled: true
# # *表示支持所有域名
http.cors.allow-origin: "*"

5 安装包分发到其他两台机器上
node01服务器执行以下命令
cd /export/servers/es
scp -r elasticsearch-6.0.0/ node02:$PWD
scp -r elasticsearch-6.0.0/ node02:$PWD

6 node02与node03服务器修改配置文件
node02服务器修改配置文件
cd /export/servers/es/elasticsearch-6.0.0/config
vim elasticsearch.yml

cluster.name: myes
node.name: node02
path.data: /export/data/es
path.logs: /export/logs/es
network.host: 192.168.52.110
http.port: 9200
discovery.zen.ping.unicast.hosts: ["node01","node02","node03"]
bootstrap.system_call_filter: false
bootstrap.memory_lock: false
# 是否支持跨域
http.cors.enabled: true
# *表示支持所有域名
http.cors.allow-origin: "*"


node03服务器修改配置文件

cd /export/servers/es/elasticsearch-6.0.0/config
vim elasticsearch.yml
cluster.name: myes
node.name: node03
path.data: /export/data/es
path.logs: /export/logs/es
network.host: 192.168.52.120
http.port: 9200
discovery.zen.ping.unicast.hosts: ["node01","node02","node03"]
bootstrap.system_call_filter: false
bootstrap.memory_lock: false
# 是否支持跨域
http.cors.enabled: true
# *表示支持所有域名
http.cors.allow-origin: "*"

更多配置文件:https://blog.csdn.net/an74520/article/details/8219814

7、三台机器修改jvm内存大小
三台机器执行以下命令修改jvm内存大小
cd /export/servers/es/elasticsearch-6.0.0/config
vi jvm.options
-Xms2g
-Xmx2g
8、三台机器修改系统配置,增加打开文件的最大数量
问题一:max file descriptors [4096] for elasticsearch process likely too low, increase to at least [65536]
ES因为需要大量的创建索引文件,需要大量的打开系统的文件,所以我们需要解除linux系统当中打开文件最大数目的限制,不然ES启动就会抛错
三台机器执行以下命令解除打开文件数据的限制
sudo vi /etc/security/limits.conf
添加如下内容: 注意*不要去掉了
* soft nofile 65536
* hard nofile 131072
* soft nproc 2048
* hard nproc 4096

问题二:max number of threads [1024] for user [es] likely too low, increase to at least [4096]
修改普通用户可以创建的最大线程数
max number of threads [1024] for user [es] likely too low, increase to at least [4096]
原因:无法创建本地线程问题,用户最大可创建线程数太小
解决方案:修改90-nproc.conf 配置文件。
三台机器执行以下命令修改配置文件
sudo vi /etc/security/limits.d/90-nproc.conf
找到如下内容:
* soft nproc 1024
#修改为
* soft nproc 4096

问题三:max virtual memory areas vm.max_map_count [65530] likely too low, increase to at least [262144]
调大系统的虚拟内存
max virtual memory areas vm.max_map_count [65530] likely too low, increase to at least [262144]
原因:最大虚拟内存太小
每次启动机器都手动执行下。
三台机器执行以下命令,注意每次启动ES之前都要执行
sudo sysctl -w vm.max_map_count=262144

备注:以上三个问题解决完成之后,重新连接secureCRT或者重新连接xshell生效
需要保存、退出、重新登录xshell才可生效。
```

2 启动es服务

```
1 启动
注意啦,同学们!这里是后台启动,要发现错误的话,去/export/logs/es目录下查看。
nohup /export/servers/es/elasticsearch-6.0.0/bin/elasticsearch >/dev/null 2>&1 &

2 访问es
在Google Chrome浏览器中,访问以下地址
http://node01:9200/?pretty
pretty:格式化的,漂亮的。
得到以下内容
{
"name": "node01",
"cluster_name": "myes",
"cluster_uuid": "cWDpO5DnR-CW7YUH4Ojt5A",
"version": {
"number": "6.0.0",
"build_hash": "8f0685b",
"build_date": "2017-11-10T18:41:22.859Z",
"build_snapshot": false,
"lucene_version": "7.0.1",
"minimum_wire_compatibility_version": "5.6.0",
"minimum_index_compatibility_version": "5.0.0"
},
"tagline": "You Know, for Search"
}

```

**3 node01服务器安装elasticsearch-head插件**

1 、node01机器安装nodejs

```shell
Node.js是一个基于 Chrome V8 引擎的 JavaScript 运行环境。
Node.js是一个Javascript运行环境(runtime environment),发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装。Node.js 不是一个 JavaScript 框架,不同于CakePHP、Django、Rails。Node.js 更不是浏览器端的库,不能与 jQuery、ExtJS 相提并论。Node.js 是一个让 JavaScript 运行在服务端的开发平台,它让 JavaScript 成为与PHP、Python、Perl、Ruby 等服务端语言平起平坐的脚本语言。
安装步骤参考:https://www.cnblogs.com/kevingrace/p/8990169.html

第一步:下载安装包
# 下载安装包
node01机器执行以下命令下载安装包
cd /home/es
wget https://npm.taobao.org/mirrors/node/v8.1.0/node-v8.1.0-linux-x64.tar.gz

第二步:解压安装包
执行以下命令进行解压
cd /home/es
tar -zxvf node-v8.1.0-linux-x64.tar.gz -C /export/servers/es/
第三步:创建软连接
# 修改目录
执行以下命令创建软连接
sudo ln -s /export/servers/es/node-v8.1.0-linux-x64/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm
sudo ln -s /export/servers/es/node-v8.1.0-linux-x64/bin/node /usr/local/bin/node
第四步:修改环境变量
#修改环境变量
sudo vim /etc/profile

export NODE_HOME=/export/servers/es/node-v8.1.0-linux-x64
export PATH=:$PATH:$NODE_HOME/bin

source /etc/profile
第五步:验证安装成功
node -v
npm –v
```

![](jiqun-images/15561465215.png)

2 、node01机器安装elasticsearch-head插件

```shell
elasticsearch-head这个插件是es提供的一个用于图形化界面查看的一个插件工具,可以安装上这个插件之后,通过这个插件来实现我们通过浏览器查看es当中的数据
安装elasticsearch-head这个插件这里提供两种方式进行安装,第一种方式就是自己下载源码包进行编译,耗时比较长,网络较差的情况下,基本上不可能安装成功
第二种方式就是直接使用我已经编译好的安装包,进行修改配置即可
1、第一种方式:在线安装elasticsearch-head插件(网速慢,不推荐)
这里选择node01进行安装
第一步:在线安装必须依赖包
# 初始化目录
cd /export/servers/es
# 安装GCC
sudo yum install -y gcc-c++ make git
第二步:从git上面克隆编译包并进行安装
cd /export/servers/es
git clone https://github.com/mobz/elasticsearch-head.git
# 进入安装目录
cd /export/servers/es/elasticsearch-head
# intall 才会有 node-modules
npm install
```

![](jiqun-images/%E5%9B%BE%E7%89%871.png)

```shell
以下进度信息
npm WARN notice [SECURITY] lodash has the following vulnerability: 1 low. Go here for more details:
npm WARN notice [SECURITY] debug has the following vulnerability: 1 low. Go here for more details: https://nodesecurity.io/advisories?search=debug&version=0.7.4 - Run `npm i npm@latest -g` to upgrade your npm version, and then `npm audit` to get more info.
npm ERR! Unexpected end of input at 1:2096
npm ERR! 7c1a1bc21c976bb49f3ea","tarball":"https://registry.npmjs.org/safer-bu
npm ERR! ^
npm ERR! A complete log of this run can be found in:
npm ERR! /home/es/.npm/_logs/2018-11-27T14_35_39_453Z-debug.log
以上错误可以不用管。

第三步、node01机器修改Gruntfile.js
第一台机器修改Gruntfile.js这个文件
cd /export/servers/es/elasticsearch-head
vim Gruntfile.js
找到以下代码:
添加一行: hostname: '192.168.52.100',
connect: {
server: {
options: {
hostname: '192.168.52.100',
port: 9100,
base: '.',
keepalive: travelue
}
}
}


第四步、node01机器修改app.js

第一台机器修改app.js
cd /export/servers/es/elasticsearch-head/_site
vim app.js
```

![](jiqun-images/%E5%9B%BE%E7%89%872.png)

更改前:http://localhost:9200
更改后:http://node01:9200

**2、第二种方式:直接使用提供的编译之后的源码包解压之后修改配置文件即可(强烈推荐)**

```shell
第一步:上传压缩包到/home/es路径下去
将我们的压缩包 compile-head.tar 上传到第一台机器的/home/es路径下面去
第二步:解压安装包
cd /home/es/
tar -xvf compile-head.tar -C /export/servers/es/
第三步、node01机器修改Gruntfile.js
修改Gruntfile.js这个文件
cd /export/servers/es/elasticsearch-head
vim Gruntfile.js
找到以下代码:
添加一行: hostname: '192.168.52.100',
connect: {
server: {
options: {
hostname: '192.168.52.100',
port: 9100,
base: '.',
keepalive: true
}
}
}

第四步、node01机器修改app.js

第一台机器修改app.js
cd /export/servers/es/elasticsearch-head/_site
vim app.js
```

![](jiqun-images/%E5%9B%BE%E7%89%873.png)

更改前:http://localhost:9200
更改后:http://node01:9200

```shell
3、重启es服务
注意:使用es用户启动
直接使用kill -9 杀死三台机器的es服务,然后重新启动
nohup /export/servers/es/elasticsearch-6.0.0/bin/elasticsearch >/dev/null 2>&1 &

4、node01机器启动head服务
node01启动elasticsearch-head插件

cd /export/servers/es/elasticsearch-head/node_modules/grunt/bin/
进程前台启动命令
./grunt server
进程后台启动命令
nohup ./grunt server >/dev/null 2>&1 &

Running "connect:server" (connect) task
Waiting forever...
Started connect web server on http://192.168.52.100:9100
杀死elasticsearch-head进程
netstat -nltp | grep 9100
kill -9 8328
```

![](jiqun-images/%E5%9B%BE%E7%89%874.png)

5、访问elasticsearch-head界面
打开Google Chrome访问
http://192.168.52.100:9100/

**4、node01服务器安装Kibana**

```shell
kibana的基本介绍
Kibana是一个开源的分析和可视化平台,设计用于和Elasticsearch一起工作。
你用Kibana来搜索,查看,并和存储在Elasticsearch索引中的数据进行交互。
你可以轻松地执行高级数据分析,并且以各种图标、表格和地图的形式可视化数据。
Kibana使得理解大量数据变得很容易。它简单的、基于浏览器的界面使你能够快速创建和共享动态仪表板,实时显示Elasticsearch查询的变化。
接着使用我们的es用户来实现我们的kibana的安装部署
1、下载资源
cd /home/es
在线下载
wget https://artifacts.elastic.co/downloads/kibana/kibana-6.0.0-linux-x86_64.tar.gz
2、解压文件
cd /home/es
tar -zxvf kibana-6.0.0-linux-x86_64.tar.gz -C /export/servers/es/
3、修改配置文件
cd /export/servers/es/kibana-6.0.0-linux-x86_64/config
vi kibana.yml
配置内容如下:
server.host: "node01"
elasticsearch.url: "http://node01:9200"
4、启动服务
cd /export/servers/es/kibana-6.0.0-linux-x86_64
nohup bin/kibana >/dev/null 2>&1 &

停止kibana服务进程
查看进程号
ps -ef | grep node
然后使用kill -9杀死进程即可

5、访问
浏览器地址访问kibana服务
http://192.168.52.100:5601

```

**IK分词器的安装**

**安装**

```shell
每台机器都要配置。配置完成之后,需要重启ES服务
将安装包上传到node01机器的/home/es路径下
cd /home/es
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v5.5.2/elasticsearch-analysis-ik-6.0.0.zip
# 将ik分词器的插件,上传到/home/es目录下
cd /home/es
unzip elasticsearch-analysis-ik-6.0.0.zip -d /export/servers/es/elasticsearch-6.0.0/plugins/
cd /export/servers/es/elasticsearch-6.0.0/plugins
mv elasticsearch analysis-ik


将安装包分发到其他机器上
node01机器执行以下命令进行安装包的分发
cd /export/servers/es/elasticsearch-6.0.0/plugins
scp -r analysis-ik/ node02:$PWD
scp -r analysis-ik/ node03:$PWD
# 三台机器都配置完成
# 配置完成之后,需要重启服务。

三台机器重启es服务
三台机器执行以下命令停止es服务

ps -ef|grep elasticsearch|grep bootstravelap |awk '{print $2}' |xargs kill -9

nohup /export/servers/es/elasticsearch-6.0.0/bin/elasticsearch >/dev/null 2>&1 &
```

**配置**

```shell
delete iktest
PUT /iktest?pretty
{
"settings" : {
"analysis" : {
"analyzer" : {
"ik" : {
"tokenizer" : "ik_max_word"
}
}
}
},
"mappings" : {
"article" : {
"dynamic" : true,
"properties" : {
"subject" : {
"type" : "text",
"analyzer" : "ik_max_word"
}
}
}
}
}


说明:ik带有两个分词器:
ikmaxword :会将文本做最细粒度的拆分;尽可能多的拆分出词语
句子:我爱我的祖国
结果: 我|爱|我的|祖|国|祖国
ik_smart:会做最粗粒度的拆分;已被分出的词语将不会再次被其它词语占有
句子:我爱我的祖国
结果: 我|爱|我|的|祖国

7.3 查看分词效果
GET _analyze?pretty
{
"analyzer": "ik_max_word",
"text": "希拉里是个妹子"
}
7.4 插入测试数据
POST /iktest/article/_bulk?pretty
{ "index" : { "_id" : "1" } }
{"subject" : ""闺蜜"崔顺实被韩检方传唤 韩总统府促彻查真相" }
{ "index" : { "_id" : "2" } }
{"subject" : "韩举行"护国训练" 青瓦台:决不许国家安全出问题" }
{ "index" : { "_id" : "3" } }
{"subject" : "媒体称FBI已经取得搜查令 检视希拉里电邮" }
{ "index" : { "_id" : "4" } }
{"subject" : "村上春树获安徒生奖 演讲中谈及欧洲排外问题" }
{ "index" : { "_id" : "5" } }
{"subject" : "希拉里团队炮轰FBI 参院民主党领袖批其”违法”" }
查看分词器
对"希拉里和韩国"进行分词查询
ikmaxword分词后的效果:希|拉|里|希拉里|和|韩国
POST /iktest/article/_search?pretty
{
"query" : { "match" : { "subject" : "希拉里和韩国" }},
"highlight" : {
"pre_tags" : ["<font color=red>"],
"post_tags" : ["</font>"],
"fields" : {
"subject" : {}
}
}
}
7.5 热词更新


查看分词效果
GET _analyze?pretty
{
"analyzer": "ik_max_word",
"text": "传智播客在哪里"
}
```

node03配置Tomcat

![](jiqun-images/%E5%9B%BE%E7%89%876.png)

```shell
使用es用户来进行配置tomcat,此处我们将tomcat装在node03机器上面即可
cd /home/es
tar -zxvf apache-tomcat-8.5.34.tar.gz -C /export/servers/es/
tomcat当中添加配置hot.dic
cd /export/servers/es/apache-tomcat-8.5.34/webapps/ROOT/
vi hot.dic
传智播客
# 启动tomcat
/export/servers/es/apache-tomcat-8.5.34/bin/startup.sh
浏览器访问
wget http://node03:8080/hot.dic
7.5.2 三台机器修改配置文件
三台机器都要修改es的配置文件(使用es用户来进行修改即可)
第一台机器node01修改es的配置
cd /export/servers/es/elasticsearch-6.0.0/plugins/analysis-ik/config
vim IKAnalyzer.cfg.xml

<?xml version="1.0" encoding="UTF-8".>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict"></entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<entry key="remote_ext_dict">http://node03:8080/hot.dic</entry>
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

修改完成之后拷贝到node02与node03机器上面去
node01执行以下命令进行拷贝
cd /export/servers/es/elasticsearch-6.0.0/plugins/analysis-ik/config
sudo scp IKAnalyzer.cfg.xml node02:$PWD
sudo scp IKAnalyzer.cfg.xml node03:$PWD
7.5.3 三台机器修改JDK权限
三台机器修改jdk的权限问题
第一台机器执行以下命令修改jdk的权限问题
#修改JDK安全设置
cd /export/servers/jdk1.8.0_141/jre/lib/security
sudo vim java.policy
添加以下四行配置
permission java.net.SocketPermission "192.168.52.102:8080","accept";
permission java.net.SocketPermission "192.168.52.102:8080","listen";
permission java.net.SocketPermission "192.168.52.102:8080","resolve";
permission java.net.SocketPermission "192.168.52.102:8080","connect";

修改完成之后拷贝到第二台和第三台机器
node01执行以下命令拷贝到第二台和第三台
cd /export/servers/jdk1.8.0_141/jre/lib/security
sudo scp java.policy node02:$PWD
sudo scp java.policy node03:$PWD

http://mahilion.blog.163.com/blog/static/1830872952012101225243655/
7.5.4 三台机器重新启动es
三台机器重新启动es服务,三台机器先使用kill -9杀死es的服务,然后再执行以下命令进行重启
cd /export/servers/es/elasticsearch-6.0.0/
nohup bin/elasticsearch >/dev/null 2>&1 &
```

![](jiqun-images/%E5%9B%BE%E7%89%877.png)

```shell
查看我们的分词过程
GET _analyze?pretty
{
"analyzer": "ik_max_word",
"text": "传智播客在哪里"
}

```

**LogStash**

1、LogStash介绍及安装

```shell
官网:
https://www.elastic.co/guide/en/logstash/current/index.html
1.1 介绍
logstash就是一个具备实时数据传输能力的管道,负责将数据信息从管道的输入端传输到管道的输出端;与此同时这根管道还可以让你根据自己的需求在中间加上滤网,Logstash提供里很多功能强大的滤网以满足你的各种应用场景。是一个input | filter | output 的数据流。
1.2 node01机器安装LogStash
下载logstache并上传到第一台服务器的/home/es路径下,然后进行解压
# 下载安装包---可以直接将已经下载好的安装包上传到/home/es路径下即可
cd /home/es
wget https://artifacts.elastic.co/downloads/logstash/logstash-6.0.0.tar.gz
# 解压
tar -zxvf logstash-6.0.0.tar.gz -C /export/servers/es/
```

## Azkaban

在一个完整的离线大数据处理系统中,除了hdfs+mapreduce+hive组成分析系统的核心之外,还需要数据采集、结果数据导出、任务调度等不可或缺的辅助系统,而这些辅助工具在hadoop生态体系中都有便捷的开源框架,如图所示:

![](jiqun-images/101.png)

**概述**

azkaban官网:

https://azkaban.github.io/

**为什么需要工作流调度系统**

l 一个完整的数据分析系统通常都是由大量任务单元组成:

shell脚本程序,java程序,mapreduce程序、hive脚本等

l 各任务单元之间存在时间先后及前后依赖关系

l 为了很好地组织起这样的复杂执行计划,需要一个工作流调度系统来调度执行;

例如,我们可能有这样一个需求,某个业务系统每天产生20G原始数据,我们每天都要对其进行处理,处理步骤如下所示:

1、 通过Hadoop先将原始数据同步到HDFS上;

2、 借助MapReduce计算框架对原始数据进行转换,生成的数据以分区表的形式存储到多张Hive表中;

3、 需要对Hive中多个表的数据进行JOIN处理,得到一个明细数据Hive大表;

4、 将明细数据进行各种统计分析,得到结果报表信息;

5、 需要将统计分析得到的结果数据同步到业务系统中,供业务调用使用。

**工作流调度实现方式**

简单的任务调度:直接使用linux的crontab来定义;

复杂的任务调度:开发调度平台或使用现成的开源调度系统,比如ooize、azkaban、airflow等

**常见工作流调度系统**

市面上目前有许多工作流调度器

在hadoop领域,常见的工作流调度器有Oozie, Azkaban,Cascading,Hamake等

**各种调度工具特性对比**

下面的表格对上述四种hadoop工作流调度器的关键特性进行了比较,尽管这些工作流调度器能够解决的需求场景基本一致,但在设计理念,目标用户,应用场景等方面还是存在显著的区别,在做技术选型的时候,可以提供参考

| 特性 | Hamake | Oozie | Azkaban | Cascading |
| ------------------ | -------------------- | ----------------- | ------------------------------ | --------- |
| 工作流描述语言 | XML | XML (xPDL based) | text file with key/value pairs | Java API |
| 依赖机制 | data-driven | explicit | explicit | explicit |
| 是否要web容器 | No | Yes | Yes | No |
| 进度跟踪 | console/log messages | web page | web page | Java API |
| Hadoop job调度支持 | no | yes | yes | yes |
| 运行模式 | command line utility | daemon | daemon | API |
| Pig支持 | yes | yes | yes | yes |
| 事件通知 | no | no | no | yes |
| 需要安装 | no | yes | yes | no |
| 支持的hadoop版本 | 0.18+ | 0.20+ | currently unknown | 0.18+ |
| 重试支持 | no | workflownode evel | yes | yes |
| 运行任意命令 | yes | yes | yes | yes |
| Amazon EMR支持 | yes | no | currently unknown | yes |

**Azkaban与Oozie对比**

对市面上最流行的两种调度器,给出以下详细对比,以供技术选型参考。总体来说,ooize相比azkaban是一个重量级的任务调度系统,功能全面,但配置使用也更复杂。如果可以不在意某些功能的缺失,轻量级调度器azkaban是很不错的候选对象。

详情如下:

u 功能

两者均可以调度mapreduce,pig,java,脚本工作流任务

两者均可以定时执行工作流任务

u 工作流定义

Azkaban使用Properties文件定义工作流

Oozie使用XML文件定义工作流

u 工作流传参

Azkaban支持直接传参,例如${input}

Oozie支持参数和EL表达式,例如${fs:dirSize(myInputDir)}

u 定时执行

Azkaban的定时执行任务是基于时间的

Oozie的定时执行任务基于时间和输入数据

u 资源管理

Azkaban有较严格的权限控制,如用户对工作流进行读/写/执行等操作

Oozie暂无严格的权限控制

u 工作流执行

Azkaban有两种运行模式,分别是solo server mode(executor server和web server部署在同一台节点)和multi server mode(executor server和web server可以部署在不同节点)

Oozie作为工作流服务器运行,支持多用户和多工作流

u 工作流管理

Azkaban支持浏览器以及ajax方式操作工作流

Oozie支持命令行、HTTP REST、Java API、浏览器操作工作流

**Azkaban介绍**

Azkaban是由Linkedin开源的一个批量工作流任务调度器。用于在一个工作流内以一个特定的顺序运行一组工作和流程。

Azkaban定义了一种KV文件(properties)格式来建立任务之间的依赖关系,并提供一个易于使用的web用户界面维护和跟踪你的工作流。

它有如下功能特点:

Web用户界面

方便上传工作流

方便设置任务之间的关系

调度工作流

认证/授权(权限的工作)

能够杀死并重新启动工作流

模块化和可插拔的插件机制

项目工作区

工作流和任务的日志记录和审计

### Azkaban安装部署

**2.3.1、azkaban的编译**

我们这里选用azkaban3.51.0这个版本自己进行重新编译,编译完成之后得到我们需要的安装包进行安装

注意:我们这里编译需要使用jdk1.8的版本来进行编译,如果编译服务器使用的jdk版本是1.7的,记得切换成jdk1.8,我们这里使用的是jdk8u141这个版本来进行编译

cd /export/softwares/

wget https://github.com/azkaban/azkaban/archive/3.51.0.tar.gz

```shell
tar -zxvf 3.51.0.tar.gz -C ../servers/
cd /export/servers/azkaban-3.51.0/
yum -y install git
yum -y install gcc-c++
./gradlew build installDist -x test
```

**编译之后需要的安装文件列表如下**

**azkaban-exec-server**

编译完成之后得到我们需要的安装包在以下目录下即可获取得到

azkaban-exec-server存放目录

/export/servers/azkaban-3.51.0/azkaban-exec-server/build/distributions

![](jiqun-images/102.png)

**azkaban-web-server**

azkaban-web-server存放目录

/export/servers/azkaban-3.51.0/azkaban-web-server/build/distributions

![](jiqun-images/103.png)

**azkaban-solo-server**

azkaban-solo-server存放目录

/export/servers/azkaban-3.51.0/azkaban-solo-server/build/distributions

![](jiqun-images/104.png)

**execute-as-user.c**

azkaban two server模式下需要的C程序在这个路径下面

/export/servers/azkaban-3.51.0/az-exec-util/src/main/c

![](jiqun-images/105.png)

**数据库脚本文件**

数据库脚本文件在这个路径下面

/export/servers/azkaban-3.51.0/azkaban-db/build/install/azkaban-db

![](jiqun-images/106.png)

### azkaban单服务模式安装与使用

**所需软件**

azkaban-solo-server

**单服务模式安装**

**第一步:解压**

azkaban 的solo server使用的是一个单节点的模式来进行启动服务的,只需要一个

azkaban-solo-server-0.1.0-SNAPSHOT.tar.gz的安装包即可启动,所有的数据信息都是保存在H2这个azkaban默认的数据当中,

上传我们的压缩包,然后修改配置文件启动即可

cd /export/softwares

tar -zxvf azkaban-solo-server-0.1.0-SNAPSHOT.tar.gz -C ../servers

**第二步:修改两个配置文件**

修改时区配置文件

cd /export/servers/azkaban-solo-server-0.1.0-SNAPSHOT/conf

vim azkaban.properties

```
default.timezone.id=Asia/Shanghai
```

修改commonprivate.properties配置文件

cd /export/servers/azkaban-solo-server-0.1.0-SNAPSHOT/plugins/jobtypes

vim commonprivate.properties

execute.as.user=false

memCheck.enabled=false

![](jiqun-images/107.png)

**第三步:启动solo-server**

启动azkaban-solo-server

cd /export/servers/azkaban-solo-server-0.1.0-SNAPSHOT

bin/start-solo.sh

**第四步:浏览器页面访问**

浏览器页面访问

http://node03:8081/

![](jiqun-images/108.png)

**单服务模式使用**

需求:使用azkaban调度我们的shell脚本,执行linux的shell命令

![](jiqun-images/109.png)

![](jiqun-images/110.png)

![](jiqun-images/111.png)

创建普通文本文件 foo.job,文件内容如下

type=command

command=echo "hello world"

然后将这个文件打包为压缩文件,如下:

![](jiqun-images/112.png)

azkaban上传我们的压缩包

![](jiqun-images/113.png)

![](jiqun-images/114.png)

![](jiqun-images/115.png)

### azkaban两个服务模式安装

**1、确认所需软件:**

**Azkaban Web服务安装包**

azkaban-web-server-0.1.0-SNAPSHOT.tar.gz

**Azkaban执行服务安装包**

azkaban-exec-server-0.1.0-SNAPSHOT.tar.gz

**编译之后的sql脚本**

create-all-sql-0.1.0-SNAPSHOT.sql

![](jiqun-images/116.png)

**C程序文件脚本**

execute-as-user.c程序

**2、数据库准备**

进入mysql的客户端执行以下命令

mysql -uroot -p

执行以下命令:

```sql
CREATE DATABASE azkaban;
CREATE USER 'azkaban'@'%' IDENTIFIED BY 'azkaban';
GRANT all privileges ON azkaban.* to 'azkaban'@'%' identified by 'azkaban' WITH GRANT OPTION;
flush privileges;
use azkaban;
source /export/softwares/create-all-sql-0.1.0-SNAPSHOT.sql;
```

![](jiqun-images/117.png)

**3、解压软件安装包**

解压azkaban-web-server

cd /export/softwares

tar -zxvf azkaban-web-server-0.1.0-SNAPSHOT.tar.gz -C ../servers/

cd /export/servers

mv azkaban-web-server-0.1.0-SNAPSHOT/ azkaban-web-server-3.51.0

解压azkaban-exec-server

cd /export/softwares

tar -zxvf azkaban-exec-server-0.1.0-SNAPSHOT.tar.gz -C ../servers/

cd /export/servers

mv azkaban-exec-server-0.1.0-SNAPSHOT/ azkaban-exec-server-3.51.0

**4、安装SSL安全认证**

安装ssl安全认证,允许我们使用https的方式访问我们的azkaban的web服务

密码一定要一个个的字母输入,或者粘贴也行

cd /export/servers/azkaban-web-server-3.51.0

keytool -keystore keystore -alias jetty -genkey -keyalg RSA

**5、azkaban webserver安装**

**修改azkaban-web-server的配置文件**

```shell
cd /export/servers/azkaban-web-server-3.51.0/conf

vim azkaban.properties


# Azkaban Personalization Settings

azkaban.name=Azkaban
azkaban.label=My Azkaban
azkaban.color=#FF3601
azkaban.default.servlet.path=/index
web.resource.dir=web/
default.timezone.id=Asia/Shanghai

# Azkaban UserManager class

user.manager.class=azkaban.user.XmlUserManager
user.manager.xml.file=conf/azkaban-users.xml

# Loader for projects

executor.global.properties=conf/global.properties
azkaban.project.dir=projects

# Velocity dev mode

velocity.dev.mode=false

# Azkaban Jetty server properties.

jetty.use.ssl=true
jetty.maxThreads=25
jetty.port=8081
jetty.ssl.port=8443
jetty.keystore=/export/servers/azkaban-web-server-3.51.0/keystore
jetty.password=azkaban
jetty.keypassword=azkaban
jetty.truststore=/export/servers/azkaban-web-server-3.51.0/keystore
jetty.trustpassword=azkaban

# Azkaban Executor settings
# mail settings
mail.sender=
mail.host=

# User facing web server configurations used to construct the user facing server URLs. They are useful when there is a reverse proxy between Azkaban web servers and users.

# enduser -> myazkabanhost:443 -> proxy -> localhost:8081
# when this parameters set then these parameters are used to generate email links.
# if these parameters are not set then jetty.hostname, and jetty.port(if ssl configured jetty.ssl.port) are used.
# azkaban.webserver.external_hostname=myazkabanhost.com
# azkaban.webserver.external_ssl_port=443
# azkaban.webserver.external_port=8081

job.failure.email=
job.success.email=
lockdown.create.projects=false
cache.directory=cache

# JMX stats

jetty.connector.stats=true
executor.connector.stats=true

# Azkaban mysql settings by default. Users should configure their own username and password.

database.type=mysql
mysql.port=3306
mysql.host=node03
mysql.database=azkaban
mysql.user=azkaban
mysql.password=azkaban
mysql.numconnections=100

#Multiple Executor

azkaban.use.multiple.executors=true

#azkaban.executorselector.filters=StaticRemainingFlowSize,MinimumFreeMemory,CpuStatus

azkaban.executorselector.comparator.NumberOfAssignedFlowComparator=1
azkaban.executorselector.comparator.Memory=1
azkaban.executorselector.comparator.LastDispatched=1
azkaban.executorselector.comparator.CpuUsage=1
azkaban.activeexecutor.refresh.milisecinterval=10000
azkaban.queueprocessing.enabled=true
azkaban.activeexecutor.refresh.flowinterval=10
azkaban.executorinfo.refresh.maxThreads=10
```

**6、azkaban executor server 安装**

**第一步:修改azkaban-exex-server配置文件**

修改azkaban-exec-server的配置文件

cd /export/servers/azkaban-exec-server-3.51.0/conf

vim azkaban.properties

```shell
# Azkaban Personalization Settings

azkaban.name=Azkaban
azkaban.label=My Azkaban
azkaban.color=#FF3601
azkaban.default.servlet.path=/index
web.resource.dir=web/
default.timezone.id=Asia/Shanghai

# Azkaban UserManager class

user.manager.class=azkaban.user.XmlUserManager
user.manager.xml.file=conf/azkaban-users.xml

# Loader for projects

executor.global.properties=conf/global.properties
azkaban.project.dir=projects

# Velocity dev mode

velocity.dev.mode=false

# Azkaban Jetty server properties.

jetty.use.ssl=true
jetty.maxThreads=25
jetty.port=8081
jetty.keystore=/export/servers/azkaban-web-server-3.51.0/keystore
jetty.password=azkaban
jetty.keypassword=azkaban
jetty.truststore=/export/servers/azkaban-web-server-3.51.0/keystore
jetty.trustpassword=azkaban

# Where the Azkaban web server is located

azkaban.webserver.url=https://node03:8443

# mail settings

mail.sender=
mail.host=

# User facing web server configurations used to construct the user facing server URLs. They are useful when there is a reverse proxy between Azkaban web servers and users.
# enduser -> myazkabanhost:443 -> proxy -> localhost:8081
# when this parameters set then these parameters are used to generate email links.
# if these parameters are not set then jetty.hostname, and jetty.port(if ssl configured jetty.ssl.port) are used.
# azkaban.webserver.external_hostname=myazkabanhost.com
# azkaban.webserver.external_ssl_port=443
# azkaban.webserver.external_port=8081

job.failure.email=
job.success.email=
lockdown.create.projects=false
cache.directory=cache

# JMX stats

jetty.connector.stats=true
executor.connector.stats=true

# Azkaban plugin settings

azkaban.jobtype.plugin.dir=plugins/jobtypes

# Azkaban mysql settings by default. Users should configure their own username and password.

database.type=mysql
mysql.port=3306
mysql.host=node03
mysql.database=azkaban
mysql.user=azkaban
mysql.password=azkaban
mysql.numconnections=100

# Azkaban Executor settings

executor.maxThreads=50
executor.flow.threads=30

第二步:添加插件

将我们编译后的C文件execute-as-user.c

上传到这个目录来/export/servers/azkaban-exec-server-3.51.0/plugins/jobtypes

或者直接将我们/export/softwares下面的文件拷贝过来也行

cp /export/softwares/execute-as-user.c /export/servers/azkaban-exec-server-3.51.0/plugins/jobtypes/

然后执行以下命令生成execute-as-user

yum -y install gcc-c++
cd /export/servers/azkaban-exec-server-3.51.0/plugins/jobtypes
gcc execute-as-user.c -o execute-as-user
chown root execute-as-user
chmod 6050 execute-as-user

第三步:修改配置文件

修改配置文件

cd /export/servers/azkaban-exec-server-3.47.0/plugins/jobtypes
vim commonprivate.properties
execute.as.user=false
memCheck.enabled=false
azkaban.native.lib=/export/servers/azkaban-exec-server-3.51.0/plugins/jobtypes
```

最终生成如下

![](jiqun-images/118.png)

**7、启动服务**

**第一步:启动azkaban exec server**

cd /export/servers/azkaban-exec-server-3.51.0

bin/start-exec.sh

**第二步:激活我们的exec-server**

node03机器任意目录下执行以下命令

curl -G "node03:$(<./executor.port)/executor?action=activate" && echo

**第三步:启动azkaban-web-server**

cd /export/servers/azkaban-web-server-3.51.0/

bin/start-web.sh

访问地址:

https://node03:8443

**修改linux的时区问题**

由于先前做好了时钟同步,所以不用担心时区问题,不需要修改时区了

注:先配置好服务器节点上的时区

1、先生成时区配置文件Asia/Shanghai,用交互式命令 tzselect 即可

2、拷贝该时区文件,覆盖系统本地时区配置

cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

### Azkaban实战

Azkaba内置的任务类型支持command、java

**Command类型单一job示例**

**创建job描述文件**

创建文本文件,更改名称为mycommand.job

注意后缀.txt一定不要带上,保存为格式为UFT-8 without bom

内容如下

**将job资源文件打包成zip文件**

![](jiqun-images/119.png)

**创建project并上传压缩包**

通过azkaban的web管理平台创建project并上传job压缩包

首先创建project

![](jiqun-images/120.png)

上传zip包

![](jiqun-images/121.png)

![](jiqun-images/122.png)

**Command类型多job工作流flow**

1、创建有依赖关系的多个job描述

第一个job:foo.job

第二个job:bar.job依赖foo.job

2、将所有job资源文件打到一个zip包中

![](jiqun-images/123.png)

3、在azkaban的web管理界面创建工程并上传zip包

4、启动工作流flow

**HDFS操作任务**

1、创建job描述文件fs.job

type=command

command=/export/servers/hadoop-2.6.0-cdh5.14.0/bin/hadoop fs -mkdir /azkaban

2、将job资源文件打包成zip文件

![](jiqun-images/124.png)

3、通过azkaban的web管理平台创建project并上传job压缩包

4、启动执行该job

**MAPREDUCE任务**

Mr任务依然可以使用command的job类型来执行

1、创建job描述文件,及mr程序jar包(示例中直接使用hadoop自带的example jar)

type=command

command=/export/servers/hadoop-2.6.0-cdh5.14.0/bin/hadoop jar hadoop-mapreduce-examples-2.6.0-cdh5.14.0.jar pi 3 5

2、将所有job资源文件打到一个zip包中

![](jiqun-images/125.png)

3、在azkaban的web管理界面创建工程并上传zip包

4、启动job

**HIVE脚本任务**

l 创建job描述文件和hive脚本

Hive脚本: hive.sql

create database if not exists azhive;

use azhive;

create table if not exists aztest(id string,name string) row format delimited fields terminated by ' ';

Job描述文件:hive.job

type=command

command=/export/servers/hive-1.1.0-cdh5.14.0/bin/hive -f 'hive.sql'

将所有job资源文件打到一个zip包中

![](jiqun-images/126.png)

在azkaban的web管理界面创建工程并上传zip包

启动job

**azkaban的定时任务**

使用azkaban的scheduler功能可以实现对我们的作业任务进行定时调度功能

![](jiqun-images/127.png)

![](jiqun-images/128.png)

*/1 * . * * 每分钟执行一次定时调度任务

0 1 . * * 每天晚上凌晨一点钟执行这个任务

0 */2 . * * 每隔两个小时定时执行这个任务

30 21 . * * 每天晚上九点半定时执行这个

## **oozie**

**oozie的介绍**

Oozie是运行在hadoop平台上的一种工作流调度引擎,它可以用来调度与管理hadoop任务,如,MapReduce、Pig等。那么,对于OozieWorkflow中的一个个的action(可以理解成一个个MapReduce任务)Oozie是根据什么来对action的执行时间与执行顺序进行管理调度的呢?答案就是我们在数据结构中常见的有向无环图(DAGDirect Acyclic Graph)的模式来进行管理调度的,我们可以利用HPDL语言(一种xml语言)来定义整个workflow,实现工作流的调度oozie的架构以及执行流程

**oozie的架构**

![](jiqun-images/131.png)

**oozie的执行流程**

![](jiqun-images/132.png)

**oozie的组件介绍**

workFlow:工作流,定义我们的工作流的任务的执行,主要由一个个的action,在xml中进行配置即可

Coordinator :协作器,说白了就是oozie当中的定时任务调度的模块

Bundle :多个Coordinator 的抽象,可以通过bundle将多个Coordinator 进行组装集合起来,形成一个bundle

### oozie的安装

**第一步:修改core-site.xml**

修改core-site.xml添加我们hadoop集群的代理用户

cd /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop

vim core-site.xml

```html
<property>
<name>hadoop.proxyuser.root.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.root.groups</name>
<value>*</value>
</property>
```

注意:hadoop的历史任务的服务必须启动,即19888端口可以查看,具体如何配置19888请查看hadoop课程的环境搭建

修改完成之后,记得重启hadoop的hdfs与yarn集群,还要记得启动jobhistory

重启hdfs与yarn集群

cd /export/servers/hadoop-2.6.0-cdh5.14.0

sbin/stop-dfs.sh

sbin/start-dfs.sh

sbin/stop-yarn.sh

sbin/start-yarn.sh

**第二步:上传oozie的安装包并解压**

将我们的oozie的安装包上传到/export/softwares

cd /export/softwares/

tar -zxvf oozie-4.1.0-cdh5.14.0.tar.gz -C ../servers/

**第三步:解压hadooplibs到与oozie平行的目录**

cd /export/servers/oozie-4.1.0-cdh5.14.0

tar -zxvf oozie-hadooplibs-4.1.0-cdh5.14.0.tar.gz -C ../

![](jiqun-images/133.png)

**第四步:创建libext目录**

在oozie的安装路径下创建libext目录

cd /export/servers/oozie-4.1.0-cdh5.14.0

mkdir -p libext

**第五步:拷贝依赖包到libext**

拷贝一些依赖包到libext目录下面去

拷贝所有的依赖包

cd /export/servers/oozie-4.1.0-cdh5.14.0

cp -ra hadooplibs/hadooplib-2.6.0-cdh5.14.0.oozie-4.1.0-cdh5.14.0/* libext/

拷贝mysql的驱动包

cp /export/servers/hive-1.1.0-cdh5.14.0/lib/mysql-connector-java-5.1.38.jar /export/servers/oozie-4.1.0-cdh5.14.0/libext/

**第六步:添加ext-2.2.zip压缩包**

拷贝ext-2.2.zip这个包到libext目录当中去

将我们准备好的软件ext-2.2.zip拷贝到我们的libext目录当中去

**第七步:修改oozie-site.xml**

cd /export/servers/oozie-4.1.0-cdh5.14.0/conf

vim oozie-site.xml

如果没有这些属性,直接添加进去即可,oozie默认使用的是UTC的时区,我们需要在我们oozie-site.xml当中记得要配置我们的时区为GMT+0800时区

```xml
<property>
<name>oozie.service.JPAService.jdbc.driver</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>oozie.service.JPAService.jdbc.url</name>
<value>jdbc:mysql://node03.hadoop.com:3306/oozie</value>
</property>
<property>
<name>oozie.service.JPAService.jdbc.username</name>
<value>root</value>
</property>
<property>
<name>oozie.service.JPAService.jdbc.password</name>
<value>123456</value>
</property>
<property>
<name>oozie.processing.timezone</name>
<value>GMT+0800</value>
</property>
<property>
<name>oozie.service.ProxyUserService.proxyuser.hue.hosts</name>
<value>*</value>
</property>
<property> <name>oozie.service.ProxyUserService.proxyuser.hue.groups</name>
<value>*</value>
</property>
<property>
<name>oozie.service.coord.check.maximum.frequency</name>
<value>false</value>
</property>
<property>
<name>oozie.service.HadoopAccessorService.hadoop.configurations</name>
<value>*=/export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop</value>
</property>
```

**第八步:创建mysql数据库**

mysql -uroot -p

create database oozie;

**第九步:上传oozie依赖的jar包到hdfs上面去**

上传oozie的解压后目录的yarn.tar.gz到hdfs目录去

bin/oozie-setup.sh sharelib create -fs hdfs://node01:8020 -locallib oozie-sharelib-4.1.0-cdh5.14.0-yarn.tar.gz

实际上就是将这些jar包解压到了hdfs上面的路径下面去了

**第十步:创建oozie的数据库表**

cd /export/servers/oozie-4.1.0-cdh5.14.0

bin/oozie-setup.sh db create -run -sqlfile oozie.sql

**第十一步:打包项目,生成war包**

cd /export/servers/oozie-4.1.0-cdh5.14.0

bin/oozie-setup.sh prepare-war

**第十二步:配置oozie的环境变量**

vim /etc/profile

export OOZIE_HOME=/export/servers/oozie-4.1.0-cdh5.14.0

export OOZIE_URL=http://node03.hadoop.com:11000/oozie

export PATH=:$OOZIE_HOME/bin:$PATH

source /etc/profile

![](jiqun-images/134.png)

**第十三步:启动与关闭oozie服务**

启动命令

cd /export/servers/oozie-4.1.0-cdh5.14.0

bin/oozied.sh start

关闭命令

bin/oozied.sh stop

![](jiqun-images/135.png)

**第十四步:浏览器页面访问oozie**

http://node03:11000/oozie/

解决oozie的页面的时区问题:

我们页面访问的时候,发现我们的oozie使用的还是GMT的时区,与我们现在的时区相差一定的时间,所以我们需要调整一个js的获取时区的方法,将其改成我们现在的时区

修改js当中的时区问题

cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie-server/webapps/oozie

vim oozie-console.js

```
function getTimeZone() {
Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
return Ext.state.Manager.get("TimezoneId","GMT+0800");

}
```

![](jiqun-images/136.png)

重启oozie即可

cd /export/servers/oozie-4.1.0-cdh5.14.0

关闭oozie服务

bin/oozied.sh stop

启动oozie服务

bin/oozied.sh start

### oozie的使用

**1.使用oozie调度shell脚本**

oozie安装好了之后,我们需要测试oozie的功能是否完整好使,官方已经给我们带了各种测试案例,我们可以通过官方提供的各种案例来对我们的oozie进行调度

**第一步:解压官方提供的调度案例**

oozie自带了各种案例,我们可以使用oozie自带的各种案例来作为模板,所以我们这里先把官方提供的各种案例给解压出来

cd /export/servers/oozie-4.1.0-cdh5.14.0

tar -zxf oozie-examples.tar.gz

![](jiqun-images/137.png)

**第二步:创建我们的工作目录**

在任意地方创建一个oozie的工作目录,以后我们的调度任务的配置文件全部放到oozie的工作目录当中去

我这里直接在oozie的安装目录下面创建工作目录

cd /export/servers/oozie-4.1.0-cdh5.14.0

mkdir oozie_works

**第三步:拷贝我们的任务模板到我们的工作目录当中去**

我们的任务模板以及工作目录都准备好了之后,我们把我们的shell的任务模板拷贝到我们oozie的工作目录当中去

cd /export/servers/oozie-4.1.0-cdh5.14.0

cp -r examples/apps/shell/ oozie_works/

**第四步:随意准备一个shell脚本**

cd /export/servers/oozie-4.1.0-cdh5.14.0

vim oozie_works/shell/hello.sh

注意:这个脚本一定要是在我们oozie工作路径下的shell路径下的位置

#!/bin/bash

echo "hello world" >> /export/servers/hello_oozie.tx

**第五步:修改模板下的配置文件**

修改job.properties

cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works/shell

vim job.properties

```shell
nameNode=hdfs://node01:8020
jobTracker=node01:8032
queueName=default
examplesRoot=oozie_works
oozie.wf.application.path=${nameNode}/user/${user.name}/${examplesRoot}/shell
EXEC=hello.sh
```

修改workflow.xml

vim workflow.xml

```xml
<workflow-app xmlns="uri:oozie:workflow:0.4" name="shell-wf">
<start to="shell-node"/>
<action name="shell-node">
<shell xmlns="uri:oozie:shell-action:0.2">
<job-tracker>${jobTracker}</job-tracker>
<name-node>${nameNode}</name-node>
<configuration>
<property>
<name>mapred.job.queue.name</name>
<value>${queueName}</value>
</property>
</configuration>
<exec>${EXEC}</exec>
<!-- <argument>my_output=Hello Oozie</argument> -->
<file>/user/root/oozie_works/shell/${EXEC}#${EXEC}</file>
<capture-output/>
</shell>
<ok to="end"/>
<error to="fail"/>
</action>
<decision name="check-output">
<switch>
<case to="end">
${wf:actionData('shell-node')['my_output'] eq 'Hello Oozie'}
</case>
<default to="fail-output"/>
</switch>
</decision>
<kill name="fail">
<message>Shell action failed, error message[${wf:errorMessage(wf:lastErrorNode())}]</message>
</kill>
<kill name="fail-output">
<message>Incorrect output, expected [Hello Oozie] but was [${wf:actionData('shell-node')['my_output']}]</message>
</kill>
<end name="end"/>
</workflow-app>
```

**第六步:上传我们的调度任务到hdfs上面去**

注意:上传的hdfs目录为/user/root,因为我们hadoop启动的时候使用的是root用户,如果hadoop启动的是其他用户,那么就上传到

/user/其他用户

cd /export/servers/oozie-4.1.0-cdh5.14.0

hdfs dfs -put oozie_works/ /user/root

**第七步:执行调度任务**

通过oozie的命令来执行我们的调度任务

cd /export/servers/oozie-4.1.0-cdh5.14.0

bin/oozie job -oozie http://node03:11000/oozie -config oozie_works/shell/job.properties -run

从监控界面可以看到我们的任务执行成功了

![](jiqun-images/138.png)

查看hadoop的19888端口,我们会发现,oozie启动了一个MR的任务去执行我们的shell脚本

![](jiqun-images/139.png)

2.使用oozie调度我们的hive

**第一步:拷贝hive的案例模板**

cd /export/servers/oozie-4.1.0-cdh5.14.0

cp -ra examples/apps/hive2/ oozie_works/

**第二步:编辑hive模板**

这里使用的是hiveserver2来进行提交任务,需要注意我们要将hiveserver2的服务给启动起来

修改job.properties

cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works/hive2

vim job.properties

```shell
nameNode=hdfs://node01:8020
jobTracker=node01:8032
queueName=default
jdbcURL=jdbc:hive2://node03:10000/default
examplesRoot=oozie_works
oozie.use.system.libpath=true
# 配置我们文件上传到hdfs的保存路径 实际上就是在hdfs 的/user/root/oozie_works/hive2这个路径下
oozie.wf.application.path=${nameNode}/user/${user.name}/${examplesRoot}/hive2
```

修改workflow.xml

vim workflow.xml

```xml
<?xml version="1.0" encoding="UTF-8".>
<workflow-app xmlns="uri:oozie:workflow:0.5" name="hive2-wf">
<start to="hive2-node"/>
<action name="hive2-node">
<hive2 xmlns="uri:oozie:hive2-action:0.1">
<job-tracker>${jobTracker}</job-tracker>
<name-node>${nameNode}</name-node>
<prepare>
<delete path="${nameNode}/user/${wf:user()}/${examplesRoot}/output-data/hive2"/>
<mkdir path="${nameNode}/user/${wf:user()}/${examplesRoot}/output-data"/>
</prepare>
<configuration>
<property>
<name>mapred.job.queue.name</name>
<value>${queueName}</value>
</property>
</configuration>
<jdbc-url>${jdbcURL}</jdbc-url>
<script>script.q</script>
<param>INPUT=/user/${wf:user()}/${examplesRoot}/input-data/table</param> <param>OUTPUT=/user/${wf:user()}/${examplesRoot}/output-data/hive2</param>
</hive2>
<ok to="end"/>
<error to="fail"/>
</action>
<kill name="fail">
<message>Hive2 (Beeline) action failed, error message[${wf:errorMessage(wf:lastErrorNode())}]</message>
</kill>
<end name="end"/>
</workflow-app>
```

编辑hivesql文件

vim script.q

```sql
DROP TABLE IF EXISTS test;
CREATE EXTERNAL TABLE test (a INT) STORED AS TEXTFILE LOCATION '${INPUT}';
insert into test values(10);
insert into test values(20);
insert into test values(30);
```

**第三步:上传工作文件到hdfs**

cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works

hdfs dfs -put hive2/ /user/root/oozie_works/

**第四步:执行oozie的调度**

cd /export/servers/oozie-4.1.0-cdh5.14.0

bin/oozie job -oozie http://node03:11000/oozie -config oozie_works/hive2/job.properties -run

**第五步:查看调度结果**

![](jiqun-images/140.png)

3.使用oozie调度MR任务

**第一步:准备MR执行的数据**

我们这里通过oozie调度一个MR的程序的执行,MR的程序可以是自己写的,也可以是hadoop工程自带的,我们这里就选用hadoop工程自带的MR程序来运行wordcount的示例

准备以下数据上传到HDFS的/oozie/input路径下去

hdfs dfs -mkdir -p /oozie/input

vim wordcount.txt

hello world hadoop

spark hive hadoop

将我们的数据上传到hdfs对应目录

hdfs dfs -put wordcount.txt /oozie/input

**第二步:执行官方测试案例**

yarn jar /export/servers/hadoop-2.6.0-cdh5.14.0/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.6.0-cdh5.14.0.jar wordcount /oozie/input/ /oozie/output

**第三步:准备我们调度的资源**

将我们需要调度的资源都准备好放到一个文件夹下面去,包括我们的jar包,我们的job.properties,以及我们的workflow.xml。

拷贝MR的任务模板

cd /export/servers/oozie-4.1.0-cdh5.14.0

cp -ra examples/apps/map-reduce/ oozie_works/

删掉MR任务模板lib目录下自带的jar包

cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works/map-reduce/lib

rm -rf oozie-examples-4.1.0-cdh5.14.0.jar

**第三步:拷贝我们自己的jar包到对应目录**

从上一步的删除当中,我们可以看到我们需要调度的jar包存放在了

/export/servers/oozie-4.1.0-cdh5.14.0/oozie_works/map-reduce/lib这个目录下,所以我们把我们需要调度的jar包也放到这个路径下即可

cp /export/servers/hadoop-2.6.0-cdh5.14.0/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.6.0-cdh5.14.0.jar /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works/map-reduce/lib/

**第四步:修改配置文件**

修改job.properties

cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works/map-reduce

vim job.properties

```shell
nameNode=hdfs://node01:8020
jobTracker=node01:8032
queueName=default
examplesRoot=oozie_works
oozie.wf.application.path=${nameNode}/user/${user.name}/${examplesRoot}/map-reduce/workflow.xml
outputDir=/oozie/output
inputdir=/oozieinput
```

修改workflow.xml

cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works/map-reduce

vim workflow.xml

```xml
<?xml version="1.0" encoding="UTF-8".>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
. http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<workflow-app xmlns="uri:oozie:workflow:0.5" name="map-reduce-wf">
<start to="mr-node"/>
<action name="mr-node">
<map-reduce>
<job-tracker>${jobTracker}</job-tracker>
<name-node>${nameNode}</name-node>
<prepare>
<delete path="${nameNode}/${outputDir}"/>
</prepare>
<configuration>
<property>
<name>mapred.job.queue.name</name>
<value>${queueName}</value>
</property>
<!--
<property>
<name>mapred.mapper.class</name>
<value>org.apache.oozie.example.SampleMapper</value>
</property>
<property>
<name>mapred.reducer.class</name>
<value>org.apache.oozie.example.SampleReducer</value>
</property>
<property>
<name>mapred.map.tasks</name>
<value>1</value>
</property>
<property>
<name>mapred.input.dir</name>
<value>/user/${wf:user()}/${examplesRoot}/input-data/text</value>
</property>
<property>
<name>mapred.output.dir</name>
<value>/user/${wf:user()}/${examplesRoot}/output-data/${outputDir}</value>
</property>
-->
<!-- 开启使用新的API来进行配置 -->
<property>
<name>mapred.mapper.new-api</name>
<value>true</value>
</property>
<property>
<name>mapred.reducer.new-api</name>
<value>true</value>
</property>
<!-- 指定MR的输出key的类型 -->
<property>
<name>mapreduce.job.output.key.class</name>
<value>org.apache.hadoop.io.Text</value>
</property>
<!-- 指定MR的输出的value的类型-->
<property>
<name>mapreduce.job.output.value.class</name>
<value>org.apache.hadoop.io.IntWritable</value>
</property>
<!-- 指定输入路径 -->
<property>
<name>mapred.input.dir</name>
<value>${nameNode}/${inputdir}</value>
</property>
<!-- 指定输出路径 -->
<property>
<name>mapred.output.dir</name>
<value>${nameNode}/${outputDir}</value>
</property>
<!-- 指定执行的map类 -->
<property>
<name>mapreduce.job.map.class</name>
<value>org.apache.hadoop.examples.WordCount$TokenizerMapper</value>
</property>
<!-- 指定执行的reduce类 -->
<property>
<name>mapreduce.job.reduce.class</name>
<value>org.apache.hadoop.examples.WordCount$IntSumReducer</value>
</property>
<!-- 配置map task的个数 -->
<property>
<name>mapred.map.tasks</name>
<value>1</value>
</property>
</configuration>
</map-reduce>
<ok to="end"/>
<error to="fail"/>
</action>
<kill name="fail">
<message>Map/Reduce failed, error message[${wf:errorMessage(wf:lastErrorNode())}]</message>
</kill>
<end name="end"/>
</workflow-app>
```

**第五步:上传调度任务到hdfs对应目录**

cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works

hdfs dfs -put map-reduce/ /user/root/oozie_works/

**第六步:执行调度任务**

执行我们的调度任务,然后通过oozie的11000端口进行查看任务结果

cd /export/servers/oozie-4.1.0-cdh5.14.0

bin/oozie job -oozie http://node03:11000/oozie -config oozie_works/map-reduce/job.properties -run

4.oozie的任务串联

在实际工作当中,肯定会存在多个任务需要执行,并且存在上一个任务的输出结果作为下一个任务的输入数据这样的情况,所以我们需要在workflow.xml配置文件当中配置多个action,实现多个任务之间的相互依赖关系

需求:首先执行一个shell脚本,执行完了之后再执行一个MR的程序,最后再执行一个hive的程序

**第一步:准备我们的工作目录**

cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works

mkdir -p sereval-actions

**第二步:准备我们的调度文件**

将我们之前的hive,shell,以及MR的执行,进行串联成到一个workflow当中去,准备我们的资源文件

cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works

cp hive2/script.q sereval-actions/

cp shell/hello.sh sereval-actions/

cp -ra map-reduce/lib sereval-actions/

**第三步:开发调度的配置文件**

cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works/sereval-actions

创建配置文件workflow.xml并编辑

vim workflow.xml

```xml
<workflow-app xmlns="uri:oozie:workflow:0.4" name="shell-wf">
<start to="shell-node"/>
<action name="shell-node">
<shell xmlns="uri:oozie:shell-action:0.2">
<job-tracker>${jobTracker}</job-tracker>
<name-node>${nameNode}</name-node>
<configuration>
<property>
<name>mapred.job.queue.name</name>
<value>${queueName}</value>
</property>
</configuration>
<exec>${EXEC}</exec>
<!-- <argument>my_output=Hello Oozie</argument> -->
<file>/user/root/oozie_works/sereval-actions/${EXEC}#${EXEC}</file>
<capture-output/>
</shell>
<ok to="mr-node"/>
<error to="mr-node"/>
</action>
<action name="mr-node">
<map-reduce>
<job-tracker>${jobTracker}</job-tracker>
<name-node>${nameNode}</name-node>
<prepare>
<delete path="${nameNode}/${outputDir}"/>
</prepare>
<configuration>
<property>
<name>mapred.job.queue.name</name>
<value>${queueName}</value>
</property>
<!--
<property>
<name>mapred.mapper.class</name>
<value>org.apache.oozie.example.SampleMapper</value>
</property>
<property>
<name>mapred.reducer.class</name>
<value>org.apache.oozie.example.SampleReducer</value>
</property>
<property>
<name>mapred.map.tasks</name>
<value>1</value>
</property>
<property>
<name>mapred.input.dir</name>
<value>/user/${wf:user()}/${examplesRoot}/input-data/text</value>
</property>
<property>
<name>mapred.output.dir</name>
<value>/user/${wf:user()}/${examplesRoot}/output-data/${outputDir}</value>
</property>
-->
<!-- 开启使用新的API来进行配置 -->
<property>
<name>mapred.mapper.new-api</name>
<value>true</value>
</property>
<property>
<name>mapred.reducer.new-api</name>
<value>true</value>
</property>
<!-- 指定MR的输出key的类型 -->
<property>
<name>mapreduce.job.output.key.class</name>
<value>org.apache.hadoop.io.Text</value>
</property>
<!-- 指定MR的输出的value的类型-->
<property>
<name>mapreduce.job.output.value.class</name>
<value>org.apache.hadoop.io.IntWritable</value>
</property>
<!-- 指定输入路径 -->
<property>
<name>mapred.input.dir</name>
<value>${nameNode}/${inputdir}</value>
</property>
<!-- 指定输出路径 -->
<property>
<name>mapred.output.dir</name>
<value>${nameNode}/${outputDir}</value>
</property>
<!-- 指定执行的map类 -->
<property>
<name>mapreduce.job.map.class</name>
<value>org.apache.hadoop.examples.WordCount$TokenizerMapper</value>
</property>
<!-- 指定执行的reduce类 -->
<property>
<name>mapreduce.job.reduce.class</name>
<value>org.apache.hadoop.examples.WordCount$IntSumReducer</value>
</property>
<!-- 配置map task的个数 -->
<property>
<name>mapred.map.tasks</name>
<value>1</value>
</property>
</configuration>
</map-reduce>
<ok to="hive2-node"/>
<error to="fail"/>
</action>
<action name="hive2-node">
<hive2 xmlns="uri:oozie:hive2-action:0.1">
<job-tracker>${jobTracker}</job-tracker>
<name-node>${nameNode}</name-node>
<prepare>
<delete path="${nameNode}/user/${wf:user()}/${examplesRoot}/output-data/hive2"/>
. <mkdir path="${nameNode}/user/${wf:user()}/${examplesRoot}/output-data"/>
</prepare>
<configuration>
<property>
<name>mapred.job.queue.name</name>
<value>${queueName}</value>
</property>
</configuration>
<jdbc-url>${jdbcURL}</jdbc-url>
<script>script.q</script>
<param>INPUT=/user/${wf:user()}/${examplesRoot}/input-data/table</param> <param>OUTPUT=/user/${wf:user()}/${examplesRoot}/output-data/hive2</param>
</hive2>
<ok to="end"/>
<error to="fail"/>
</action>
<decision name="check-output">
<switch>
<case to="end">
${wf:actionData('shell-node')['my_output'] eq 'Hello Oozie'}
</case>
<default to="fail-output"/>
</switch>
</decision>
<kill name="fail">
<message>Shell action failed, error message[${wf:errorMessage(wf:lastErrorNode())}]</message>
</kill>
<kill name="fail-output">
<message>Incorrect output, expected [Hello Oozie] but was [${wf:actionData('shell-node')['my_output']}]</message>
</kill>
<end name="end"/>
</workflow-app>
```

开发我们的job.properties配置文件

cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works/sereval-actions

vim job.properties

```shell
nameNode=hdfs://node01:8020
jobTracker=node01:8032
queueName=default
examplesRoot=oozie_works
EXEC=hello.sh
outputDir=/oozie/output
inputdir=/oozie/input
jdbcURL=jdbc:hive2://node03:10000/default
oozie.use.system.libpath=true
# 配置我们文件上传到hdfs的保存路径 实际上就是在hdfs 的/user/root/oozie_works/sereval-actions这个路径下
oozie.wf.application.path=${nameNode}/user/${user.name}/${examplesRoot}/sereval-actions/workflow.xml
```

**第四步:上传我们的资源文件夹到hdfs对应路径**

cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works/

hdfs dfs -put sereval-actions/ /user/root/oozie_works/

**第五步:执行调度任务**

cd /export/servers/oozie-4.1.0-cdh5.14.0/

bin/oozie job -oozie http://node03:11000/oozie -config oozie_works/serveral-actions/job.properties -run

**5、oozie的任务调度,定时任务执行**

在oozie当中,主要是通过Coordinator 来实现任务的定时调度,与我们的workflow类似的,Coordinator 这个模块也是主要通过xml来进行配置即可,接下来我们就来看看如何配置Coordinator 来实现任务的定时调度Coordinator 的调度主要可以有两种实现方式

第一种:基于时间的定时任务调度,

oozie基于时间的调度主要需要指定三个参数,第一个起始时间,第二个结束时间,第三个调度频率

第二种:基于数据的任务调度,只有在有了数据才会去出发执行

这种是基于数据的调度,只要在有了数据才会触发调度任务

**oozie当中定时任务的设置**

**第一步:拷贝定时任务的调度模板**

cd /export/servers/oozie-4.1.0-cdh5.14.0

cp -r examples/apps/cron oozie_works/cron-job

**第二步:拷贝我们的hello.sh脚本**

cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works

cp shell/hello.sh cron-job/

**第三步:修改配置文件**

修改job.properties

cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works/cron-job

vim job.properties

```
nameNode=hdfs://node01:8020
jobTracker=node01:8032
queueName=default
examplesRoot=oozie_works
oozie.coord.application.path=${nameNode}/user/${user.name}/${examplesRoot}/cron-job/coordinator.xml
start=2018-08-22T19:20+0800
end=2019-08-22T19:20+0800
EXEC=hello.sh
workflowAppUri=${nameNode}/user/${user.name}/${examplesRoot}/cron-job/workflow.xml
```

修改coordinator.xml

vim coordinator.xml

```xml
<!--
oozie的frequency 可以支持很多表达式,其中可以通过定时每分,或者每小时,或者每天,或者每月进行执行,也支持可以通过与linux的crontab表达式类似的写法来进行定时任务的执行
例如frequency 也可以写成以下方式
frequency="10 9 * * *" 每天上午的09:10:00开始执行任务
frequency="0 1 * * *" 每天凌晨的01:00开始执行任务
-->
<coordinator-app name="cron-job" frequency="${coord:minutes(1)}" start="${start}" end="${end}" timezone="GMT+0800"
xmlns="uri:oozie:coordinator:0.4">
<action>
<workflow>
<app-path>${workflowAppUri}</app-path>
<configuration>
<property>
<name>jobTracker</name>
<value>${jobTracker}</value>
</property>
<property>
<name>nameNode</name>
<value>${nameNode}</value>
</property>
<property>
<name>queueName</name>
<value>${queueName}</value>
</property>
</configuration>
</workflow>
</action>
</coordinator-app>


```

修改workflow.xml

vim workflow.xml

```xml
<workflow-app xmlns="uri:oozie:workflow:0.5" name="one-op-wf">
<start to="action1"/>
<action name="action1">
<shell xmlns="uri:oozie:shell-action:0.2">
<job-tracker>${jobTracker}</job-tracker>
<name-node>${nameNode}</name-node>
<configuration>
<property>
<name>mapred.job.queue.name</name>
<value>${queueName}</value>
</property>
</configuration>
<exec>${EXEC}</exec>
<!-- <argument>my_output=Hello Oozie</argument> -->
<file>/user/root/oozie_works/cron-job/${EXEC}#${EXEC}</file>
<capture-output/>
</shell>
<ok to="end"/>
<error to="end"/>
</action>
<end name="end"/>
</workflow-app>
```

**第四步:上传到hdfs对应路径**

cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works

hdfs dfs -put cron-job/ /user/root/oozie_works/

**第五步:运行定时任务**

cd /export/servers/oozie-4.1.0-cdh5.14.0

bin/oozie job -oozie http://node03:11000/oozie -config oozie_works/cron-job/job.properties -run

**oozie当中任务的查看以及杀死**

**查看所有普通任务**

oozie jobs

**查看定时任务**

oozie jobs -jobtype coordinator

![](jiqun-images/141.png)

**杀死某个任务**

oozie可以通过jobid来杀死某个定时任务

oozie job -kill [id]

例如我们可以使用命令

oozie job -kill 0000085-180628150519513-oozie-root-C

来杀死我们定时任务

![](jiqun-images/142.png)

### hue整合oozie

**第一步:停止oozie与hue的进程**

通过命令停止oozie与hue的进程,准备修改oozie与hue的配置文件

**第二步:修改oozie的配置文件(老版本的bug,新版本已经不需要了)这一步我们都不需要做了**

修改oozie的配置文件oozie-site.xml

```xml
<property> <name>oozie.service.WorkflowAppService.system.libpath</name>
<value>/user/oozie/share/lib</value>
</property>
<property>
<name>oozie.use.system.libpath</name>
<value>true</value>
</property>
```

重新上传所有的jar包到hdfs的/user/oozie/share/lib路径下去

cd /export/servers/oozie-4.1.0-cdh5.14.0

bin/oozie-setup.sh sharelib create -fs hdfs://node01:8020 -locallib oozie-sharelib-4.1.0-cdh5.14.0-yarn.tar.gz

**第三步:修改hue的配置文件**

修改hue的配置文件hue.ini

[liboozie]

```shell
# The URL where the Oozie service runs on. This is required in order for
# users to submit jobs. Empty value disables the config check.
oozie_url=http://node03.hadoop.com:11000/oozie
# Requires FQDN in oozie_url if enabled
# security_enabled=false
# Location on HDFS where the workflows/coordinator are deployed when submitted.
remote_deployement_dir=/user/root/oozie_works
```

修改oozie的配置文件大概在1151行左右的样子

[oozie]

```shell
# Location on local FS where the examples are stored.

# local_data_dir=/export/servers/oozie-4.1.0-cdh5.14.0/examples/apps

# Location on local FS where the data for the examples is stored.

# sample_data_dir=/export/servers/oozie-4.1.0-cdh5.14.0/examples/input-data

# Location on HDFS where the oozie examples and workflows are stored.

# Parameters are $TIME and $USER, e.g. /user/$USER/hue/workspaces/workflow-$TIME

#remote_data_dir=/user/root/oozie_works/examples/apps

# Maximum of Oozie workflows or coodinators to retrieve in one API call.

oozie_jobs_count=100

# Use Cron format for defining the frequency of a Coordinator instead of the old frequency number/unit.

enable_cron_scheduling=true

# Flag to enable the saved Editor queries to be dragged and dropped into a workflow.

enable_document_action=true

# Flag to enable Oozie backend filtering instead of doing it at the page level in Javascript. Requires Oozie 4.3+.

enable_oozie_backend_filtering=true

# Flag to enable the Impala action.

enable_impala_action=true
```

[filebrowser]

```shell
# Location on local filesystem where the uploaded archives are temporary stored.

archive_upload_tempdir=/tmp

# Show Download Button for HDFS file browser.

show_download_button=true

# Show Upload Button for HDFS file browser.

show_upload_button=true

# Flag to enable the extraction of a uploaded archive in HDFS.

enable_extract_uploaded_archive=true
```

**第四步:启动hue与oozie的进程**

启动hue进程

cd /export/servers/hue-3.9.0-cdh5.14.0

build/env/bin/supervisor

启动oozie进程

cd /export/servers/oozie-4.1.0-cdh5.14.0

bin/oozied.sh start

页面访问hue

http://node03.hadoop.com:8888/

### oozie使用过程当中可能遇到的问题

**1) Mysql权限配置**

授权所有主机可以使用root用户操作所有数据库和数据表

**2)** **workflow.xml配置的时候不要忽略file属性**

**3)** **jps查看进程时,注意有没有bootstrap**

**4)** **关闭oozie**

如果bin/oozied.sh stop无法关闭,则可以使用kill -9 [pid],之后oozie根目录下的oozie-server/temp/xxx.pid文件一定要删除。

**5) Oozie重新打包时,一定要注意先关闭进程,删除对应文件夹下面的pid文件。(可以参考第4条目)**

**6) 配置文件一定要生效**

起始标签和结束标签无对应则不生效,配置文件的属性写错了,那么则执行默认的属性。

**7) libext下边的jar存放于某个文件夹中,导致share/lib创建不成功。**

**9) 修改Hadoop配置文件,需要重启集群。一定要记得scp到其他节点。**

**10) JobHistoryServer必须开启,集群要重启的。**

**11) Mysql配置如果没有生效的话,默认使用derby数据库。**

**12) 在本地修改完成的job配置,必须重新上传到HDFS。**

**13) 将HDFS中上传的oozie配置文件下载下来查看是否有错误。**

**14) Linux用户名和Hadoop的用户名不一致。**

**15)sharelib找不到,包括重新初始化oozie**

**如果部署oozie出错,修复执行,初始化oozie:**

**1、停止oozie(要通过jps检查bootstrap进程是否已经不存在)**

**2、删除oozie-server/temp/***

**3、删除HDFS上的sharelib文件夹**

**4、删除oozie.sql文件,删除Mysql中删除oozie库,重新创建**

**5、重新按照顺序执行文档中oozie****的安装重新再来一遍**

**hadoop基础环境增强**

**Hadoop High Availability**

HA(High Available), 高可用,是保证业务连续性的有效解决方案,一般有两个或两个以上的节点,分为**活动节点(**Active**)及**备用节点(Standby)。通常把正在执行业务的称为活动节点,而作为活动节点的一个备份的则称为备用节点。当活动节点出现问题,导致正在运行的业务(任务)不能正常运行时,备用节点此时就会侦测到,并立即接续活动节点来执行业务。从而实现业务的不中断或短暂中断。

Hadoop1.X版本,NN是HDFS集群的单点故障点,每一个集群只有一个NN,如果这个机器或进程不可用,整个集群就无法使用。为了解决这个问题,出现了一堆针对HDFS HA的解决方案(如:Linux HA, VMware FT, shared NAS+NFS, BookKeeper, QJM/Quorum Journal Manager, BackupNode等)。

在HA具体实现方法不同情况下,HA框架的流程是一致的, 不一致的就是如何存储、管理、同步edits编辑日志文件。

在Active NN和Standby NN之间要有个共享的存储日志的地方,Active NN把edit Log写到这个共享的存储日志的地方,Standby NN去读取日志然后执行,这样Active和Standby NN内存中的HDFS元数据保持着同步。一旦发生主从切换Standby NN可以尽快接管Active NN的工作。

**Namenode HA**

**Namenode HA详解**

hadoop2.x之后,Clouera提出了QJM/Qurom Journal Manager,这是一个基于Paxos算法(分布式一致性算法)实现的HDFS HA方案,它给出了一种较好的解决思路和方案,QJM主要优势如下:

不需要配置额外的高共享存储,降低了复杂度和维护成本。

消除spof(单点故障)。

系统鲁棒性(Robust)的程度可配置、可扩展。

![](jiqun-images/143.png)

基本原理就是用2N+1台 JournalNode 存储EditLog,每次写数据操作有>=N+1返回成功时即认为该次写成功,数据不会丢失了。当然这个算法所能容忍的是最多有N台机器挂掉,如果多于N台挂掉,这个算法就失效了。这个原理是基于Paxos算法。

在HA架构里面SecondaryNameNode已经不存在了,为了保持standby NN时时的与Active NN的元数据保持一致,他们之间交互通过JournalNode进行操作同步。

任何修改操作在 Active NN上执行时,JournalNode进程同时也会记录修改log到至少半数以上的JN中,这时 Standby NN 监测到JN 里面的同步log发生变化了会读取 JN 里面的修改log,然后同步到自己的目录镜像树里面,如下图:

![](jiqun-images/144.png)

当发生故障时,Active的 NN 挂掉后,Standby NN 会在它成为Active NN 前,读取所有的JN里面的修改日志,这样就能高可靠的保证与挂掉的NN的目录镜像树一致,然后无缝的接替它的职责,维护来自客户端请求,从而达到一个高可用的目的。

在HA模式下,datanode需要确保同一时间有且只有一个NN能命令DN。为此:

每个NN改变状态的时候,向DN发送自己的状态和一个序列号。

DN在运行过程中维护此序列号,当failover时,新的NN在返回DN心跳时会返回自己的active状态和一个更大的序列号。DN接收到这个返回则认为该NN为新的active。

如果这时原来的active NN恢复,返回给DN的心跳信息包含active状态和原来的序列号,这时DN就会拒绝这个NN的命令

**Failover Controller**

HA模式下,会将FailoverController部署在每个NameNode的节点上,作为一个单独的进程用来监视NN的健康状态。**FailoverController主要包括三个组件:**

HealthMonitor: 监控NameNode是否处于unavailable或unhealthy状态。当前通过RPC调用NN相应的方法完成。

ActiveStandbyElector: 监控NN在ZK中的状态。

ZKFailoverController: 订阅HealthMonitor 和ActiveStandbyElector 的事件,并管理NN的状态,另外zkfc还负责解决fencing(也就是脑裂问题)。

上述三个组件都在跑在一个JVM中,这个JVM与NN的JVM在同一个机器上。但是两个独立的进程。一个典型的HA集群,有两个NN组成,每个NN都有自己的ZKFC进程。

![](jiqun-images/145.png)

**ZKFailoverController主要职责:**

**l** **健康监测:**周期性的向它监控的NN发送健康探测命令,从而来确定某个NameNode是否处于健康状态,如果机器宕机,心跳失败,那么zkfc就会标记它处于一个不健康的状态

**l** **会话管理:**如果NN是健康的,zkfc就会在zookeeper中保持一个打开的会话,如果NameNode同时还是Active状态的,那么zkfc还会在Zookeeper中占有一个类型为短暂类型的znode,当这个NN挂掉时,这个znode将会被删除,然后备用的NN将会得到这把锁,升级为主NN,同时标记状态为Active

l 当宕机的NN新启动时,它会再次注册zookeper,发现已经有znode锁了,便会自动变为Standby状态,如此往复循环,保证高可靠,需要注意,目前仅仅支持最多配置2个NN

**l** **master选举:**通过在zookeeper中维持一个短暂类型的znode,来实现抢占式的锁机制,从而判断那个NameNode为Active状态

**Yarn HA**

Yarn作为资源管理系统,是上层计算框架(如MapReduce,Spark)的基础。在Hadoop 2.4.0版本之前,Yarn存在单点故障(即ResourceManager存在单点故障),一旦发生故障,恢复时间较长,且会导致正在运行的Application丢失,影响范围较大。从Hadoop 2.4.0版本开始,Yarn实现了ResourceManager HA,在发生故障时自动failover,大大提高了服务的可靠性。

ResourceManager(简写为RM)作为Yarn系统中的主控节点,负责整个系统的资源管理和调度,内部维护了各个应用程序的ApplictionMaster信息、NodeManager(简写为NM)信息、资源使用等。由于资源使用情况和NodeManager信息都可以通过NodeManager的心跳机制重新构建出来,因此只需要对ApplicationMaster相关的信息进行持久化存储即可。

在一个典型的HA集群中,两台独立的机器被配置成ResourceManger。在任意时间,有且只允许一个活动的ResourceManger,另外一个备用。切换分为两种方式:

**手动切换**:在自动恢复不可用时,管理员可用手动切换状态,或是从Active到Standby,或是从Standby到Active。

**自动切换**:基于Zookeeper,但是区别于HDFS的HA,2个节点间无需配置额外的ZFKC守护进程来同步数据。

![](jiqun-images/146.png)

#### **Hadoop HA集群的搭建**

如何在已有的节点上面搭建HA高可用集群

集群服务规划:

| 机器ip | 192.168.52.100 | 192.168.52.110 | 192.168.52.120 |
| --------------- | ----------------- | ----------------- | ----------------- |
| 主机名称 | node01.hadoop.com | node02.hadoop.com | node03.hadoop.com |
| NameNode | 是(active) | 是(standBy) | 否 |
| DataNode | 是 | 是 | 是 |
| journalNode | 是 | 是 | 是 |
| ZKFC | 是 | 是 | 否 |
| ResourceManager | 否 | 是(standBy) | 是(active) |
| NodeManager | 是 | 是 | 是 |
| zookeeper | 是 | 是 | 是 |
| jobHistory | | | 是 |

**第一步:停止服务**

停止hadoop集群的所有服务,包括HDFS的服务,以及yarn集群的服务,包括impala的服务,hive的服务以及oozie的服务等

**停止oozie服务**

node03停止oozie服务

cd /export/servers/oozie-4.1.0-cdh5.14.0

bin/oozied.sh stop

**停止hue服务**

node03停止hue的服务

**停止impala服务**

直接使用kill -9杀死进程即可

node03停止impala相关服务

service impala-catalog stop

service impala-state-store stop

service impala-server stop

node02停止impala相关服务

service impala-server stop

node01停止impala相关服务

service impala-server stop

**停止hive服务**

node03停止hive服务

通过kill命令直接杀死相关hive进程即可

![](jiqun-images/147.png)

**停止hadoop服务**

node01机器执行以下命令停止hadoop服务

cd /export/servers/hadoop-2.6.0-cdh5.14.0

sbin/stop-dfs.sh

sbin/stop-yarn.sh

sbin/mr-jobhistory-daemon.sh stop historyserver

**第二步:启动所有节点的zookeeper服务**

cd /export/servers/zookeeper-3.4.5-cdh5.14.0

bin/zkServer.sh start

**第三步:更改配置文件**

所有节点修改配置文件,注意yarn-site.xml当中的

yarn.resourcemanager.ha.id 这个属性值,node03机器与node02机器的配置值不太一样

**修改core-site.xml**

```xml
<!--
<property>
<name>fs.default.name</name>
<value>hdfs://192.168.52.100:8020</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/tempDatas</value>
</property>
<property>
<name>io.file.buffer.size</name>
<value>4096</value>
</property>
<property>
<name>fs.trash.interval</name>
<value>10080</value>
</property>
-->
<property>
<name>ha.zookeeper.quorum</name>
<value>node01.hadoop.com:2181,node02.hadoop.com:2181,node03.hadoop.com:2181</value>
</property>
<property>
<name>fs.defaultFS</name>
<value>hdfs://hann</value>
</property>
<!-- 缓冲区大小,实际工作中根据服务器性能动态调整 -->
<property>
<name>io.file.buffer.size</name>
<value>4096</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/tempDatas</value>
</property>
<property>
<name>fs.trash.interval</name>
<value>10080</value>
</property>
<property>
<name>hadoop.proxyuser.root.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.root.groups</name>
<value>*</value>
</property>
```

**修改hdfs-site.xml**

```xml
<!-- NameNode存储元数据信息的路径,实际工作中,一般先确定磁盘的挂载目录,然后多个目录用,进行分割 -->
<!-- 集群动态上下线
<property>
<name>dfs.hosts</name>
<value>/export/servers/hadoop-2.7.4/etc/hadoop/accept_host</value>
</property>
<property>
<name>dfs.hosts.exclude</name>
<value>/export/servers/hadoop-2.7.4/etc/hadoop/deny_host</value>
</property>
-->
<!--
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>node01:50090</value>
</property>
<property>
<name>dfs.namenode.http-address</name>
<value>node01:50070</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:///export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/namenodeDatas</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/datanodeDatas</value>
</property>
<property>
<name>dfs.namenode.edits.dir</name>
<value>file:///export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/dfs/nn/edits</value>
</property>
<property>
<name>dfs.namenode.checkpoint.dir</name>
<value>file:///export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/dfs/snn/name</value>
</property>
<property>
<name>dfs.namenode.checkpoint.edits.dir</name>
<value>file:///export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/dfs/nn/snn/edits</value>
</property>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
<property>
<name>dfs.blocksize</name>
<value>134217728</value>
</property>
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
</property>
<property>
<name>dfs.client.read.shortcircuit</name>
<value>true</value>
</property>
<property>
<name>dfs.domain.socket.path</name>
<value>/var/run/hdfs-sockets/dn</value>
</property>
<property>
<name>dfs.client.file-block-storage-locations.timeout.millis</name>
<value>10000</value>
</property>
<property>
<name>dfs.datanode.hdfs-blocks-metadata.enabled</name>
<value>true</value>
</property>
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
</property>
-->
<property>
<name>dfs.nameservices</name>
<value>hann</value>
</property>
<property>
<name>dfs.ha.namenodes.hann</name>
<value>nn1,nn2</value>
</property>
<property>
<name>dfs.namenode.rpc-address.hann.nn1</name>
<value>node01.hadoop.com:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.hann.nn2</name>
<value>node02.hadoop.com:8020</value>
</property>
<property>
<name>dfs.namenode.servicerpc-address.hann.nn1</name>
<value>node01.hadoop.com:8022</value>
</property>
<property>
<name>dfs.namenode.servicerpc-address.hann.nn2</name>
<value>node02.hadoop.com:8022</value>
</property>

<property>
<name>dfs.namenode.http-address.hann.nn1</name>
<value>node01.hadoop.com:50070</value>
</property>
<property>
<name>dfs.namenode.http-address.hann.nn2</name>
<value>node02.hadoop.com:50070</value>
</property>
<property>
<name>dfs.namenode.shared.edits.dir</name> <value>qjournal://node01.hadoop.com:8485;node02.hadoop.com:8485;node03.hadoop.com:8485/hann</value>
</property>
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/dfs/jn</value>
</property>
<property>
<name>dfs.client.failover.proxy.provider.hann</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
</property>
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/root/.ssh/id_rsa</value>
</property>
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:///export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/namenodeDatas</value> </property>
<property>
<name>dfs.namenode.edits.dir</name>
<value>file:///export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/dfs/nn/edits</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/datanodeDatas</value>
</property>
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
<property>
<name>dfs.blocksize</name>
<value>134217728</value>
</property>
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
</property>
<property>
<name>dfs.client.read.shortcircuit</name>
<value>true</value>
</property>
<property>
<name>dfs.domain.socket.path</name>
<value>/var/run/hdfs-sockets/dn</value>
</property>
<property>
<name>dfs.client.file-block-storage-locations.timeout.millis</name>
<value>10000</value>
</property>
<property>
<name>dfs.datanode.hdfs-blocks-metadata.enabled</name>
<value>true</value>
</property>
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
</property>
```

**修改mapred-site.xml**

```xml
<!--
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>mapreduce.job.ubertask.enable</name>
<value>true</value>
</property>
<property>
<name>mapreduce.jobhistory.address</name>
<value>node01:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>node01:19888</value>
</property>
-->
<!--
<property>
<name>mapreduce.map.output.compress</name>
<value>true</value>
</property>
<property>
<name>mapreduce.map.output.compress.codec</name>
<value>org.apache.hadoop.io.compress.SnappyCodec</value>
</property>
<property>
<name>mapreduce.output.fileoutputformat.compress</name>
<value>true</value>
</property>
<property>
<name>mapreduce.output.fileoutputformat.compress.type</name>
<value>RECORD</value>
</property>
<property>
<name>mapreduce.output.fileoutputformat.compress.codec</name>
<value>org.apache.hadoop.io.compress.SnappyCodec</value>
</property>

-->
<!--指定运行mapreduce的环境是yarn -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<!-- MapReduce JobHistory Server IPC host:port -->
<property>
<name>mapreduce.jobhistory.address</name>
<value>node03:10020</value>
</property>
<!-- MapReduce JobHistory Server Web UI host:port -->
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>node03:19888</value>
</property>
<!-- The directory where MapReduce stores control files.默认 ${hadoop.tmp.dir}/mapred/system --><property>
<name>mapreduce.jobtracker.system.dir</name>
<value>/export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/jobtracker</value>
</property>
<!-- The amount of memory to request from the scheduler for each map task. 默认 1024-->
<property>
<name>mapreduce.map.memory.mb</name>
<value>1024</value>
</property>
<!-- <property>
<name>mapreduce.map.java.opts</name>
<value>-Xmx1024m</value>
</property> -->
<!-- The amount of memory to request from the scheduler for each reduce task. 默认 1024-->
<property>
<name>mapreduce.reduce.memory.mb</name>
<value>1024</value>
</property>
<!-- <property>
<name>mapreduce.reduce.java.opts</name>
<value>-Xmx2048m</value>
</property> -->
<!-- 用于存储文件的缓存内存的总数量,以兆字节为单位。默认情况下,分配给每个合并流1MB,给个合并流应该寻求最小化。默认值100-->
<property>
<name>mapreduce.task.io.sort.mb</name>
<value>100</value>
</property>
<!-- <property>
<name>mapreduce.jobtracker.handler.count</name>
<value>25</value>
</property>-->

<!-- 整理文件时用于合并的流的数量。这决定了打开的文件句柄的数量。默认值10-->
<property>
<name>mapreduce.task.io.sort.factor</name>
<value>10</value>
</property>

<!-- 默认的并行传输量由reduce在copy(shuffle)阶段。默认值5-->

<property>
<name>mapreduce.reduce.shuffle.parallelcopies</name>
<value>25</value>
</property>
<property>
<name>yarn.app.mapreduce.am.command-opts</name>
<value>-Xmx1024m</value>
</property>
<!-- MR AppMaster所需的内存总量。默认值1536-->
<property>
<name>yarn.app.mapreduce.am.resource.mb</name>
<value>1536</value>
</property>
<!-- MapReduce存储中间数据文件的本地目录。目录不存在则被忽略。默认值${hadoop.tmp.dir}/mapred/local-->
<property>
<name>mapreduce.cluster.local.dir</name>
<value>/export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/mapreduce/local</value>
</property>
```

**修改yarn-site.xml**

注意:yarn.resourcemanager.ha.id 这个属性的配置,node03的这个属性值与node02的这个属性值内容不同

```xml
<!--
<property>
<name>yarn.resourcemanager.hostname</name>
<value>node01</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>604800</value>
</property>
-->
<!-- Site specific YARN configuration properties -->
<!-- 是否启用日志聚合.应用程序完成后,日志汇总收集每个容器的日志,这些日志移动到文件系统,例如HDFS. -->
<!-- 用户可以通过配置"yarn.nodemanager.remote-app-log-dir"、"yarn.nodemanager.remote-app-log-dir-suffix"来确定日志移动到的位置 -->
<!-- 用户可以通过应用程序时间服务器访问日志 -->
<!-- 启用日志聚合功能,应用程序完成后,收集各个节点的日志到一起便于查看 -->
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<!--开启resource manager HA,默认为false-->
<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
<!-- 集群的Id,使用该值确保RM不会做为其它集群的active -->
<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>mycluster</value>
</property>
<!--配置resource manager 命名-->
<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>
<!-- 配置第一台机器的resourceManager -->
<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>node03.hadoop.com</value>
</property>
<!-- 配置第二台机器的resourceManager -->
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>node02.hadoop.com</value>
</property>
<!-- 配置第一台机器的resourceManager通信地址 -->
<property>
<name>yarn.resourcemanager.address.rm1</name>
<value>node03.hadoop.com:8032</value>
</property>
<property>
<name>yarn.resourcemanager.scheduler.address.rm1</name>
<value>node03.hadoop.com:8030</value>
</property>
<property>
<name>yarn.resourcemanager.resource-tracker.address.rm1</name>
<value>node03.hadoop.com:8031</value>
</property>
<property>
<name>yarn.resourcemanager.admin.address.rm1</name>
<value>node03.hadoop.com:8033</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.address.rm1</name>
<value>node03.hadoop.com:8088</value>
</property>
<!-- 配置第二台机器的resourceManager通信地址 -->
<property>
<name>yarn.resourcemanager.address.rm2</name>
<value>node02.hadoop.com:8032</value>
</property>
<property>
<name>yarn.resourcemanager.scheduler.address.rm2</name>
<value>node02.hadoop.com:8030</value>
</property>
<property>
<name>yarn.resourcemanager.resource-tracker.address.rm2</name>
<value>node02.hadoop.com:8031</value>
</property>
<property>
<name>yarn.resourcemanager.admin.address.rm2</name>
<value>node02.hadoop.com:8033</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.address.rm2</name>
<value>node02.hadoop.com:8088</value>
</property>
<!--开启resourcemanager自动恢复功能-->
<property>
<name>yarn.resourcemanager.recovery.enabled</name>
<value>true</value>
</property>
<!--在node3上配置rm1,在node2上配置rm2,注意:一般都喜欢把配置好的文件远程复制到其它机器上,但这个在YARN的另一个机器上一定要修改,其他机器上不配置此项-->
<property>
<name>yarn.resourcemanager.ha.id</name>
<value>rm1</value>
<description>If we want to launch more than one RM in single node, we need this configuration</description>
</property>
<!--用于持久存储的类。尝试开启-->
<property>
<name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
</property>
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>node01.hadoop.com:2181,node02.hadoop.com:2181,node03.hadoop.com:2181</value>
<description>For multiple zk services, separate them with comma</description>
</property>
<!--开启resourcemanager故障自动切换,指定机器-->
<property>
<name>yarn.resourcemanager.ha.automatic-failover.enabled</name>
<value>true</value>
<description>Enable automatic failover; By default, it is enabled only when HA is enabled.</description>
</property>
<property>
<name>yarn.client.failover-proxy-provider</name>
<value>org.apache.hadoop.yarn.client.ConfiguredRMFailoverProxyProvider</value>
</property>
<!-- 允许分配给一个任务最大的CPU核数,默认是8 -->
<property>
<name>yarn.nodemanager.resource.cpu-vcores</name>
<value>4</value>
</property>
<!-- 每个节点可用内存,单位MB -->
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>512</value>
</property>
<!-- 单个任务可申请最少内存,默认1024MB -->
<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>512</value>
</property>
<!-- 单个任务可申请最大内存,默认8192MB -->
<property>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>512</value>
</property>
<!--多长时间聚合删除一次日志 此处-->
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>2592000</value><!--30 day-->
</property>
<!--时间在几秒钟内保留用户日志。只适用于如果日志聚合是禁用的-->
<property>
<name>yarn.nodemanager.log.retain-seconds</name>
<value>604800</value><!--7 day-->
</property>
<!--指定文件压缩类型用于压缩汇总日志-->
<property>
<name>yarn.nodemanager.log-aggregation.compression-type</name>
<value>gz</value>
</property>
<!-- nodemanager本地文件存储目录-->
<property>
<name>yarn.nodemanager.local-dirs</name>
<value>/export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/yarn/local</value>
</property>
<!-- resourceManager 保存最大的任务完成个数 -->
<property>
<name>yarn.resourcemanager.max-completed-applications</name>
<value>1000</value>
</property>
<!-- 逗号隔开的服务列表,列表名称应该只包含a-zA-Z0-9_,不能以数字开始-->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<!--rm失联后重新链接的时间-->
<property>
<name>yarn.resourcemanager.connect.retry-interval.ms</name>
<value>2000</value>
</property>

改完之后,将配置文件分发到其他的各个节点

还要记得改node02机器的yarn-site.xml
```

**第四步:服务的启动**

**第一步:初始化zookeeper**

在node01机器上进行zookeeper的初始化,其本质工作是创建对应的zookeeper节点

cd /export/servers/hadoop-2.6.0-cdh5.14.0

bin/hdfs zkfc -formatZK

**第二步:启动journalNode**

三台机器执行以下命令启动journalNode,用于我们的元数据管理

cd /export/servers/hadoop-2.6.0-cdh5.14.0

sbin/hadoop-daemon.sh start journalnode

**第三步:初始化journalNode**

node01机器上准备初始化journalNode

cd /export/servers/hadoop-2.6.0-cdh5.14.0

bin/hdfs namenode -initializeSharedEdits -force

**第四步:启动namenode**

node01机器上启动namenode

cd /export/servers/hadoop-2.6.0-cdh5.14.0

sbin/hadoop-daemon.sh start namenode

node02机器上启动namenode

cd /export/servers/hadoop-2.6.0-cdh5.14.0

bin/hdfs namenode -bootstrapStandby

sbin/hadoop-daemon.sh start namenode

**第五步:启动所有节点的datanode进程**

在node01机器上启动所有节点的datanode进程

cd /export/servers/hadoop-2.6.0-cdh5.14.0

sbin/hadoop-daemons.sh start datanode

**第六步:启动zkfc**

在node01机器上面启动zkfc进程

cd /export/servers/hadoop-2.6.0-cdh5.14.0

sbin/hadoop-daemon.sh start zkfc

在node02机器上面启动zkfc进程

cd /export/servers/hadoop-2.6.0-cdh5.14.0

sbin/hadoop-daemon.sh start zkfc

**第七步:启动yarn进程**

node03机器上启动yarn集群

cd /export/servers/hadoop-2.6.0-cdh5.14.0

sbin/start-yarn.sh

node02机器上启动yarn集群

cd /export/servers/hadoop-2.6.0-cdh5.14.0

sbin/start-yarn.sh

**第八步:启动jobhsitory**

node03节点启动jobhistoryserver

cd /export/servers/hadoop-2.6.0-cdh5.14.0

sbin/mr-jobhistory-daemon.sh start historyserver

#### **Hadoop Federation**

**背景概述**

单NameNode的架构使得HDFS在集群扩展性和性能上都有潜在的问题,当集群大到一定程度后,NameNode进程使用的内存可能会达到上百G,NameNode成为了性能的瓶颈。因而提出了namenode水平扩展方案-- Federation。

Federation中文意思为联邦,联盟,是NameNode的Federation,也就是会有多个NameNode。多个NameNode的情况意味着有多个namespace(命名空间),区别于HA模式下的多NameNode,它们是拥有着同一个namespace。既然说到了NameNode的命名空间的概念,这里就看一下现有的HDFS数据管理架构,如下图所示:

![](jiqun-images/148.png)

从上图中,我们可以很明显地看出现有的HDFS数据管理,数据存储2层分层的结构.也就是说,所有关于存储数据的信息和管理是放在NameNode这边,而真实数据的存储则是在各个DataNode下.而这些隶属于同一个NameNode所管理的数据都是在同一个命名空间下的.而一个namespace对应一个block pool。Block Pool是同一个namespace下的block的集合.当然这是我们最常见的单个namespace的情况,也就是一个NameNode管理集群中所有元数据信息的时候.如果我们遇到了之前提到的NameNode内存使用过高的问题,这时候怎么办.元数据空间依然还是在不断增大,一味调高NameNode的jvm大小绝对不是一个持久的办法.这时候就诞生了HDFS Federation的机制.

**Federation架构设计**

HDFS Federation是解决namenode内存瓶颈问题的水平横向扩展方案。

Federation意味着在集群中将会有多个namenode/namespace。这些namenode之间是联合的,也就是说,他们之间相互独立且不需要互相协调,各自分工,管理自己的区域。分布式的datanode被用作通用的数据块存储存储设备。每个datanode要向集群中所有的namenode注册,且周期性地向所有namenode发送心跳和块报告,并执行来自所有namenode的命令。

![](jiqun-images/149.png)

Federation一个典型的例子就是上面提到的NameNode内存过高问题,我们完全可以将上面部分大的文件目录移到另外一个NameNode上做管理.**更重要的一点在于,这些NameNode是共享集群中所有的DataNode的,它们还是在同一个集群内的****。**

这时候在DataNode上就不仅仅存储一个Block Pool下的数据了,而是多个(在DataNode的datadir所在目录里面查看BP-xx.xx.xx.xx打头的目录)。

**概括起来:**

多个NN共用一个集群里的存储资源,每个NN都可以单独对外提供服务。

每个NN都会定义一个存储池,有单独的id,每个DN都为所有存储池提供存储。

DN会按照存储池id向其对应的NN汇报块信息,同时,DN会向所有NN汇报本地存储可用资源情况。

**HDFS Federation不足**

HDFS Federation并没有完全解决单点故障问题。虽然namenode/namespace存在多个,但是从单个namenode/namespace看,仍然存在单点故障:如果某个namenode挂掉了,其管理的相应的文件便不可以访问。Federation中每个namenode仍然像之前HDFS上实现一样,配有一个secondary namenode,以便主namenode挂掉一下,用于还原元数据信息。

所以一般集群规模真的很大的时候,会采用HA+Federation的部署方案。也就是每个联合的namenodes都是ha的。

**Federation示例配置**

这是一个包含两个Namenode的Federation示例配置:

```xml
<configuration>
<property>
<name>dfs.nameservices</name>
<value>ns1,ns2</value>
</property>
<property>
<name>dfs.namenode.rpc-address.ns1</name>
<value>nn-host1:rpc-port</value>
</property>
<property>
<name>dfs.namenode.http-address.ns1</name>
<value>nn-host1:http-port</value>
</property>
<property>
<name>dfs.namenode.secondaryhttp-address.ns1</name>
<value>snn-host1:http-port</value>
</property>
<property>
<name>dfs.namenode.rpc-address.ns2</name>
<value>nn-host2:rpc-port</value>
</property>
<property>
<name>dfs.namenode.http-address.ns2</name>
<value>nn-host2:http-port</value>
</property>
<property>
<name>dfs.namenode.secondaryhttp-address.ns2</name>
<value>snn-host2:http-port</value> </property> .... Other common configuration ...</configuration>
```

## clouderaManager搭建

Cloudera Manager是cloudera公司提供的一种大数据的解决方案,可以通过ClouderaManager管理界面来对我们的集群进行安装和操作,提供了良好的UI界面交互,使得我们管理集群不用熟悉任何的linux技术,只需要通过网页浏览器就可以实现我们的集群的操作和管理,让我们使用和管理集群更加的方便。

**整体架构**

![](jiqun-images/150.png)

Cloudera Manager的核心是Cloudera Manager Server。Server托管Admin Console Web Server和应用程序逻辑。它负责安装软件、配置、启动和停止服务以及管理运行服务的群集。

解释:

· Agent:安装在每台主机上。它负责启动和停止进程,解压缩配置,触发安装和监控主机

· Management Service:执行各种监控、报警和报告功能的一组角色的服务。

· Database:存储配置和监控信息

· Cloudera Repository:可供Cloudera Manager分配的软件的存储库(repo库)

· Client:用于与服务器进行交互的接口:

· Admin Console:管理员控制台

· API:开发人员使用 API可以创建自定义的Cloudera Manager应用程序

**Cloudera Management Service**

Cloudera Management Service 可作为一组角色实施各种管理功能

· Activity Monitor:收集有关服务运行的活动的信息

· Host Monitor:收集有关主机的运行状况和指标信息

· Service Monitor:收集有关服务的运行状况和指标信息

· Event Server:聚合组件的事件并将其用于警报和搜索

· Alert Publisher :为特定类型的事件生成和提供警报

· Reports Manager:生成图表报告,它提供用户、用户组的目录的磁盘使用率、磁盘、io等历史视图

**信号检测**

默认情况下,Agent 每隔 15 秒向 Cloudera Manager Server 发送一次检测信号。但是,为了减少用户延迟,在状态变化时会提高频率。

**状态管理**

· 模型状态捕获什么进程应在何处运行以及具有什么配置

· 运行时状态是哪些进程正在何处运行以及正在执行哪些命令(例如,重新平衡 HDFS 或执行备份/灾难恢复计划或滚动升级或停止)

· 当您更新配置(例如Hue Server Web 端口)时,您即更新了模型状态。但是,如果 Hue 在更新时正在运行,则它仍将使用旧端口。当出现这种不匹配情况时,角色会标记为具有”过时的配置”。要重新同步,您需重启角色(这会触发重新生成配置和重启进程)

· 特殊情况如果要加入一些clouder manager控制台没有的属性时候都在高级里面嵌入

**服务器和客户端配置**

· 如使用HDFS,文件 /etc/hadoop/conf/hdfs-site.xml 仅包含与 HDFS 客户端相关的配置

· 而 HDFS 角色实例(例如,NameNode 和 DataNode)会从/var/run/cloudera-scm-agent/process/unique-process-name下的每个进程专用目录获取它们的配置

**进程管理**

· 在 Cloudera Manager 管理的群集中,只能通过 Cloudera Manager 启动或停止服务。ClouderaManager 使用一种名为 supervisord的开源进程管理工具,它会重定向日志文件,通知进程失败,为合适用户设置调用进程的有效用户 ID 等等

· Cloudera Manager 支持自动重启崩溃进程。如果一个角色实例在启动后反复失败,Cloudera Manager还会用不良状态标记该实例

· 特别需要注意的是,停止 Cloudera Manager 和 Cloudera Manager Agent 不会停止群集;所有正在运行的实例都将保持运行

· Agent 的一项主要职责是启动和停止进程。当 Agent 从检测信号检测到新进程时,Agent 会在/var/run/cloudera-scm-agent 中为它创建一个目录,并解压缩配置

· Agent 受到监控,属于 Cloudera Manager 的主机监控的一部分:如果 Agent 停止检测信号,主机将被标记为运行状况不良

**主机管理**

· Cloudera Manager 自动将作为群集中的托管主机身份:JDK、Cloudera Manager Agent、CDH、Impala、Solr 等参与所需的所有软件部署到主机

· Cloudera Manager 提供用于管理参与主机生命周期的操作以及添加和删除主机的操作

· Cloudera Management Service Host Monitor 角色执行运行状况检查并收集主机度量,以使您可以监控主机的运行状况和性能

**安全**

**·** **身份验证**

· Hadoop中身份验证的目的仅仅是证明用户或服务确实是他或她所声称的用户或服务,通常,企业中的身份验证通过单个分布式系统(例如,轻型目录访问协议 (LDAP) 目录)进行管理。LDAP身份验证包含由各种存储系统提供支持的简单用户名/密码服务

· Hadoop 生态系统的许多组件会汇总到一起来使用 Kerberos 身份验证并提供用于在 LDAP 或 AD 中管理和存储凭据的选项

**·** **授权**
CDH 当前提供以下形式的访问控制:

· 适用于目录和文件的传统 POSIX 样式的权限

· 适用于 HDFS 的扩展的访问控制列表 (ACL)

· Apache HBase 使用 ACL 来按列、列族和列族限定符授权各种操作 (READ, WRITE, CREATE, ADMIN)

· 使用 Apache Sentry 基于角色进行访问控制

**·** **加密**

· 需要获得企业版的Cloudera(Cloudera Navigator 许可)

**clouderaManager环境安装前准备**

准备两台虚拟机,其中一台作为我们的主节点,安装我们的ClouderaManager Server与ClouderaManager agent,另外一台作为我们的从节点只安装我们的clouderaManager agent

机器规划如下

| 服务器IP | 192.168.52.100 | 192.168.52.110 |
| ------------------ | ----------------- | ----------------- |
| 主机名 | node01.hadoop.com | node02.hadoop.com |
| 主机名与IP地址映射 | 是 | 是 |
| 防火墙 | 关闭 | 关闭 |
| selinux | 关闭 | 关闭 |
| jdk | 安装 | 安装 |
| ssh免密码登录 | 是 | 是 |
| mysql数据库 | 否 | 是 |
| 服务器内存 | 16G | 8G |

所有机器统一两个路径

mkdir -p /export/softwares/

mkdir -p /export/servers/

**两台机器更改主机名**

第一台机器更改主机名

vim /etc/sysconfig/network

NETWORKING=yes

HOSTNAME=node01.hadoop.com

第二台机器更改主机名

vim /etc/sysconfig/network

NETWORKING=yes

HOSTNAME=node02.hadoop.com

**更改主机名与IP地址的映射**

两台机器更改hosts文件

vim /etc/hosts

192.168.52.100 node01.hadoop.com

192.168.52.110 node02.hadoop.com

**两台机器关闭防火墙**

service iptables stop

chkconfig iptables off

**两台机器关闭selinux**

vim /etc/selinux/config

SELINUX=disabled

![](jiqun-images/151.png)

**两台机器安装jdk**

将我们的jdk的压缩包上传到node01.hadoop.com的/export/softwares路径下

cd /export/softwares/

tar -zxvf jdk-8u141-linux-x64.tar.gz -C /export/servers/

配置环境变量

vim /etc/profile

export JAVA_HOME=/export/servers/jdk1.8.0_141

export PATH=:$JAVA_HOME/bin:$PATH

source /etc/profile

第二台机器同样安装jdk即可

**两台机器实现SSH免密码登录**

**第一步:两台器生成公钥与私钥**

两台机器上面执行以下命令,然后按下三个回车键即可生成公钥与私钥

ssh-keygen -t rsa

![](jiqun-images/152.png)

**第二步:两台机器将公钥拷贝到同一个文件当中去**

两台机器执行以下命令

ssh-copy-id node01.hadoop.com

**第三步:拷贝authorized_keys到其他机器**

第一台机器上将authorized_keys拷贝到第二台机器

scp /root/.ssh/authorized_keys node02.hadoop.com:/root/.ssh/

**第二台机器安装mysql数据库**

通过yum源,在线安装mysql

yum install mysql mysql-server mysql-devel

/etc/init.d/mysqld start

/usr/bin/mysql_secure_installation

进入mysql客户端执行以下命令

grant all privileges on *.* to 'root'@'%' identified by '123456' with grant option;

flush privileges;

![](jiqun-images/153.png)

**解除linux系统打开文件最大数量的限制**

两台机器都需要执行

vi /etc/security/limits.conf

添加以下内容

. soft noproc 11000

. hard noproc 11000

. soft nofile 65535

. hard nofile 65535

**设置linux交换区内存**

两台机器都要执行

执行命令

echo 10 > /proc/sys/vm/swappiness

并编辑文件sysctl.conf:

vim /etc/sysctl.conf

添加或修改

vm.swappiness = 0

两台机器都要执行:

echo never > /sys/kernel/mm/transparent_hugepage/defrag

echo never > /sys/kernel/mm/transparent_hugepage/enabled

并编辑文件rc.local :

vim /etc/rc.local

echo never > /sys/kernel/mm/transparent_hugepage/defrag

echo never > /sys/kernel/mm/transparent_hugepage/enabled

![](jiqun-images/154.png)

**两台机器时钟同步**

两台机器需要进行时钟同步操作,保证两台机器时间相同

crontab –e

*/1 * * * * /usr/sbin/ntpdate ntp4.aliyun.com;

**两台服务器关闭防火墙**

service iptables stop

chkconfig iptables off

服务器关机重启

clouderaManager安装资源下载

**第一步:下载安装资源并上传到服务器**

我们这里安装CM5.14.0这个版本,需要下载以下这些资源,一共是四个文件即可

下载cm5的压缩包

下载地址:http://archive.cloudera.com/cm5/cm/5/

具体文件地址:

http://archive.cloudera.com/cm5/cm/5/cloudera-manager-el6-cm5.14.0_x86_64.tar.gz

下载cm5的parcel包

下载地址:

http://archive.cloudera.com/cdh5/parcels/

第一个文件具体下载地址:

http://archive.cloudera.com/cdh5/parcels/5.14.0/CDH-5.14.0-1.cdh5.14.0.p0.24-el6.parcel

第二个文件具体下载地址:

http://archive.cloudera.com/cdh5/parcels/5.14.0/CDH-5.14.0-1.cdh5.14.0.p0.24-el6.parcel.sha1

第三个文件具体下载地址:

http://archive.cloudera.com/cdh5/parcels/5.14.0/manifest.json

将这四个安装包都上传到第一台机器的/export/softwares路径下

![](jiqun-images/155.png)

**第二步:解压压缩包到指定路径**

解压CM安装包到/opt路径下去

cd /export/softwares

tar -zxvf cloudera-manager-el6-cm5.14.0_x86_64.tar.gz -C /opt/

**第三步:将我们的parcel包的三个文件拷贝到对应路径**

将我们的parcel包含三个文件,拷贝到/opt/cloudera/parcel-repo路径下面去,并记得有个文件需要重命名

cd /export/softwares/

cp CDH-5.14.0-1.cdh5.14.0.p0.24-el6.parcel CDH-5.14.0-1.cdh5.14.0.p0.24-el6.parcel.sha1 manifest.json /opt/cloudera/parcel-repo/

![](jiqun-images/156.png)

重命名标黄的这个文件

cd /opt/cloudera/parcel-repo/

mv CDH-5.14.0-1.cdh5.14.0.p0.24-el6.parcel.sha1 CDH-5.14.0-1.cdh5.14.0.p0.24-el6.parcel.sha

![](jiqun-images/157.png)

**第四步:所有节点添加普通用户并给与sudo权限**

在node01机器上面添加普通用户并赋予sudo权限

执行以下命令创建普通用户cloudera-scm

useradd --system --home=/opt/cm-5.14.0/run/cloudera-scm-server --no-create-home --shell=/bin/false --comment "Cloudera SCM User" cloudera-scm

赋予cloudera-scm普通用户的sudo权限

visudo

cloudera-scm ALL=(ALL) NOPASSWD: ALL

![](jiqun-images/158.png)

**第五步:更改主节点的配置文件**

node01机器上面更改配置文件

vim /opt/cm-5.14.0/etc/cloudera-scm-agent/config.ini

server_host=node01.hadoop.com

![](jiqun-images/159.png)

**第六步:将/opt目录下的安装包发放到其他机器**

将第一台机器的安装包发放到其他机器

cd /opt

scp -r cloudera/ cm-5.14.0/ node02.hadoop.com:/opt

**第七步:创建一些数据库备用**

node02机器上面创建数据库

hive 数据库

create database hive DEFAULT CHARSET utf8 COLLATE utf8_general_ci;

集群监控数据库

create database amon DEFAULT CHARSET utf8 COLLATE utf8_general_ci;

hue 数据库

create database hue DEFAULT CHARSET utf8 COLLATE utf8_general_ci;

oozie 数据库

create database oozie DEFAULT CHARSET utf8 COLLATE utf8_general_ci;

**第八步:准备数据库连接的驱动包**

在所有机器上面都准备一份数据库的连接驱动jar包放到/usr/share/java路径下

准备一份mysql的驱动连接包,放到/usr/share/java路径下去

cd /export/softwares/

wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.45.tar.gz

tar -zxvf mysql-connector-java-5.1.45.tar.gz

cd /export/softwares/mysql-connector-java-5.1.45

cp mysql-connector-java-5.1.45-bin.jar /usr/share/java/mysql-connector-java.jar

拷贝驱动包到第二台机器

cd /usr/share/java

scp mysql-connector-java.jar node02.hadoop.com:$PWD

**第九步:为clouderaManager创建数据库**

node01服务器执行

/opt/cm-5.14.0/share/cmf/schema/scm_prepare_database.sh mysql -hnode02.hadoop.com -uroot -p123456 --scm-host node01.hadoop.com scm root 123456

命令说明:/**opt**/**cm**-5.14.0/share/cmf/schema/scm_prepare_database.**sh** 数据库类型 -h数据库主机 –u数据库用户名 –p数据库密码 --scm-host **cm**主机 数据库名称 用户名 密码

![](jiqun-images/160.png)

**第十步:启动服务**

主节点启动clouderaManager Server与ClouderaManager agent服务

/opt/cm-5.14.0/etc/init.d/cloudera-scm-server start

/opt/cm-5.14.0/etc/init.d/cloudera-scm-agent start

![](jiqun-images/161.png)

从节点node02启动ClouderaManager agent服务

/opt/cm-5.14.0/etc/init.d/cloudera-scm-agent start

**第十一步:浏览器页面访问**

http://node01:7180/cmf/login

默认用户名admin

密码 admin

## Hue

一、编译

```shell
#1-下载安装包并解压
tar -zxvf hue-3.9.0-cdh5.14.0.tar.gz -C /export/servers/

#2-安装依赖
yum install ant asciidoc cyrus-sasl-devel cyrus-sasl-gssapi cyrus-sasl-plain gcc gcc-c++ krb5-devel libffi-devel libxml2-devel libxslt-devel make mysql mysql-devel openldap-devel python-devel sqlite-devel gmp-devel -y

#3-卸载安装的jdk1.7
java -version
rpm -qa | grep java
rpm -e --nodeps java-1.7.0-openjdk-1.7.0.231-2.6.19.1.el6_10.x86_64 java-1.5.0-gcj-1.5.0.0-29.1.el6.x86_64 tzdata-java-2019b-2.el6.noarch java-1.7.0-openjdk-devel-1.7.0.231-2.6.19.1.el6_10.x86_64 java_cup-0.10k-5.el6.x86_64

#4-修改hue的配置文件:$HUE_HOME/desktop/conf/hue.ini
--hue的配置
21行: secret_key=qwertasdfgyuiophjkl
28行: http_host=hpsk.bigdata01.com
32行: is_hue_4=true
41行: time_zone=Asia/Shanghai
68行: server_user=root
69行: server_group=root
72行: default_user=root
75行: default_hdfs_superuser=root
--Hue存储信息数据库的配置
595行: engine=mysql
596行: host=hpsk.bigdata03.com
597行: port=3306
598行: user=root
599行: password=123456
605行: name=hue
--MySQL中创建hue数据库:第三台机器
mysql -uroot -p
create database hue default character set utf8 default collate utf8_general_ci;

#5-编译
cd /export/servers/hue-3.9.0-cdh5.14.0
make apps

#6-添加Linux中的hue用户
useradd hue
passwd hue
```

**1、Hue的介绍**

HUE=**Hadoop User Experience**

Hue是一个开源的Apache Hadoop UI系统,由Cloudera Desktop演化而来,最后Cloudera公司将其贡献给Apache基金会的Hadoop社区,它是基于Python Web框架Django实现的。

通过使用Hue我们可以在浏览器端的Web控制台上与Hadoop集群进行交互来分析处理数据,例如操作HDFS上的数据,运行MapReduce Job,执行Hive的SQL语句,浏览HBase数据库等等。

**HUE链接**

· Site: http://gethue.com/

· Github: https://github.com/cloudera/hue

· Reviews: [https://review.cloudera.org](https://review.cloudera.org/)

**Hue的架构**

![](jiqun-images/162.png)

**核心功能**

· SQL编辑器,支持Hive, Impala, MySQL, Oracle, PostgreSQL, SparkSQL, Solr SQL, Phoenix…

· 搜索引擎Solr的各种图表

· Spark和Hadoop的友好界面支持

· 支持调度系统Apache Oozie,可进行workflow的编辑、查看

HUE提供的这些功能相比Hadoop生态各组件提供的界面更加友好,但是一些需要debug的场景可能还是需要使用原生系统才能更加深入的找到错误的原因。

HUE中查看Oozie workflow时,也可以很方便的看到整个workflow的DAG图,不过在最新版本中已经将DAG图去掉了,只能看到workflow中的action列表和他们之间的跳转关系,想要看DAG图的仍然可以使用oozie原生的界面系统查看。

1,访问HDFS和文件浏览

2,通过web调试和开发hive以及数据结果展示

3,查询solr和结果展示,报表生成

4,通过web调试和开发impala交互式SQL Query

5,spark调试和开发

7,oozie任务的开发,监控,和工作流协调调度

8,Hbase数据查询和修改,数据展示

9,Hive的元数据(metastore)查询

10,MapReduce任务进度查看,日志追踪

11,创建和提交MapReduce,Streaming,Java job任务

12,Sqoop2的开发和调试

13,Zookeeper的浏览和编辑

14,数据库(MySQL,PostGres,SQlite,Oracle)的查询和展示

一句话总结:Hue是一个友好的界面集成框架,可以集成我们各种学习过的以及将要学习的框架,一个界面就可以做到查看以及执行所有的框架

**2、Hue的安装**

Hue的安装支持多种方式,包括rpm包的方式进行安装,tar.gz包的方式进行安装以及cloudera manager的方式来进行安装等,我们这里使用tar.gz包的方式来记性安装

**第一步:下载Hue的压缩包并上传到linux解压**

Hue的压缩包的下载地址:

http://archive.cloudera.com/cdh5/cdh/5/

我们这里使用的是CDH5.14.0这个对应的版本,具体下载地址为

http://archive.cloudera.com/cdh5/cdh/5/hue-3.9.0-cdh5.14.0.tar.gz

下载然后上传到linux系统,然后进行解压

cd /export/softwares/

tar -zxvf hue-3.9.0-cdh5.14.0.tar.gz -C ../servers/

**第二步:编译安装启动**

**2.1、linux系统安装依赖包:**

联网安装各种必须的依赖包

yum install ant asciidoc cyrus-sasl-devel cyrus-sasl-gssapi cyrus-sasl-plain gcc gcc-c++ krb5-devel libffi-devel libxml2-devel libxslt-devel make mysql mysql-devel openldap-devel python-devel sqlite-devel gmp-devel

**2.2、开始配置Hue**

cd /export/servers/hue-3.9.0-cdh5.14.0/desktop/conf

vim hue.ini

```shell
#通用配置
[desktop]
secret_key=jFE93j;2[290-eiw.KEiwN2s3['d;/.q[eIW^y#e=+Iei*@Mn<qW5o
http_host=node03.hadoop.com
is_hue_4=true
time_zone=Asia/Shanghai
server_user=root
server_group=root
default_user=root
default_hdfs_superuser=root
#配置使用mysql作为hue的存储数据库,大概在hue.ini的587行左右
[[database]]
engine=mysql
host=node03.hadoop.com
port=3306
user=root
password=123456
name=hue
```

**2.3、创建mysql数据库**

创建hue数据库

create database hue default character set utf8 default collate utf8_general_ci;

注意:实际工作中,还需要为hue这个数据库创建对应的用户,并分配权限,我这就不创建了,所以下面这一步不用执行了

grant all on hue.* to 'hue'@'%' identified by 'hue';

**2.4、准备进行编译**

```
cd /export/servers/hue-3.9.0-cdh5.14.0
make apps
```

**2.5、linux系统添加普通用户hue**

```
useradd hue
passwd hue
```

**2.6、启动hue进程**

```
cd /export/servers/hue-3.9.0-cdh5.14.0/
build/env/bin/supervisor
```

**2.7、页面访问**

http://node03:8888

第一次访问的时候,需要设置管理员用户和密码

我们这里的管理员的用户名与密码尽量保持与我们安装hadoop的用户名和密码一致,

我们安装hadoop的用户名与密码分别是root 123456

初次登录使用root用户,密码为123456

![](jiqun-images/163.png)

进入之后发现我们的hue页面报错了,这个错误主要是因为hive的原因,因为我们的hue与hive集成的时候出错了,所以我们需要配置我们的hue与hive进行集成,接下里就看看我们的hue与hive以及hadoop如何进行集成

**3.hue与其他框架的集成**

**3.1、hue与hadoop的HDFS以及yarn集成**

**第一步:更改所有hadoop节点的core-site.xml配置**

记得更改完core-site.xml之后一定要重启hdfs与yarn集群

```xml
<property>
<name>hadoop.proxyuser.root.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.root.groups</name>
<value>*</value>
</property>
```

**第二步:更改所有hadoop节点的hdfs-site.xml**

```xml
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
</property>
```

**第三步:重启hadoop集群**

在node01机器上面执行以下命令

```shell
cd /export/servers/hadoop-2.6.0-cdh5.14.0
sbin/stop-dfs.sh
sbin/start-dfs.sh
sbin/stop-yarn.sh
sbin/start-yarn.sh
```

**第四步:停止hue的服务,并继续配置hue.ini**

cd /export/servers/hue-3.9.0-cdh5.14.0/desktop/conf

vim hue.ini

```shell
配置我们的hue与hdfs集成
[[hdfs_clusters]]
[[[default]]]
fs_defaultfs=hdfs://node01.hadoop.com:8020
webhdfs_url=http://node01.hadoop.com:50070/webhdfs/v1
hadoop_hdfs_home=/export/servers/hadoop-2.6.0-cdh5.14.0
hadoop_bin=/export/servers/hadoop-2.6.0-cdh5.14.0/bin
hadoop_conf_dir=/export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop
配置我们的hue与yarn集成
[[yarn_clusters]]
[[[default]]]
resourcemanager_host=node01
resourcemanager_port=8032
submit_to=True
resourcemanager_api_url=http://node01:8088
history_server_api_url=http//node01:19888
```

**3.2、配置hue与hive集成**

如果需要配置hue与hive的集成,我们需要启动hive的metastore服务以及hiveserver2服务(impala需要hive的metastore服务,hue需要hvie的hiveserver2服务)

**更改hue的配置hue.ini**

修改hue.ini

```shell
[beeswax]
hive_server_host=node03.hadoop.com
hive_server_port=10000
hive_conf_dir=/export/servers/hive-1.1.0-cdh5.14.0/conf
server_conn_timeout=120
auth_username=root
auth_password=12345
[metastore]
#允许使用hive创建数据库表等操作
enable_new_create_table=true

#启动hive的metastore服务
去node03机器上启动hive的metastore以及hiveserver2服务
cd /export/servers/hive-1.1.0-cdh5.14.0
nohup bin/hive --service metastore &
nohup bin/hive --service hiveserver2 &
重新启动hue,然后就可以通过浏览器页面操作hive了
```

**3.3、配置hue与impala的集成**

停止hue的服务进程

修改hue.ini配置文件

```shell
[impala]
server_host=node03
server_port=21050
impala_conf_dir=/etc/impala/conf
```

**3.4、配置hue与mysql的集成**

找到databases 这个选项,将这个选项下面的mysql注释给打开,然后配置mysql即可,大概在1547

```shell
[[[mysql]]]
nice_name="My SQL DB"
engine=mysql
host=node03.hadoop.com
port=3306
user=root
password=123456
```

**3.5、重新启动hue的服务**

cd /export/servers/hue-3.9.0-cdh5.14.0/

build/env/bin/supervisor

**3.6、解决hive以及impala执行权限不足的问题**

在我们hive当中执行任意的查询,只要是需要跑MR的程序,就会报错,发现权限不够的异常,具体详细信息如下:

```shell
INFO : Compiling command(queryId=root_20180625191616_d02efd23-2322-4f3d-9cb3-fc3a06ff4ce0): select count(1) from mystu
INFO : Semantic Analysis Completed
INFO : Returning Hive schema: Schema(fieldSchemas:[FieldSchema(name:_c0, type:bigint, comment:null)], properties:null)
INFO : Completed compiling command(queryId=root_20180625191616_d02efd23-2322-4f3d-9cb3-fc3a06ff4ce0); Time taken: 0.065 seconds
INFO : Concurrency mode is disabled, not creating a lock manager
INFO : Executing command(queryId=root_20180625191616_d02efd23-2322-4f3d-9cb3-fc3a06ff4ce0): select count(1) from mystu
INFO : Query ID = root_20180625191616_d02efd23-2322-4f3d-9cb3-fc3a06ff4ce0
INFO : Total jobs = 1
INFO : Launching Job 1 out of 1
INFO : Starting task [Stage-1:MAPRED] in serial mode
INFO : Number of reduce tasks determined at compile time: 1
INFO : In order to change the average load for a reducer (in bytes):
INFO : set hive.exec.reducers.bytes.per.reducer=<number>
INFO : In order to limit the maximum number of reducers:
INFO : set hive.exec.reducers.max=<number>
INFO : In order to set a constant number of reducers:
INFO : set mapreduce.job.reduces=<number>
ERROR : Job Submission failed with exception 'org.apache.hadoop.security.AccessControlException(Permission denied: user=admin, access=EXECUTE, inode="/tmp":root:supergroup:drwxrwx---
```

我们需要给hdfs上面的几个目录执行权限即可

hdfs dfs -chmod o+x /tmp

hdfs dfs -chmod o+x /tmp/hadoop-yarn

hdfs dfs -chmod o+x /tmp/hadoop-yarn/staging

![](jiqun-images/164.png)

或者我们可以这样执行

hdfs dfs -chmod -R o+x /tmp

可以将/tmp目录下所有的文件及文件夹都赋予权限

继续执行hive的任务就不会报错了

# 大数据组件

## hadoop

启动服务
第一次启动一定要格式化:NameNode在哪台就在哪台做
bin/hdfs namenode -format
-》启动hdfs(在NameNode的机器上执行)
sbin/start-dfs.sh
-》启动yarn(在ResourceManager那台机器上执行)
sbin/start-yarn.sh

**apache hadoop三种架构介绍(standAlone,伪分布,分布式环境介绍以及安装)**

hadoop 文档

http://hadoop.apache.org/docs/

**StandAlone集群搭建**

**第一步:下载apache hadoop并上传到服务器**

下载链接:

http://archive.apache.org/dist/hadoop/common/hadoop-2.7.5/hadoop-2.7.5.tar.gz

解压命令

cd /export/softwares

tar -zxvf hadoop-2.7.5.tar.gz -C ../servers/

![](jiqun-images/1565531349733.png)

**第二步:修改配置文件**

```xml
修改core-site.xml
第一台机器执行以下命令
cd /export/servers/hadoop-2.7.5/etc/hadoop
vim core-site.xml
<configuration>
<property>
<name>fs.default.name</name>
<value>hdfs://192.168.52.100:8020</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/export/servers/hadoop-2.7.5/hadoopDatas/tempDatas</value>
</property>
<!-- 缓冲区大小,实际工作中根据服务器性能动态调整 -->
<property>
<name>io.file.buffer.size</name>
<value>4096</value>
</property>

<!-- 开启hdfs的垃圾桶机制,删除掉的数据可以从垃圾桶中回收,单位分钟 -->
<property>
<name>fs.trash.interval</name>
<value>10080</value>
</property>
</configuration>

修改hdfs-site.xml
第一台机器执行以下命令
cd /export/servers/hadoop-2.7.5/etc/hadoop
vim hdfs-site.xml
<configuration>
<!-- NameNode存储元数据信息的路径,实际工作中,一般先确定磁盘的挂载目录,然后多个目录用,进行分割 -->
<!-- 集群动态上下线
<property>
<name>dfs.hosts</name>
<value>/export/servers/hadoop-2.7.4/etc/hadoop/accept_host</value>
</property>

<property>
<name>dfs.hosts.exclude</name>
<value>/export/servers/hadoop-2.7.4/etc/hadoop/deny_host</value>
</property>
-->

<property>
<name>dfs.namenode.secondary.http-address</name>
<value>hadoop1:50090</value>
</property>

<property>
<name>dfs.namenode.http-address</name>
<value>hadoop01:50070</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:///export/servers/hadoop-2.7.5/hadoopDatas/namenodeDatas,file:///export/servers/hadoop-2.7.5/hadoopDatas/namenodeDatas2</value>
</property>
<!-- 定义dataNode数据存储的节点位置,实际工作中,一般先确定磁盘的挂载目录,然后多个目录用,进行分割 -->
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///export/servers/hadoop-2.7.5/hadoopDatas/datanodeDatas,file:///export/servers/hadoop-2.7.5/hadoopDatas/datanodeDatas2</value>
</property>

<property>
<name>dfs.namenode.edits.dir</name>
<value>file:///export/servers/hadoop-2.7.5/hadoopDatas/nn/edits</value>
</property>

<property>
<name>dfs.namenode.checkpoint.dir</name>
<value>file:///export/servers/hadoop-2.7.5/hadoopDatas/snn/name</value>
</property>
<property>
<name>dfs.namenode.checkpoint.edits.dir</name>
<value>file:///export/servers/hadoop-2.7.5/hadoopDatas/dfs/snn/edits</value>
</property>

<property>
<name>dfs.replication</name>
<value>3</value>
</property>

<property>
<name>dfs.permissions</name>
<value>false</value>
</property>

<property>
<name>dfs.blocksize</name>
<value>134217728</value>
</property>
</configuration>

修改hadoop-env.sh
第一台机器执行以下命令
cd /export/servers/hadoop-2.7.5/etc/hadoop
vim hadoop-env.sh
vim hadoop-env.sh
export JAVA_HOME=/export/servers/jdk1.8.0_141

修改mapred-site.xml
第一台机器执行以下命令
cd /export/servers/hadoop-2.7.5/etc/hadoop
vim mapred-site.xml
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>

<property>
<name>mapreduce.job.ubertask.enable</name>
<value>true</value>
</property>

<property>
<name>mapreduce.jobhistory.address</name>
<value>node01:10020</value>
</property>

<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>node01:19888</value>
</property>
</configuration>

修改yarn-site.xml
第一台机器执行以下命令
cd /export/servers/hadoop-2.7.5/etc/hadoop
vim yarn-site.xml
<configuration>
<property>
<name>yarn.resourcemanager.hostname</name>
<value>node01</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>

<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>604800</value>
</property>
</configuration>

修改mapred-env.sh
第一台机器执行以下命令
cd /export/servers/hadoop-2.7.5/etc/hadoop
vim mapred-env.sh
export JAVA_HOME=/export/servers/jdk1.8.0_141
修改slaves
第一台机器执行以下命令
cd /export/servers/hadoop-2.7.5/etc/hadoop
vim slaves
localhost
```

**第三步:启动集群**

要启动 Hadoop 集群,需要启动 HDFS 和 YARN 两个模块。
注意: 首次启动 HDFS 时,必须对其进行格式化操作。 本质上是一些清理和
准备工作,因为此时的 HDFS 在物理上还是不存在的。
hdfs namenode -format 或者 hadoop namenode –format

启动命令:

创建数据存放文件夹

第一台机器执行以下命令

cd /export/servers/hadoop-2.7.5

mkdir -p /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/tempDatas

mkdir -p /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/namenodeDatas

mkdir -p /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/namenodeDatas2

mkdir -p /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/datanodeDatas

mkdir -p /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/datanodeDatas2

mkdir -p /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/nn/edits

mkdir -p /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/snn/name

mkdir -p /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/dfs/snn/edits

准备启动

第一台机器执行以下命令

cd /export/servers/hadoop-2.6.0-cdh5.14.0/

bin/hdfs namenode -format

sbin/start-dfs.sh

sbin/start-yarn.sh

sbin/mr-jobhistory-daemon.sh start historyserver

三个端口查看界面

[http://node01:50070/explorer.html#/](#/) 查看hdfs

http://node01:8088/cluster 查看yarn集群

http://node01:19888/jobhistory 查看历史完成的任务

**5.2、伪分布式环境搭建(适用于学习测试开发集群模式)**

服务规划

| 服务器IP | 192.168.52.100 | 192.168.52.110 | 192.168.52.120 |
| ----------------- | ----------------- | ----------------- | ----------------- |
| 主机名 | node01.hadoop.com | node02.hadoop.com | node03.hadoop.com |
| NameNode | 是 | 否 | 否 |
| SecondaryNameNode | 是 | 否 | 否 |
| dataNode | 是 | 是 | 是 |
| ResourceManager | 是 | 否 | 否 |
| NodeManager | 是 | 是 | 是 |

```shell
停止单节点集群,删除/export/servers/hadoop-2.7.5/hadoopDatas文件夹,然后重新创建文件夹
第一台机器执行以下命令
cd /export/servers/hadoop-2.7.5
sbin/stop-dfs.sh
sbin/stop-yarn.sh
sbin/mr-jobhistory-daemon.sh stop historyserver

删除hadoopDatas然后重新创建文件夹
rm -rf /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas

重新创建文件夹
mkdir -p /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/tempDatas
mkdir -p /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/namenodeDatas
mkdir -p /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/namenodeDatas2
mkdir -p /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/datanodeDatas
mkdir -p /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/datanodeDatas2
mkdir -p /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/nn/edits
mkdir -p /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/snn/name
mkdir -p /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/dfs/snn/edits

修改slaves文件,然后将安装包发送到其他机器,重新启动集群即可
第一台机器执行以下命令
cd /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop
vim slaves
node01
node02
node03


安装包的分发
第一台机器执行以下命令
cd /export/servers/
scp -r hadoop-2.6.0-cdh5.14.0 node02:$PWD
scp -r hadoop-2.6.0-cdh5.14.0 node03:$PWD


启动集群
第一台机器执行以下命令
cd /export/servers/hadoop-2.6.0-cdh5.14.0
bin/hdfs namenode -format
sbin/start-dfs.sh
sbin/start-yarn.sh
sbin/mr-jobhistory-daemon.sh start historyserver
```

**5.3、分布式环境搭建(适用于工作当中正式环境搭建)**

使用完全分布式,实现namenode高可用,ResourceManager的高可用

集群运行服务规划

| | 192.168.1.100 | 192.168.1.110 | 192.168.1.120 |
| ----------- | ------------- | --------------- | ---------------- |
| zookeeper | zk | zk | zk |
| HDFS | JournalNode | JournalNode | JournalNode |
| NameNode | NameNode | | |
| ZKFC | ZKFC | | |
| DataNode | DataNode | DataNode | |
| YARN | | ResourceManager | ResourceManager |
| NodeManager | NodeManager | NodeManager | |
| MapReduce | | | JobHistoryServer |

**安装包解压**

停止之前的hadoop集群的所有服务,并删除所有机器的hadoop安装包,然后重新解压hadoop压缩包

解压压缩包

第一台机器执行以下命令进行解压

cd /export/softwares

tar -zxvf hadoop-2.7.5.tar.gz -C ../servers/

**配置文件的修改**

**修改core-site.xml**

第一台机器执行以下命令

cd /export/servers/hadoop-2.7.5/etc/hadoop

vim core-site.xml

```xml
<configuration>

<!-- 指定NameNode的HA高可用的zk地址 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>node01:2181,node02:2181,node03:2181</value>
</property>

<!-- 指定HDFS访问的域名地址 -->

<property>

<name>fs.defaultFS</name>
<value>hdfs://ns</value>
</property>

<!-- 临时文件存储目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/export/servers/hadoop-2.7.5/data/tmp</value>

</property>

<!-- 开启hdfs垃圾箱机制,指定垃圾箱中的文件七天之后就彻底删掉 单位为分钟 -->

<property>
<name>fs.trash.interval</name>
<value>10080</value>
</property>
</configuration>
```

**修改hdfs-site.xml**

第一台机器执行以下命令

cd /export/servers/hadoop-2.7.5/etc/hadoop

vim hdfs-site.xml

```xml
<configuration>

<!-- 指定命名空间 -->
<property>
<name>dfs.nameservices</name>
<value>ns</value>
</property>

<!-- 指定该命名空间下的两个机器作为我们的NameNode -->

<property>
<name>dfs.ha.namenodes.ns</name>
<value>nn1,nn2</value>
</property>

<!-- 配置第一台服务器的namenode通信地址 -->

<property>
<name>dfs.namenode.rpc-address.ns.nn1</name>
<value>node01:8020</value>
</property>
<!-- 配置第二台服务器的namenode通信地址 -->

<property>
<name>dfs.namenode.rpc-address.ns.nn2</name>
<value>node02:8020</value>
</property>

<!-- 所有从节点之间相互通信端口地址 -->

<property>
<name>dfs.namenode.servicerpc-address.ns.nn1</name>
<value>node01:8022</value>
</property>

<!-- 所有从节点之间相互通信端口地址 -->

<property>
<name>dfs.namenode.servicerpc-address.ns.nn2</name>
<value>node02:8022</value>
</property>

<!-- 第一台服务器namenode的web访问地址 -->

<property>
<name>dfs.namenode.http-address.ns.nn1</name>
<value>node01:50070</value>
</property>

<!-- 第二台服务器namenode的web访问地址 -->

<property>
<name>dfs.namenode.http-address.ns.nn2</name>
<value>node02:50070</value>
</property>

<!-- journalNode的访问地址,注意这个地址一定要配置 -->

<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://node01:8485;node02:8485;node03:8485/ns1</value>
</property>

<!-- 指定故障自动恢复使用的哪个java类 -->

<property>
<name>dfs.client.failover.proxy.provider.ns</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>

<!-- 故障转移使用的哪种通信机制 -->

<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
</property>

<!-- 指定通信使用的公钥 -->

<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/root/.ssh/id_rsa</value>
</property>

<!-- journalNode数据存放地址 -->

<property>
<name>dfs.journalnode.edits.dir</name>
<value>/export/servers/hadoop-2.7.5/data/dfs/jn</value>
</property>

<!-- 启用自动故障恢复功能 -->

<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>

<!-- namenode产生的文件存放路径 -->

<property>
<name>dfs.namenode.name.dir</name>
<value>file:///export/servers/hadoop-2.7.5/data/dfs/nn/name</value>
</property>

<!-- edits产生的文件存放路径 -->

<property>
<name>dfs.namenode.edits.dir</name>
<value>file:///export/servers/hadoop-2.7.5/data/dfs/nn/edits</value>
</property>

<!-- dataNode文件存放路径 -->

<property>
<name>dfs.datanode.data.dir</name>
<value>file:///export/servers/hadoop-2.7.5/data/dfs/dn</value>
</property>

<!-- 关闭hdfs的文件权限 -->

<property>
<name>dfs.permissions</name>
<value>false</value>
</property>

<!-- 指定block文件块的大小 -->

<property>
<name>dfs.blocksize</name>
<value>134217728</value>
</property>

</configuration>
```

**修改yarn-site.xml,注意node03与node02配置不同**

第一台机器执行以下命令

cd /export/servers/hadoop-2.7.5/etc/hadoop

vim yarn-site.xml

```xml
<configuration>

<!-- Site specific YARN configuration properties -->

<!-- 是否启用日志聚合.应用程序完成后,日志汇总收集每个容器的日志,这些日志移动到文件系统,例如HDFS. -->

<!-- 用户可以通过配置"yarn.nodemanager.remote-app-log-dir"、"yarn.nodemanager.remote-app-log-dir-suffix"来确定日志移动到的位置 -->

<!-- 用户可以通过应用程序时间服务器访问日志 -->


<!-- 启用日志聚合功能,应用程序完成后,收集各个节点的日志到一起便于查看 -->

<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>

<!--开启resource manager HA,默认为false-->

<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>

<!-- 集群的Id,使用该值确保RM不会做为其它集群的active -->

<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>mycluster</value>
</property>

<!--配置resource manager 命名-->

<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>

<!-- 配置第一台机器的resourceManager -->

<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>node03</value>
</property>

<!-- 配置第二台机器的resourceManager -->

<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>node02</value>
</property>

<!-- 配置第一台机器的resourceManager通信地址 -->

<property>
<name>yarn.resourcemanager.address.rm1</name>
<value>node03:8032</value>
</property>
<property>
<name>yarn.resourcemanager.scheduler.address.rm1</name>
<value>node03:8030</value>
</property>
<property>
<name>yarn.resourcemanager.resource-tracker.address.rm1</name>
<value>node03:8031</value>
</property>
<property>
<name>yarn.resourcemanager.admin.address.rm1</name>
<value>node03:8033</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.address.rm1</name>
<value>node03:8088</value>
</property>

<!-- 配置第二台机器的resourceManager通信地址 -->
<property>
<name>yarn.resourcemanager.address.rm2</name>
<value>node02:8032</value>
</property>
<property>
<name>yarn.resourcemanager.scheduler.address.rm2</name>
<value>node02:8030</value>
</property>
<property>
<name>yarn.resourcemanager.resource-tracker.address.rm2</name>
<value>node02:8031</value>
</property>
<property>
<name>yarn.resourcemanager.admin.address.rm2</name>
<value>node02:8033</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.address.rm2</name>
<value>node02:8088</value>
</property>

<!--开启resourcemanager自动恢复功能-->

<property>
<name>yarn.resourcemanager.recovery.enabled</name>
<value>true</value>
</property>

<!--在node1上配置rm1,在node2上配置rm2,注意:一般都喜欢把配置好的文件远程复制到其它机器上,但这个在YARN的另一个机器上一定要修改,其他机器上不配置此项-->
<property>
<name>yarn.resourcemanager.ha.id</name>
<value>rm1</value>
<description>If we want to launch more than one RM in single node, we need this configuration</description>
</property>

<!--用于持久存储的类。尝试开启-->
<property>
<name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
</property>
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>node02:2181,node03:2181,node01:2181</value>
<description>For multiple zk services, separate them with comma</description>
</property>

<!--开启resourcemanager故障自动切换,指定机器-->

<property>
<name>yarn.resourcemanager.ha.automatic-failover.enabled</name>
<value>true</value>
<description>Enable automatic failover; By default, it is enabled only when HA is enabled.</description>
</property>
<property>
<name>yarn.client.failover-proxy-provider</name>
<value>org.apache.hadoop.yarn.client.ConfiguredRMFailoverProxyProvider</value>
</property>

<!-- 允许分配给一个任务最大的CPU核数,默认是8 -->

<property>
<name>yarn.nodemanager.resource.cpu-vcores</name>
<value>4</value>
</property>

<!-- 每个节点可用内存,单位MB -->

<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>512</value>
</property>

<!-- 单个任务可申请最少内存,默认1024MB -->

<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>512</value>
</property>

<!-- 单个任务可申请最大内存,默认8192MB -->

<property>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>512</value>
</property>

<!--多长时间聚合删除一次日志 此处-->

<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>2592000</value><!--30 day-->
</property>

<!--时间在几秒钟内保留用户日志。只适用于如果日志聚合是禁用的-->

<property>
<name>yarn.nodemanager.log.retain-seconds</name>
<value>604800</value><!--7 day-->
</property>

<!--指定文件压缩类型用于压缩汇总日志-->

<property>
<name>yarn.nodemanager.log-aggregation.compression-type</name>
<value>gz</value>
</property>

<!-- nodemanager本地文件存储目录-->

<property>
<name>yarn.nodemanager.local-dirs</name>
<value>/export/servers/hadoop-2.7.5/yarn/local</value>
</property>

<!-- resourceManager 保存最大的任务完成个数 -->

<property>
<name>yarn.resourcemanager.max-completed-applications</name>
<value>1000</value>
</property>

<!-- 逗号隔开的服务列表,列表名称应该只包含a-zA-Z0-9_,不能以数字开始-->

<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>

<!--rm失联后重新链接的时间-->

<property>
<name>yarn.resourcemanager.connect.retry-interval.ms</name>
<value>2000</value>
</property>
</configuration>
```

**修改mapred-site.xml**

cd /export/servers/hadoop-2.7.5/etc/hadoop

vim mapred-site.xml

```xml
<configuration>

<!--指定运行mapreduce的环境是yarn -->

<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>

<!-- MapReduce JobHistory Server IPC host:port -->

<property>
<name>mapreduce.jobhistory.address</name>
<value>node03:10020</value>
</property>

<!-- MapReduce JobHistory Server Web UI host:port -->

<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>node03:19888</value>
</property>

<!-- The directory where MapReduce stores control files.默认 ${hadoop.tmp.dir}/mapred/system -->

<property>
<name>mapreduce.jobtracker.system.dir</name>
<value>/export/servers/hadoop-2.7.5/data/system/jobtracker</value>
</property>

<!-- The amount of memory to request from the scheduler for each map task. 默认 1024-->

<property>
<name>mapreduce.map.memory.mb</name>
<value>1024</value>
</property>
<!-- <property>
<name>mapreduce.map.java.opts</name>
<value>-Xmx1024m</value>
</property> -->

<!-- The amount of memory to request from the scheduler for each reduce task. 默认 1024-->
<property>
<name>mapreduce.reduce.memory.mb</name>
<value>1024</value>
</property>
<!-- <property>
<name>mapreduce.reduce.java.opts</name>
<value>-Xmx2048m</value>
</property> -->

<!-- 用于存储文件的缓存内存的总数量,以兆字节为单位。默认情况下,分配给每个合并流1MB,给个合并流应该寻求最小化。默认值100-->

<property>
<name>mapreduce.task.io.sort.mb</name>
<value>100</value>
</property>
<!-- <property>
<name>mapreduce.jobtracker.handler.count</name>
<value>25</value>
</property>-->
<!-- 整理文件时用于合并的流的数量。这决定了打开的文件句柄的数量。默认值10-->
<property>
<name>mapreduce.task.io.sort.factor</name>
<value>10</value>
</property>

<!-- 默认的并行传输量由reduce在copy(shuffle)阶段。默认值5-->

<property>
<name>mapreduce.reduce.shuffle.parallelcopies</name>
<value>25</value>

</property>
<property>
<name>yarn.app.mapreduce.am.command-opts</name>
<value>-Xmx1024m</value>
</property>

<!-- MR AppMaster所需的内存总量。默认值1536-->

<property>
<name>yarn.app.mapreduce.am.resource.mb</name>
<value>1536</value>
</property>

<!-- MapReduce存储中间数据文件的本地目录。目录不存在则被忽略。默认值${hadoop.tmp.dir}/mapred/local-->

<property>
<name>mapreduce.cluster.local.dir</name>
<value>/export/servers/hadoop-2.7.5/data/system/local</value>
</property>
</configuration>
```

**修改slaves**

第一台机器执行以下命令

cd /export/servers/hadoop-2.7.5/etc/hadoop

vim slaves

```
node01
node02
node03
```

**修改hadoop-env.sh**

第一台机器执行以下命令

```shell
cd /export/servers/hadoop-2.7.5/etc/hadoop

vim hadoop-env.sh

export JAVA_HOME=/export/servers/jdk1.8.0_141
```

**集群启动过程**

将第一台机器的安装包发送到其他机器上

第一台机器执行以下命令:

```shell
cd /export/servers

scp -r hadoop-2.7.5/ node02:$PWD

scp -r hadoop-2.7.5/ node03:$PWD
```

三台机器上共同创建目录

三台机器执行以下命令

```shell
mkdir -p /export/servers/hadoop-2.7.5/data/dfs/nn/name

mkdir -p /export/servers/hadoop-2.7.5/data/dfs/nn/edits

mkdir -p /export/servers/hadoop-2.7.5/data/dfs/nn/name

mkdir -p /export/servers/hadoop-2.7.5/data/dfs/nn/edits
```

更改node02的rm2

第二台机器执行以下命令

cd /export/servers/hadoop-2.7.5/etc/hadoop

vim yarn-site.xml

```xml
<!--在node3上配置rm1,在node2上配置rm2,注意:一般都喜欢把配置好的文件远程复制到其它机器上,

但这个在YARN的另一个机器上一定要修改,其他机器上不配置此项

注意我们现在有两个resourceManager 第三台是rm1 第二台是rm2

这个配置一定要记得去node02上面改好

<property>
<name>yarn.resourcemanager.ha.id</name>
<value>rm2</value>
<description>If we want to launch more than one RM in single node, we need this configuration</description>
</property>


```

**启动HDFS过程**

```shell
node01机器执行以下命令

cd /export/servers/hadoop-2.7.5

bin/hdfs zkfc -formatZK

sbin/hadoop-daemons.sh start journalnode

bin/hdfs namenode -format

bin/hdfs namenode -initializeSharedEdits -force

sbin/start-dfs.sh

node02上面执行

cd /export/servers/hadoop-2.7.5

bin/hdfs namenode -bootstrapStandby

sbin/hadoop-daemon.sh start namenode
```

**启动yarn过程**

```shell
node03上面执行

cd /export/servers/hadoop-2.7.5

sbin/start-yarn.sh

node02上执行

cd /export/servers/hadoop-2.7.5

sbin/start-yarn.sh
```

**查看resourceManager状态**

```shell
node03上面执行

cd /export/servers/hadoop-2.7.5

bin/yarn rmadmin -getServiceState rm1

node02上面执行

cd /export/servers/hadoop-2.7.5

bin/yarn rmadmin -getServiceState rm2
```

**node03启动jobHistory**

```shell
node03机器执行以下命令启动jobHistory

cd /export/servers/hadoop-2.7.5

sbin/mr-jobhistory-daemon.sh start historyserver
```

**hdfs状态查看**

node01机器查看hdfs状态

[http://192.168.52.100:50070/dfshealth.html#tab-overview](#tab-overview)

node02机器查看hdfs状态

[http://192.168.52.110:50070/dfshealth.html#tab-overview](#tab-overview)

**yarn集群访问查看**

http://node03:8088/cluster

**历史任务浏览界面**

页面访问:

http://192.168.52.120:19888/jobhistory

--------------------------------------------------------------------------------------------------

三、hadoop环境的搭建

```shell
-》搭建模式
-》本地模式:MapReduce独立运行(用于测试程序逻辑)
-》伪分布式:1台机器模拟分布式
-》分布式:多台机器
-》搭建Apache的伪分布式环境
-》安装jdk
-》卸载自带的
rpm -qa | grep java
rpm -e --nodeps java-1.7.0-openjdk-1.7.0.231-2.6.19.1.el6_10.x86_64 tzdata-java-2019b-2.el6.noarch java-1.7.0-openjdk-devel-1.7.0.231-2.6.19.1.el6_10.x86_64
-》安装jdk
-》下载解压
下载:名称+版本.tar.gz
-》环境准备:
mkdir -p /export/software 放安装包
mkdir -p /export/servers 安装目录
mkdir -p /export/datas 放临时数据
-》解压:
cd /export/softwares/
tar -zxvf hadoop-2.7.6.tar.gz -C ../servers/
-》认识一下目录
cd /export/servers/hadoop-2.7.6
bin:二进制的客户端命令
etc:存放配置文件
etc/conf
lib:存放jar包的目录
sbin:存放管理类的脚本
启动服务
share:hadoop所有的jar包
-》修改配置
配置环境变量
hadoop-env.sh
mapred-env.sh
yarn-env.sh
修改JAVA_HOME
```

```xml
自定义属性配置
core-site.xml:hadoop的全局属性
<!--配置HDFS的入口地址,即NameNode的地址-->
<property>
<name>fs.defaultFS</name>
<value>hdfs://hpsk.bigdata.com:8020</value>
</property>
<!--配置Hadoop的本地存储位置-->
<property>
<name>hadoop.tmp.dir</name>
<value>/export/servers/hadoop-2.7.6/datas</value>
</property>
hdfs-site.xml:配置hdfs的属性
<!--关闭hdfs的访问权限-->
<property>
<name>dfs.permissions.enabled</name>
<value>false</value>
</property>
<!--修改存储的副本只存一份-->
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
mapred-site.xml:配置MapReduce的属性
mv etc/hadoop/mapred-site.xml.template etc/hadoop/mapred-site.xml
<!--配置MapReduce的运行容器-->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
yarn-site.xml:配置YARN的属性
<!--ResourceManager的地址-->
<property>
<name>yarn.resourcemanager.hostname</name>
<value>hpsk.bigdata.com</value>
</property>
<!--Yarn上运行程序的类型为MapReduce-->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>

slaves:配置哪些机器是从节点
hpsk.bigdata.com

-》启动服务
在第一次启动Hdfs的时候,要格式化
bin/hdfs namenode -format
启动NameNode和DataNode
sbin/hadoop-daemon.sh start namenode
sbin/hadoop-daemon.sh start datanode
启动ResourceManager和NodeManager
sbin/yarn-daemon.sh start resourcemanager
sbin/yarn-daemon.sh start nodemanager
-》测试
http://192.168.134.200:50070 HDFS的webUI http
8020 通信 rpc
http://192.168.134.200:8088 YARN的WebUI
8032 通信 rpc
```

```
-》回顾:
大数据是什么?应用有哪些?
大数据技术架构的业务流程:
数据生成:Java、js、ios
文件
数据库
数据采集
Flume、sqoop、kafka、Logstash、datax
数据存储:数据仓库
HDFS => Hive/Hbase
数据计算
MapReduce、Spark、FLink
数据应用
数据分析
机器学习
NLP
Hadoop的发展以及应用:
HDFS
YARN+Mapreduce
Hadoop中组件架构:主从架构
HDFS:
NameNode
DataNode
YARN
ResourceManager
NodeManager
```

```
-》需要自己根据Hadoop源码进行编译,生成安装包
1-如果你需要修改源码
2-如果你要对工具进行二次开发
3-做一些自定义的环境配置
压缩:snappy、lzo、lz4
```


四、分布式集群

```shell
-》搭建分布式集群
-》硬件环境
实体机
云主机
-》软件环境
-》Linux的配置
1-将三台机器安装好操作系统
2-配置各自的IP、主机名、映射/etc/hosts(每台机器要有所有机器的映射)
192.168.134.221 hpsk.bigdata01.com
192.168.134.222 hpsk.bigdata02.com
192.168.134.223 hpsk.bigdata03.com
3-关闭防火墙和selinux
4-配置所有机器之间的免密钥登录
5-配置所有机器的时间同步
6-配置统一的用户、以及目录
普通用户:hpsk
使用root用户完成以下操作
useradd hpsk
passwd hpsk
visudo:会打开一个文件,该文件中可以配置让普通用户越权执行命令
hpsk ALL=(root) NOPASSWD: ALL
以后如果要越权执行,在命令前面加上sudo
sudo mkdir -p /export/software
sudo mkdir -p /export/servers
sudo mkdir -p /export/datas
sudo chown -R hpsk:hpsk /export/software
sudo chown -R hpsk:hpsk /export/servers
sudo chown -R hpsk:hpsk /export/datas
-》安装Hadoop
集群设计:
node1 node2 node3
DataNode DataNode DataNode
NodeManager NodeManager NodeManager
NameNode NameNode(standby)
ResourceManager(standby) ResourceManager
```

```shell
-》三台机器安装jdk
-》选择任意一台机器安装Hadoop
-》下载解压
tar -zxvf hadoop-2.6.0-cdh5.14.0.tar.gz -C ../servers/
-》修改配置
#-env.sh:配置环境变量
hadoop-env.sh
mapred-env.sh
yarn-env.sh
JAVA_HOME:/export/servers/jdk1.8.0_141
#-site.xml:配置每个组件的属性
core-site.xml
hdfs-site.xml
mapred-site.xml
yarn-site.xml
slaves:所有从节点的地址
hpsk.bigdata01.com
hpsk.bigdata02.com
hpsk.bigdata03.com
-》分发
scp -r hadoop-2.6.0-cdh5.14.0 192.168.134.222:/export/servers/
scp -r hadoop-2.6.0-cdh5.14.0 192.168.134.223:/export/servers/
-》启动服务
第一次启动一定要格式化:NameNode在哪台就在哪台做
bin/hdfs namenode -format
-》启动hdfs(在NameNode的机器上执行)
sbin/start-dfs.sh
-》启动yarn(在ResourceManager那台机器上执行)
sbin/start-yarn.sh
```

```
-》搭建高可用(Zookeeper,来实现两个主节点)
Hadoop集群:单点故障
||
Zookeeper:高可用

HA:高可用
```

```shell
进程:
NameNode:active
NameNode:Standby
zookeeper:奇数台
datanode
zkfc:监控NameNode,并且实现NameNode与Zookeeper进行通信
JournalNode:

-》将当前搭建好的分布式环境,全部关机,保存快照

||
-》安装Zookeeper
-》下载解压
-》修改配置
-》分发
-》启动服务
-》配置Hadoop
三台机器都要创建:
mkdir journalnode
core-site.xml
hdfs-site.xml
yarn-site.xml
-》分发:
scp etc/hadoop/core-site.xml etc/hadoop/hdfs-site.xml etc/hadoop/yarn-site.xml 192.168.134.222:/export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/
scp etc/hadoop/core-site.xml etc/hadoop/hdfs-site.xml etc/hadoop/yarn-site.xml 192.168.134.223:/export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/
记住修改第三台机器的 yarn-site为rm2
删除第一台机器yarn-site.xml中的yarn.resourcemanager.ha.id属性
```

```shell
-》启动过程
-》清空之前格式化的数据
三台机器:rm -rf datas/*
-》启动三台机器的所有的journalnode
sbin/hadoop-daemon.sh start journalnode
-》执行格式化:第一台
bin/hdfs namenode -format
-》将格式化后的数据发送给另外一台
scp -r datas 192.168.134.222:/export/servers/hadoop-2.6.0-cdh5.14.0
-》关联Zookeeper,初始化Zookeeper
bin/hdfs zkfc -formatZK
-》关闭所有journalnode
sbin/hadoop-daemon.sh stop journalnode
-》直接启动hdfs
sbin/start-dfs.sh
```

```
如果搭建集群中出现了错误:
以.log结尾的就是日志
tail -100f logs/
```

## hive

```shell
#1、解压hive

cd /export/softwares

tar -zxvf hive-1.1.0-cdh5.14.0.tar.gz -C ../servers/

#2、 直接启动 bin/hive

cd ../servers/

cd hive-1.1.0-cdh5.14.0/

bin/hive

hive> create database mytest;

#使用mysql共享hive元数据

mysql数据库的安装(使用yum源进行安装,强烈推荐)

#第一步:在线安装mysql相关的软件包

yum install mysql mysql-server mysql-devel

#第二步:启动mysql的服务

/etc/init.d/mysqld start

#第三步:通过mysql安装自带脚本进行设置

/usr/bin/mysql_secure_installation

#第四步:进入mysql的客户端然后进行授权

grant all privileges on *.* to 'root'@'%' identified by '123456' with grant option;

flush privileges;
```

![](jiqun-images/1565530248241.png)

修改hive的配置文件

1.修改hive-env.sh

```shell
#添加我们的hadoop的环境变量

cd /export/servers/hive-1.1.0-cdh5.14.0/conf

cp hive-env.sh.template hive-env.sh

vim hive-env.sh

#添加环境变量

HADOOP_HOME=/export/servers/hadoop-2.6.0-cdh5.14.0

# Hive Configuration Directory can be controlled by:

export HIVE_CONF_DIR=/export/servers/hive-1.1.0-cdh5.14.0/conf
```

2.修改hive-site.xml

. cd /export/servers/hive-1.1.0-cdh5.14.0/conf

. vim hive-site.xml

```xml
<?xml-stylesheet type="text/xsl" href="configuration.xsl".>
<configuration>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://node03.hadoop.com:3306/hive?createDatabaseIfNotExist=true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123456</value>
</property>
<property>
<name>hive.cli.print.current.db</name>
<value>true</value>
</property>
<property>
<name>hive.cli.print.header</name>
<value>true</value>
</property>
<property>
<name>hive.server2.thrift.bind.host</name>
<value>node03.hadoop.com</value>
</property>

<!--
<property>
<name>hive.metastore.uris</name>
<value>thrift://node03.hadoop.com:9083</value>
</property>
-->
</configuration>
```

```shell
上传mysql的lib驱动包

将mysql的lib驱动包上传到hive的lib目录下

cd /export/servers/hive-1.1.0-cdh5.14.0/lib

将mysql-connector-java-5.1.38.jar 上传到这个目录下
```

**2.6.2 使用方式**

**第一种交互方式:Hive交互shell**

```sql
cd /export/servers/hive-1.1.0-cdh5.14.0

bin/hive

查看所有的数据库

hive (default)> show databases;

创建一个数据库

hive (default)> create database myhive;

使用该数据库并创建数据库表

hive (default)> use myhive;

hive (myhive)> create table test(id int,name string);
```

以上命令操作完成之后,一定要确认mysql里面出来一个数据库hive

**第二种交互方式:Hive JDBC服务**

```shell
#启动hiveserver2服务

#前台启动

cd /export/servers/hive-1.1.0-cdh5.14.0

bin/hive --service hiveserver2

#后台启动

cd /export/servers/hive-1.1.0-cdh5.14.0

nohup bin/hive --service hiveserver2 &

#beeline连接hiveserver2

bin/beeline

beeline> !connect jdbc:hive2://node03.hadoop.com:10000
```

![](jiqun-images/1565530678504.png)

注意:如果使用beeline方式连接hiveserver2,一定要保证hive在mysql当中的元数据库已经创建成功,不然就会拒绝连接

**第三种交互方式:Hive命令**

使用 –e 参数来直接执行hql的语句

bin/hive -e "use myhive;select * from test;"

使用 –f 参数通过指定文本文件来执行hql的语句

vim hive.sql

use myhive;select * from test;

bin/hive -f hive.sql

更多参数参考以下

![](jiqun-images/1565530720831.png)

## flume

**第一步:下载解压修改配置文件**

Flume的安装非常简单,只需要解压即可,当然,前提是已有hadoop环境

上传安装包到数据源所在节点上

这里我们采用在第三台机器来进行安装

tar -zxvf flume-ng-1.6.0-cdh5.14.0.tar.gz -C /export/servers/

cd /export/servers/apache-flume-1.6.0-cdh5.14.0-bin/conf

cp flume-env.sh.template flume-env.sh

vim flume-env.sh

export JAVA_HOME=/export/servers/jdk1.8.0_141

**第二步:开发配置文件**

根据数据采集的需求**配置采集方案**,描述在配置文件中(文件名可任意自定义)

配置我们的网络收集的配置文件

在flume的conf目录下新建一个配置文件(采集方案)

vim /export/servers/apache-flume-1.6.0-cdh5.14.0-bin/conf/netcat-logger.conf

# 定义这个agent中各组件的名字

a1.sources = r1

a1.sinks = k1

a1.channels = c1

# 描述和配置source组件:r1

a1.sources.r1.type = netcat

a1.sources.r1.bind = 192.168.52.120

a1.sources.r1.port = 44444

# 描述和配置sink组件:k1

a1.sinks.k1.type = logger

# 描述和配置channel组件,此处使用是内存缓存的方式

a1.channels.c1.type = memory

a1.channels.c1.capacity = 1000

a1.channels.c1.transactionCapacity = 100

# 描述和配置source channel sink之间的连接关系

a1.sources.r1.channels = c1

a1.sinks.k1.channel = c1

**第三步:启动配置文件**

**指定采集方案配置文件**,在相应的节点上启动flume agent

先用一个最简单的例子来测试一下程序环境是否正常

启动agent去采集数据

bin/flume-ng agent -c conf -f conf/netcat-logger.conf -n a1 -Dflume.root.logger=INFO,console

-c conf 指定flume自身的配置文件所在目录

-f conf/netcat-logger.con 指定我们所描述的采集方案

-n a1 指定我们这个agent的名字

**第四步:安装telent准备测试**

在node02机器上面安装telnet客户端,用于模拟数据的发送

yum -y install telnet

telnet node03 44444 # 使用telnet模拟数据发送

![](jiqun-images/1568129979058.png)

![](jiqun-images/1568130053324.png)

```shell
-》安装Flume:不是分布式程序
flume-ng-1.6.0-cdh5.14.0.tar.gz
ng:next
og:orignal
-》下载解压
tar -zxvf flume-ng-1.6.0-cdh5.14.0.tar.gz -C ../servers/
-》修改配置
flume-env.sh
java_home
export HADOOP_HOME=/export/servers/hadoop-2.6.0-cdh5.14.0
1-知道HDFS的地址
a-配置Hadoop_Home
b-将Hadoop的配置文件放入flume conf目录下
core-site.xml hdfs-site.xml【如果配置了HA,需要放】
c-在flume的agent指定hdfs的地址
2-调用Hadoop的jar包
-》开发agent,运行agent
需求:读取Nginx的日志文件,缓存在内存中,发送到日志中
exec memChannel logSink
```
## **Kafka**

**1.准备3台虚拟机**

本机也要加

```properties
192.168.72.141 node01
192.168.72.142 node02
192.168.72.143 node03
```

**2.初始化环境**

1)安装jdk、安装zookeeper

2)安装目录

安装包存放的目录:/export/software

. 安装程序存放的目录:/export/servers

. 数据目录:/export/data

. 日志目录:/export/logs

```properties
mkdir -p /export/servers/
mkdir -p /export/software/
mkdir -p /export/data/
mkdir -p /export/logs/
```

3)安装用户

. 安装hadoop,会创建一个hadoop用户

. 安装kafka,创建一个kafka用户

. 或者 创建bigdata用户,用来安装所有的大数据软件。

. **本例**:**使用root用户**

4)验证环境

a) jdk环境

![](jiqun-images/1544866443419.png)

b) zookeeper环境

![](jiqun-images/1544786940692.png)

**3.搭建Kafka集群**

**3.1.准备安装包**

![](jiqun-images/1544787035414.png)

由于kafka是scala语言编写的,基于scala的多个版本,kafka发布了多个版本。

其中2.11是推荐版本。

**3.2.下载安装包及解压**

```properties
tar -zxvf kafka_2.11-1.0.0.tgz -C /export/servers/
cd /export/servers/
mv kafka_2.11-1.0.0 kafka
```

1)删除之前的安装记录

```properties
rm -rf /export/servers/kafka
rm -rf /export/data/kafka/
```

2)解压文件

```properties
tar -zxvf kafka_2.11-1.0.0.tgz -C /export/servers/
```

3)重命名

```properties
mv kafka_2.11-1.0.0/ kafka
```

**3.3.查看目录及修改配置文件**

**3.3.1查看目录**

![](jiqun-images/1544787057518.png)

**3.3.2修改配置文件**

进入配置目录,查看server.properties文件

cat server.properties |grep -v "#"

![](jiqun-images/1544787073410.png)

通过以上命令,查看到了默认的配置文件,对默认的文件进行修改。

修改三个地方

vi server.properties

1) Borker.id

2) 数据存放的目录,**注意目录如果不存在,需要新建下。**

3) zookeeper的地址信息

```properties
#broker.id 标识了kafka集群中一个唯一broker。
broker.id=0
num.network.threads=3
num.io.threads=8
socket.send.buffer.bytes=102400
socket.receive.buffer.bytes=102400
socket.request.max.bytes=104857600

#存放生产者生产的数据 数据一般以topic的方式存放
log.dirs=/export/data/kafka
num.partitions=1
num.recovery.threads.per.data.dir=1
offsets.topic.replication.factor=1
transaction.state.log.replication.factor=1
transaction.state.log.min.isr=1
log.retention.hours=168
log.segment.bytes=1073741824
log.retention.check.interval.ms=300000

#zk的信息
zookeeper.connect=node01:2181,node02:2181,node03:2181
zookeeper.connection.timeout.ms=6000
group.initial.rebalance.delay.ms=0

#可选配置
delete.topic.enable=true
host.name=192.168.72.141
```

**3.3分发配置文件及修改brokerid**

将修改好的配置文件,分发到node02,node03上。

先在node02、node03上删除以往的安装记录

```properties
# 创建一个数据存放目录 /export/data/kafka
mkdir -p /export/data/kafka
```

分发安装包

```properties
scp -r /export/servers/kafka/ node02:/export/servers/
scp -r /export/servers/kafka/ node03:/export/servers/
```

修改node02上的broker.id

```properties
vi /export/servers/kafka/config/server.properties
```

![](jiqun-images/1544787262549.png)

修改node03上的broker.id

```properties
vi /export/servers/kafka/config/server.properties
```

![](jiqun-images/1544787309119.png)

注意:host.name各个机器也不相同,也需要进行修改

**3.4.启动集群**

```properties
cd /export/servers/kafka/bin
nohup ./kafka-server-start.sh /export/servers/kafka/config/server.properties > /dev/null 2>&1 &

/dev/null 黑洞 不要了
2>&1 将其他级别的日志也输出到黑洞
nohup & 后台启动


输出到文件:
nohup ./kafka-server-start.sh /export/servers/kafka/config/server.properties > /export/logs/kafka/kafka.log 2>&1 &

如果/export/logs/kafka不存在,先创建这个目录,这个目录存放启动后产生的日志
mkdir -p /export/logs/kafka
```

**3.5.查看Kafka集群**

由于kafka集群并没有UI界面可以查看。

需要借助外部工具,来查看kafka的集群

这个工具是一个java程序,必须要安装好JDK

![](jiqun-images/1544787326910.png)

![](jiqun-images/1544787370274.png)

![](jiqun-images/1560493552920.png)

**3.6 自动化启动脚本**

- startKafka.sh

```properties
#!/bin/sh
cat /export/servers/kafka/bin/slave | while read line
do
{
echo $line
ssh $line "source /etc/profile;nohup /export/servers/kafka/bin/kafka-server-start.sh /export/servers/kafka/config/server.properties >/dev/null 2>&1 &"
}&
wait
done
```

- stopKafka.sh

```properties
#!/bin/sh
cat /export/servers/kafka/bin/slave | while read line
do
{
echo $line
ssh $line "source /etc/profile;jps |grep Kafka |cut -c 1-5 |xargs kill -s 9 "
}&
wait
done
```

- slave 存放的位置:/export/servers/kafka/bin/slave

```
node01
node02
node03
```

## Sqoop

**sqoop实战及原理**

** sqoop安装**

安装sqoop的前提是已经具备java和hadoop的环境

**1、下载并解压**

下载地址

http://archive.cloudera.com/cdh5/cdh/5/

sqoop1版本详细下载地址

http://archive.cloudera.com/cdh5/cdh/5/sqoop-1.4.6-cdh5.14.0.tar.gz

sqoop2版本详细下载地址

http://archive.cloudera.com/cdh5/cdh/5/sqoop2-1.99.5-cdh5.14.0.tar.gz

我们这里使用sqoop1的版本,下载之后上传到/export/softwares目录下,然后进行解压

cd /export/softwares

tar -zxvf sqoop-1.4.6-cdh5.14.0.tar.gz -C ../servers/

**2、修改配置文件**

cd /export/servers/sqoop-1.4.6-cdh5.14.0/conf/

cp sqoop-env-template.sh sqoop-env.sh

vim sqoop-env.sh

export HADOOP_COMMON_HOME=/export/servers/hadoop-2.6.0-cdh5.14.0

export HADOOP_MAPRED_HOME=/export/servers/hadoop-2.6.0-cdh5.14.0

export HIVE_HOME=/export/servers/hive-1.1.0-cdh5.14.0

**3、加入额外的依赖包**

sqoop的使用需要添加两个额外的依赖包,一个是mysql的驱动包,一个是java-json的的依赖包,不然就会报错

mysql-connector-java-5.1.40.jar

java-json.jar

![](jiqun-images/129.png)

将这个两个jar包添加到sqoop的lib目录下

**4、验证启动**

cd /export/servers/sqoop-1.4.6-cdh5.14.0

bin/sqoop-version

![](jiqun-images/130.png)

## Impata

**通过本地yum源进行安装impala**

所有cloudera软件下载地址

http://archive.cloudera.com/cdh5/cdh/5/

http://archive.cloudera.com/cdh5/

一、挂载磁盘

```shell
1-手动添加一块硬盘:详细过程参考图片
注意该虚拟硬盘所在的物理硬盘剩余空间至少大于15GB
2-创建分区
fdisk -l 确认出现/dev/sdb该硬盘设备
fdisk /dev/sdb 对sdb硬盘进行分区
p 查看当前硬盘的分区信息
n 创建新分区
p 分区类型为主分区
1 分区号为1
回车 硬盘起始位置,默认为0
回车 硬盘结束位置,默认为最大值
p 查看当前硬盘的分区信息
w 保存并退出
mkfs -t ext4 /dev/sdb1 格式化硬盘分区

3-挂载目录
创建挂载目录:
mkdir /export/users
手动临时挂载:
mount /dev/sdb1 /export/users
验证是否挂载成功:
df -h
永久挂载,开机自动加载:
echo "/dev/sdb1 /export/users ext4 defaults 0 0" >> /etc/fstab
```

二、配置Impala的yum源

```properties
1-上传5G的CDH的RPM包到/export/users目录下
使用secureFX或者Xftp上传,不要使用rz命令上传

2-直接解压在/export/users目录下
tar -zxvf cdh5.14.0-centos6.tar.gz

3-安装http服务实现局域网yum源
在第1台机器上安装http服务,以后所有的安装都直接请求第一台机器
yum -y install httpd
service httpd start
cd /etc/yum.repos.d
vim /etc/yum.repos.d/localimp.repo 编辑该文件,将以下内容放入该文件中

编辑的yum源
[localimp]
name=localimp
baseurl=http://hpsk.bigdata01.com/cdh5.14.0/
gpgcheck=0
enabled=1
将cdh的本地源地址,放入httpd的资源目录下:
ln -s /export/users/cdh/5.14.0 /var/www/html/cdh5.14.0

4-将制作好的yum源的配置文件发送给其他机器
scp /etc/yum.repos.d/localimp.repo 192.168.134.222:/etc/yum.repos.d/
scp /etc/yum.repos.d/localimp.repo 192.168.134.223:/etc/yum.repos.d/
```

三、安装分布式Impala

```properties
1-节点功能:
impala-catalog: 元数据管理
impala-state-store: 主节点
impala-server/Impalad: 从节点

2-节点划分:
服务名称 node01 node02 node03
impala-catalog ★
impala-state-store ★
impala-server ★ ★ ★

3-安装Impala
第二台机器:
yum install impala -y
yum install impala-server -y
yum install impala-state-store -y
yum install impala-catalog -y
yum install impala-shell -y
第一台和第三台机器:
yum install impala-server -y
```

四、配置Hadoop的shortcircuit短路机制
短路:客户端直接获取数据块,不经过DataNode,DataNode只负责提供位置信息

```properties
1-在所有Hadoop节点上创建一下目录:用于保存读取的socket
mkdir -p /var/run/hdfs-sockets

2-在所有DataNode的节点的hdfs-site.xml中添加如下配置
<property>
<name>dfs.client.read.shortcircuit</name>
<value>true</value>
</property>
<property>
<name>dfs.domain.socket.path</name>
<value>/var/run/hdfs-sockets/dn</value>
</property>
<property>
<name>dfs.client.file-block-storage-locations.timeout.millis</name>
<value>10000</value>
</property>
<property>
<name>dfs.datanode.hdfs-blocks-metadata.enabled</name>
<value>true</value>
</property>

3-分发修改完的hdfs-site.xml到所有机器
scp /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/hdfs-site.xml 192.168.134.222:/export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/
scp /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/hdfs-site.xml 192.168.134.223:/export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/

4-启动HDFS集群
cd /export/servers/hadoop-2.6.0-cdh5.14.0/
sbin/start-dfs.sh

检测配置是否生效
more /export/servers/hadoop-2.6.0-cdh5.14.0/logs/hadoop-root-datanode-hpsk.bigdata01.com.log | grep /var/run/hdfs-sockets/
||
结果:
Listening on UNIX domain socket: /var/run/hdfs-sockets/dn



```

五、配置Hive的metastore服务

```properties
1-修改每台机器的hive-site.xml文件,添加metastore服务的配置
<!--配置Hive的MetaStore服务-->
<property>
<name>hive.metastore.uris</name>
<value>thrift://hadoop03:9083</value>
</property>
<property>
<name>hive.metastore.client.socket.timeout</name>
<value>3600</value>
</property>
2-确保每一台机器都有Hive
scp -r /export/servers/hive-1.1.0-cdh5.14.0 192.168.134.221:/export/servers/
scp -r /export/servers/hive-1.1.0-cdh5.14.0 192.168.134.222:/export/servers/

3-在第三台机器启动metastore服务和hiveserver2服务测试
确保mysql已经正常启动
nohup bin/hive --service metastore 2>&1 >>logs/metastore.log &
nohup bin/hiveserver2 2>&1 >>logs/hiveserver.log &

检查端口是否开放:
netstat -atunlp | grep 9083
netstat -atunlp | grep 10000
在任意一台机器上启动beeline连接测试
cd /export/servers/hive-1.1.0-cdh5.14.0/
bin/beeline
!connect jdbc:hive2://hpsk.bigdata03.com:10000
root
123456
show databases;
```

六、配置Impala与Hadoop、Hive的集成

```properties
1-Impala的配置文件目录为/etc/impala/conf
ll /etc/impala/conf/
2-在所有的Impala Server的节点中添加core-site.xml、hdfs-site.xml、hive-site.xml
ln -s /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/core-site.xml /etc/impala/conf/core-site.xml
ln -s /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/hdfs-site.xml /etc/impala/conf/hdfs-site.xml
ln -s /export/servers/hive-1.1.0-cdh5.14.0/conf/hive-site.xml /etc/impala/conf/hive-site.xml
```

七、修改Impala自身配置

```properties
1-修改每台Impala节点的配置文件
vim /etc/default/impala
IMPALA_CATALOG_SERVICE_HOST=hpsk.bigdata02.com
IMPALA_STATE_STORE_HOST=hpsk.bigdata02.com

2-为每台Impala节点添加MySQL的jdbc驱动包
ln -s /export/servers/hive-1.1.0-cdh5.14.0/lib/mysql-connector-java-5.1.38.jar /usr/share/java/mysql-connector-java.jar
检查:
ll /usr/share/java/mysql-connector-java.jar

3-修改每台Impala节点的bigtop文件的JAVA_HOME
vim /etc/default/bigtop-utils
export JAVA_HOME=/export/servers/jdk1.8.0_141
```


八、启动Impala服务

```properties
第二台机器启动三个服务:
service impala-state-store start
service impala-catalog start
service impala-server start
第一台和第三台机器启动一个服务:
service impala-server start
查看进程:ps -ef | grep impala

查看web端:
访问impalad的管理界面
http://hpsk.bigdata02.com:25000/
访问statestored的管理界面
http://hpsk.bigdata02.com:25010/
```

**安装 Impala**

以前面配置好的CDH 5.14.0本地源对Impala进行安装部署使用。

前提条件
安装好Hadoop、Hive、MySQL
Hadoop:node1主节点,其他为从节点
Hive:node1
MySQL:node1
配置好本地yum源
Hadoop 本地库配置
Hadoop 框架需要支持C程序访问接口,查看下图,如果有该路径下有这么些文件,就
证明支持C接口

![1568260738236](jiqun-images/1568260738236.png)

使用Hadoop自带工具类检查支持的native库

![1568260754294](jiqun-images/1568260754294.png)

安装规划

![1568260851077](jiqun-images/1568260851077.png)

主节点cdh01执行以下命令进行安装

```shell
yum install impala impala-server impala-state-store impala-catalog impala-
shell bigtop-utils -y
# 备注:安装的时间较长
```

从节点cdh02和cdh03上安装以下服务

```shell
yum install impala impala-server impala-shell bigtop-utils -y
#备注:安装时间较长
```

**配置Impala**

![1568260950999](jiqun-images/1568260950999.png)

备注:

```
bigtop(CDH):统一管理hadoop以及相关组件之间的依赖关系的组件
```

1)、修改hive-site.xml文件(cdh01)
Impala依赖于Hive,所以首先需要进行Hive的配置修改;
cdh01机器修改 hive-site.xml 内容如下:
vim /export/servers/hive/conf/hive-site.xml

```xml
<configuration>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://node1:3306/hive?
createDatabaseIfNotExist=true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123456</value>
</property>
<property>
<name>hive.cli.print.current.db</name>
<value>true</value>
</property>
<property>
<name>hive.cli.print.header</name>
<value>true</value>
</property>
<property>
<name>hive.server2.thrift.bind.host</name>
<value>node3</value>
</property>
<property>
<name>hive.metastore.uris</name>
<value>thrift://node1:9083</value>
</property>
<property>
<name>hive.metastore.client.socket.timeout</name>
<value>3600</value>
</property>
</configuration>
```

2)添加mysql的jar包放入hive的lib目录下

![1568261044091](jiqun-images/1568261044091.png)

3)、将hive的安装包发送到cdh02与cdh03上(如果其他节点安装Hive)

在cdh01上执行命令

```properties
cd /export/servers/
scp -r hive-1.1.0-cdh5.14.0/ node2:$PWD
scp -r hive-1.1.0-cdh5.14.0/ node3:$PWD
```

备注:集群中可以只在一个节点安装Hive。如果只有一个节点安装Hive,这步可省略

4)、启动hive的metastore服务

在cdh01上启动hive的metastore服务

```properties
cd /export/servers/hive
nohup bin/hive --service metastore &
```

注意:一定要保证mysql的服务正常启动,否则metastore的服务不能够启动
启动MetaStore服务脚本 metastore-start.sh :

```shell
#!/bin/sh
HIVE_HOME=/export/servers/hive
## 启动服务的时间
DATE_STR=`/bin/date '+%Y%m%d%H%M%S'`
# 日志文件名称(包含存储路径)
HIVE_SERVER2_LOG=${HIVE_HOME}/hivemetastore-${DATE_STR}.log
## 启动服务
/usr/bin/nohup ${HIVE_HOME}/bin/hive --service metastore >
${HIVE_SERVER2_LOG} 2>&1 &
```

![1568261259020](jiqun-images/1568261259020.png)

5)、所有Hadoop节点修改hdfs-site.xml添加以下内容
所有节点创建文件夹
mkdir -p /var/run/hdfs-sockets
修改所有节点的 hdfs-site.xml 添加以下配置,修改完之后重启hdfs集群生效 vim
/export/servers/hadoop/etc/hadoop/hdfs-site.xml

```xml
<!-- impala的优化 -->
<property>
<!-- 短路读取,就是允许impala把一些信息存储在本地磁盘上,可以加快计算的
速度 -->
<name>dfs.client.read.shortcircuit</name>
<value>true</value>
</property>
<property>
<name>dfs.domain.socket.path</name>
<value>/var/run/hdfs-sockets/dn</value>
<!--Datanode和DFSClient之间沟通的Socket的本地路径套接口文件-->
</property>
<!--打开”块位置的存储的元数据信息”-->
<property>
<name>dfs.datanode.hdfs-blocks-metadata.enabled</name>
<value>true</value>
</property>
<property>
<name>dfs.client.file-block-storage-
locations.timeout.millis</name>
<value>10000</value>
</property>
```

同步配置文件到所有HDFS集群

```properties
cd /export/servers/hadoop/etc/hadoop
scp -r hdfs-site.xml bigdata-cdh02.itcast.cn:$PWD
scp -r hdfs-site.xml bigdata-cdh03.itcast.cn:$PWD
```

备注:

当在Impala上执行查询的时候,会到多个datanode上分布式地读取block数据,如果
Impala拥有更多的block信息,将会更高效的获取数据并处理。
Short-circuit read意味着会从datanode的本地文件系统直接读取数据,而不用首先与
datanode进行通信,这肯定会提高性能。

6)、重启hdfs

在Hadoop集群的主节点cdh01上执行

```properties
sh hdfs-stop-cluster.sh
sh hdfs-start-cluster.sh
```

7)、创建Hadoop与Hive的配置文件的连接
Impala的配置目录为 /etc/impala/conf
这个路径下面需要把 core-site.xml,hdfs-site.xml以及hive-site.xml 拷贝到这里
来,使用软连接的方式。【将Hadoop、Hive的配置告诉 Impala】
cdh01、cdh02、cdh03上执行以下命令创建链接到Impala配置目录下来

```shell
ln -s /export/servers/hadoop/etc/hadoop/core-site.xml
/etc/impala/conf/core-site.xml
ln -s /export/servers/hadoop/etc/hadoop/hdfs-site.xml
/etc/impala/conf/hdfs-site.xml
ln -s /export/servers/hive/conf/hive-site.xml /etc/impala/conf/hive-
site.xml
```

8)、所有节点修改impala默认配置

vim /etc/default/impala

```properties
#指定集群的CATALOG_SERVICE和STATE_STORE服务地址
IMPALA_CATALOG_SERVICE_HOST=bigdata-cdh01.itcast.cn
IMPALA_STATE_STORE_HOST=bigdata-cdh01.itcast.cn
```

Impala配置文件 /etc/default/impala 中内容

```shell
IMPALA_CATALOG_SERVICE_HOST=bigdata-cdh01.itcast.cn
IMPALA_STATE_STORE_HOST=bigdata-cdh01.itcast.cn
IMPALA_STATE_STORE_PORT=24000
IMPALA_BACKEND_PORT=22000
IMPALA_LOG_DIR=/var/log/impala
IMPALA_CATALOG_ARGS=" -log_dir=${IMPALA_LOG_DIR} "
IMPALA_STATE_STORE_ARGS=" -log_dir=${IMPALA_LOG_DIR} -
state_store_port=${IMPALA_STATE_STORE_PORT}"
IMPALA_SERVER_ARGS="
-log_dir=${IMPALA_LOG_DIR}
-catalog_service_host=${IMPALA_CATALOG_SERVICE_HOST}
-state_store_port=${IMPALA_STATE_STORE_PORT}
-use_statestore
-state_store_host=${IMPALA_STATE_STORE_HOST}
-be_port=${IMPALA_BACKEND_PORT}"
ENABLE_CORE_DUMPS=false
# LIBHDFS_OPTS=-Djava.library.path=/usr/lib/impala/lib
# MYSQL_CONNECTOR_JAR=/usr/share/java/mysql-connector-java.jar
# IMPALA_BIN=/usr/lib/impala/sbin
# IMPALA_HOME=/usr/lib/impala
# HIVE_HOME=/usr/lib/hive
# HBASE_HOME=/usr/lib/hbase
# IMPALA_CONF_DIR=/etc/impala/conf
# HADOOP_CONF_DIR=/etc/impala/conf
# HIVE_CONF_DIR=/etc/impala/conf
# HBASE_CONF_DIR=/etc/impala/conf
```

9)、node1 创建mysql的驱动包的软连接

```
ln -s /export/servers/hive/lib/mysql-connector-java-5.1.27-bin.jar
/usr/share/java/mysql-connector-java.jar
```

备注:
需要启动 hive metastore 服务的节点,要执行此步;
/usr/share/java 目录不存在的,需要手工创建

10)、所有节点修改bigtop的java路径
修改bigtop的java_home路径
vim /etc/default/bigtop-utils

```
export JAVA_HOME=/export/servers/jdk
```

11)、启动impala服务

在主节点node1启动以下三个服务进程

```properties
service impala-state-store start
service impala-catalog start
service impala-server start
```

在从节点node2和node3上启动impala-server

```
service impala-server start
```

查看impala进程是否存在

```
ps -ef | grep impala
```

![1568261821749](jiqun-images/1568261821749.png)

注意:启动之后所有关于impala的日志默认都在 /var/log/impala 这个路径下,cdh01机器
上面应该有三个进程,cdh02与cdh03机器上面只有一个进程,如果进程个数不对,去对应目
录下查看报错日志

**一键服务脚本**

```shell
# 启动服务脚本
vim start-impala-kudu.sh
# -----------------------------------------------------------
#!/bin/sh
for host in 01 02 03
do
echo "bigdata-cdh${host}.itcast.cn is starting......"
ssh bigdata-cdh${host}.itcast.cn "service kudu-master start; service
kudu-tserver start"
ssh bigdata-cdh${host}.itcast.cn service impala-server start
echo ""
done
ssh bigdata-cdh01.itcast.cn service impala-catalog start
ssh bigdata-cdh01.itcast.cn service impala-state-store start
# -----------------------------------------------------------
chmod +x start-impala-kudu.sh
# 停止服务脚本
vim stop-impala-kudu.sh
# -----------------------------------------------------------
#!/bin/sh
for host in node1 node2 node3
do
echo "bigdata-cdh${host}.itcast.cn is stop"
ssh bigdata-cdh${host}.itcast.cn "service kudu-master stop; service kudu-
tserver stop"
ssh bigdata-cdh${host}.itcast.cn service impala-server stop
echo ""
done
ssh bigdata-cdh01.itcast.cn service impala-catalog stop
ssh bigdata-cdh01.itcast.cn service impala-state-store stop
# -----------------------------------------------------------
chmod +x stop-impala-kudu.sh
# 服务状态监测脚本
vim status-impala-kudu.sh
# -----------------------------------------------------------
#!/bin/sh
for host in node1 node2 node3
do
echo "check bigdata-cdh${host}.itcast.cn server"
ssh bigdata-cdh${host}.itcast.cn "service kudu-master status; service
kudu-tserver status"
ssh bigdata-cdh${host}.itcast.cn service impala-server status
echo ""
done
ssh bigdata-cdh01.itcast.cn service impala-catalog status
ssh bigdata-cdh01.itcast.cn service impala-state-store status
# -----------------------------------------------------------
chmod +x status-impala-kudu.sh
# 重启服务脚本
vim restart-impala-kudu.sh
# -----------------------------------------------------------
#!/bin/sh
for host in node1 node2 node3
do
echo "bigdata-cdh${host}.itcast.cn is Restarting"
ssh bigdata-cdh${host}.itcast.cn "service kudu-master restart; service
kudu-tserver restart"
ssh bigdata-cdh${host}.itcast.cn service impala-server restart
echo ""
done
ssh bigdata-cdh01.itcast.cn service impala-catalog restart
ssh bigdata-cdh01.itcast.cn service impala-state-store restart
# -----------------------------------------------------------
chmod +x restart-impala-kudu.sh
```

12)、浏览器页面访问

web访问端口

```
- impalad 25000
- statestored 25010
- catalogd 25020
```

访问impalad的管理界面http://bigdata-cdh01.itcast.cn:25000/

访问statestored的管理界面http://bigdata-cdh01.itcast.cn:25010

访问catalogd 的管理界面http://bigdata-cdh01.itcast.cn:25020

进入交互式命令行:

```shell
[root@bigdata-cdh01 kudu]# impala-shell
Starting Impala Shell without Kerberos authentication
Connected to bigdata-cdh01.itcast.cn:21000
Server version: impalad version 2.11.0-cdh5.14.0 RELEASE (build
d68206561bce6b26762d62c01a78e6cd27aa7690)
***************************************************************************
********
Welcome to the Impala shell.
(Impala Shell v2.11.0-cdh5.14.0 (d682065) built on Sat Jan 6 13:27:16 PST
2018)
To see a summary of a query's progress that updates in real-time, run 'set
LIVE_PROGRESS=1;'.
***************************************************************************
********
[bigdata-cdh01.itcast.cn:21000] >
```

![1568261972274](jiqun-images/1568261972274.png)

测试SQL语句执行:

```
select * from emp ;
select * from dept ;
select e.ename, e.sal, d.dname from emp e join dept d on e.deptno =
d.deptno ;
```

**Impala与Kudu整合**

在每一个服务器的impala的配置文件中添加如下配置:
vim /etc/default/impala

```shell
# 在IMPALA_SERVER_ARGS下添加:
-kudu_master_hosts=bigdata-cdh01.itcast.cn:7051,bigdata-
cdh02.itcast.cn:7051,bigdata-cdh03.itcast.cn:7051
```

![1568262050064](jiqun-images/1568262050064.png)

```
impala的安装路径: /usr/lib/impala impala的服务配置主文件: /etc/default/impala
impala的配置文件: /etc/impala/conf impala的日志: /var/log/impala
```

![1568262169211](jiqun-images/1568262169211.png)

## kudu

**1、软件安装方式**

Linux下常见的软件安装方式:二进制文件安装、rpm、yum

i、二进制包

![1568257901491](jiqun-images/1568257901491.png)

二进制包里面包括了已经经过编译,可以马上运行的程序;
只需要下载和解包(安装)、配置,就马上可以使用;
缺点:对环境依赖大;

ii、rpm
早期被称为RedHat Package Manager,但由于目前RPM非常流行,且已经成为Linux工业
标准。所以RPM现在又被称为RPM is Package Manager;
RPM的功能:打包、安装、查询、升级、卸载、校验等功能;
RPM包并不是跨平台的。RedHat的RPM包与SUSE的RPM包不能混用。RedHat的安装,初
始软件也都是使用RPM包进行安装的;
RPM的缺点:程序与程序之间存在非常复杂的依赖关系,RPM无法解决软件包的依赖关
系;
iii、Yum
YUM被称为 Yellow dog Updater Modified;
YUM使用Python语言编写,对 RPM 包进行管理;
可以通过HTTP服务器下载、FTP服务器下载、本地文件的等方式获得软件包;
可以从指定的服务器自动下载RPM包并且安装;
可以自动处理依赖性关系;
yum的主配置文件(一般不改动):/etc/yum.conf

```shell
main]
#RPM包的缓存位置
cachedir=/var/cache/yum/$basearch/$releasever
#RPM包在本地是否需要长期保存。1表示yes,0表示no
keepcache=0
#日志级别
debuglevel=2
#日志文件位置
logfile=/var/log/yum.log
#下载的RPM包是否需要与本地平台完全匹配。1表示yes,0表示no
exactarch=1
obsoletes=1
#是否需要自动来源合法性检测
gpgcheck=1
plugins=1
installonly_limit=5
bugtracker_url=http://bugs.centos.org/set_project.php?
project_id=19&ref=http://bugs.cen
tos.org/bug_report_page.php?category=yum
distroverpkg=centos-release
```

YUM的片段配置:/etc/yum.repos.d/*.repo

```shell
cd /etc/yum.repos.d/
ls
# 有以下文件,仅有CentOS-Base.repo文件有效。文件中有 enabled=0 表示不生效
CentOS-Base.repo
CentOS-Debuginfo.repo
CentOS-fasttrack.repo
CentOS-Media.repo
CentOS-Vault.repo
#配置文件中重要的字段:
# [ ... ]:仓库的名称。不能重复;
# name:对仓库的描述,该项必须有;
# baseurl:配置仓库的路径。用于指定一个url;
# mirrorlist:指向一个镜像列表,里面有多个url;
# enabled:是否启用当前仓库。值为1或0,默认为1;
# gpgcheck:是否需要gpg校验。值为1或0,默认为1;
```

可以自定义yum的配置

1、自定义CentOS-Base.repo【3个节点都要改】
在 CentOS-Base.repo 中指定从 mirrorlist.centos.org 去下载相关的 rpm 包,速度慢;
这里改为从阿里云下载相关的 rpm 包。

```shell
# 第一步将原来的 CentOS-Base.repo 文件备份
mv CentOS-Base.repo CentOS-Base.repo.bak
# 下载并重命名文件(注意这里设置的 CentOS6 )
wget -O /etc/yum.repos.d/CentOS-Base.repo
http://mirrors.aliyun.com/repo/Centos-6.repo
```

2、自定义localimp.repo(指定从Http服务下载 rpm )【3个节点都要改】

```shell
cd /etc/yum.repos.d/
vi localimp.repo
# 以下为文件内容
[localimp]
name=localimp
baseurl=http://bigdata-cdh01.itcast.cn/cdh5.14.0
gpgcheck=0
enabled=1
# 清理yum缓存,并生成新的缓存
yum clean all
yum makecache
# 备注:gpkcheck=0 表示对从这个源下载的rpm包不进行校验
```

yum的常用命令

```shell
# 清空本地yum的缓存
yum clean all
# 在本地建立缓存
yum makecache
# 安装软件包
yum [-y] install 包1 包2 包3 ...
# 卸载软件包
yum remover 包1 包2 包3 ...
```

**2、节点规划**

| 节点 | kudu-master | kudu-tserver |
| ---- | ----------- | ------------ |
| 01 | yes | yes |
| 02 | yes | yes |
| 03 | yes | yes |

**3、配置本地的CDH-yum源**

![1568258322393](jiqun-images/1568258322393.png)

备注:要下载少量的软件包,需要网络支持,虚拟机要能联网

1)、 配置本地Yum的Repository

![1568258408873](jiqun-images/1568258408873.png)

备注:这里选择在 cdh01 上操作

```properties
所有cloudera软件下载地址:
http://archive.cloudera.com/cdh5/
访问:http://archive.cloudera.com/cdh5/repo-as-tarball/5.14.0/cdh5.14.0-
centos6.tar.gz
下载cdh5.14.0-centos6.tar.gz文件,大小约5G左右。
```

2)、上传压缩包并解压

软件位置:cdh01; /export/servers/cdh5.14.0-centos6.tar.gz

```shell
# 把5个G的压缩文件上传其中某一台服务器,这里上传到“node1”上并进行解压。
#(这里需要确保服务器的磁盘空间是充足的,如果磁盘容量不够,就需要扩容,增大磁盘的容量,具
体操作可以参考:
# https://www.cnblogs.com/bitter-first-sweet-last/p/6638634.html)
tar -zxvf cdh5.14.0-centos6.tar.gz -C /export/servers
```

![1568258483342](jiqun-images/1568258483342.png)

3)、 创建apache httpd的读取连接

【在node1上执行即可]

```shell
# 创建软链接
ln -s /export/servers/cdh/5.14.0 /var/www/html/cdh5.14.0
# 删除软链接
cd /var/www/html/
rm ./cdh5.14.0
```

页面访问本地yum源,出现这个界面表示本地yum源制作成功 访问http://bigdata-cdh01.itcas
t.cn/cdh5.14.0
备注:3个节点都需要能通过 web 方式访问

```shell
访问异常:You don't have permission to access /cdh5.14.0/ on this server
需要关闭Selinux服务
(1)临时关闭
执行命令:setenforce 0
(2) 永久关闭
vim /etc/sysconfig/selinux
SELINUX=enforcing 改为 SELINUX=disabled
重启服务reboot
```

![1568258575560](jiqun-images/1568258575560.png)

4)、 制作本地yum源

```shell
# 镜像源是centos当中下载相关软件的地址,可以通过制作镜像源来指定yum去哪里下载kudu的rpm
包;
# 这里我们使用httpd作为服务端,启动httpd的服务来作为镜像源的下载地址;
# 这里用第三台机器作为镜像源的服务端。在node1机器上执行以下命令:
yum -y install httpd
service httpd start
# 备注:以上操作在node1上完成即可!
# 创建文件【3个节点都需完成】
cd /etc/yum.repos.d
vim localimp.repo
# 以下为文件内容
[localimp]
name=localimp
baseurl=http://bigdata-cdh01.itcast.cn/cdh5.14.0
gpgcheck=0
enabled=1
```

将node1上制作好的localimp配置文件发放到所有需要kudu的节点上去

```shell
/etc/yum.repos.d
scp -r localimp.repo bigdata-cdh02.itcast.cn:$PWD
scp -r localimp.repo bigdata-cdh03.itcast.cn:$PWD
```

备注:
保证cdh01上httpd服务时启动的
保证在所有节点上,使用浏览器可以访问 http://bigdata-cdh01.itcast.cn/cdh5.14.0/

4、 安装 Kudu

备注:在所有节点上操作
使用yum命令,在不同的服务器下载对应的服务

| 服务<br/>器 | 安装命令 |
| ----------- | ------------------------------------------------------------ |
| 01 | yum install -y kudu kudu-master kudu-tserver kudu-client0 kudu-client-<br/>devel |
| 02 | yum install -y kudu kudu-master kudu-tserver kudu-client0 kudu-client-<br/>devel |
| 03 | yum install -y kudu kudu-master kudu-tserver kudu-client0 kudu-client-<br/>devel |

命令说明:

```shell
yum install kudu # Kudu的基本包
yum install kudu-master # KuduMaster
yum install kudu-tserver # KuduTserver
yum install kudu-client0 #Kudu C++客户端共享库
yum install kudu-client-devel # Kudu C++客户端共享库 SDK
```

安装方式:yum
软件存放路径:/usr/lib/kudu
配置文件路径:/etc/kudu/conf/
缺省配置路径:/etc/default/
系统日志存放路径:/var/log/kudu/
配置数据目录:
数据日志与数据存放路径:/export/servers/kudu

**4、配置 Kudu服务**
备注:在所有节点上操作
安装完成后, 需在所有节点 /etc/kudu/conf 目录有两个文件: master.gflagfile 和
tserver.gflagfile 。
修改 master.gflagfile (修改日志、数据存放位置、添加主机地址)

```shell
# cat /etc/kudu/conf/master.gflagfile
# Do not modify these two lines. If you wish to change these variables,
# modify them in /etc/default/kudu-master.
--fromenv=rpc_bind_addresses
--fromenv=log_dir
# 修改原参数,添加最后一个参数
--fs_wal_dir=/export/servers/kudu/master/wal
--fs_data_dirs=/export/servers/kudu/master/data
--master_addresses=bigdata-cdh01.itcast.cn:7051,bigdata-
cdh02.itcast.cn:7051,bigdata-cdh03.itcast.cn:7051
```

修改 tserver.gflagfile (修改日志、数据存放位置、添加主机地址)

```shell
# Do not modify these two lines. If you wish to change these variables,
# modify them in /etc/default/kudu-tserver.
--fromenv=rpc_bind_addresses
--fromenv=log_dir
# 修改原参数,添加最后一个参数
--fs_wal_dir=/export/servers/kudu/tserver/wal
--fs_data_dirs=/export/servers/kudu/tserver/data
--tserver_master_addrs=bigdata-cdh01.itcast.cn:7051,bigdata-
cdh02.itcast.cn:7051,bigdata-cdh03.itcast.cn:7051
```

修改 /etc/default/kudu-master

```shell
# 这一行没有变,指定了日志的位置
export FLAGS_log_dir=/var/log/kudu
#每台机器的master地址要与主机名一致,这里是在node1上
export FLAGS_rpc_bind_addresses=bigdata-cdh01.itcast.cn:7051
```

修改 /etc/default/kudu-tserver

```shell
# 这一行没有变,指定了日志的位置
export FLAGS_log_dir=/var/log/kudu
#每台机器的tserver地址要与主机名一致,这里是在node1上
export FLAGS_rpc_bind_addresses=bigdata-cdh01.itcast.cn:7050
```

创建目录,更改宿主(所有节点)

```shell
mkdir -p /export/servers/kudu/master
mkdir -p /export/servers/kudu/tserver
#kudu默认用户是kudu,需要将/export/servers/kudu权限修改成kudu
chown -R kudu:kudu /export/servers/kudu/
```

附录Master与TServer相关配置:
Configuring the Kudu Master
https://kudu.apache.org/docs/configuration.html#_configuring_the_kudu_master
https://kudu.apache.org/docs/configuration_reference.html#kudu-master_supported

Configuring Tablet Servers
https://kudu.apache.org/docs/configuration.html#_configuring_tablet_servers
https://kudu.apache.org/docs/configuration_reference.html#kudu-tserver_supported

**6、Kudu集群启动关闭**
备注:操作在所有节点上操作
1)、启动 Kudu
1、启动的时候要注意时间同步
安装ntp服务
yum -y install ntp
设置开机启动
service ntpd start
chkconfig ntpd on
可以在每台服务器执行
/etc/init.d/ntpd restart
**备注:kudu非常依赖ntp,ntp没启动或不正常,kudu都无法启动。启动kudu之前一定先检查ntp的状态。**

```shell
# 监测nptd状态
$ ntptime
ntp_gettime() returns code 0 (OK)
time e0e0df2b.4940cc60 Tue, Jul 23 2019 9:19:39.286, (.286145635),
maximum error 33885 us, estimated error 0 us, TAI offset 0
ntp_adjtime() returns code 0 (OK)
modes 0x0 (),
offset 0.000 us, frequency 0.000 ppm, interval 1 s,
maximum error 33885 us, estimated error 0 us,
status 0x2001 (PLL,NANO),
time constant 10, precision 0.001 us, tolerance 500 ppm,
# 查看配置时间同步服务器状态
$ ntpstat
synchronised to local net at stratum 11
time correct to within 11 ms
polling server every 1024 s
#
$ ntpq -pn
remote refid st t when poll reach delay offset
jitter
========================================================================
======
192.168.59.140 .INIT. 16 u - 1024 0 0.000 0.000
0.000
*127.127.1.0 .LOCL. 10 l 52 64 377 0.000 0.000
0.000
```

2、启动命令
在每台服务器上都执行下面脚本

```shell
service kudu-master start
service kudu-tserver start
或者
sudo service kudu-master start
sudo service kudu-tserver start
```

2)、关闭 Kudu

. 1、关闭命令
. 在每台服务器上都执行下面脚本

```shell
service kudu-master stop
service kudu-tserver stop
或者
sudo service kudu-master stop
sudo service kudu-tserver stop
```

3)、一键服务脚本

```shell
# 启动服务脚本
vi start-kudu.sh
# --------------------------------------------------
#!/bin/sh
for host in 01 02 03
do
echo "bigdata-cdh$host.itcast.cn is running"
ssh bigdata-cdh$host.itcast.cn "service kudu-master start; service kudu-
tserver start"
echo "
done
# --------------------------------------------------
chmod +x start-kudu.sh
# 停止服务脚本
vi stop-kudu.sh
# --------------------------------------------------
#!/bin/sh
for host in 01 02 03
do
echo "bigdata-cdh$host.itcast.cn is stop"
ssh bigdata-cdh$host.itcast.cn "service kudu-master stop; service kudu-
tserver stop"
echo ""
done
# --------------------------------------------------
chmod +x stop-kudu.sh
# 服务状态监测脚本
vi status-kudu.sh
# --------------------------------------------------
#!/bin/sh
for host in 01 02 03
do
echo "check bigdata-cdh$host.itcast.cn server"
ssh bigdata-cdh$host.itcast.cn "service kudu-master status; service
kudu-tserver status"
echo ""
done
# --------------------------------------------------
chmod +x status-kudu.sh
# 重启服务脚本
vi restart-kudu.sh
# --------------------------------------------------
#!/bin/sh
for host in 01 02 03
do
echo "bigdata-cdh$host.itcast.cn is Restarting"
ssh bigdata-cdh$host.itcast.cn "service kudu-master restart; service
kudu-tserver restart"
echo ""
done
# --------------------------------------------------
chmod +x restart-kudu.sh
```

**7、安装过成中可能出现的问题**

官方文档:https://kudu.apache.org/docs/troubleshooting.html
1、给用户添加sudo权限的时候报错

```shell
sudo: /etc/sudoers is world writable
解决方式:pkexec chmod 555 /etc/sudoers
```

. 2、启动kudu的时候报错

```shell
Failed to start Kudu Master Server. Return value: 1 [FAILED]
去日志文件中查看:
错误:F0810 09:04:08.354552 4866 master_main.cc:68] Check failed: _s.ok()
Bad status:
Service unavailable: Cannot initialize clock: Error reading clock. Clock
considered
unsynchronized
解决:
第一步:首先检查是否有安装ntp:如果没有安装则使用以下命令安装:
yum -y install ntp
第二步:设置随机启动:
service ntpd start
chkconfig ntpd on
第三步: 添加计划任务
crontab -e
*/1 * * * * /usr/sbin/ntpdate ntp4.aliyun.com
# 查看计划任务
crontab -l
备注:ntp的配置文件 /etc/ntp.conf
上面的方式比较简单,让每个节点与阿里的时间服务器同步时间。缺点是:要求虚拟机都能上网,
对网络依赖高。
也可以设置为:在局域网内做时间同步,减少网络依赖。可参考:
https://blog.csdn.net/xcg132566/article/details/86521815
```

3、启动过程中报错

```properties
F0810 21:31:12.620932 20143 master_main.cc:71] Check failed: _s.ok() Bad
status:
Invalid argument: Unable to initialize catalog manager: Failed to
initialize sys tables
async: on-disk master list
解决:
(1):停掉master和tserver
(2):删除掉之前所有的/export/servers/kudu/master/*
和/export/servers/kudu/tserver/*
```

4、启动过程中报错

```properties
F0913 15:12:00.628237 20859 master_main.cc:74] Check failed: _s.ok() Bad
status: IO
error: Could not create new FS layout: unable to create file system
roots: unable to
write instance metadata: Call to mkstemp() failed on name template
/export/servers/kudu/master/instance.kudutmp.XXXXXX: Permission denied
(error 13)
这是因为kudu默认使用kudu权限进行执行,可能遇到文件夹的权限不一致情况,更改文件夹权限
即可
```

5、启动过程中报错

```
错误描述:kudu-master、kudu-tserver 不能启动;
ntp服务启动;用 service ntpd status 显示服务正常;
在 /var/log/kudu/kudu-master.FATAL 有如下错误:
stdout:
ntp_gettime() returns code 5 (ERROR)
time e072ca67.fa770000 Tue, Apr 30 2019 21:21:43.978, (.978378),
maximum error 16000000 us, estimated error 16000000 us, TAI offset 0
ntp_adjtime() returns code 5 (ERROR)
modes 0x0 (),
offset 0.000 us, frequency -5.973 ppm, interval 1 s,
maximum error 16000000 us, estimated error 16000000 us,
status 0x41 (PLL,UNSYNC),
time constant 7, precision 1.000 us, tolerance 500 ppm,
这个错误是由于ntp不正常导致,输入ntptime也显示如上的错误。
解决方法:重启ntp服务即可。service ntpd restart
```

**8、Kudu的图形界面**
启动好kudu之后可以访问kudu的web管理界面
访问地址:http://bigdata-cdh01.itcast.cn:8051

Master的web地址
http://bigdata-cdh01.itcast.cn:8051/masters

TServer的web地址
http://bigdata-cdh01.itcast.cn:8051/tablet-servers

**9、Kudu安装小结**
启动服务的方式: service kudu-master start|stop|status
service kudu-tserver start|stop|status

![1568259864152](jiqun-images/1568259864152.png)

**10、附录:局域网内部时间同步**

Kudu对NTP服务要求较高,如果NTP未配置或者由于网络原因导致NTP不能正常工作,kudu相
关无法无法正常启动。为了屏蔽网络的因素,可以选择在局域网内部配置NTP。
现有3个节点cdh01(192.168.59.140)、cdh02(192.168.59.150)、
cdh03(192.168.59.160),选择cdh01作为时间同步服务器,其他节点为客户端同步时间到
该节点。
备注:请检查所有节点关闭防火墙。
1、安装NTP(所有节点)
2、修改配置文件(所有节点)

```shell
vim /etc/ntp.conf
# 注释以下四行:
#server 0.centos.pool.ntp.org iburst
#server 1.centos.pool.ntp.org iburst
#server 2.centos.pool.ntp.org iburst
#server 3.centos.pool.ntp.org iburst
```

3、修改node1的配置文件,添加相应内容

```shell
# 给192.168.59.0网段,子网掩码为255.255.255.0的局域网机所有机器同步时间的权限
restrict 192.168.59.0 mask 255.255.255.0 notrap nomodify
# prefer代表优先使用此ip做同步
server 192.168.59.140 prefer
# 当所有服务器都不能使用时,使用本机作为同步服务器
server 127.127.1.0
# 127.127.1.0 为第10层。ntp和127.127.1.0同步完后,就变成了11层
# ntp是层次阶级的。同步上层服务器的 stratum 大小不能超过或等于16
fudge 127.127.1.0 stratum 10
```

4、修改node2、node3的配置文件,添加相应内容

```shell
vim /etc/ntp.conf
server 192.168.59.140 prefer
server 127.127.1.0
fudge 127.127.1.0 stratum 10
```

5、启动NTP服务

```shell
service ntpd start
chkconfig ntpd on
```

6、检查ntp服务是否成功输入: ntpstat
输出如下则启动成功并且同步已完成:

```
synchronised to local net at stratum 11
time correct to within 11 ms
polling server every 64 s
```

![1568262319540](jiqun-images/1568262319540.png)

## Hbase

注意事项:HBase强依赖zookeeper和hadoop,安装HBase之前一定要保证zookeeper和hadoop启动成功,且服务正常运行

**第一步:下载对应的HBase的安装包**

所有关于CDH版本的软件包下载地址如下

http://archive.cloudera.com/cdh5/cdh/5/

HBase对应的版本下载地址如下

http://archive.cloudera.com/cdh5/cdh/5/hbase-1.2.0-cdh5.14.0.tar.gz

**第二步:压缩包上传并解压**

```properties
将我们的压缩包上传到node01服务器的/export/softwares路径下并解压
cd /export/softwares/
tar -zxvf hbase-1.2.0-cdh5.14.0-bin.tar.gz -C ../servers/
```

**第三步:修改配置文件**

```properties
第一台机器进行修改配置文件
cd /export/servers/hbase-1.2.0-cdh5.14.0/conf
```

**修改第一个配置文件hbase-env.sh**

```properties
注释掉HBase使用内部zk

vim hbase-env.sh

export JAVA_HOME=/export/servers/jdk1.8.0_141
export HBASE_MANAGES_ZK=false
```

**修改第二个配置文件hbase-site.xml**

```
修改hbase-site.xml
vim hbase-site.xml
```

```xml
<configuration>
<property>
<name>hbase.rootdir</name>
<value>hdfs://node01:8020/hbase</value>
</property>

<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>

<!-- 0.98后的新变动,之前版本没有.port,默认端口为60000 -->
<property>
<name>hbase.master.port</name>
<value>16000</value>
</property>

<property>
<name>hbase.zookeeper.quorum</name>
<value>node01:2181,node02:2181,node03:2181</value>
</property>

<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/export/servers/zookeeper-3.4.5-cdh5.14.0/zkdatas</value>
</property>
</configuration>
```

**修改第三个配置文件regionservers**

```
vim regionservers

node01
node02
node03
```

**创建back-masters配置文件,实现HMaster的高可用**

```
cd /export/servers/hbase-1.2.0-cdh5.14.0/conf
vim backup-masters

node02
```

**第四步:安装包分发到其他机器**

```properties
将我们第一台机器的hbase的安装包拷贝到其他机器上面去
cd /export/servers/
scp -r hbase-1.2.0-cdh5.14.0/ node02:$PWD
scp -r hbase-1.2.0-cdh5.14.0/ node03:$PWD
```

**第五步:三台机器创建软连接**

```shell
因为hbase需要读取hadoop的core-site.xml以及hdfs-site.xml当中的配置文件信息,所以我们三台机器都要执行以下命令创建软连接
ln -s /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/core-site.xml /export/servers/hbase-1.2.0-cdh5.14.0/conf/core-site.xml
ln -s /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/hdfs-site.xml /export/servers/hbase-1.2.0-cdh5.14.0/conf/hdfs-site.xml
```

**第六步:三台机器添加HBASE_HOME的环境变量**

```properties
vim /etc/profile
export HBASE_HOME=/export/servers/hbase-1.2.0-cdh5.14.0
export PATH=:$HBASE_HOME/bin:$PATH
```

**第七步:HBase集群启动**

```
第一台机器执行以下命令进行启动
cd /export/servers/hbase-1.2.0-cdh5.14.0
bin/start-hbase.sh
```

警告提示:HBase启动的时候会产生一个警告,这是因为jdk7与jdk8的问题导致的,如果linux服务器安装jdk8就会产生这样的一个警告

![1565785581520](jiqun-images/1565785581520.png)

我们可以只是掉所有机器的hbase-env.sh当中的

“HBASE_MASTER_OPTS”和“HBASE_REGIONSERVER_OPTS”配置 来解决这个问题。不过警告不影响我们正常运行,可以不用解决

```
我们也可以执行以下命令单节点进行启动
启动HMaster命令
bin/hbase-daemon.sh start master
启动HRegionServer命令
bin/hbase-daemon.sh start regionserver


为了解决HMaster单点故障问题,我们可以在node02和node03机器上面都可以启动HMaster节点的进程,以实现HMaster的高可用
bin/hbase-daemon.sh start master
```

**第八步:页面访问**

浏览器页面访问

http://node01:60010/master-status

### hive与HBase的整合

hive与我们的HBase各有千秋,各自有着不同的功能,但是归根接地,hive与hbase的数据最终都是存储在hdfs上面的,一般的我们为了存储磁盘的空间,不会将一份数据存储到多个地方,导致磁盘空间的浪费,我们可以直接将数据存入hbase,然后通过hive整合hbase直接使用sql语句分析hbase里面的数据即可,非常方便

hive: 是一个数据仓库工具,是做离线数据统计,不支持实时读写,不能修改和删除

hbase:是一个nosql数据库,支持实时读写,不支持关流查询

![](jiqun-images/1565845666070.png)

**需求一:将hive分析结果的数据,保存到HBase当中去**

**第一步:拷贝hbase的五个依赖jar包到hive的lib目录下**

将我们HBase的五个jar包拷贝到hive的lib目录下

hbase的jar包都在/export/servers/hbase-1.2.0-cdh5.14.0/lib

我们需要拷贝五个jar包名字如下

hbase-client-1.2.0-cdh5.14.0.jar

hbase-hadoop2-compat-1.2.0-cdh5.14.0.jar

hbase-hadoop-compat-1.2.0-cdh5.14.0.jar

hbase-it-1.2.0-cdh5.14.0.jar

hbase-server-1.2.0-cdh5.14.0.jar

我们直接在node03执行以下命令,通过创建软连接的方式来进行jar包的依赖

```shell
ln -s /export/servers/hbase-1.2.0-cdh5.14.0/lib/hbase-client-1.2.0-cdh5.14.0.jar /export/servers/hive-1.1.0-cdh5.14.0/lib/hbase-client-1.2.0-cdh5.14.0.jar
ln -s /export/servers/hbase-1.2.0-cdh5.14.0/lib/hbase-hadoop2-compat-1.2.0-cdh5.14.0.jar /export/servers/hive-1.1.0-cdh5.14.0/lib/hbase-hadoop2-compat-1.2.0-cdh5.14.0.jar
ln -s /export/servers/hbase-1.2.0-cdh5.14.0/lib/hbase-hadoop-compat-1.2.0-cdh5.14.0.jar /export/servers/hive-1.1.0-cdh5.14.0/lib/hbase-hadoop-compat-1.2.0-cdh5.14.0.jar
ln -s /export/servers/hbase-1.2.0-cdh5.14.0/lib/hbase-it-1.2.0-cdh5.14.0.jar /export/servers/hive-1.1.0-cdh5.14.0/lib/hbase-it-1.2.0-cdh5.14.0.jar
ln -s /export/servers/hbase-1.2.0-cdh5.14.0/lib/hbase-server-1.2.0-cdh5.14.0.jar /export/servers/hive-1.1.0-cdh5.14.0/lib/hbase-server-1.2.0-cdh5.14.0.jar
```

**第二步:修改hive的配置文件**

编辑node03服务器上面的hive的配置文件hive-site.xml添加以下两行配置

cd /export/servers/hive-1.1.0-cdh5.14.0/conf

vim hive-site.xml

```xml
<property>
<name>hive.zookeeper.quorum</name>
<value>node01,node02,node03</value>
</property>
<property>
<name>hbase.zookeeper.quorum</name>
<value>node01,node02,node03</value>
</property>
```

**第三步:修改hive-env.sh配置文件添加以下配置**

cd /export/servers/hive-1.1.0-cdh5.14.0/conf

vim hive-env.sh

```properties
export HADOOP_HOME=/export/servers/hadoop-2.6.0-cdh5.14.0
export HBASE_HOME=/export/servers/hbase-1.2.0-cdh5.14.0
export HIVE_CONF_DIR=/export/servers/hive-1.1.0-cdh5.14.0/conf
```

**第四步:hive当中建表并加载以下数据**

**hive当中建表**

进入hive客户端

```
cd /export/servers/hive-1.1.0-cdh5.14.0/
bin/hive
```

创建hive数据库与hive对应的数据库表

```sql
create database course;
use course;
create external table if not exists course.score(id int,cname string,score int) row format delimited fields terminated by ',' stored as textfile ;
```

**进行加载数据**

进入hive客户端进行加载数据

```sql
hive (course)> load data local inpath '/export/servers/tmp/hive-hbase.txt' into table score;
hive (course)> select * from score;
```

**第五步:创建hive管理表与HBase进行映射**

我们可以创建一个hive的管理表与hbase当中的表进行映射,hive管理表当中的数据,都会存储到hbase上面去

hive当中创建内部表

```sql
create table course.hbase_score(id int,cname string,score int)
stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
with serdeproperties("hbase.columns.mapping" = "cf:name,cf:score")
tblproperties("hbase.table.name" = "hbase_score");
```

通过insert overwrite select 插入数据

```sql
insert overwrite table course.hbase_score select id,cname,score from course.score;
```

**第六步:hbase当中查看表hbase_score**

进入hbase的客户端查看表hbase_score,并查看当中的数据

```
hbase(main):023:0> list
TABLE
hbase_score
myuser myuser2 student user
5 row(s) in 0.0210 seconds

=> ["hbase_score", "myuser", "myuser2", "student", "user"]
hbase(main):024:0> scan 'hbase_score'
ROW COLUMN+CELL
1 column=cf:name, timestamp=1550628395266, value=zhangsan
1 column=cf:score, timestamp=1550628395266, value=80
2 column=cf:name, timestamp=1550628395266, value=lisi
2 column=cf:score, timestamp=1550628395266, value=60
3 column=cf:name, timestamp=1550628395266, value=wangwu
3 column=cf:score, timestamp=1550628395266, value=30
4 column=cf:name, timestamp=1550628395266, value=zhaoliu
4 column=cf:score, timestamp=1550628395266, value=70
4 row(s) in 0.0360 seconds
```

**需求二:创建hive外部表,映射HBase当中已有的表模型,直接通过**

**第一步:HBase当中创建表并手动插入加载一些数据**

进入HBase的shell客户端,手动创建一张表,并插入加载一些数据进去

```sql
reate 'hbase_hive_score',{ NAME =>'cf'}
put 'hbase_hive_score','1','cf:name','zhangsan'
put 'hbase_hive_score','1','cf:score', '95'

put 'hbase_hive_score','2','cf:name','lisi'
put 'hbase_hive_score','2','cf:score', '96'

put 'hbase_hive_score','3','cf:name','wangwu'
put 'hbase_hive_score','3','cf:score', '97'
```

操作成功结果如下:

```sql
hbase(main):049:0> create 'hbase_hive_score',{ NAME =>'cf'}
0 row(s) in 1.2970 seconds

=> Hbase::Table - hbase_hive_score
hbase(main):050:0> put 'hbase_hive_score','1','cf:name','zhangsan'
0 row(s) in 0.0600 seconds

hbase(main):051:0> put 'hbase_hive_score','1','cf:score', '95'
0 row(s) in 0.0310 seconds

hbase(main):052:0> put 'hbase_hive_score','2','cf:name','lisi'
0 row(s) in 0.0230 seconds

hbase(main):053:0> put 'hbase_hive_score','2','cf:score', '96'
0 row(s) in 0.0220 seconds

hbase(main):054:0> put 'hbase_hive_score','3','cf:name','wangwu'
0 row(s) in 0.0200 seconds

hbase(main):055:0> put 'hbase_hive_score','3','cf:score', '97'
0 row(s) in 0.0250 seconds
```

**第二步:建立hive的外部表,映射HBase当中的表以及字段**

在hive当中建立外部表,

进入hive客户端,然后执行以下命令进行创建hive外部表,就可以实现映射HBase当中的表数据

```sql
CREATE external TABLE course.hbase2hive(id int, name string, score int) STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,cf:name,cf:score") TBLPROPERTIES("hbase.table.name" ="hbase_hive_score");
```

### Sqoop整合HBase

sqoop是一个数据导入导出的工具,可以将关系型数据库当中的数据导入到大数据平台来,也可以将大数据平台当中的数据导入到关系型数据库当中去

我们也可以通过sqoop导入数据到hbase或者从hbase当中导出数据

```
cd /export/servers/sqoop-1.4.6-cdh5.14.0/conf
vim sqoop-env.sh
```

```properties
#Set path to where bin/hadoop is available
export HADOOP_COMMON_HOME=/export/servers/hadoop-2.6.0-cdh5.14.0

#Set path to where hadoop-*-core.jar is available
export HADOOP_MAPRED_HOME=/export/servers/hadoop-2.6.0-cdh5.14.0

#set the path to where bin/hbase is available
export HBASE_HOME=/export/servers/hbase-1.2.0-cdh5.14.0

#Set the path to where bin/hive is available
export HIVE_HOME=/export/servers/hive-1.1.0-cdh5.14.0
```

**第二步:在mysql当中创建数据库以及数据库表并插入数据**

**创建数据库表**

```sql
CREATE DATABASE IF NOT EXISTS library;
USE library;
CREATE TABLE book(
id INT(4) PRIMARY KEY NOT NULL AUTO_INCREMENT,
NAME VARCHAR(255) NOT NULL,
price VARCHAR(255) NOT NULL);
```

**插入数据**

```sql
INSERT INTO book(NAME, price) VALUES('Lie Sporting', '30');
INSERT INTO book (NAME, price) VALUES('Pride & Prejudice', '70');
INSERT INTO book (NAME, price) VALUES('Fall of Giants', '50');
```

**第三步:将mysql表当中的数据导入HBase表当中去**

执行以下命令,将mysql表当中的数据导入到HBase当中去

```shell
bin/sqoop import
--connect jdbc:mysql://192.168.52.102:3306/library
--username root
--password 123456
--table book
--columns "id,name,price"
--column-family "info"
--hbase-create-table
--hbase-row-key "id"
--hbase-table "hbase_book"
--num-mappers 1 //启动n个mapper来并行导入 默认是四个
--split-by id //按照某一列来切分表的工作单元
```

**第四步:HBase当中查看表数据**

进入hbase的shell客户端,通过scan查看数据

```sql
hbase(main):057:0> scan 'hbase_book'
ROW COLUMN+CELL
1 column=info:name, timestamp=1550634017823, value=Lie Sporting
1 column=info:price, timestamp=1550634017823, value=30
2 column=info:name, timestamp=1550634017823, value=Pride & Prejudice
2 column=info:price, timestamp=1550634017823, value=70
3 column=info:name, timestamp=1550634017823, value=Fall of Giants
3 column=info:price, timestamp=1550634017823, value=50

```

**需求二:将HBase当中的数据导出到mysql当中来**

将hbase_book这张表当中的数据导出到mysql当中来

注意:sqoop不支持我们直接将HBase当中的数据导出,所以我们可以通过以下的转换进行导出

Hbase→hive外部表→hive内部表→通过sqoop→mysql

**第一步:创建hive外部表**

进入hive客户端,创建hive外部表,映射hbase当中的hbase_book表

```sql
CREATE EXTERNAL TABLE course.hbase2mysql (id int,name string,price int)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES (
"hbase.columns.mapping" =
":key,info:name, info:price"
)
TBLPROPERTIES( "hbase.table.name" = "hbase_book",
"hbase.mapred.output.outputtable" = "hbase2mysql");
```

**第二步:创建hive内部表并将外部表数据插入到内部表当中来**

进入hive客户端,执行以下命令,创建hive内部表,并将外部表的数据插入到hive的内部表当中来

```sql
CREATE TABLE course.hbase2mysqlin(id int,name string,price int);
```

**第三步:外部表数据插入内部表**

进入hive客户端执行以下命令,将hive外部表数据插入到hive内部表当中来

```sql
insert overwrite table course.hbase2mysqlin select * from course.hbase2mysql;
```

**第四步:清空mysql表数据**

进入mysql客户端,执行以下命令,将mysql表数据清空

```sql
TRUNCATE TABLE book;
```

**第五步:执行sqoop导出hive内部表数据到**

```sql
sqoop export -connect jdbc:mysql://192.168.52.102:3306/library -username root -password 123456 -table book -export-dir /user/hive/warehouse/course.db/hbase2mysqlin --input-fields-terminated-by '01' --input-null-string '\N' --input-null-non-string '\N';将空null转换成自己想要的值
```

Sqoop整合hbase

![](jiqun-images/1565845619733.png)

![](jiqun-images/1565846083611.png)

## **spark**

Spark 2.x 环境搭建要点

**第一、Spark Quick Start**

**1、环境配置**

解压编译打包Spark压缩包

```shell
# tar -zxf spark-2.2.0-bin-2.6.0-cdh5.14.0.tgz
```

基本配置:

**第一步、安装Scala-2.11.8**

```shell
# tar -zxf scala-2.11.8.tgz -C /export/servers/
```

配置系统环境变量(也可以不配置)

**第二步、修改配置名称**

```shell
# cd /export/servers/spark-2.2.0-bin-2.6.0-cdh5.14.0
# cd conf
# mv spark-env.sh.template spark-env.sh
```

**第三步、修改配置文件**

$SPARK_HOME/conf/spark-env.sh,增加如下内容:

```shell
## 设置JAVA和SCALA安装目录
JAVA_HOME=/export/servers/jdk
SCALA_HOME=/export/servers/scala

## HADOOP软件配置文件目录,读取HDFS上文件和运行YARN集群
HADOOP_CONF_DIR=/export/servers/hadoop/etc/hadoop
```

**第四步、启动HDFS集群**

```shell
# 执行脚本
./hdfs-start-cluster.sh
```

**第五步、本地模式运行spark-shell**

```shell
bin/spark-shell --master local[2]
```

**2、词频统计WordCount**

SparkCore中最重要的数据结构:RDD,弹性分布式数据集,当做Scala集合中List列表就可以

**第一步、读取数据,封装到RDD中,数据类型为String**

```scala
// 读取HDFS上数据文件
val inputRDD = sc.textFile("/datas/wordcount.input")

// 获取RDD集合中第一行数据
inputRDD.first

// 获取RDD集合元素个数
inputRDD.count
```

**第二步、处理数据,单词分割,每个单词出现一次,按照单词分组,进行统计**

```scala
// 单词分割
val wordsRDD = inputRDD.flatMap(line => line.split("\s+"))

// 将单词转换为二元组,表示每个单词出现一次
val tuplesRDD = wordsRDD.map(word => (word, 1))

// 使用reduceByKey函数,先将相同Key的Values合并在一起,在调用reduce函数将Values值进行聚合操作
val wordCountRDD = tuplesRDD.reduceByKey((a, b) => a + b)

// 调用collect函数,将RDD中的元素返回到Array数组中,注意collect慎用
wordCountRDD.collect()
```

**第三步、将结果存储到HDFS目录中**

```scala
wordCountRDD.saveAsTextFile("/datas/sparkOutput/")
```

**第四步、查看输出结果**

```shell
# 查看文件,使用通配符*
bin/hdfs dfs -text /datas/sparkOutput/pa*
```

运行官方Example中**圆周率PI**计算

```SHELL
SPARK_HOME=/export/servers/spark-2.2.0-bin-2.6.0-cdh5.14.0
${SPARK_HOME}/bin/spark-submit
--master local[4]
--class org.apache.spark.examples.SparkPi
${SPARK_HOME}/examples/jars/spark-examples_2.11-2.2.0.jar
10
```

**第二、Spark Standalone Cluster**

**1、Standalone 集群环境搭建**

**配置MASTER、Workers、HistoryServer**:`$SPARK_HOME/conf/spark-env.sh`
内容如下:

```shell
SPARK_MASTER_HOST=bigdata-cdh01.itcast.cn
SPARK_MASTER_PORT=7077
SPARK_MASTER_WEBUI_PORT=8080
SPARK_WORKER_CORES=2
SPARK_WORKER_MEMORY=2g
SPARK_WORKER_PORT=7078
SPARK_WORKER_WEBUI_PORT=8081
SPARK_HISTORY_OPTS="-Dspark.history.fs.logDirectory=hdfs://bigdata-cdh01.itcast.cn:8020/spark/eventLogs/ -Dspark.history.fs.cleaner.enabled=true"
```

- **创建EventLogs存储目录:**

```shell
bin/hdfs dfs -mkdir -p /spark/eventLogs/
```

- **Workers主机名称:**$SPARK_HOME/conf/slaves

内容如下:

```shell
bigdata-cdh01.itcast.cn
bigdata-cdh02.itcast.cn
bigdata-cdh03.itcast.cn
```

- **配置所有Spark应用运行保存EventLogs**:$SPARK_HOME/conf/spark-defaults.conf
内容如下:

```shell
spark.eventLog.enabled true
spark.eventLog.dir hdfs://bigdata-cdh01.itcast.cn:8020/spark/eventLogs/
spark.eventLog.compress true
```

- **分发到集群所有机器**

```shell
scp -r spark-2.2.0-bin-2.6.0-cdh5.14.0/ bigdata-cdh02.itcast.cn:$PWD
scp -r spark-2.2.0-bin-2.6.0-cdh5.14.0/ bigdata-cdh03.itcast.cn:$PWD
```

- **启动服务进程**

- 在Master节点上启动,进入`$SPARK_HOME`

- 主节点Master:

```shell
sbin/start-master.sh
```

WEB UI:http://bigdata-cdh02.itcast.cn:8080

- 从节点Workers:

```shell
sbin/start-slaves.sh
```

**备注:**必须配置主节点到所有从节点的SSH无密钥登录,集群各个机器时间同步

- 历史服务器HistoryServer:

```shell
sbin/start-history-server.sh
```

WEB UI:http://bigdata-cdh01.itcast.cn:18080

- **运行官方Example中圆周率PI计算**

```shell
SPARK_HOME=/export/servers/spark-2.2.0-bin-2.6.0-cdh5.14.0
${SPARK_HOME}/bin/spark-submit
--master spark://bigdata-cdh01.itcast.cn:7077
--class org.apache.spark.examples.SparkPi
${SPARK_HOME}/examples/jars/spark-examples_2.11-2.2.0.jar
100
```

**2、Standalone HA 集群**

基于Zookeeper配置Master高可用:

http://spark.apache.org/docs/2.2.0/spark-standalone.html#standby-masters-with-zookeeper

- **停止Spark Standalone集群**

```shell
sbin/stop-master.sh
sbin/stop-slaves.sh
```

- **增加Zookeeper配置**:`$SPARK_HOME/conf/spark-env.sh`

内容如下:

```shell
SPARK_DAEMON_JAVA_OPTS="-Dspark.deploy.recoveryMode=ZOOKEEPER -Dspark.deploy.zookeeper.url=bigdata-cdh01.itcast.cn:2181,bigdata-cdh02.itcast.cn:2181,bigdata-cdh03.itcast.cn:2181 -Dspark.deploy.zookeeper.dir=/spark-ha"
```

删除内容:

```shell
SPARK_MASTER_HOST=bigdata-cdh02.itcast.cn
```

- **将`spark-env.sh`分发集群**

```shell
scp -r spark-env.sh bigdata-cdh02.itcast.cn:$PWD
scp -r spark-env.sh bigdata-cdh03.itcast.cn:$PWD
```

- **启动集群服务**

- 启动Zokeeper 集群服务,进入$ZOOKEEPER_HOME

```shell
bin/zkServer.sh start
```

- 在cdh02和cdh03机器启动Master

```shell
sbin/start-master.sh
```

WEB UI:http://bigdata-cdh02.itcast.cn:8080 、 http://bigdata-cdh03.itcast.cn:8080

- 在cdh02(Activer Master)机器启动所有Workers:Master为Alive节点上执行

```shell
sbin/start-slaves.sh
```

- **运行官方Example中圆周率PI计算**

```shell
SPARK_HOME=/export/servers/spark-2.2.0-bin-2.6.0-cdh5.14.0
${SPARK_HOME}/bin/spark-submit
--master spark://hadoop02:7077,hadoop03:7077
--class org.apache.spark.examples.SparkPi
${SPARK_HOME}/examples/jars/spark-examples_2.11-2.2.0.jar
100
```

**第三、Spark On YARN**

- **设置环境变量**

```shell
HADOOP_CONF_DIR=/export/servers/hadoop/etc/hadoop
YARN_CONF_DIR=/export/servers/hadoop/etc/hadoop
```

前面已设置,可以不用同时设置HADOOP_CONF_DIR和YARN_CONF_DIR

- **配置服务监控(MRHistoryServer和Spark HistoryServer)**

`$HADOOP_HOME/etc/hadoop/yarn-site.xml`,内容如下:

```xml
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<property>
<name>yarn.log.server.url</name>
<value>http://bigdata-cdh03.itcast.cn:19888/jobhistory/logs</value>
</property>
```

- **同步所有YARN集群机器**

```shell
scp -r yarn-site.xml bigdata-cdh02.itcast.cn:$PWD
scp -r yarn-site.xml bigdata-cdh03.itcast.cn:$PWD
```

- **Spark Applicaiton默认配置**

`$SPARK_HOME/conf/spark-defaults.conf`文件增加如下内容:

```properties
spark.yarn.historyServer.address bigdata-cdh01.itcast.cn:18080
```

- **启动HDFS集群、YARN集群和MRHistoryServer服务**

- HDFS 服务

```shell
# cdh01
sbin/hadoop-daemon.sh start namenode
# cdh01,cdh02,cdh03
sbin/hadoop-daemon.sh start datanode
```

- YARN 服务

```shell
# cdh02
sbin/yarn-daemon.sh start resourcemanager

# cdh01,cdh02,cdh03
sbin/yarn-daemon.sh start nodemanager
```

- MRHistoryServer 服务

```shell
# cdh03
sbin/mr-jobhistory-daemon.sh start historyserver
```

- **启动Spark HistoryServer服务**

```shell
# cdh01
sbin/start-history-server.sh
```

WEB UI:http://bigdata-cdh01.itcast.cn:18080

- **运行官方Example中圆周率PI计算**

```shell
SPARK_HOME=/export/servers/spark-2.2.0-bin-2.6.0-cdh5.14.0
${SPARK_HOME}/bin/spark-submit
--master yarn
--class org.apache.spark.examples.SparkPi
${SPARK_HOME}/examples/jars/spark-examples_2.11-2.2.0.jar
10
```

**第四、Spark Submit Application**

**1、应用提交spark-submit**

```shell
Usage: spark-submit [options] <app jar | python file> [app arguments]
```

如果使用Java或Scala语言编程程序,需要将应用编译后达成Jar包形式,提交运行。

**2、基本参数配置**

```shell
# 表示应用运行的模式,要么是本地local要么是集群(Standalone、YARN、Mesos)
--master MASTER_URL
# 本地模式: local[2] Standalone集群:spark://xxx:7077,yyy:7077 YARN 集群: yarn

# 表示Drive Program运行的地方,也叫做应用部署模式,默认值为client,通常在生成环境中使用cluster
--deploy-mode DEPLOY_MODE

# 表示运行Spark Application的类名称,注意为类的全名称(包含包名)
--class CLASS_NAME

# 表示的是应用运行的名称,通常在应用开发的时候指定
--name NAME A name of your application.

# 表示应用的类所依赖的第三方的Jar包指定路径,通常在本地文件系统中,多个Jar包使用逗号隔开
--jars JARS

# 表示应用运行时指定的某些参数配置,http://spark.apache.org/docs/2.2.0/configuration.html
--conf PROP=VALUE

# 当value中值有空格组成的时候,使用双引号将key=value引起来
--conf "PROP=VALUE"
```

动态加载Spark Applicaiton运行时的参数,通过`--conf`进行指定,如下使用方式:

```bash
# 第一种方式: 属性的值中没有空格
--conf spark.eventLog.enabled=false

# 第二种方式:属性的值中有空格,将属性和值统一使用双引号引起来
--conf "spark.executor.extraJavaOptions=-XX:+PrintGCDetails -XX:+PrintGCTimeStamps"
```

Spark Application运行包括两部分组成:Driver Program 和Executors,都是JVM进程,所以可以设置每个JVM进程中的资源,资源包括CPU Cores核数和内存Memory大小。

**3、Driver Program 参数配置**

```shell
# 指定Driver Program JVM进程内存大小,默认值为1g
--driver-memory MEM

# 表示Driver 运行CLASS PATH路径,使用不多
--driver-class-path

## Spark standalone with cluster deploy mode:运行在Standalone 中cluster Deploy Mode,默认值为1
--driver-cores NUM

## 运行在YARN in cluster mode,默认值是1
--driver-cores NUM

## 运行在standalone的 中cluster Deploy Mode下,表示当Driver运行异常失败,可以自己重启
--supervise
```

**4、Executor参数配置**

```shell
# Executor运行所需内存大小
--executor-memory MEM

# Execturo 运行的CPU Cores,默认的情况下,在Standalone集群上为Worker节点所有可有的CpuCores,在YARN集群下为1
--executor-cores NUM

# 表示运行在Standalone集群下,所有Executor的CPU Cores,结合--executor-cores计算出Executor个数
--total-executor-cores NUM

# 表示在YARN集群下,Executor的个数,默认值为2
--num-executors

# 表示Executor运行的队列,默认为default队列
--queue QUEUE_NAME
```

**第五、IDEA 开发环境**

创建Maven工程、创建模块module,配置pom.xml文件内容如下:

```xml
<!-- 指定仓库位置,依次为aliyun、cloudera和jboss仓库 -->
<repositories>
<repository>
<id>aliyun</id>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
<repository>
<id>cloudera</id>
<url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
</repository>
<repository>
<id>jboss</id>
<url>http://repository.jboss.com/nexus/content/groups/public</url>
</repository>
</repositories>

<properties>
<scala.version>2.11.8</scala.version>
<scala.binary.version>2.11</scala.binary.version>
<spark.version>2.2.0</spark.version>
<hadoop.version>2.6.0-cdh5.14.0</hadoop.version>
</properties>

<dependencies>
<!-- 依赖Scala语言 -->
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
</dependency>
<!-- Spark Core 依赖 -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_${scala.binary.version}</artifactId>
<version>${spark.version}</version>
</dependency>
<!-- Hadoop Client 依赖 -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>${hadoop.version}</version>
</dependency>
</dependencies>

<build>
<outputDirectory>target/classes</outputDirectory>
<testOutputDirectory>target/test-classes</testOutputDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
</resources>
<!-- Maven 编译的插件 -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
<configuration>
<args>
<arg>-dependencyfile</arg>
<arg>${project.build.directory}/.scala_dependencies</arg>
</args>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
```

### 集成Hive

Spark SQL主要目的是使得用户可以在Spark上使用SQL,其数据源既可以是RDD,也可以是外部
的数据源(比如文本、Hive、Json等)。Spark SQL的其中一个分支就是Spark on Hive,也就是
使用Hive中HQL的解析、逻辑执行计划翻译、执行计划优化等逻辑,可以近似认为仅将物理执行
计划从MR作业替换成了Spark作业。SparkSql整合hive就是获取hive表中的元数据信息,然后通
过SparkSql来操作数据。
http://spark.apache.org/docs/2.2.0/sql-programming-guide.html#hive-tables
1)、编译Spark源码支持HIVE集成
参考文档:http://spark.apache.org/docs/2.2.0/building-spark.html#building-with-hive-and-j
dbc-support

![](jiqun-images/1568130865748.png)

编译命令如下:
./dev/make-distribution.sh --name custom-spark --tgz -Phadoop-2.6 -
Dhadoop.version=2.6.0-cdh5.14.0 -Phive -Phive-thriftserver -Pyarn

```shell
2)、未启动Hive MetaStore服务
集成Hive,实质就是:SparkSQL应用运行时,可以读取Hive MetaStore中元数据,配置如下:

第一步:拷贝 hive-site.xml 配置文件至 SPARK_HOME/conf 目录下(建议创建软连接)
Configuration of Hive is done by placing your `hive-site.xml`, `core-
site.xml` (for security configuration), and `hdfs-site.xml` (for HDFS
configuration) file in `conf/`.

第二步:将MySQL驱动包放入 SPARK_HOME/jars 下
$ cp -r $HIVE_HOME/lib/mysql-connector-java-5.1.27-bin.jar $SPARK_HOME/jars
注意,在hive-site.xml配置属性 hive.metastore.warehouse.dir 数据仓库HDFS目录
Note that the hive.metastore.warehouse.dir property in hive-site.xml is
deprecated since Spark 2.0.0. Instead, use spark.sql.warehouse.dir to
specify the default location of database in warehouse.

创建SparkSession启用集成Hive

val spark = SparkSession
.builder()
.appName("Spark Hive Example")
.config("spark.sql.warehouse.dir", warehouseLocation)
.enableHiveSupport()
.getOrCreate()
import spark.implicits._
import spark.sql

3)、启动Hive MetaStore服务
当启动Hive MetaStore服务以后,SparkSQL集成Hive时只要连接到MetaStore服务地址即可读
取元数据。

第一步、启动Hive MetaStore服务,脚本 metastore-start.sh 如下:

#!/bin/sh
HIVE_HOME=/export/servers/hive
## 启动服务的时间
DATE_STR=`/bin/date '+%Y%m%d%H%M%S'`
# 日志文件名称(包含存储路径)
HIVE_SERVER2_LOG=${HIVE_HOME}/logs/hivemetastore-${DATE_STR}.log
## 启动服务
/usr/bin/nohup ${HIVE_HOME}/bin/hive --service metastore >
${HIVE_SERVER2_LOG} 2> &1 &
启动服务:
$ sh metastore-start.sh

附录:配置Hive MetaStore服务,在 hive-site.xml 添加如下配置:
<property>
<name>hive.metastore.uris</name>
<value>thrift://bigdata-cdh01.itcast.cn:9083</value>
</property>
<property>
<name>hive.metastore.local</name>
<value>false</value>
</property>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>

第二步、创建 hive-site.xml 文件,放入 $SPARK_HOME/conf 目录下,内容如下:
<?xml version="1.0".>
<?xml-stylesheet type="text/xsl" href="configuration.xsl".>
<configuration>
<property>
<name>hive.metastore.uris</name>
<value>thrift://bigdata-cdh01.itcast.cn:9083</value>
</property>
<property>
<name>spark.sql.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>
</configuration>

4)、启动spark-sql交互式命令行
启动spark-sql交互式命令行
# 以本地模式运行spark-sql交互式命令行
$ cd /export/servers/spark-2.2.0-bin-2.6.0-cdh5.14.0/
$ bin/spark-sql --master local[2] --conf spark.sql.shuffle.partitions=4 --
conf spark.sql.warehouse.dir=hdfs://hadoop01:8020/user/hive/warehouse
```

![](jiqun-images/%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20190907213700.png)

```shell
5)、启动Spark ThriftServer服务
启动Spark ThriftServer服务,客户端Beeline命令行连接,开发测试:

# 以本地模式运行
SPARK_HOME=/export/servers/spark-2.2.0-bin-2.6.0-cdh5.14.0/
# 启动Spark ThriftServer服务
${SPARK_HOME}/sbin/start-thriftserver.sh
--hiveconf hive.server2.thrift.port=10000
--hiveconf hive.server2.thrift.bind.host=hadoop03
--conf spark.sql.shuffle.partitions=4
--conf spark.sql.warehouse.dir=hdfs://hadoop01:8020/user/hive/warehouse
--master local[4]

Beeline客户端连接:
SPARK_HOME=/export/servers/spark-2.2.0-bin-2.6.0-cdh5.14.0/
${SPARK_HOME}/bin/beeline
beeline> !connect jdbc:hive2://hadoop03:10000
Enter username for jdbc:hive2://hadoop03:10000: itcast
Enter password for jdbc:hive2://hadoop03:10000: ******
```

![](jiqun-images/%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20190907213811.png)

### 集成HBase

SparkSQL读取Hive表中的数据,通过Hive与HBase集成来读取HBase表的数据。
1)、依赖JAR包,添加到SparkSQL应用的CLASSPATH下面

```
hbase-client-1.2.0-cdh5.14.0.jar
hbase-common-1.2.0-cdh5.14.0.jar
hbase-hadoop2-compat-1.2.0-cdh5.14.0.jar
hbase-hadoop-compat-1.2.0-cdh5.14.0.jar
hbase-prefix-tree-1.2.0-cdh5.14.0.jar
hbase-protocol-1.2.0-cdh5.14.0.jar
hbase-server-1.2.0-cdh5.14.0.jar
hive-hbase-handler-1.1.0-cdh5.14.0.jar
htrace-core-3.2.0-incubating.jar
metrics-core-2.2.0.jar
```

2)、将HBase Client配置文件放置到$SPARK_HOME/conf目录(创建软连接)

```shell
cd /export/servers/spark-2.2.0-bin-2.6.0-cdh5.14.0/conf
ln -s /export/servers/hbase/conf/hbase-site.xml hbase-site.xml
```

3)、启动spark-sql命令行,添加依赖jar包

```shell
SPARK_HOME=/export/servers/spark-2.2.0-bin-2.6.0-cdh5.14.0
${SPARK_HOME}/bin/spark-sql
--master local[2]
--jars ${SPARK_HOME}/lib/hbase-client-1.2.0-
cdh5.14.0.jar,${SPARK_HOME}/lib/hbase-common-1.2.0-
cdh5.14.0.jar,${SPARK_HOME}/lib/hbase-hadoop2-compat-1.2.0-
cdh5.14.0.jar,${SPARK_HOME}/lib/hbase-hadoop-compat-1.2.0-
cdh5.14.0.jar,${SPARK_HOME}/lib/hbase-prefix-tree-1.2.0-
cdh5.14.0.jar,${SPARK_HOME}/lib/hbase-protocol-1.2.0-
cdh5.14.0.jar,${SPARK_HOME}/lib/hbase-server-1.2.0-
cdh5.14.0.jar,${SPARK_HOME}/lib/hive-hbase-handler-1.1.0-
cdh5.14.0.jar,${SPARK_HOME}/lib/htrace-core-3.2.0-
incubating.jar,${SPARK_HOME}/lib/metrics-core-2.2.0.jar
--conf spark.sql.shuffle.partitions=4
--conf spark.sql.warehouse.dir=hdfs://bigdata-
cdh01.itcast.cn:8020/user/hive/warehouse
```

![1567904474989](jiqun-images/1567904474989.png)

4)、启动SparkThrift Server服务
使用 spark.executor.extraClassPath 和 spark.driver.extraClassPath 将依赖的JAR包添
加到CLASSPATH路径下。

```shell
SPARK_HOME=/export/servers/spark-2.2.0-bin-2.6.0-cdh5.14.0
${SPARK_HOME}/sbin/start-thriftserver.sh
--hiveconf hive.server2.thrift.port=10000
--hiveconf hive.server2.thrift.bind.host=bigdata-cdh03.itcast.cn
--master local[2]
--conf spark.executor.extraClassPath=${SPARK_HOME}/lib/*
--conf spark.driver.extraClassPath=${SPARK_HOME}/lib/*
--conf spark.sql.shuffle.partitions=4
--conf spark.sql.warehouse.dir=hdfs://bigdata-
cdh01.itcast.cn:8020/user/hive/warehouse
```

![1567904518414](jiqun-images/1567904518414.png)

## Flink

**环境搭建**

**standAlone**

安装包下载地址:

```shell
https://archive.apache.org/dist/flink/flink-1.7.0/
```

1.上传:rz/ftp

2.解压

```shell
tar -zxvf flink-1.6.0-bin-hadoop26-scala_2.11.tgz -C /export/servers/
```

![](jiqun-images/1567299947321.png)

3.配置文件修改

vim flink-conf.yaml

```shell
jobmanager.rpc.address: node01
jobmanager.rpc.port: 6123
jobmanager.heap.size: 1024
taskmanager.heap.size: 1024
taskmanager.numberOfTaskSlots: 1
taskmanager.memory.preallocate: false
parallelism.default: 1
jobmanager.web.port: 8081
taskmanager.tmp.dirs: /export/servers/flink-1.6.0/tmp


jobmanager.rpc.address: node01 #JobManager的外部地址,它是分布式系统的主/协调器(DEFAULT:localhost)设置成你master节点的IP地址
jobmanager.rpc.port: 6123 #JobManager的端口号(DEFAULT:6123)
jobmanager.heap.size: 1024 #JobManager的默认JVM堆大小(以兆字节为单位)
taskmanager.heap.size: 1024 #用于TaskManagers的JVM堆大小(以兆字节为单位)


taskmanager.numberOfTaskSlots: 1 #每台机器可用的CPU数量(默认值:1)
taskmanager.memory.preallocate: false #是否进行预分配内存,默认不进行预分配,这样在我们不使用flink集群时候不会占用集群资源

parallelism.default: 1 #指定程序的默认并行度
jobmanager.web.port: 8081 #JobManager的Web界面的端口(默认:8081)
taskmanager.tmp.dirs:/export/servers/flink-1.6.0/tmp #临时文件的目录
```

vim masters

```
node01:8081
```

vim slaves

```
node01
node02
node03
```

4.分发安装包

```
scp -r flink-1.6.0/ node02:$PWD
scp -r flink-1.6.0/ node03:$PWD
```

5.启停

```
./start-cluster.sh #启动
./stop-cluster.sh #停止
```

![](jiqun-images/1567300649169.png)

6.页面访问

```
node01:8081
```

7.测试

```
bin/flink run examples/batch/WordCount.jar
```

![](jiqun-images/1567301809767.png)

**standAlone-HA(高可用)**

1.配置文件修改

vim flink-conf.yaml

```shell
#HA
state.backend: filesystem #检查点的配置
state.backend.fs.checkpointdir: hdfs://node01:8020/flink-checkpoints
high-availability: zookeeper #HA 高可用模式的配置
high-availability.storageDir: hdfs://node01:8020/flink/ha/ #元数据
high-availability.zookeeper.quorum: node01:2181,node02:2181,node03:2181
```

vim master

```
node01:8081
node02:8081
```

分发配置文件

```shell
scp flink-conf.yaml node02:$PWD
scp flink-conf.yaml node03:$PWD
scp masters node02:$PWD
scp masters node03:$PWD
```

> 注意: node02节点上的flink-conf.yaml:
>
> jobmanager.rpc.address: node02

启动

```shell
start-dfs.sh #hdfs
zkServer.sh start #zookeeper
./start-cluster.sh #flink
```

> 启动高可用集群:需先启动hdfs,zookeeper

页面访问

```
node01:8081
```

**flink on yarn**

企业生产环境主要采用模式

优点:能够最大化的利用企业中的集群资源

部署架构

![](jiqun-images/1567303451949.png)

**1.配置文件修改**

(1)vim etc/hadoop/yarn-site.xml

```
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
```

> node01,node02,node03都需要配置
>
> 执行任务的内存,超过分配的内存阀值,也不会关闭任务

(2)vim /etc/profile

```
export HADOOP_CONF_DIR=/export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop
```

> node01,node02,node03都需要配置
>
> 编辑完成之后,一定要source
>
> source /etc/profile

![](jiqun-images/1567303791835.png)

**2.提交作业**

**(1)yarn-session**

- 先申请yarn资源,一次性申请好yarn资源

- 再提交作业

- 适用于大量的小作业

- 申请的内存资源,不会自动关闭资源,需要手动关闭

提交作业的命令:

先申请资源:

```shell
./yarn-session.sh -n 2 -tm 1024 -jm 1024 -s 1
./yarn-session.sh -n 2 -tm 1024 -jm 1024 -s 1 -d #分离模式,申请好资源,会自动退出会话窗口
```

-n: taskmanager容器的数量

-s: slot,cpu的核数

-d: 表示分离模式

-tm: 表示申请的taskmanager的内存

-jm:表示申请的jobmanager的内存

再提交作业:

```
bin/flink run ../examples/batch/WordCount.jar
```

查看yarn资源ID

```shell
yarn application -list #查看
yarn application -kill yarn-ID #杀掉yarn资源ID
```

查看命令:

```shell
./yarn-session.sh -help
```

![](jiqun-images/1567305748097.png)

**2)yarn-cluster**

- 提交作业的时候,再申请资源,不需要提前申请资源
- 适用于大作业,适用于一次性的批量作业
- 任务执行完毕会自动关闭资源

提交作业:

```shell
flink run -m yarn-cluster -yn 1 -ytm 1024 -yjm 1024 -ys 1 /export/servers/flink-1.6.0/examples/batch/WordCount.jar
```

-yn : 表示taskmanager的容器数量

-ytm:表示taskmanager的申请内存

-yjm:表示申请的jobmanager的内存

-ys: 表示slot的数量

查看帮助命令:

```
flink run -m yarn-cluster -help
```

原文地址:https://www.cnblogs.com/Diyo/p/11559846.html