[NodeJS] Express 在 JSDC.tw 2012 的效能分析

首先繼續廣播一下,雖然研討會結束了,但是 JSDC.tw 2012 議程仍舊有資料的更新,如果沒有參與到的人可以前往查看。然後我出糗的片段就可以跳過不要看了這樣。

然後其實這一篇是我的檢討文(喂


NodeJS + Express

我的投影片原始碼,可以在我的 gitHub 上面找到。基本上投影片的原理我就不在這邊炫耀充版面,主要使用的東西有下列這些,

  • NodeJS, v0.6.18
  • Express, v2.5.9
  • Redis, v2.2.12
  • Socket.IO, v0.9.6
  • Forever, v0.9.1

首先,Socket.IO 是負責這次投影片的所有互動功能,Redis 則是負責 Session 與 Message 的處理與儲存,Forever 則是一個 daemon,可以把 nodejs 跑在背景服務這樣。Express 應該就不用多說了,他是提供前後端與頁面處理這樣。

實際狀況

首先我先把時間切開來,我開始講投影片的時間大概是 17:07 分左右,五分鐘有 1191 個連線,然後在 17:11:50 的時候開始出現 504 Gateway timeout 的錯誤。

扣掉 120 個 504 的連線錯誤,然後扣掉額外的連線(可能由 jsdc 連外跳轉的連線),指向 jsdc 的連線約莫 192 個,剩下有絕大部分是連去我的 jquery 的 plugin 畫面,所以略過不計。

所以五分鐘以內,國際會議廳的連入數量是 539 個連線數(HTTP 200 的狀態

這 539 個連線數,由 Redis 的紀錄來看,訊息資料量總共是 132 條,包含 Session 紀錄與聊天紀錄。然後繪圖資料量大概是 2126 上下,實際的繪圖資料量沒辦法統計,因為瞬間就被擠爆了,所以那些 socket 應該根本沒有廣播出去。

操作環境

所以,我們概括來看一下,

  • 機器是 Amazon EC2 micro,我特別在 JSDC 前一天將他轉移到日本機房
  • Ubuntu 12.04LTS
  • net.core.somaxconn = 128
  • NodeJS 環境忘記改,當天是 development mode
  • 總共連線人數依照 session 來看有 110 個上下(只看國際會議廳當天連線,其他 IP 不計入
  • Express 需要處理前端畫面呈現
  • Socket.IO 最忙,每個請求進來都是以廣播的方式送出
  • Redis 紀錄所有 socket 動作,也很忙

連線的動作大概是這樣,

Express
Socket.IO
Nginx
Client
Redis Server
換手給 NodeJS,順便做掉一些靜態檔案
處理 Nginx 與 Client 發出的請求
對 Client 發出廣播
紀錄 Session/Message/Draw 軌跡
同時將資料寫入 log 中,紀錄所有動作
這是隨便亂畫的傳輸狀態示意狀況

Amazon EC2 連線紀錄

由於實在無法確切的紀錄下當時的連線數量,當時以 AWS 的 Network In/Out 紀錄來看,最高峰值分別是,

  • Network Out: 49,748,111 Bytes
  • Network In: 20,194,283 Bytes

以上的峰值在 5 分鐘從 1,973,019 增加至 49,748,111 之後就開始慢慢下跌,所以說,以 AWS micro 等級的機器來說,這五分鐘內的 CPU Utilization 從 15% 上升到 95.9%,這時候就開始有 504 Gateway timeout 的情況發生了。

對於 Socket.IO 與 Express 的紀錄檔來看,其實整個紀錄狀況都還算蠻健康的,如果以會場內,110 個人次(以 session 來看,扣掉第一次存取的非快取狀態,那麼可以計算出,

  • 每個 socket 回應 header 單純以 21 bytes 計算,剩餘量 4,947,511 共造成 235,595 次的回應
  • 資料流進入的量單純以發出請求的 header 計算(871 bytes,共有 23,185 次請求

以 HTTP request header 來看大概會是這樣,

GET / HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) 
Gecko/20091102 Firefox/3.5.5
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://jsdc.hinablue.me/

以 HTTP response header 來看大概是這樣,

HTTP/1.1 200 OK
X-Powered-By: Express/0.9.6
Server: Nginx/1.1.0
Content-Type: text/html;charset=UTF-8
Content-Length: 21
Date: Sat, 19 May 2012 00:32:46 GMT

小結

其實中研院國際會議廳的網路相當穩定(非常棒!讓我撐了 2 分鐘投影片沒有掛掉,雖然到最後還是因為伺服器沒有反應而投影片操作失靈,不過感覺還是非常穩定的!

整體的狀況看來,有幾個有趣的地方,

  • Amazon EC2 micro 無法承載超大量連線(或許瞬間不行?
  • 其實我試過連 small 也不太行
  • Socket.IO 使用 xhr-polling 效率會爆跌(封測的時候發現的
  • Express 如果把某些靜態檔案由 Nginx 做掉,效率會更好
  • 下次記得要開 production mode(遮臉
  • Redis Server 對瞬間資料寫入很穩定
  • 可以把 net.core.somaxconn 開大一點(不確定對 websocket 有無幫助
  • Express 跟 Socket.IO 之間的溝通,應該可以用 callback 的方式改寫
  • NodeJS 真的不要在背景做複雜的運算
  • 下次這種超大連線應該可以用 cluster 改寫
  • 但是 Amazon EC2 要多核心很貴,所以上述那一點就算了這樣

這次 JSDC.tw 算是自己對於 NodeJS 的一個愉快的壓測體驗(喂,所以我才跟 Ben 說我當然不要講 30 分鐘的 Session 啊,不然才上台 2 分鐘投影片就被玩壞了怎麼辦 XD

最後,歡迎大家加入 NodeJS 台灣 大家一起來玩吧!

Hina Chen
偏執與強迫症的患者,算不上是無可救藥,只是我已經遇上我的良醫了。
Taipei