欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于NodeJS的前后端分離的思考與實(shí)踐(六)Nginx + Node.js + Java 的軟件棧部署實(shí)踐

 更新時(shí)間:2014年09月26日 11:17:26   投稿:hebedich  
關(guān)于前后端分享的思考,我們已經(jīng)有五篇文章闡述思路與設(shè)計(jì)。本文介紹淘寶網(wǎng)收藏夾將 Node.js 引入傳統(tǒng)技術(shù)棧的具體實(shí)踐。

淘寶網(wǎng)線上應(yīng)用的傳統(tǒng)軟件棧結(jié)構(gòu)為 Nginx + Velocity + Java,即:

在這個(gè)體系中,Nginx 將請(qǐng)求轉(zhuǎn)發(fā)給 Java 應(yīng)用,后者處理完事務(wù),再將數(shù)據(jù)用 Velocity 模板渲染成最終的頁(yè)面。

引入 Node.js 之后,我們勢(shì)必要面臨以下幾個(gè)問(wèn)題:

技術(shù)棧的拓?fù)浣Y(jié)構(gòu)該如何設(shè)計(jì),部署方式該如何選擇,才算是科學(xué)合理?項(xiàng)目完成后,該如何切分流量,對(duì)運(yùn)維來(lái)說(shuō)才算是方便快捷?遇到線上的問(wèn)題,如何最快地解除險(xiǎn)情,避免更大的損失?如何確保應(yīng)用的健康情況,在負(fù)載均衡調(diào)度的層面加以管理?承系統(tǒng)拓?fù)?/p>

按照我們?cè)谇昂蠖朔蛛x的思考與實(shí)踐(二)- 基于前后端分離的模版探索一文中的思路,Velocity 需要被 Node.js 取代,從而讓這個(gè)結(jié)構(gòu)變成:

這當(dāng)然是最理想的目標(biāo)。然而,在傳統(tǒng)棧中首次引入 Node.js 這一層畢竟是個(gè)新嘗試。為了穩(wěn)妥起見(jiàn),我們決定只在收藏夾的寶貝收藏頁(yè)面(shoucang.taobao.com/item_collect.htm)啟用新的技術(shù),其它頁(yè)面沿用傳統(tǒng)方案。即,由 Nginx 判斷請(qǐng)求的頁(yè)面類型,決定這個(gè)請(qǐng)求究竟是要轉(zhuǎn)發(fā)給 Node.js 還是 Java。于是,最后的結(jié)構(gòu)成了:

部署方案

上面的結(jié)構(gòu)看起來(lái)沒(méi)什么問(wèn)題了,但其實(shí)新問(wèn)題還等在前面。在傳統(tǒng)結(jié)構(gòu)中,Nginx 與 Java 是部署在同一臺(tái)服務(wù)器上的,Nginx 監(jiān)聽(tīng) 80 端口,與監(jiān)聽(tīng)高位 7001 端口的 Java 通信?,F(xiàn)在引入了 Node.js ,需要新跑一個(gè)監(jiān)聽(tīng)端口的進(jìn)程,到底是將 Node.js 與 Nginx + Java 部署在同一臺(tái)機(jī)器,還是將 Node.js 部署在單獨(dú)的集群呢?
我們來(lái)比較一下兩種方式各自特點(diǎn):

淘寶網(wǎng)收藏夾是一個(gè)擁有千萬(wàn)級(jí)日均 PV 的應(yīng)用,對(duì)穩(wěn)定性的要求性極高(事實(shí)上任何產(chǎn)品的線上不穩(wěn)定都是不能接受的)。如果采用同集群部署方案,只需要一次文件分發(fā),兩次應(yīng)用重啟即可完成發(fā)布,萬(wàn)一需要回滾,也只需要操作一次基線包。性能上來(lái)說(shuō),同集群部署也有一些理論優(yōu)勢(shì)(雖然內(nèi)網(wǎng)的交換機(jī)帶寬與延時(shí)都是非常樂(lè)觀的)。至于一對(duì)多或者多對(duì)一的關(guān)系,理論上可能做到服務(wù)器更加充分的利用,但相比穩(wěn)定性上的要求,這一點(diǎn)并不那么急迫需要去解決。所以在收藏夾的改造中,我們選擇了同集群部署方案。

灰度方式

為了保證最大程度的穩(wěn)定,這次改造并沒(méi)有直接將 Velocity 代碼完全去掉。應(yīng)用集群中有將近 100 臺(tái)服務(wù)器,我們以服務(wù)器為粒度,逐漸引入流量。也就是說(shuō),雖然所有的服務(wù)器上都跑著 Java + Node.js 的進(jìn)程,但 Nginx 上有沒(méi)有相應(yīng)的轉(zhuǎn)發(fā)規(guī)則,決定了獲取這臺(tái)服務(wù)器上請(qǐng)求寶貝收藏的請(qǐng)求是否會(huì)經(jīng)過(guò) Node.js 來(lái)處理。其中 Nginx 的配置為:

location = "/item_collect.htm" {
  proxy_pass http://127.0.0.1:6001; # Node.js 進(jìn)程監(jiān)聽(tīng)的端口
}

只有添加了這條 Nginx 規(guī)則的服務(wù)器,才會(huì)讓 Node.js 來(lái)處理相應(yīng)請(qǐng)求。通過(guò) Nginx 配置,可以非常方便快捷地進(jìn)行灰度流量的增加與減少,成本很低。如果遇到問(wèn)題,可以直接將 Nginx 配置進(jìn)行回滾,瞬間回到傳統(tǒng)技術(shù)棧結(jié)構(gòu),解除險(xiǎn)情。

第一次發(fā)布時(shí),我們只有兩臺(tái)服務(wù)器上啟用了這條規(guī)則,也就是說(shuō)大致有不到 2% 的線上流量是走 Node.js 處理的,其余的流量的請(qǐng)求仍然由 Velocity 渲染。以后視情況逐步增加流量,最后在第三周,全部服務(wù)器都啟用了。至此,生產(chǎn)環(huán)境 100% 流量的商品收藏頁(yè)面都是經(jīng) Node.js 渲染出來(lái)的(可以查看源代碼搜索 Node.js 關(guān)鍵字)。

轉(zhuǎn)

灰度過(guò)程并不是一帆風(fēng)順的。在全量切流量之前,遇到了一些或大或小的問(wèn)題。大部分與具體業(yè)務(wù)有關(guān),值得借鑒的是一個(gè)技術(shù)細(xì)節(jié)相關(guān)的陷阱。

健康檢查

在傳統(tǒng)的架構(gòu)中,負(fù)載均衡調(diào)度系統(tǒng)每隔一秒鐘會(huì)對(duì)每臺(tái)服務(wù)器 80 端口的特定 URL 發(fā)起一次 get 請(qǐng)求,根據(jù)返回的 HTTP Status Code 是否為 200 來(lái)判斷該服務(wù)器是否正常工作。如果請(qǐng)求 1s 后超時(shí)或者 HTTP Status Code 不為 200,則不將任何流量引入該服務(wù)器,避免線上問(wèn)題。

這個(gè)請(qǐng)求的路徑是 Nginx -> Java -> Nginx,這意味著,只要返回了 200,那這臺(tái)服務(wù)器的 Nginx 與 Java 都處于健康狀態(tài)。引入 Node.js 后,這個(gè)路徑變成了 Nginx -> Node.js -> Java -> Node.js -> Nginx。相應(yīng)的代碼為:

  var http = require('http');
  app.get('/status.taobao', function(req, res) {
    http.get({
      host: '127.1',
      port: 7001,
      path: '/status.taobao'
    }, function(res) {
      res.send(res.statusCode);
    }).on('error', function(err) {
      logger.error(err);
      res.send(404);
    });
  });

但是在測(cè)試過(guò)程中,發(fā)現(xiàn) Node.js 在轉(zhuǎn)發(fā)這類請(qǐng)求的時(shí)候,每六七次就有一次會(huì)耗時(shí)幾秒甚至十幾秒才能得到 Java 端的返回。這樣會(huì)導(dǎo)致負(fù)載均衡調(diào)度系統(tǒng)認(rèn)為該服務(wù)器發(fā)生異常,隨即切斷流量,但實(shí)際上這臺(tái)服務(wù)器是能夠正常工作的。這顯然是一個(gè)不小的問(wèn)題。

排查一番發(fā)現(xiàn),默認(rèn)情況下, Node.js 會(huì)使用 HTTP Agent 這個(gè)類來(lái)創(chuàng)建 HTTP 連接,這個(gè)類實(shí)現(xiàn)了 socket 連接池,每個(gè)主機(jī)+端口對(duì)的連接數(shù)默認(rèn)上限是 5。同時(shí) HTTP Agent 類發(fā)起的請(qǐng)求中默認(rèn)帶上了 Connection: Keep-Alive,導(dǎo)致已返回的連接沒(méi)有及時(shí)釋放,后面發(fā)起的請(qǐng)求只能排隊(duì)。

最后的解決辦法有三種:

禁用 HTTP Agent,即在在調(diào)用 get 方法時(shí)額外添加參數(shù) agent: false,最后的代碼為:

  var http = require('http');
  app.get('/status.taobao', function(req, res) {
    http.get({
      host: '127.1',
      port: 7001,
      agent: false,
      path: '/status.taobao'
    }, function(res) {
      res.send(res.statusCode);
    }).on('error', function(err) {
      logger.error(err);
      res.send(404);
    });
  });

設(shè)置 http 對(duì)象的全局 socket 數(shù)量上限:

 http.globalAgent.maxSockets = 1000;

在請(qǐng)求返回的時(shí)候及時(shí)主動(dòng)斷開(kāi)連接:

http.get(options, function(res) {
  }).on("socket", function (socket) {
  socket.emit("agentRemove"); // 監(jiān)聽(tīng) socket 事件,在回調(diào)中派發(fā) agentRemove 事件
});

實(shí)踐上我們選擇第一種方法。這么調(diào)整之后,健康檢查就沒(méi)有再發(fā)現(xiàn)其它問(wèn)題了。

Node.js 與傳統(tǒng)業(yè)務(wù)場(chǎng)景結(jié)合的實(shí)踐才剛剛起步,仍然有大量值得深入挖掘的優(yōu)化點(diǎn)。比比如,讓 Java 應(yīng)用徹底中心化后,是否可以考分集群部署,以提高服務(wù)器利用率?;蛘?,發(fā)布與回滾的方式是否能更加靈活可控。等等細(xì)節(jié),都值得再進(jìn)一步研究。

相關(guān)文章

  • nodejs 日志模塊winston的使用方法

    nodejs 日志模塊winston的使用方法

    本篇文章主要介紹了nodejs 日志模塊winston的使用方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-05-05
  • 基于NodeJS的前后端分離的思考與實(shí)踐(六)Nginx + Node.js + Java 的軟件棧部署實(shí)踐

    基于NodeJS的前后端分離的思考與實(shí)踐(六)Nginx + Node.js + Java 的軟件棧部署實(shí)踐

    關(guān)于前后端分享的思考,我們已經(jīng)有五篇文章闡述思路與設(shè)計(jì)。本文介紹淘寶網(wǎng)收藏夾將 Node.js 引入傳統(tǒng)技術(shù)棧的具體實(shí)踐。
    2014-09-09
  • 解決修復(fù)npm安裝全局模塊權(quán)限的問(wèn)題

    解決修復(fù)npm安裝全局模塊權(quán)限的問(wèn)題

    今天小編就為大家分享一篇解決修復(fù)npm安裝全局模塊權(quán)限的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-05-05
  • NodeJS模塊與ES6模塊系統(tǒng)語(yǔ)法及注意點(diǎn)詳解

    NodeJS模塊與ES6模塊系統(tǒng)語(yǔ)法及注意點(diǎn)詳解

    這篇文章主要給大家介紹了關(guān)于NodeJS模塊與ES6模塊系統(tǒng)語(yǔ)法及注意點(diǎn)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-01-01
  • nodejs與瀏覽器中全局對(duì)象區(qū)別點(diǎn)總結(jié)

    nodejs與瀏覽器中全局對(duì)象區(qū)別點(diǎn)總結(jié)

    在本篇文章里小編給大家整理的是一篇關(guān)于nodejs與瀏覽器中全局對(duì)象區(qū)別點(diǎn)總結(jié)內(nèi)容,對(duì)此有需要的朋友們可以學(xué)習(xí)下。
    2021-12-12
  • 詳解Node.js如何處理ES6模塊

    詳解Node.js如何處理ES6模塊

    學(xué)習(xí)JavaScript語(yǔ)言,你會(huì)發(fā)現(xiàn)它有兩種格式的模塊。一種是ES6模塊,簡(jiǎn)稱ESM;另一種是Node.js專用的CommonJS模塊,簡(jiǎn)稱 CJS。這兩種模塊不兼容。很多人使用Node.js,只會(huì)用require()加載模塊,遇到ES6模塊就不知道該怎么辦。本文就來(lái)談?wù)凟S6模塊在Node.js里面怎么使用。
    2021-05-05
  • NodeJs環(huán)境安裝與配置的實(shí)現(xiàn)步驟

    NodeJs環(huán)境安裝與配置的實(shí)現(xiàn)步驟

    本文主要介紹了NodeJs環(huán)境安裝與配置,包括配置環(huán)境和配置國(guó)內(nèi)鏡像,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-01-01
  • nodejs開(kāi)發(fā)微博實(shí)例

    nodejs開(kāi)發(fā)微博實(shí)例

    本文給大家分享的是使用node.js實(shí)現(xiàn)開(kāi)發(fā)微博的實(shí)例,主要是看了nodejs開(kāi)發(fā)指南之后發(fā)現(xiàn)書(shū)上的代碼很多已經(jīng)不能用了,原因是express版本升級(jí)了,所以今天就嘗試著吧開(kāi)發(fā)微博的實(shí)例也升下級(jí),推薦給大家。
    2015-03-03
  • 詳解nodejs 文本操作模塊-fs模塊(四)

    詳解nodejs 文本操作模塊-fs模塊(四)

    本篇文章詳細(xì)的講訴fa.fstat方法,這個(gè)State對(duì)象中,包含的數(shù)據(jù)都有哪些,并且他們分別代表的含義是什么。具有一定的參考價(jià)值,有興趣的可以了解一下。
    2016-12-12
  • 淺談node node-sass sass-loader版本對(duì)應(yīng)問(wèn)題

    淺談node node-sass sass-loader版本對(duì)應(yīng)問(wèn)題

    本文主要介紹了淺談node node-sass sass-loader版本對(duì)應(yīng)問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09

最新評(píng)論