因为Hadoop对集群中各个机器的时间同步要求比较高,要求各个机器的系统时间不能相差太多,不然会造成很多问题,比如,最常见的连接超时问题,所以需要配置集群中各个机器和互联网的时间服务器进行时间同步,但是在实际生成环境中,集群中大部分服务器是不能连接外网的,这时候可以在内网搭建一个自己的服务器(NTP服务器),然后让集群的各个机器与这个时间服务器定时的进行时间同步。
# 查看当前节点时间
date
只需要在所有节点执行命令
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
实际上就是把Shanghai时间的文件复制到localtime中
每个节点上都要执行,保证系统当前时间标准为上海时间
我们选择第一台机器(hadoop01)为NTP服务器,其他机器和这台机器进行定时的时间同步
1、检查NTP服务是否已经安装
rpm -qa | grep ntp
如果没有安装输入命令
yum install -y ntp
进行安装
2、修改配置文件 ntp.conf
vi /etc/ntp.conf
2.1、启用restrict限定该机器网段
# 将restrict 192.168.74.136 mask 255.255.255.0 nomodify notrap行注释掉
# 并将网段改为自己本机的网段,也可以直接输入本机的ip地址
2.2、注释掉server域名配置
# server0.centos.pool.ntp.orgiburst
# server1.centos.pool.ntp.orgiburst
# server2.centos.pool.ntp.orgiburst
# server3.centos.pool.ntp.orgiburst
以上4个server是时间服务器的域名,这里不需要连接互联网,所以将它们注释掉
2.3、在该文件中添加下边两行,让本机和本地硬件时间同步
server 127.127.1.0
fudge 127.127.1.0 stratum 10
默认的配置文件里这两个是被注释掉的。NTP服务器会根据这里的配置,把自己的时间作为NTP服务器的时间,即和自己同步,考虑到有的局域网里不可以访问外网,所有这里需要配置该配置项。
3、启动NTP服务
chkconfig ntpd on
即可。这样每次机器启动时,NTP服务都会自动启动。crontab -e
即可,然后在会话中输入:0-59/10**** /usr/sbin/ntpdate hadoop01
- 1 其中0-59/10****,表示每隔10分钟进行一次时钟同步,空格隔开的五段是crontab语法格式中时间段,一共5段,其中*号表示任意时间,每一段时间的具体含义如下:
- 1、第一段:代表分
- 2、第二段:代表小时
- 3、第三段:代表日期
- 4、第四段:代表月份
- 5、第五段:代表星期
- 2、其中/usr/sbin/ntpdate hadoop01表示执行的命令,即本机和主机名为hadoop01的机器进行定时的时钟同步
- 3、在其他节点进行同样的操作,然后过10分钟之后再次查看3台机器的时间,如果3台机器的时间一致就表示实现了时间的定时同步
vi /etc/hosts
192.168.64.141 cdh001
192.168.64.145 cdh002
192.168.64.146 cdh003
# 关闭防火墙
systemctl stop firewalld.service
# 查看防火墙状态
systemctl status firewalld.service
# 开启禁止启动
systemctl disable firewalld.service
# 一路回车
ssh-keygen -t rsa
cd /home/hadoop1/.ssh
cp id_rsa.pub authorized_keys
cat ~/.ssh/id_rsa.pub | ssh root@cdh001 'cat >> ~/.ssh/authorized_keys'
scp -r ~/.ssh/authorized_keys root@cdh002:~/.ssh/
scp -r ~/.ssh/authorized_keys root@cdh003:~/.ssh/
创建/home/hadoop/tools脚本存放目录
mkdir /home/hadoop/tools
编写脚本配置文件和分发文件
deploy.conf
deploy.sh
runRemoteCmd.sh
deploy.conf
# 集群角色规划
cdh001,master,all,zk,
cdh002,slave,all,zk,
cdh003,slave,all,zk,
deploy.sh
#!/bin/bash
if [ $# -lt 3 ]
then
echo "Usage:./deploy.sh srcFile(or Dir) descFile(or Dir) MachineTag"
echo "Usage:./deploy.sh srcFile(or Dir) descFile(or Dir) MachineTag confFile"
exit
fi
src=$1
dest=$2
tag=$3
if [ 'b'$4'b' == 'bb' ]
then
confFile=/home/hadoop/tools/deploy.conf
else
confFile=$4
fi
if [ -f $confFile ]
then
if [ -f $src ]
then
for server in `cat $confFile | grep -v '^#' |grep ','$tag',' |awk -F',' '{print $1}'`
do
scp $src $server":"$dest
done
elif [ -d $src ]
then
for server in `cat $confFile | grep -v '^#' |grep ','$tag',' |awk -F',' '{print $1}'`
do
scp -r $src $server":"$dest
done
else
echo "Error:No source file exist"
fi
else
echo "Error:Please assign config file"
fi
添加权限
chmod u+x deploy.sh
测试脚本
./deploy.sh deploy.conf /home/ slave
runRemoteCmd.sh
#!/bin/bash
if [ $# -lt 2 ]
then
echo "Usage:./runRemoteCmd.sh Command MachineTag"
echo "Usage:./runRemoteCmd.sh Command MachineTag confFile"
exit
fi
cmd=$1
tag=$2
if [ 'b'$3'b' == 'bb' ]
then
confFile=/home/hadoop/tools/deploy.conf
else
confFile=$3
fi
if [ -f $confFile ]
then
for server in `cat $confFile | grep -v '^#' |grep ','$tag',' |awk -F',' '{print $1}'`
do
echo "*************$server*************"
ssh $server "source ~/.bashrc; $cmd"
done
else
echo "Error:Please assign config file"
fi
添加权限
chmod u+x runRemoteCmd.sh
测试脚本
./runRemoteCmd.sh "ls" all
配置环境变量 vi ~/.bashrc
# 测试脚本在什么目录路径写成哪个目录
PATH=/home/hadoop/tools:$PATH
export PATH
# 更新
source ~/.bashrc
批量创建各个节点相应目录
runRemoteCmd.sh "mkdir /home/hadoop/app" slave
runRemoteCmd.sh "mkdir /home/hadoop/data" slave
通过 tar -zxvf
命令对Zookeeper安装包进行解压即可。
为了方便版本的更新和学习使用,可以创建zookeeper软件连向zookeeper真是安装路径。可以使用如下命令:ln -s zookeeper-xxx zookeeper
进去zookeeper配置目录
cd /home/hadoop/app/zookeeper-3.4.5-cdh5.10.0/conf
修改配置
vi zoo.cfg
# zookeeper 使用的基本时间,服务器之间或客户端与服务器之间维持心跳的时间间隔
tickTime=2000
# 配置 zookeeper 接受客户端初始化连接时最长能忍受多少个心跳时间间隔数
initLimit=10
# Leader 与 Follower 之间发送消息,请求和应答时间长度
syncLimit=5
# 数据目录需要提前创建
dataDir=/home/hadoop/data/zookeeper/zkdata
# 日志目录需要提前创建
dataLogDir=/home/hadoop/data/zookeeper/zkdatalog
# 访问端口号
clientPort=2181
# server 每个节点服务编号=服务器ip地址:集群通信端口:选举端口
server.1=cdh001:2888:3888
server.2=cdh002:2888:3888
server.3=cdh003:2888:3888
将zookeeper安装目录整体分发到其他节点
deploy.sh zookeeper-3.4.5-cdh5.10.0/home/hadoop/app slave
并分别创建软连接
ln -s zookeeper-3.4.5-cdh5.10.0 zookeeper
runRemoteCmd.sh "mkdir -p /home/hadoop/data/zookeeper/zkdata" all
runRemoteCmd.sh "mkdir -p /home/hadoop/data/zookeeper/zkdatalog" all
分别到各个节点,进入/home/hadoop/data/zookeeper/zkdata
目录,
创建文件 myid
,里面的内容分别填充为:1、2、3
cd /home/hadoop/data/zookeeper/zkdata
vi myid
# 内容
1
启动Zookeeper
runRemoteCmd.sh "/home/hadoop/app/zookeeper/bin/zkServer.sh start" all
查看zookeeper进程
runRemoteCmd.sh "jps" all
查看zookeeper状态
runRemoteCmd.sh "/home/hadoop/app/zookeeper/bin/zkServer.sh status" all
/home/hadoop/app/zookeeper/bin/zkCli.sh
zookeeper支持某些特定的四字命令,用来获取zookeeper服务的当前状态及相关信息。用户在客户端可以通过telnet或nc向zookeeper提交相应的命令。
示例:
echo conf | nc localhost 2180
命令 | 描述 |
---|---|
conf | 输出server的详细配置信息 |
cons | 输出指定server上所有客户端连接的详细信息,包括IP、会话ID等 |
dump | 这个命令针对leader执行,用于输出所有等待列队中的会话和零时节点的信息 |
envi | 用于输出server的环境变量。包括操作系统环境和Java环境 |
ruok | 用于测试server是否处于无措状态。如果正常,则返回“imok”,否则没有任何反应 |
stat | 输出server简要状态和连接客户端信息 |
wchs | 列出所有watcher的概要信息 |
wchc | 列出所有watcher信息,以watcher的session为归组单元排列 |
wchp | 列出所有watcher信息,以watcher的path为归组单元排列 |
bin/zkCli.sh -server localhost:2181 或者 bin/zkCli.sh
连接成功之后,输入help命令会显示zookeeper所有操作命令
ls /
create /test helloword
get /test
set /test zookeeper
delete /test
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
/**
* 连接zookeeper
*/
public class ConnectionWatcher implements Watcher {
private static final Integer SESSION_TIMEOUT = 5000;
protected ZooKeeper zooKeeper;
private CountDownLatch countDownLatch = new CountDownLatch(1);
public void connect(String hosts) throws IOException, InterruptedException {
zooKeeper = new ZooKeeper(hosts, SESSION_TIMEOUT, this);
countDownLatch.await();
}
@Override
public void process(WatchedEvent event) {
if (event.getState() == Event.KeeperState.SyncConnected){
// 等待zookeeper连接完成,释放等待
countDownLatch.countDown();
}
}
public void close() throws InterruptedException {
zooKeeper.close();
}
}
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.Stat;
import java.nio.charset.Charset;
import java.util.List;
/**
* zookeeper API 操作
*/
public class API_Zookeeper extends ConnectionWatcher {
/**
* 创建Znode节点
*/
public String create(String path, String data) throws KeeperException, InterruptedException {
return zooKeeper.create(path, data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
/**
* 判断Znode节点是否存在
*/
public Stat exists(String path, boolean watch) throws KeeperException, InterruptedException {
return zooKeeper.exists(path, watch);
}
/**
* 获Znode取节点数据
*/
public String getData(String path, boolean watch, Stat stat) throws KeeperException, InterruptedException {
byte[] data = zooKeeper.getData(path, watch, stat);
return new String(data, Charset.forName("UTF-8"));
}
/**
* 修改Znode节点数据
*/
public void setData(String path, String data) throws KeeperException, InterruptedException {
zooKeeper.setData(path, data.getBytes(Charset.forName("UTF-8")), -1);
}
/**
* 获取Znode子节点
*/
public List<String> getChildren(String path, boolean watch) throws KeeperException, InterruptedException {
return zooKeeper.getChildren(path, watch);
}
/**
* 删除Znode节点
* @param path
*/
public void deleteZnode(String path, int version) throws KeeperException, InterruptedException {
zooKeeper.delete(path, version);
}
}
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.data.Stat;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
public class Zookeeper_Test {
private API_Zookeeper readWriteZookeeper;
/**
* 连接zookeeper
*/
@Before
public void connect(){
String hosts = "192.168.64.141:2181,192.168.64.145:2181,192.168.64.146:2181";
try {
readWriteZookeeper = new API_Zookeeper();
readWriteZookeeper.connect(hosts);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 创建节点
*/
@Test
public void createZnode() throws KeeperException, InterruptedException {
String path = "/test";
String data = "believer";
String result = readWriteZookeeper.create(path, data);
System.out.println(result);
}
/**
* 创建子节点
*/
@Test
public void createZnodeChildren() throws KeeperException, InterruptedException {
String path = "/test/tools";
String data = "believer";
String result = readWriteZookeeper.create(path, data);
System.out.println(result);
}
/**
* 判断节点是否存在
*/
@Test
public void exists() throws KeeperException, InterruptedException {
String path = "/test";
boolean wathc = false;
Stat stat = readWriteZookeeper.exists(path, wathc);
System.out.println(stat.getAversion());
}
/**
* 获Znode取节点数据
*/
@Test
public void getData() throws KeeperException, InterruptedException {
String path = "/test";
boolean watch = false;
Stat stat = new Stat();
String data = readWriteZookeeper.getData(path, watch, stat);
System.out.println(data);
}
/**
* 修改Znode节点数据
*/
@Test
public void setData() throws KeeperException, InterruptedException {
String path = "/test";
String data = "welcome";
readWriteZookeeper.setData(path, data);
}
/**
* 获取Znode子节点
*/
@Test
public void getChildren() throws KeeperException, InterruptedException {
String path = "/test";
List<String> children = readWriteZookeeper.getChildren(path, false);
for (String znode: children){
System.out.println(znode);
}
}
/**
* 删除Znode节点
*/
@Test
public void deleteZnode() throws KeeperException, InterruptedException {
String path = "/test";
String childrenPath1 = "/test/app";
String childrenPath2 = "/test/tools";
readWriteZookeeper.deleteZnode(path, -1);
}
}
配置服务是分布式应用所需要的基本服务之一,它使用集群中的机器可以共享配置信息。简而言之,zookeeper可以作为一个具有高可用性的配置存储系统,允许分布式应用的各个节点检索和更新配置文件信息。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>hadoop_zookeeper</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>6</source>
<target>6</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
/**
* 连接zookeeper
*/
public class ConnectionWatcher implements Watcher {
private static final Integer SESSION_TIMEOUT = 5000;
protected ZooKeeper zooKeeper;
private CountDownLatch countDownLatch = new CountDownLatch(1);
public void connect(String hosts) throws IOException, InterruptedException {
zooKeeper = new ZooKeeper(hosts, SESSION_TIMEOUT, this);
countDownLatch.await();
}
@Override
public void process(WatchedEvent event) {
if (event.getState() == Event.KeeperState.SyncConnected){
// 等待zookeeper连接完成,释放等待
countDownLatch.countDown();
}
}
public void close() throws InterruptedException {
zooKeeper.close();
}
}
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.Stat;
import java.nio.charset.Charset;
import java.util.List;
/**
* zookeeper API 操作
*/
public class API_Zookeeper extends ConnectionWatcher {
/**
* 获Znode取节点数据
*/
public String getData(String path, boolean watch, Stat stat) throws KeeperException, InterruptedException {
byte[] data = zooKeeper.getData(path, watch, stat);
return new String(data, Charset.forName("UTF-8"));
}
/**
* 修改Znode节点数据
*/
public void setData(String path, String data, int version) throws KeeperException, InterruptedException {
zooKeeper.setData(path, data.getBytes(Charset.forName("UTF-8")), version);
}
/**
* 读取并监听Znode节点数据
*/
public String readData(String path, Watcher watcher, Stat stat) throws KeeperException, InterruptedException {
byte[] data = zooKeeper.getData(path, watcher, stat);
return new String(data, Charset.forName("UTF-8"));
}
}
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import java.io.IOException;
/**
* Watcher监听Znode节点变化
*/
public class ConfigWatcher implements Watcher {
private API_Zookeeper api_zookeeper;
public static final String path = "/config";
public ConfigWatcher(String hosts) throws IOException, InterruptedException {
api_zookeeper = new API_Zookeeper();
api_zookeeper.connect(hosts);
}
public void displayConfig() throws KeeperException, InterruptedException {
String result = api_zookeeper.readData(path, this, null);
System.out.println(result);
}
@Override
public void process(WatchedEvent event) {
if (event.getType() == Event.EventType.NodeDataChanged){
try {
displayConfig();
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
ConfigWatcher configWatcher =
new ConfigWatcher("192.168.64.141:2181,192.168.64.145:2181,192.168.64.146:2181");
configWatcher.displayConfig();
Thread.sleep(Long.MAX_VALUE);
}
}
import org.apache.zookeeper.KeeperException;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.TimeUnit;
public class ConfigUpdate {
private API_Zookeeper api_zookeeper;
public static final String path = "/config";
private Random random = new Random();
public ConfigUpdate(String hosts) throws IOException, InterruptedException {
api_zookeeper = new API_Zookeeper();
api_zookeeper.connect(hosts) ;
}
public void run() throws KeeperException, InterruptedException {
while (true){
String data = random.nextInt(100) + "";
// 更新Znode节点数据
api_zookeeper.setData(path, data, -1);
System.out.printf("write %s to %s\n",path, data);
TimeUnit.SECONDS.sleep(random.nextInt(10));
}
}
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
ConfigUpdate configUpdate =
new ConfigUpdate("192.168.64.141:2181,192.168.64.145:2181,192.168.64.146:2181");
configUpdate.run();
}
}