zanePerfor監控系統在高流量專案下的架構配置建議實踐說明

zane1發表於2019-04-09

HI!,你好,我是zane,zanePerfor是一款我開發的一個前端效能監控平臺,現在支援web瀏覽器端和微信小程式端。

我定義為一款完整,高效能,高可用的前端效能監控系統,這是未來會達到的目的,現今的架構也基本支援了高可用,高效能的部署。實際上還不夠,在很多地方還有優化的空間,我會持續的優化和升級。

開源不易,如果你也熱愛技術,擁抱開源,希望能小小的支援給個star。

專案的github地址:github.com/wangweiange…

專案開發文件說明:blog.seosiwei.com/performance…


zanePerfor應用理論上能夠支援千萬級以上pv專案,但實際情況需要依賴於伺服器和資料庫的效能,以下項儘可能的從各種配置來提升應用的效能。

備註:以下內容以選擇redis訊息佇列來闡述和說明。


一:相關專案配置項說明

config.default.js 配置說明複製程式碼

1、servers叢集模式下伺服器之間主要通過內網進行通訊,因此在這裡hostname我們需要配置成內網IP,做如下更改即可

// 叢集配置(一般預設即可)
    config.cluster = {
        listen: {
            port: config.port,
            hostname: address.ip(),  // 此處替換127.0.0.1
            ip: address.ip(),
        },
    };複製程式碼


2、實時統計任務在大流量專案下時間儘可能的長一些,即能減輕資料庫的壓力也能提升實時統計的準確性 (定時任務時間間隔建議5-20分鐘之間)

// 執行pvuvip定時任務的時間間隔 預設每分鐘定時執行一次 (可更改)
config.pvuvip_task_minute_time = '0 */1 * * * *';
// 更改為
config.pvuvip_task_minute_time = '0 */10 * * * *';複製程式碼


3、上報和消費資料方式選擇redis

// 上報原始資料使用redis儲存、kafka儲存、還是使用mongodb儲存
config.report_data_type = 'redis'; // redis  mongodb  kafka複製程式碼


4、在資料庫效能足夠強悍的情況下,每次定時任務的時間儘量短,消費的資料儘量多,訊息佇列池儘量不做限制

config.redis_consumption = {
    // 定時任務執行時間
    task_time: '*/10 * * * * *',
    // 每次定時任務消費執行緒數(web端)
    thread_web: 2000,
    // 每次定時任務消費執行緒數(wx端)
    thread_wx: 2000,
    // 訊息佇列池限制數, 0:不限制 number: 限制條數,高併發時服務優雅降級方案
    total_limit_web: 0,
    total_limit_wx: 0,
};複製程式碼
  • task_time 消費訊息定時任務間隔

  • thread_wx 每次消費資料條數

  • total_limit_wx 限制訊息佇列中總條數

以上配置表示:每10秒鐘消費2000條資料,不對上報資料條數做限制 (如果定時任務設定了type: 'all',消費資料會成倍數增加)。


5、解析使用者IP使用redis方式,並關閉檔案快取(備註:流量大時,本地檔案儲存的資料會比較大,每次載入會比較耗時)

// 解析使用者ip地址為城市是使用redis還是使用mongodb
config.ip_redis_or_mongodb = 'redis'; // redus  mongodb

// 檔案快取ip對應地理位置(檔名)
config.ip_city_cache_file = {
    isuse: false, // 是否開啟本地檔案快取(資料量太大時建議不開啟)
    web: 'web_ip_city_cache_file.txt',
    wx: 'wx_ip_city_cache_file.txt',
};複製程式碼


6、mongodb叢集模式下url連結需要更改為內網ip,連線池可以稍微調大一些

// mongodb 服務
const dbclients = {
    db3: {
        // 叢集分片
        url: 'mongodb://192.168.1.10:30000/performance',
        options: {
            autoReconnect: true,
            poolSize: 50,
        },
    },
};複製程式碼


二:HTTP層面說明(以下內容已在程式中實現)

1、設定Connection,關閉keep-alive

為什麼要關閉?

  • 在高併發專案下,tcp保持連線時間不要太長,因此nginx的keepalive_timeout儘量設定的更短
  • 同一域下請求頻率低、請求次數少的http連結儘量減少tcp連結時間,因此keepalive_timeout儘量設定低

而對於本應用來說,上面兩條都已滿足,因此關閉keep-alive選項。

// node服務實現:
ctx.set('Connection', 'close');

// nginx服務實現:
http {
    keepalive_timeout: 0;
}複製程式碼


2、返回空body資訊

  • 上報介面接收到請求就儘快返回狀態碼,邏輯處理放到後面處理
  • body返回內容儘量簡短或者為空
// 程式碼實現:
async wxReport() {
    const { ctx } = this;
    ctx.set('Access-Control-Allow-Origin', '*');
    ctx.set('Connection', 'close');
    ctx.status = 200;

    // 後續邏輯處理...
}複製程式碼


三:node單機叢集

使用node.js的Cluster 模組開啟多程式,儘可能的榨乾伺服器資源,利用上多核 CPU 的併發優勢。同時也保證單機服務的穩定性。

egg.js提供多程式模型和程式間通訊。

傳送門:eggjs.org/zh-cn/core/…

開啟方式:

// 應用package.json
// 案例中開啟兩個worker程式,預設會開啟伺服器cpu核數個worker程式
"scripts": {
    "start": "egg-scripts start --daemon --workers=2 --title=performance",
}複製程式碼


四:Mongodb叢集搭建

高流量,高併發專案少不了mongodb叢集的搭建,關於mongodb叢集搭建請參考以下兩篇文章:

zanePerfor前端效能監控平臺高可用之Mongodb叢集分片架構

zanePerfor前端效能監控平臺高可用之Mongodb副本集讀寫分離架構

案例:現在有3臺伺服器,內網ip分別為:(10.1.0.86、10.1.0.97、10.1.0.70),現在我們來搭建由三臺伺服器組建的叢集。

1、分別在每臺伺服器上建立如下3個檔案

kdir -p /data/mongod/s0
mkdir -p /data/mongod/log
mkdir -p /data/mongod/c0複製程式碼

2、分別在每臺伺服器上啟動Shard Server

mongod --dbpath /data/mongod/s0 --logpath /data/mongod/log/s0.log --fork --smallfiles --port 27020 --bind_ip 10.1.0.86 --shardsvr
mongod --dbpath /data/mongod/s0 --logpath /data/mongod/log/s0.log --fork --smallfiles --port 27020 --bind_ip 10.1.0.97 --shardsvr
mongod --dbpath /data/mongod/s0 --logpath /data/mongod/log/s0.log --fork --smallfiles --port 27020 --bind_ip 10.1.0.70 --shardsvr複製程式碼

3、分別在每臺伺服器上啟動Config Server

mongod --dbpath /data/mongod/c0 --logpath  /data/mongod/log/c0.log --fork --smallfiles --port 27100 --bind_ip 10.1.0.86 --replSet rs1 --configsvr
mongod --dbpath /data/mongod/c0 --logpath  /data/mongod/log/c0.log --fork --smallfiles --port 27100 --bind_ip 10.1.0.97 --replSet rs1 --configsvr
mongod --dbpath /data/mongod/c0 --logpath  /data/mongod/log/c0.log --fork --smallfiles --port 27100 --bind_ip 10.1.0.70 --replSet rs1 --configsvr複製程式碼

4、配置副本集

// 進入97的mongo
mongo --port 27100 --host 10.1.0.97

// 使用admin賬戶
use admin

// 初始化副本集
rs.initiate({_id:"rs1",members:[{_id:0,host:"10.1.0.97:27100"},{_id:1,host:"10.1.0.86:27100"},{_id:2,host:"10.1.0.70:27100"}]})

// 檢視副本集狀態
rs.status()複製程式碼

5、啟動Route Process服務

mongos  --logpath /data/mongod/log/mongo.log --port 30000 --bind_ip 10.1.0.97 --fork --configdb rs1/10.1.0.97:27100,10.1.0.86:27100,10.1.0.70:27100複製程式碼

6、配置Sharding分片

// 進入路由伺服器
mongo --port 30000 --host 10.1.0.97

// 新增分片
sh.addShard("10.1.0.97:27020")
sh.addShard("10.1.0.86:27020")
sh.addShard("10.1.0.70:27020")

// 檢視分片資訊
sh.status();複製程式碼

7、設定分片資料庫與片鍵

//指定需要分片的資料庫
sh.enableSharding("performance")

//建立索引(需要對片建建立索引)
db.wx_ajaxs_wx3feeea844b1d03ffs.ensureIndex({"path":1})

//設定分片(對performance資料庫的wx_ajaxs_wx3feeea844b1d03ffs表按照path欄位以hashed的方式分片)
sh.shardCollection("performance.wx_ajaxs_wx3feeea844b1d03ffs", { "path": "hashed"})

//檢視分片資訊
sh.status()複製程式碼

其他表分片重複以上步驟即可, 至此一個簡單的3臺伺服器叢集搭建完畢。

注意事項:對mongodb進行分片時需要繫結內網IP,不然請求無法連通。

備註:應用中對瀏覽器端 | 微信小程式端 預設使用 _id欄位 進行分片, 儘量不要更改。


zanePerfor監控系統在高流量專案下的架構配置建議實踐說明

五:servers負載均衡

servers負載:即把所有上報的請求分發到不同的servers進行處理,減小單個servers服務的壓力,也減輕了單個伺服器的壓力。

  • zanePerfor做到了一套程式碼多服務部署的方案

  • 應用保證了多服務同時執行時,task任務不重複執行

此處servers負載均衡採用nginx方案,ng配置如下:

upstream ps-servers {
    server 10.1.0.86:7001 weight=1 max_fails=4 fail_timeout=5;
    server 10.1.0.97:7001 weight=1 max_fails=4 fail_timeout=5;
    server 10.1.0.70:7001 weight=2 max_fails=4 fail_timeout=5;
}複製程式碼

引數說明:

weight=number:設定伺服器的權重,預設情況下為1
max_conns=number:限制到代理伺服器的同時活動連線的最大數量,預設為0
max_fails=number:伺服器通訊的失敗嘗試次數
fail_timeout=number:伺服器通訊失敗超時時間,預設為10
backup:將伺服器標記為備份伺服器。它將在主伺服器不可用時傳遞請求
down:將伺服器標記為永久不可用


六:redis叢集

應用中有很多功能都會依賴於redis的快取能力,因此一臺高效能的redis或者redis叢集顯得很有必要。

官方如此介紹redis的強勁效能:效能極高 – Redis能讀的速度是110000次/s,寫的速度是81000次/s ,理論上來說單臺redis就能滿足絕大部分的應用。

至於redis是否需要叢集的支援,需要根據各個應用的情況來決定,博主暫時用的單臺redis,500w PV內暫未遇見效能問題。

至於redis叢集的搭建此處暫不做介紹,暫時掛個官網參考連結:redis.io/topics/clus…


zanePerfor在高流量專案下的架構配置建議實踐說明(完)。



相關文章