最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

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

引入 Node.js 之后,我們勢必要面臨以下幾個問題:

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

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

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

部署方案

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

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

灰度方式

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

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

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

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

轉(zhuǎn)

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

健康檢查

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

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

  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);
    });
  });

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

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

最后的解決辦法有三種:

禁用 HTTP Agent,即在在調(diào)用 get 方法時額外添加參數(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);
    });
  });

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

 http.globalAgent.maxSockets = 1000;

在請求返回的時候及時主動斷開連接:

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

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

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

相關(guān)文章

最新評論

文山县| 湄潭县| 宜宾市| 长沙县| 澎湖县| 遵义县| 金寨县| 台前县| 九江县| 滨州市| 连云港市| 兴国县| 瓦房店市| 宁都县| 普宁市| 平罗县| 资源县| 鄄城县| 疏附县| 曲阜市| 会昌县| 乐业县| 特克斯县| 阿鲁科尔沁旗| 井陉县| 河北省| 林口县| 上杭县| 栾城县| 丰县| 綦江县| 建德市| 湄潭县| 峡江县| 阿合奇县| 闻喜县| 利川市| 平邑县| 柞水县| 莱西市| 桂林市|