zookeeper服务抽离配置

需要linux环境,这里采用虚拟机配置,采用xshell进行连接,好处是安装插件之后可以在任意目录与本地环境上传下载

常用端口查询命令:
lsof -i
lsof -i:端口号 查看端口pid
netstat -ntlp 查看所有端口
netstat -tunpl|grep 端口号 查看进程占用情况
kill -9 PID 强杀进程
yum  install lrzsz
// rz 命令上传到Linux  
// sz [path] 命令下载文件到本地

安装zookeeper首先需要安装jdk,然后安装zookeeper,详情见如下:

https://blog.csdn.net/kong1287988804/article/details/75639414

https://blog.csdn.net/kong1287988804/article/details/75661122

之后使用xshell连接到服务器,
./zkServer.sh start 顺利启动zookeeper服务,然后需要启动zookeeper客户端来添加节点,跳转到zookeeper所在目录的bin中

./zkCli.sh
ZooKeeper -server host:port cmd args
stat path [watch] // 查看节点状态
set path data [version] // set数据
ls path [watch] // 查看节点
delquota [-n|-b] path
ls2 path [watch] // 查看节点增强版
setAcl path acl
setquota -n|-b val path
history
redo cmdno
printwatches on|off
delete path [version] // 删除节点路径
sync path
listquota path
rmr path // 递归删除
get path [watch] // 获取节点信息
create [-s] [-e] path data acl // 创建节点初始化数据
addauth scheme auth
quit
getAcl path
close
connect host:port

我们创建节点 /registry/HelloService/Baidu, 里面再包含name和url

create /registry data
create /registry/HelloService data
create /registry/HelloService/Baidu data
create /registry/HelloService/Baidu/name baidu
create /registry/HelloService/Baidu/url  https://www.baidu.com

在根目录中新建一个文件夹zkClient,接着建文件

还是先把node环境配一下

// 在根目录 cd /
wget https://nodejs.org/dist/v12.18.1/node-v12.18.1-linux-x64.tar.xz    // 下载
tar xf node-v12.18.1-linux-x64.tar.xz  // 解压                                 
mv node-v12.18.1-linux-x64 /apps/node-v12.18.1-linux-x64
vi /etc/profile 
// 在最下面添加  
export PATH=$PATH:/apps/node-v12.18.1-linux-x64/bin         
source /etc/profile // 立即生效
[root@localhost ~]# node -v
v12.18.1             
// 关闭防火墙
//centos从7开始默认用的是firewalld,这个是基于iptables的,虽然有iptables的核心,但是iptables的服务是没安装的。所以你只要停止firewalld服务即可: 
sudo systemctl stop firewalld.service && sudo systemctl disable firewalld.service
// 如果你要改用iptables的话,需要安装iptables服务: 
sudo yum install iptables-services 
sudo systemctl enable iptables && sudo systemctl enable ip6tables 
sudo systemctl start iptables && sudo systemctl start ip6tables

service iptables status 
service iptables stop --停止
service iptables start --启动
// 查看端口
ifconfig -a
zkClient文件夹里面创建文件
// client.js
var express = require('express');
var zookeeper = require('node-zookeeper-client');
var httpProxy = require('http-proxy');
var cluster = require('cluster');
var os = require('os');
var cache = {};

var CPUS = os.cpus().length;

var PORT = 8084;    // 本服务,zk中转服务端口 随便
var CONNECTION_STRING = '127.0.0.1:2181';   // zk服务
var REGISTRY_ROOT = '/registry';

var app = express();

let whiteList = ['http://192.168.80.128:3000'] // 服务器ip+网站端口
app.use(function(req,res,next){
	let origin = req.headers.origin;
	if(whiteList.includes(origin)){
		res.setHeader('Access-Control-Allow-Origin', origin);
		res.setHeader('Access-Control-Allow-Headers', 'Origin,Accept,Content-Type,X-Requested-With,Authorization,Referer,Access-Control-Allow-Origin,User-Agent,Service-Name,key');
		res.setHeader('Access-Control-Allow-Methods', 'GET,POST,OPTION,DELETE,PUT');
		res.setHeader('Access-Control-Expose-Headers', '*');
	}
	next();
})

if (cluster.isMaster) {
    for (var i = 0; i < CPUS; i++) {
        cluster.fork();
    }
}
else {
    //连接zookeeper
    var zk = zookeeper.createClient(CONNECTION_STRING);
    zk.connect();

    //创建代理服务器对象并监听错误事件
    var proxy = httpProxy.createProxyServer();
    proxy.on('error', function (err, req, res) {
        res.end();//输出空白响应数据
    });

    //启动web服务器
    //app.use(express.static('./'));

    app.all('*', function (req, res) {
        //处理图标请求
        if (req.path == '/favicon.ico') {
            res.end();
            return;
        }
        //获取服务名称
        var serviceName = req.get('Service-Name');
	    var key = req.get('key');
        console.log(key);
        console.log('ServiceName:%s', serviceName);
        if (!serviceName) {
            console.log('Service-Name request header is not exist');
            res.end();
            return;
        }
        //获取服务路径
        var servicePath = REGISTRY_ROOT + "/" + serviceName;
        console.log('ServicePath:%s', servicePath);
        console.log('cache[serviceName]:'+JSON.stringify(cache));
        if (cache[serviceName]) {
            console.log("-----------cache---------------"+cache[serviceName]);
            res.send(cache[serviceName])
            //proxy.web(req, res, {
            //    target: 'http://' + cache[serviceName] //目标地址
            //});
        }else {
            //获取服务路径下的地址节点
            zk.getChildren(servicePath, function (error, addressNodes) {
                console.log(addressNodes)
                if (error) {
                    console.log(error.stack);
                    res.end();
                    return;
                }
                var size = addressNodes.length;
                console.log(size)
                if (size == 0) {
                    console.log('address node is not exist');
                    res.end();
                    return;
                }
                //生成地址容器
                var addressPath = servicePath + "/";
                if (size == 1) {
                    //若只有唯一地址,则获取该地址
                    addressPath += addressNodes[0];
                } else {
                    //若存在多个地址,则获取key
                    addressPath += key;  // 本例子中由于有name和url两个,所以取了key也就是url
                }
                console.log('addressPath:%s', addressPath);
                //获取服务地址
                zk.getData(addressPath, function (err, serviceAddress) {
                    if (error) {
                        console.log(error.stack);
                        res.end();
                        return;
                    }
                    console.log('serviceAddress:%s', serviceAddress);
                    if (!serviceAddress) {
                        console.log('serviceAddress is not exist');
                        res.end();
                        return;
                    }

                    cache[serviceName] = serviceAddress;
                    console.log("cache"+  serviceName+": "+cache[serviceName]);

		            res.send(cache[serviceName]);

                    //执行反向代理
                    //proxy.web(req, res, {
                    //    target: 'http://' + serviceAddress //目标地址
                    //});
                });
            });
        }
    })

    app.listen(PORT, function () {
        console.log('server is running at %d', PORT);
    })
}
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Demo</title>
</head>
<body>
<div id="console"></div>
<div id="container">
    <h1>
        hello world
    </h1>
</div>
<button id="btn" >点我一下调用服务</button>

</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
    $(function () {
        $("#btn").click(function () {
            //alert("hello world");
            $.ajax({
                method: 'GET',
                url: 'http://192.168.80.128:8084/hello',
                headers: {
                    'Service-Name': 'HelloService/Baidu',
                    'key': 'url'
                },
                success: function (data) {
                    // 拿到的data是存的 https://www.baidu.com
                    $("#console").text(data);
                    //window.open(data)
                }
            })
        });

    })
</script>
</html>
// static.js

const express = require('express');
const app = express();

app.use(express.static('./'));


app.listen(3000, () => {
    console.log('running at 3000');
})