日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
使用 Rust 加速前端 Log Service

Intro

前陣子在公司內(nèi)搭建了一個 Log Service,用來記錄前端的報錯信息,代碼一頓亂寫搞的七七八八之后實現(xiàn)了***版的功能。

松溪ssl適用于網(wǎng)站、小程序/APP、API接口等需要進行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為成都創(chuàng)新互聯(lián)公司的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18982081108(備注:SSL證書合作)期待與您的合作!

流程很簡單,前端將以下格式的信息用 get 發(fā)到 Log Service:

{
  "url": "https://www.arkie.cn/scenarios",
  "channel": "frontend",
  "level": "FATAL",
  "crashId": "02x32f3",
  "stack": "base64 string ......",
  ...
}

Log Service 接受到這個請求以后,將 Stack 解析成 JSON : JSON.parse(decodeURIComponent(Buffer.from(query.stack, 'base64').toString())) , 解析后的 stack 是這樣的 :

[
  { "filename": "https://arkie-public.oss-cn-hangzhou.aliyuncs.com/js/main.c3600f3f.js", line: 1, column: 334222 },
  { "filename": "https://arkie-public.oss-cn-hangzhou.aliyuncs.com/js/common.752d2f13.js", line: 1, column: 113242 },
]

然后 Log service 會根據(jù)文件對應(yīng)的 sourcemap (前端各項目 deploy 的時候已經(jīng)上傳到私有 CDN 了) 解析出原始報錯位置。比如:

{
  filename: './src/modules/design/design.container.tsx',
  line: 102
}

***會將這些處理后的信息輸出到阿里云的 LogHub。

優(yōu)化

做完***個脆弱的版本后發(fā)現(xiàn)時間僅僅過去了一天半,所以開始考慮優(yōu)化的事情了。

***個版本有兩個問題,***個問題是在后端處理 log 的流程太長導(dǎo)致性能消耗有點大,第二個問題是實時處理 Log 在后面用戶增多之后服務(wù)器會不堪重負,而其實 Log Service 的實時性要求并沒有那么高。

對于***個問題,可以優(yōu)化代碼性能(能優(yōu)化才怪),分拆步驟(這個靠譜)來解決,第二個問題也可以通過分拆數(shù)據(jù)處理步驟來解決。

而分拆處理步驟這個解決方案可以通過在 Log Service 中加入一個 queue 來解決。比如接受到前端請求后,直接將原始數(shù)據(jù)塞到 queue 中,然后有一個 consumer 按一個***速率從 queue 中取出原始日志,處理之后再放入 LogHub,這一部分的細節(jié)就不贅述了,要寫的話展開又是一個長篇大論。

而優(yōu)化性能這方面,我本來沒有抱什么希望,因為實在是看不出有啥可優(yōu)化的。 base64 decode --> JSON.parse --> sourcemap parse 都用的是***層的標(biāo)準(zhǔn)庫調(diào)用( sourcemap parse 用的是 Mozilla 出品的 https://github.com/mozilla/source-map )

然而在上線的前夕,我突然想起了前不久學(xué)習(xí) Rust 的時候看到的一個庫 neon-bindings

Rust!Rust!

是不是可以用更快的語言來優(yōu)化 Sourcemap 處理的過程呢,同時大部分主要的繁瑣的業(yè)務(wù)還是使用 TypeScript 編寫。

調(diào)研了一圈發(fā)現(xiàn),已經(jīng)有國內(nèi)的公司在項目里面用 neon 寫業(yè)務(wù)了: https://www.zhihu.com/question/19903210/answer/207779913

并且大家熟悉的 sentry 在生產(chǎn)環(huán)境中也是使用 Rust 來 parse Sourcemap https://segmentfault.com/a/1190000007299177,雖然他們是 binding 到了 python 上,但他們已經(jīng)把 Rust 代碼開源出來了: https://github.com/getsentry/rust-sourcemap

也就是說我只需要把這部分的 Rust 代碼通過 neon-bindgs 封裝成 NodeJS 可調(diào)用的模塊就行了,不像 sentry 還要 port 出 C API 再通過 python 調(diào)用 C 的代碼,美滋滋。

寫代碼的過程和原理就省略了,代碼可以在: https://github.com/Brooooooklyn/sourcemap-decoder 看到,主要分享一些數(shù)據(jù)和踩的坑:

Benchmark

所以 Rust 比 JavaScript 代碼在處理同樣的 Sourcemap 時 parse 快多少呢?

我做了一個簡單的 benchmark, 測試結(jié)果如下:

$ node benchmark

JavaScript parse time 50794 microseconds

Rust parse time: 39 microseconds

JavaScript parse result, Source: webpack:///src/utils/logger/logger.ts, Line: 56

Rust parse result, Source: webpack:///./src/utils/logger/logger.ts, Line: 56

:sparkles:  Done in 0.33s.

Hardware Info:

ProductName:    Mac OS X
ProductVersion: 10.13.3
BuildVersion:   17D47
Model Name: MacBook Pro
Model Identifier: MacBookPro14,2
Processor Name: Intel Core i5
Processor Speed: 3.1 GHz
Number of Processors: 1
Total Number of Cores: 2
L2 Cache (per Core): 256 KB
L3 Cache: 4 MB
Memory: 16 GB

Benchmark 代碼: https://github.com/Brooooooklyn/sourcemap-decoder/blob/master/benchmark/index.js

因為每次調(diào)用 Rust 的代碼會有一次 bootstrap 的過程以及 JavaScript 代碼在運行很多次后會被 JIT 優(yōu)化,在一次性運行幾萬次的情況下差距可能縮小為十幾倍,有興趣大家可以自行嘗試。

CI/CD

剛寫完打算上線的時候,想讓 production 的鏡像盡量小一點(我們用的 Docker),所以直接在 Production 的 Image 上用了 node:8-alpine 作為 base image,相應(yīng)的,CI 的鏡像(我們使用的是 Gitlab runner 的 Docker executor )也是用同樣的 base image,然后花了三個多小時嘗試在 Alpine 上安裝 latest rust toolchains 后失敗了,***不得不忍受 100 多 m 的體積差切換到了 node:8-slim。最終的國內(nèi)可以流暢 build 的 Dockerfile 在 https://github.com/Brooooooklyn/sourcemap-decoder/blob/master/Dockerfile

Toolschains 安裝

由于眾所周知的原因,CI 在剛開始 build image 的時候異常的緩慢,直到超時被 Gitlab kill 掉,經(jīng)過一個多小時頑強的抵抗后將所有可能撞墻的步驟全部替換成了 USTC 的 mirror。

主要是 dev 機器 rustup 安裝需要:

curl https://sh.rustup.rs -sSf | sed "s/https:\/\/static.rust-lang.org\/rustup\/dist/https:\/\/mirrors.ustc.edu.cn\/rust-static\/rustup\/dist/g" | sh

使用 USTC 的源安裝 Rustup

build 前需要:

cat > $HOME/.cargo/config << EOF
[source.crates-io]
registry = "https://github.com/rust-lang/crates.io-index"
replace-with = 'ustc'
[source.ustc]
registry = "git://mirrors.ustc.edu.cn/crates.io-index"
EOF

讓 Cargo 也是用 UTSC 的源(CI 環(huán)境也需要執(zhí)行同樣的命令)

在 CI 的 Docker Image build 的時候需要 替換 Rust 下載源 以及 替換 Rustup源

詳情請參考 README


分享名稱:使用 Rust 加速前端 Log Service
標(biāo)題路徑:http://www.dlmjj.cn/article/dpciiod.html