基于nodejs+zookeeper服務(wù)發(fā)現(xiàn)

本文使用nodejs作為微服務(wù)API網(wǎng)關(guān)猴凹,從而將消費(fèi)端的請(qǐng)求痒筒,隨機(jī)路由到一個(gè)可用的服務(wù)節(jié)點(diǎn)上宰闰。核心代碼如下:

本文參考了《架構(gòu)探險(xiǎn)》輕量級(jí)服務(wù)架構(gòu)
本文示例代碼:node-zookeeper-demo

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;
var CONNECTION_STRING = '127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183';
var REGISTRY_ROOT = '/registry';

var app = express();

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

    //創(chuàng)建代理服務(wù)器對(duì)象并監(jiān)聽錯(cuò)誤事件
    var proxy = httpProxy.createProxyServer();
    proxy.on('error', function (err, req, res) {
        res.end();//輸出空白響應(yīng)數(shù)據(jù)
    });

    //啟動(dòng)web服務(wù)器
    app.use(express.static('public'));
    app.all('*', function (req, res) {
        //處理圖標(biāo)請(qǐng)求
        if (req.path == '/favicon.ico') {
            res.end();
            return;
        }
        //獲取服務(wù)名稱
        var serviceName = req.get('Service-Name');
        
        console.log('ServiceName:%s', serviceName);
        if (!serviceName) {
            console.log('Service-Name request header is not exist');
            res.end();
            return;
        }
        //獲取服務(wù)路徑
        var servicePath = REGISTRY_ROOT + "/" + serviceName;
        console.log('ServicePath:%s', servicePath);
        console.log('cache[serviceName]:'+JSON.stringify(cache));
        if (cache[serviceName]) {
        //if(false){
            //TODO
            /*zk.exists(servicePath, function (event) {
                if (event.NODE_DELETED) {
                    cache = {};
                }
            }, function (error, stat) {
                if (stat) {

                }
            })*/
            console.log("-----------cache---------------"+cache[serviceName]);
            proxy.web(req, res, {
                target: 'http://' + cache[serviceName] //目標(biāo)地址
            });

        }
        else {

            //獲取服務(wù)路徑下的地址節(jié)點(diǎn)
            zk.getChildren(servicePath, function (error, addressNodes) {
                if (error) {
                    console.log(error.stack);
                    res.end();
                    return;
                }
                var size = addressNodes.length;
                if (size == 0) {
                    console.log('address node is not exist');
                    res.end();
                    return;
                }
                //生成地址容器
                var addressPath = servicePath + "/";
                if (size == 1) {
                    //若只有唯一地址,則獲取該地址
                    addressPath += addressNodes[0];
                } else {
                    //若存在多個(gè)地址簿透,則隨機(jī)獲取一個(gè)地址
                    addressPath += addressNodes[parseInt(Math.random() * size)];
                }
                console.log('addressPath:%s', addressPath);
                //獲取服務(wù)地址
                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]);

                    //執(zhí)行反向代理
                    proxy.web(req, res, {
                        target: 'http://' + serviceAddress //目標(biāo)地址
                    });
                });

            });
        }

    });

    app.listen(PORT, function () {
        console.log('server is running at %d', PORT);
    });
}

使用supervisor app-gateway.js啟動(dòng)API網(wǎng)關(guān)后:(supervisor可以定時(shí)監(jiān)聽文件的變化移袍,代碼更新無需重啟)

啟動(dòng)網(wǎng)關(guān)

當(dāng)然也需要啟動(dòng)在上文《基于ZooKeeper的服務(wù)注冊(cè)實(shí)現(xiàn)》提到的兩個(gè)客戶端,讓服務(wù)在ZooKeeper上注冊(cè)老充。

測(cè)試頁(yè)面

<!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" >點(diǎn)我一下調(diào)用服務(wù)</button>

</body>
<script src="js/jquery-2.2.3.min.js"></script>
<script>
    $(function () {
        $("#btn").click(function () {
            //alert("hello world");
            $.ajax({
                method: 'GET',
                url: '/hello',
                headers: {
                    'Service-Name': 'HelloService'
                },
                success: function (data) {
                    $("#console").text(data);
                }
            })
        });

    })
</script>
</html>

點(diǎn)擊測(cè)試按鈕葡盗,在界面服務(wù)的顯示運(yùn)行結(jié)果"Hello"

運(yùn)行結(jié)果

AB測(cè)試(Apache Bench)模擬1000個(gè)用戶每次并發(fā)100請(qǐng)求:
:在測(cè)試前,將serviceName設(shè)為固定值:var serviceName='HelloService'

AB測(cè)試

閱讀本文啡浊,請(qǐng)結(jié)合上篇文章《基于ZooKeeper的服務(wù)注冊(cè)實(shí)現(xiàn)》進(jìn)行理解觅够。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市巷嚣,隨后出現(xiàn)的幾起案子喘先,更是在濱河造成了極大的恐慌,老刑警劉巖廷粒,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窘拯,死亡現(xiàn)場(chǎng)離奇詭異红且,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)树枫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門直焙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來景东,“玉大人砂轻,你說我怎么就攤上這事〗锿拢” “怎么了搔涝?”我有些...
    開封第一講書人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)和措。 經(jīng)常有香客問我庄呈,道長(zhǎng),這世上最難降的妖魔是什么派阱? 我笑而不...
    開封第一講書人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任诬留,我火速辦了婚禮,結(jié)果婚禮上贫母,老公的妹妹穿的比我還像新娘文兑。我一直安慰自己,他們只是感情好腺劣,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開白布绿贞。 她就那樣靜靜地躺著,像睡著了一般橘原。 火紅的嫁衣襯著肌膚如雪籍铁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,549評(píng)論 1 312
  • 那天趾断,我揣著相機(jī)與錄音拒名,去河邊找鬼。 笑死芋酌,一個(gè)胖子當(dāng)著我的面吹牛增显,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播隔嫡,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼甸怕,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了腮恩?” 一聲冷哼從身側(cè)響起梢杭,我...
    開封第一講書人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎秸滴,沒想到半個(gè)月后武契,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年咒唆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了届垫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡全释,死狀恐怖装处,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情浸船,我是刑警寧澤妄迁,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站李命,受9級(jí)特大地震影響登淘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜封字,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一黔州、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧阔籽,春花似錦流妻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至项贺,卻和暖如春君躺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背开缎。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工棕叫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人奕删。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓俺泣,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親完残。 傳聞我的和親對(duì)象是個(gè)殘疾皇子伏钠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)谨设,斷路器熟掂,智...
    卡卡羅2017閱讀 134,714評(píng)論 18 139
  • 前言 首先本文不討論為什么要服務(wù)化,包括服務(wù)化的優(yōu)點(diǎn)缺點(diǎn)扎拣。其次本文也不討論什么是微服務(wù)赴肚,也不討論微服務(wù)和SOA的區(qū)...
    章耿閱讀 2,482評(píng)論 1 16
  • ZooKeeper介紹 Zookeeper 分布式服務(wù)框架是 Apache Hadoop 的一個(gè)子項(xiàng)目素跺,它主要是用...
    Coselding閱讀 11,417評(píng)論 1 37
  • 算是看了一下午的六級(jí)吧,有人監(jiān)督誉券,而且還是彼此陌生的人互相監(jiān)督指厌,到底是完成了,盡管中途也說過再不想看了這種話踊跟,人總...
    曼特寧閱讀 252評(píng)論 1 0
  • 1617/10/30 周一 晴空萬里 咳咳~好了踩验,該說正事了……真不愿承認(rèn)自己是17年的大三黨。 坐在無聊的課堂...
    白羊逐夢(mèng)閱讀 626評(píng)論 4 2