Node和Java性能對比(僅供參考)

背景引出

線上網站遭受攻擊,首頁被強刷,致使服務器node性能過載,影響用戶正常頁面訪問。html

大體架構:客戶端發起請求 --> node(充當中間件,訪問後端API渲染頁面) --> java(處理業務邏輯)--> databasejava

現象&問題

現象 疑惑
Nodejs cup 滿負載 與Nodejs高性能不符?
後端 Java 的負載和Node相反 怎麼性能會優於Nodejs?

node和java來個簡單測試(偏娛樂向)

前期測試準備

分別用如下方式模擬一個線上獲取用戶信息的接口:node

  1. node直連mysql
  2. node調用java接口來獲取數據。

框架:koa+koa-router+sequelize+request+pm2mysql

備註:因爲不太清楚後端業務數據取值邏輯,儘量還原response data,會存在必定的數據包誤差。linux

簡要代碼sql

router.all('/api/java', async function(ctx, next) {
    let uid = ctx.cookies.get('uid');
        // request代理給後端java API接口
    ctx.body = await new Http({ctx}).request({
        url: '/user/getbalance'
    })
})
router.all('/api/node', async function(ctx, next) {
    let uid = ctx.cookies.get('uid');
        // 經過sequelize從mysql查詢
    let data = await Promise.all([
        user.balance(uid),
        user.integral(uid),
        user.coupon(uid),
        user.memberProp(uid)
    ]);
    ctx.body = data
});

分組測試&結論

在測試環境,直接局域網ab測試,避免網絡io損耗。
測試不一樣併發條件(100->200->500->1k->2k),1w請求總耗時;同時node增長核數(1核->2核->4核->8核)shell

Java測試(node代理給java)

再次備註:經過node訪問java接口。(要模擬線上環境,會由於node的瓶頸形成java負載太低)數據庫

圖片描述

Node測試

node直連數據庫apache

圖片描述

Java&node

直接訪問java接口,硬碰硬vim

圖片描述

測試結論

  1. node的強項處理非阻塞異步IO,但因爲是單進程,雖然請求數量增長↑,實際到達java應用的請求被限制在一個峯值max,解釋了圖1紅柱:當cpu1核時,併發數增多,耗時不變
  2. 知道了node cpu瓶頸的緣由,經過pm2增長核數,讓java獲得更多的資源去處理。圖1深藍淺藍:cpu核數增長,耗時縮短
  3. 當cpu升值8核(測試環境滿核),node基本不會hold住任何請求(top小於50%),直接丟到java端,到達java請求數倍增,但因爲java語言特色(同步阻塞式)、外界因素(測試環境複雜),相反時間沒有獲得降低而是有上升趨勢。圖1橘色:有上升趨勢
  4. 依託於多核的性能,node充分利用硬件資源,核數增長↑,執行能力正比例上升↑。圖2:耗時隨cpu核數增長,而倍減
  5. 結合圖1,圖2:打開cpu限制後,不難發現node性能迅速上升,符合外界宣傳,(注:使用了Promise.all更加快了異步處理速度)
  6. 圖3:node性能好於java,但併發2k時,二者仍是不分上下,仍是要分不一樣場景對2者有個組合使用(注:由於數據庫等緣由,java在處理業務時,會大批出現jdbc等問題)

計劃改進方案

  • 使用pm2修改node運行環境,增長node端處理量,解決node瓶頸
  • 從新設計架構方式,在將來有條件時,能作到node橫向水平擴展,避免單臺機器cpu瓶頸,能處理高峯壓力&惡意攻擊
  • 線下進一步瞭解node性能問題

apach ab

簡單介紹

apache ab

運行腳本:ab + 請求數量 + 併發數量 + 測試地址

[root@localhost pressure_analysis]# ab -n 10000 -c 1000 http://127.0.0.1:3301/anal/api/java

參數說明:

指標 數值 說明
Concurrency Level 1000 併發數量
Complete requests 10000 所有完成的請求數量
Time taken for tests 7.907 seconds 運行測試腳本總用時
Total transferred 2880000 bytes 數據包大小
Requests per second 1264.76 [#/sec] (mean) 平均每秒請求數量(Complete requests/Time taken for tests)
Time per request 790.661 [ms] (mean) 單個請求平均耗時(Concurrency Level*Time taken for tests)
Transfer rate 355.71 [Kbytes/sec] received 數據包傳輸速率

ab工具使用到的一些問題

apr_socket_recv: Connection reset by peer (104)

sysctl命令被用於在內核運行時動態地修改內核的運行參數,可用的內核參數在目錄/proc/sys中。它包含一些TCP/ip堆棧和虛擬內存系統的高級選項, 這可讓有經驗的管理員提升引人注目的系統性能。
[root@localhost pressure_analysis]# vim /etc/sysctl.conf
net.ipv4.tcp_syncookies = 0

[root@localhost pressure_analysis]# sysctl -p

socket: Too many open files (24)

ulimit用來限制系統用戶對shell資源的訪問
# 注意到open files限制1024
[root@localhost pressure_analysis]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 257702
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 257702
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

# 修改配置
[root@localhost pressure_analysis]# ulimit  -n 5000

參考

相關文章
相關標籤/搜索