zookeeper注册服务信息---注册服务信息/获取服务信息(nodejs typescrip)

2017-10-17更新 修复无法自动建立多级目录问题。

使用node-zookeeper-client,其它的安装不上,各种报错之后放弃。

核心功能:适用于RPC服务端  zookeeper 注册节点信息, 适用于RPC客户端获取节点信息,并另有简单负载均衡功能。

npm install node-zookeeper-client

简单说zookeeperRPC,包含如下功能注册服务端信息(znode临时节点),移除注册节点。获取服务端节点,
获取负载服务端节点。

注意:zookeeper 客户端连接时在某些环境下会出现    执行exists时报  UNIMPLEMENTED[-6] 继续执行建立节点和设置值时会连续报错,调整配置后 执行exists时报  UNIMPLEMENTED[-6]

配置调整如下

public static _option:zookeeper.Option ={
        sessionTimeout:60000,
        spinDelay:5000,
        retries:3,
};

其它方法不报错了。具体原因不详。

zookeeperRPC

核心功能:

1)register:注册zookeeper节点信息

2)logout:注销zookeeper节点信息

3)getRegistration:获取注册的服务器信息

4)getLoadBalanceServer:获取负载均衡后的服务器地址


  
  
import { ZookeeperHelper } from '../../common/ZookeeperHelper'; import * as zookeeper from 'node-zookeeper-client'; import { Registration } from "../../Model/Registration"; var loadbalance = require('loadbalance'); //var cache = require('../Model/local-storage'); /**  * ZookeeperRPC  *  * @export  * @class ZookeeperRPC  */ export class ZookeeperRPC {     protected _zookeeperHelper: ZookeeperHelper = new ZookeeperHelper();     protected _getLoadBalanceServerCallBack: (loadbalance?: string) => void;     protected _cache: Array<string>;     protected _path: string;     public registerTransaction() {         //cache.setItem("ROUTE_KEY", {});     }
    /**      * 字符串format "sadfadf{0}vvvv{1}"      *      * @param {string} string      * @param {...any[]} args      * @returns {string}      * @memberof ZookeeperRPC      */     public stringFormat(string: string, ...args: any[]): string {         //var args = arguments;         return string.replace(/\{(\d+)\}/g,             function (m, i) {                 return args[i];             });     }
    /**      * 注册服务器信息      *      * @param {string} path      * @param {Registration} reg      * @memberof zookeeperRPC      */     public register(path: string, reg: Registration) {         this._zookeeperHelper.connect();         this._path = path;         //this._client.once("connected", callback);         this._zookeeperHelper.exists(this._path, (error, stat) => {             console.log("stat" + stat);             console.log("error" + error);             //console.log("::::::::::::::::::::::" + this._zookeeperHelper._client.getSessionId().toString('hex'));             reg.sessionid = this._zookeeperHelper._client.getSessionId().toString('hex');             var dataBuffer = new Buffer(JSON.stringify(reg));             if (stat) {                 //console.log('节点存在.');                 // console.log(this._path + "/" + ipport);                 this._zookeeperHelper.setData(this._path, dataBuffer);                 //this._zookeeperHelper.close();
            } else {                 //console.log('register 该节点不存在.');                 //console.log('该节点不存在.' + path);                 //this._path="/tttt";                 this._zookeeperHelper.mkdirp(this._path, (error, path) => {                     //console.log("this._path:" + this._path);                     if (error) {                         console.log("tttttttttt:" + error);                     }                     //console.log("path 123456 ::::::" + path);                     this._zookeeperHelper.setData(this._path, dataBuffer);                 });                 // let path = "/servicecenter-dev/services/" + reg.servicenamespace + "/providers";///" + reg.ip + ":" + reg.port;
                // this._zookeeperHelper.create(path, dataBuffer);             }         });     }
    /**      * 注销-服务信息      *      * @param {string} path      * @memberof ZookeeperRPC      */     public logout(path: string) {         this._zookeeperHelper.remove(path);     }
    /**      * 获取注册服务信息      *      * @param {string} path      * @param {((error: Error | zookeeper.Exception, children: string[], stat: zookeeper.Stat) => void)} callback      * @memberof ZookeeperRPC      */     public getRegistration(path: string, callback: (error: Error | zookeeper.Exception, children: string[], stat: zookeeper.Stat) => void) {         this._zookeeperHelper.getPathServices(path, callback);     }
    /**      * 获取负载均衡后的服务器地址      *      * @param {string} path      * @param {((error: Error | zookeeper.Exception, children: string[], stat: zookeeper.Stat) => void)} callback      * @memberof ZookeeperRPC      */     public getLoadBalanceServer(path: string, callback: (loadbalance?: string) => void) {         this._getLoadBalanceServerCallBack = callback;         if (this._cache) {             let engine = loadbalance.roundRobin(this._cache);             let pick = engine.pick();             callback(pick);             return;         } else {             this._zookeeperHelper.getPathServices(path, (error: Error | zookeeper.Exception, children: string[], stat: zookeeper.Stat) => {                 if (error) {                     return;                 }                 if (children.length > 0) {                     //设置本地缓存和负载策略                     this._cache = children;                     //cache.setItem("ROUTE_KEY")[path] = loadbalance.roundRobin(children);                     let engine = loadbalance.roundRobin(children);                     let pick = engine.pick();                     callback(pick);                     /*测试                     for (var index = 0; index < 100; index++) {                         var pick = engine.pick();                         callback(pick);                     }*/                     return;                 }             });         }     } } /* var z = new ZookeeperRPC(); var reg: Registration = {     servicenamespace: "YinXin.BaoXian.RPC.test",     sessionid: "z._client.getSessionId().toString()",     ip: "127.0.0.888",     port: 2011,     boostpercent: 10 }; z.register("/test1.1", reg); z.register("/test1.2", reg); */

ZookeeperHelper

核心功能:

1)md_full_path:建立zookeeper多节点信息,如/test/BBB/CCC/DDD/EEE 会直接依次全部建立完毕。

2)其它 功能详见注释。

import { BaseZookeeper } from './BaseZookeeper';
import * as zookeeper from 'node-zookeeper-client';
import { Registration } from "../Model/Registration";
/**
 * ZookeeperHelper
 * 
 * @export
 * @class ZookeeperHelper
 * @extends {BaseZookeeper}
 */
export class ZookeeperHelper extends BaseZookeeper {
    protected _getPathServices_callback?: (error: Error | zookeeper.Exception, children: string[], stat: zookeeper.Stat) => void;




    /**
     * 注册服务器信息
     * 
     * @param {string} path 
     * @param {Registration} reg 
     * @memberof zookeeperHelper
     */
    public register(path: string, reg: Registration) {
        this.connect();
        //this._client.once("connected", callback);
        reg.sessionid = this._client.getSessionId().toString('hex');
        // console.log("::::::::::::::::::::::" + this._client.getSessionId().toString('hex'));
        var dataBuffer = new Buffer(JSON.stringify(reg));
        this.create(path, dataBuffer);

    }
    /**
     * 连接
     * 
     * @memberof ZookeeperHelper
     */
    public connect() {
        let state = this._client.getState();
        if (state == zookeeper.State.DISCONNECTED) {
            //console.log("当前连接状态!" + state);

            this._client.connect();
            //console.log("已连接!");
            let sessionTimeout = this._client.getSessionTimeout();
            //console.log(sessionTimeout);

            //console.log(this._client);
        }


    }

    /**
     * 关闭
     * 
     * @memberof ZookeeperHelper
     */
    public close() {
        console.log("Zookeeper 连接已关闭!");
        this._client.close();
    }

    /**
    * 注册节点信息
    * 
    * @param {string} path 
    * @param {(Buffer | null)} data 
    * @memberof zookeeperHelper
    */
    public create(path: string, data: Buffer | null) {
        this.connect();
        if (data) {
            this._client.create(path, data, (error: Error | zookeeper.Exception, path: string) => {
                this.create_callback(error, path);
            });
        }
        else {
            this._client.create(path, (error: Error | zookeeper.Exception, path: string) => {
                this.create_callback(error, path);
            });

        }

    }

    /**
     * create 回调
     * 
     * @param {(Error|zookeeper.Exception)} error 
     * @param {string} path 
     * @memberof zookeeperHelper
     */
    public create_callback(error: Error | zookeeper.Exception, path: string) {
        if (error) {
            console.log("zookeeper create error:" + error);
        }

    }

    /**
     * 移除该节点
     * 
     * @param {string} path 
     * @memberof zookeeperHelper
     */
    public remove(path: string) {
        this.connect();

        this._client.remove(path, -1, (error: Error | zookeeper.Exception) => {
            if (error) {
                console.log("zookeeper remove error:" + error);
                return;
            }
            console.log('Node is deleted.');

        })
    }

    /**
     * 是否存在该路径
     * 
     * @param {string} path 
     * @param {((error: Error | zookeeper.Exception, stat: zookeeper.Stat) => void)} callback 
     * @memberof zookeeperHelper
     */
    public exists(path: string, callback: (error: Error | zookeeper.Exception, stat: zookeeper.Stat) => void) {
        this.connect();
        this._client.exists(path, callback.bind(this));
    }
    public exists_callback(error: Error | zookeeper.Exception, stat: zookeeper.Stat) {
        if (error) {
            console.log(error);

            return;
        }
        if (stat) {
            console.log('节点存在.');
        } else {
            console.log('该节点不存在.');
        }
        console.log("exists关闭");

    }

    /**
     * 设置数据
     * 
     * @param {string} path 
     * @param {Buffer} data 
     * @memberof zookeeperHelper
     */
    public setData(path: string, data: Buffer) {
        this.connect();
        //console.log("fffffffffff::::::::" + path);
        this._client.setData(path, data, (error, stat) => {
            //console.log("22222222222::::::::" + path);
            if (error) {
                console.log("zookeeper setData error:" + error);
                return;
            }
            if (stat) {
                //console.log(stat);
            } 
            console.log("setData执行完毕");

        });
    }

    /**
     * 获取数据
     * 
     * @param {string} path   
     * @memberof zookeeperHelper
     */
    public getData(path: string) {
        this.connect();
        this._client.getData(
            path,
            (event) => {
                console.log('Got event: %s.', event);
            },
            (error, data, stat) => {
                if (error) {
                    console.log(error);
                    return;
                }
                if (stat) {
                    console.log(stat);
                    console.log(data.toString());
                } else {
                    console.log(stat);
                }

            });
    }

    /**
     * 获取zookeeper下所有节点
     * 
     * @param {string} path 
     * @memberof zookeeperHelper
     */
    public getPathServices(path: string, callback: (error: Error | zookeeper.Exception, children: string[], stat: zookeeper.Stat) => void) {
        this.connect();
        this._getPathServices_callback = callback;
        this._client.getChildren(
            path,
            /*(event) => {
                //console.log('Got Services watcher event: %s', event);
                this.getPathServices(this._service_root_path);
            },*/
            (error, children, stat) => {
                if (this._getPathServices_callback) {
                    this._getPathServices_callback(error, children, stat);
                }
                if (error) {

                    return;
                }
                console.log(children);
                this._getPathServices_callback = undefined;

            }
        );
    }
    /**
     * 建立路径-临时znode
     * 
     * @param {string} path 
     * @param {((error: Error | zookeeper.Exception, path: string) => void)} [callback] 
     * @memberof ZookeeperHelper
     */
    public mkdirp(path: string, callback?: (error: Error | zookeeper.Exception, path: string) => void) {
        this.connect();
        //this.md_full_path(path, callback);
        
        //console.log("执行mkdir");
        if (callback) {
            //console.log("执行临时Znode");
            this._client.mkdirp(path, zookeeper.CreateMode.EPHEMERAL, callback.bind(this));
        } else {
            this._client.mkdirp(path, (error, path) => {
                if (error) {
                    console.log("zookeeper mkdirp error :" + error);
                }
                // console.log("mkdirp  error:mkdirp:::::12345678910" + error);

            });
        }
    }
    protected _mdPath?: string[];
    protected _mdIndex: number;

    /**
     * 建立全目录
     * 
     * @param {string} path 
     * @param {((error: Error | zookeeper.Exception, path: string) => void)} [callback] 
     * @memberof ZookeeperHelper
     */
    public md_full_path(path: string, callback?: (error: Error | zookeeper.Exception, path: string) => void) {

        path = path.substring(1, path.length);
        //console.log("pppp:" + path);
        this._mdPath = path.split("/");
        //console.log("pppccccp:" + this._mdPath);
        this._mdIndex = 0;
        //for (let i = 0; i < len; i++) {
        this.md("/" + this._mdPath[0], callback);

    }
    /**
     * 建立目录递归
     * 
     * @private
     * @param {string} path 
     * @param {((error?: Error | zookeeper.Exception, path?: string) => void)} [callback] 
     * @memberof ZookeeperHelper
     */
    private md(path: string, callback?: (error?: Error | zookeeper.Exception, path?: string) => void) {
        this.exists(path, (error: Error | zookeeper.Exception, stat: zookeeper.Stat) => {
            //console.log("fdffffff:" + this._mdPath + " " + this._mdIndex + " ");
            this._mdIndex++;
            if (error && callback) {
                //console.log("md " + error);
                callback(error, undefined);
                return;
            } else {
                //console.log("sssssssssssss    ");
                if (stat == undefined) {//目录不存在
                    //console.log(path + "目录不存在");
                    var creatModel = zookeeper.CreateMode.PERSISTENT;
                    if (this._mdPath && this._mdPath.length < this._mdIndex) {
                        creatModel = zookeeper.CreateMode.EPHEMERAL;
                        //console.log("临时目录");
                        //if (callback) callback(error, path);
                    }

                    this._client.mkdirp(path, creatModel, (error, path) => {

                        //this._client.mkdirp(path, (error, path) => {
                        if (error) {
                            console.log("zookeeper mkdirp error :" + error);
                        }
                        this.performRecursion(error, path, callback);
                    });
                }
                else {//目录存在
                    //console.log(path + "目录存在");
                    //console.log("callback" + callback)
                    this.performRecursion(error, path, callback);
                    /* var mdpath = this.get_mdpath()
                     if (mdpath != "") {
                         this.md(mdpath, callback);
                         return;
                     } else {
                         if (callback)
                             callback(error, path);
                     }*/
                }
            }
        })
    }
    /**
     *判断递归路径是否有值,如存在则执行递归。
     * 
     * @private
     * @param {(Error | zookeeper.Exception)} error 
     * @param {string} path 
     * @param {((error?: Error | zookeeper.Exception, path?: string) => void)} [callback] 
     * @memberof ZookeeperHelper
     */
    private performRecursion(error: Error | zookeeper.Exception, path: string, callback?: (error?: Error | zookeeper.Exception, path?: string) => void) {
        var mdpath = this.get_mdpath();
        //console.log("performRecursion" + mdpath);
        if (mdpath != "") {
            this.md(mdpath, callback);
        } else if (callback) {
            //console.log("zhixing====================:");
            callback(error, path);
        }
    }
    /**
     * 获取递归的path路径
     * 
     * @private
     * @type {string}
     * @memberof ZookeeperHelper
     */
    private get_mdpath() {
        var mdpath: string = "";
        //console.log("mdpath:" + this._mdPath)
        //console.log("_mdIndex_mdIndex_mdIndex:" + this._mdIndex)
        if (this._mdPath && this._mdIndex) {
            mdpath = "";
            let len = this._mdPath.length;
            for (let i = 0; i < this._mdIndex; i++) {
                mdpath += "/" + this._mdPath[i];
            }
            //this._mdIndex++;
            if (this._mdPath) {
                //console.log("fdffffff:" + " " + this._mdIndex + " " + this._mdPath.length);
                if (this._mdPath.length < this._mdIndex) {
                    //console.log("执行BBBBBB++ " + this._mdIndex);
                    //console.log(this._mdPath);
                    return "";
                }
            }
            //console.log("mdpath------------------:" + mdpath + "    " + this._mdIndex);

        }
        return mdpath;
    }


}


 

BaseZookeeper

import * as zookeeper from "node-zookeeper-client";
import { ZookeeperEvent } from "../Enum/ZookeeperEvent";
/**
 * BaseZookeeper
 * 
 * @export
 * @class BaseZookeeper
 */
export class BaseZookeeper {
    public static _connectionString = "192.168.145.3:2281";
    public static _option: zookeeper.Option;
    public _client: zookeeper.Client;
    public _hosts: string = "192.168.145.3:2281,192.168.145.4:2281,192.168.145.7:228";
    public _service_root_path: string = "/";
    constructor() {
        this._client = zookeeper.createClient(BaseZookeeper._connectionString, BaseZookeeper._option);
        this.startClinetListener();
    }

    /**
     * 创建客户端
     * 
     * @memberof BaseZookeeper
     */
    public createClinet(){
        this._client = zookeeper.createClient(BaseZookeeper._connectionString, BaseZookeeper._option);
        this.startClinetListener();
    }

    /**
     * 启动客户端监听
     * 
     * @memberof BaseZookeeper
     */
    public startClinetListener() {
        this._client.addListener(ZookeeperEvent.STATE, this.listenStateHandle.bind(this));
        this._client.addListener(ZookeeperEvent.CONNECTED, this.listenConnectedHandle.bind(this));
        this._client.addListener(ZookeeperEvent.CONNECTEDREADONLY, this.listenConnectedreadonlyHandle.bind(this));
        this._client.addListener(ZookeeperEvent.DISCONNECTED, this.listenDisconnectedHandle.bind(this));
        this._client.addListener(ZookeeperEvent.EXPIRED, this.listenExpiredHandle.bind(this));
        this._client.addListener(ZookeeperEvent.AUTHENTICATIONFAILED, this.listenAuthenticationfailedHandle.bind(this));
    }
    /**
     * zookeeper State 监听
     * 
     * @param {zookeeper.State} state 
     * @memberof BaseZookeeper
     */
    public listenStateHandle(state: zookeeper.State) {
        console.log("zookeeper state:" + state);
        if (state === zookeeper.State.SYNC_CONNECTED) {
            console.log('Client state is changed to connected.');
        }
        if (state == zookeeper.State.EXPIRED) {//过期
            this.createClinet();
            this._client.connect();
            console.log("过期重新创建!");
        }
    }

    /**
     * zookeeper Connected 监听
     * 
     * @memberof BaseZookeeper
     */
    public listenConnectedHandle() {
        console.log("zookeeper Connected");
    }

    /**
     * zookeeper Connectedreadonly 监听
     * 
     * @memberof BaseZookeeper
     */
    public listenConnectedreadonlyHandle() {
        console.log("zookeeper Connectedreadonly");
    }

    /**
     * zookeeper Disconnected 监听
     * 
     * @memberof BaseZookeeper
     */
    public listenDisconnectedHandle() {
        console.log("zookeeper Disconnected");
    }

    /**
     * zookeeper Expired 监听
     * 
     * @memberof BaseZookeeper
     */
    public listenExpiredHandle() {
        console.log("zookeeper Expired");
    }

    /**
     * zookeeper Authenticationfailed 监听
     * 
     * @memberof BaseZookeeper
     */
    public listenAuthenticationfailedHandle() {
        console.log("zookeeper Authenticationfailed");
    }

}

enum

export enum ZookeeperEvent {
    STATE = "state",
    CONNECTED = "connected",
    CONNECTEDREADONLY = "connectedReadOnly",
    DISCONNECTED = "disconnected",
    EXPIRED = "expired",
    AUTHENTICATIONFAILED = "authenticationFailed",
  
}



 
 
 

                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值