一、准备工作
1.下载安装vmware,步骤省略。
2.下载CentOS系统ios包:http://isoredirect.centos.org/centos/7/isos/x86_64/CentOS-7-x86_64-Everything-1611.iso
3.下载安装Xshell5,步骤省略。
4.下载安装git,步骤省略。
5.zookeeper官网:http://zookeeper.apache.org/
6.zookeeper用于golang的api:https://github.com/samuel/go-zookeeper
7.vmware中依次点击“创建新的虚拟机”->“典型”->“安装程序光盘映像文件”选择上面下载的ios文件,然后一路下一步即可快速安装CentOS系统。
至于为什么安装CentOS,其实其他linux版本也可以。安装完成的CentOS系统如下图:
二、安装配置zookeeper
点击屏幕左上角的Applications,打开Terminal,下面我们把zookeeper下载到/usr/local目录下,这个目录可以理解为windows下的C:/Progrem Files/目录。
首先切换到root权限:
输入su,回车,看到Password:后输入密码,注意密码不会显示出来,输入完毕直接回车就好。
接下来执行命令进入/usr/local目录:
cd /usr/local
下载 zookeeper-3.5.3-beta.tar.gz:
wget https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.5.3-beta/zookeeper-3.5.3-beta.tar.gz
terminal里会出现下载进度条,进度条读完后文件下载完毕,我们先将其解压缩:
tar -xvf zookeeper-3.5.3-beta.tar.gz
接下来我们进入conf目录进行设置:
cd zookeeper-3.5.3-beta/conf/
复制 zoo_sample.cfg 文件的并命名为为 zoo.cfg:
cp zoo_sample.cfg zoo.cfg
我们编辑zoo.cfg,进行相关设置:
vi zoo.cfg
这个时候如果想修改这个文件的内容,按下间键盘上的“i”键,最下方就会变成INSERT,就可以修改了
移动光标,将
dataDir=/tmp/zookeeper
改为
dataDir=/usr/local/zookeeper-3.5.3-beta
按Esc退出编辑模式,然后输入:wq回车进行保存并关闭文件。
下面我们查看一下虚拟机的局域网ip地址:
ifconfig
可以看到我虚拟机的IP地址为:192.168.40.129
这里我们要用到一个软件xshell5,其实在CentOS的terminal下运行也是一样的,但是如果zookeeper安装在服务器端而不是本地虚拟机的话,使用xshell5就会显得更方便了,所以这里我们使用xshell5。
打开xshell5,登录我们的虚拟机:
用户名填root,密码是虚拟机的密码。
进入zookeeper的运行目录:
cd /usr/local/zookeeper-3.5.3-beta/bin
下面我们启动zookeeper的服务:
./zkServer.sh start
出现STARTED,说明我们的zookeeper已经启动了,我们可以通过它提供的clint端在命令行下直接进行一些简易的操作,输入:
./zkCli.sh
可以看到我们已经进入了zookeeper的clint端。
输入help,可以查看一些命令行下的命令。
三、golang实现分布式系统的Leader选举
下面我们利用搭建好的zookeeper,使用golang实现分布式系统的Leader选举
安装配置golang环境不是本文讨论的重点,这里省略。
我们可以利用git来获取,git可自行下载安装,下面是git命令。
查看golang的位置:
which go
设置GOROOT:
export GOROOT=/c/Go
我将golang程序放到了d盘的golang文件夹下,那么设置一下GOPATH:
export GOPATH=/d/golang/
获取zookeeper对go的api:
go get github.com/samuel/go-zookeeper/zk
下面在d盘golang文件夹下新建一个go项目,写入如下代码来模拟Leader选举的过程:
package main
import (
"github.com/samuel/go-zookeeper/zk"
"errors"
"time"
"fmt"
)
type ZookeeperConfig struct {
Servers []string
RootPath string
MasterPath string
}
type ElectionManager struct {
ZKClientConn *zk.Conn
ZKConfig *ZookeeperConfig
IsMasterQ chan bool
}
func NewElectionManager(zkConfig *ZookeeperConfig, isMasterQ chan bool) *ElectionManager {
electionManager := &ElectionManager{
nil,
zkConfig,
isMasterQ,
}
electionManager.initConnection()
return electionManager
}
func (electionManager *ElectionManager) Run() {
err := electionManager.electMaster()
if err != nil {
fmt.Println("elect master error, ", err)
}
electionManager.watchMaster()
}
// 判断是否成功连接到zookeeper
func (electionManager *ElectionManager) isConnected() bool {
if electionManager.ZKClientConn == nil {
return false
} else if electionManager.ZKClientConn.State() != zk.StateConnected {
return false
}
return true
}
// 初始化zookeeper连接
func (electionManager *ElectionManager) initConnection() error {
// 连接为空