精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

如何實現一個 APM watchdog,你學會了嗎?

開發 前端
在 APM 中,保證及時并準確地獲取應用的信息是非常重要的,這樣才能保證應用出現問題時,我們可以高效地找到并解決問題。本文以之前提交給 Node.js 的 PR 為例,介紹如何實現一個 APM watchdog 來對應用進行監控。

Hello,大家好,之前說不打算更新公眾號了,后面有時間的話還是會偶爾更新下,記錄和分享下一些技術相關的內容,今天分享下如何實現一個 APM watchdog。

在 APM 中,保證及時并準確地獲取應用的信息是非常重要的,這樣才能保證應用出現問題時,我們可以高效地找到并解決問題。本文以之前提交給 Node.js 的 PR 為例,介紹如何實現一個 APM watchdog 來對應用進行監控。這個 PR 的實現思想來自我們在內部實現的 APM watchdog,但是因為邏輯復雜,目前暫時還沒有時間去推進。

首先來看一下如何使用,然后看看一下如何實現。

new MemoryProfileWatchdog({
// 內存閾值,達到該閾值則采集堆快照
maxRss: 1024 * 1024,
maxUsedHeapSize: 1024 * 1024,
// 輪詢間隔
interval: 1000,
// 快照寫到哪個文件
filename: filepath,
});

可以看到,啟動一個 watchdog 非常簡單,我們只需要配置一些監控的閾值和輪訓時間。監控的數據是基于定時輪詢的,因為沒有相關的訂閱發布機制,當 watchdog 監控到數據達到閾值時就會采集堆快照,因為這里是一個內存 watchdog,我們也可以實現 CPU watchdog,原理是一樣的。接著看看實現,首先看 JS 層的實現。

class MemoryProfileWatchdog {
#handle;
constructor(options) {
this.#handle = new profiler.MemoryProfileWatchdog({
...options,
filename,
});

this.#handle.start();
}
stop() {
if (this.#handle) {
this.#handle.stop();
this.#handle = null;
}
}
}

JS 層的實現非常簡單,只是對 C++ 層的簡單封裝,所以直接來看 C++ 層的實現,我們忽略一些細節,只關注核心邏輯。

class ProfileWatchdog : public BaseObject {
public:
enum class ProfileWatchdogState { kInitialized, kRunning, kClosing, kClosed };
ProfileWatchdog(Environment* env, v8::Local<v8::Object> object);
~ProfileWatchdog() override;
static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(Environment* env);
// 啟動 / 停止 watchdog
static void Start(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Stop(const v8::FunctionCallbackInfo<v8::Value>& args);
void Start(Environment* env);
void Stop();
// 提交一個任務
template <typename Fn>
void AddTask(Fn&& cb, CallbackFlags::Flags flags = CallbackFlags::Flags::kRefed);
// 處理一個任務
void HandleTasks();
// 啟動一個定時器
void SetTimeout();
// 定時器回調,具體的邏輯由子類實現
virtual bool TimeoutHandler() = 0;

protected:
// 輪詢間隔
uint64_t interval_;
private:
static void Run(void* arg);
static void Timer(uv_timer_t* timer);
// 子線程
uv_thread_t thread_;
uv_loop_t loop_;
// 主線程和子線程的通信結構體
uv_async_t async_;
// 定時器
uv_timer_t timer_;
// 任務隊列
CallbackQueue<void> tasks_;
Mutex task_mutex_;
};

ProfileWatchdog 實現了 watchdog 機制,具體需要監控什么數據由子類實現,比如內存 watchdog。

class MemoryProfileWatchdog : public ProfileWatchdog {
public:
MemoryProfileWatchdog(Environment* env,
v8::Local<v8::Object> object,
v8::Local<v8::Object> options);
static void Init(Environment* env, v8::Local<v8::Object> target);
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
bool TimeoutHandler() override;

private:
// 需要監控的數據指標
size_t max_rss_ = 0;
size_t max_used_heap_size_ = 0;
std::string filename_;
};

有了基本的了解后,接下來看具體實現。

void ProfileWatchdog::Start(Environment* env) {
int rc;
// 初始化一個事件循環結構體
rc = uv_loop_init(&loop_);
// 初始化線程間通信結構體
rc = uv_async_init(&loop_, &async_, [](uv_async_t* task_async) {
ProfileWatchdog* w = ContainerOf(&ProfileWatchdog::async_, task_async);
w->HandleTasks();
});
// 初始化并啟動一個定時器
rc = uv_timer_init(&loop_, &timer_);
rc = uv_timer_start(&timer_, &ProfileWatchdog::Timer, interval_, 0);
// 創建 watchdog 線程
rc = uv_thread_create(&thread_, &ProfileWatchdog::Run, this);
}

當啟動一個 watchdog 時就會執行 Start,Start 函數中主要初始化了線程間通信的結構體,然后啟動一個定時器,最后創建一個 watchdog 線程。因為 Node.js 是單線程的,為了保證 watchdog 在 JS 繁忙時仍可正常工作,我們需要借助子線程。創建子線程后,子線程就會開始執行 ProfileWatchdog::Run。

void ProfileWatchdog::Run(void* arg) {
ProfileWatchdog* wd = static_cast<ProfileWatchdog*>(arg);
uv_run(&wd->loop_, UV_RUN_DEFAULT);
CheckedUvLoopClose(&wd->loop_);
}

Run 的邏輯很簡單,就是啟動一個事件循環,因為我們前面啟動了一個定時器,所以這個事件循環里就會定時執行定時器回調 ProfileWatchdog::Timer。

void ProfileWatchdog::Timer(uv_timer_t* timer) {
ProfileWatchdog* w = ContainerOf(&ProfileWatchdog::timer_, timer);
// 往主線程插入一個任務
env->RequestInterrupt([watchdog = std::move(w)](Environment* env) {
// 執行定時器的邏輯,由具體的 watchdog 實現,返回 true 表示重啟定時器,否則監控到此為止
if (watchdog->TimeoutHandler()) {
// 往子線程里插入一個任務,該任務是重啟定時器
watchdog->AddTask(
[watchdog = std::move(watchdog)]() { watchdog->SetTimeout(); });
}
});
}

Timer 中通過 env->RequestInterrupt 往主線程插入一個任務,因為有些代碼是不能在子線程里執行的,另外 RequestInterrupt 可以保證在 JS 繁忙或阻塞在事件驅動模塊時仍然可以執行我們的任務,那么這個任務具體做什么呢?看看內存 watchdog 的 TimeoutHandler 實現。

bool MemoryProfileWatchdog::TimeoutHandler() {
bool reached = false;
if (max_rss_) {
size_t rss = 0;
uv_resident_set_memory(&rss);
if (rss >= max_rss_) {
reached = true;
}
}

if (!reached && max_used_heap_size_) {
Isolate* isolate = env()->isolate();
HeapStatistics heap_statistics;
isolate->GetHeapStatistics(&heap_statistics);
if (heap_statistics.used_heap_size() >= max_used_heap_size_) {
reached = true;
}
}
// 內存達到閾值,采集快照
if (reached) {
HeapProfiler::HeapSnapshotOptions options;
options.numerics_mode = HeapProfiler::NumericsMode::kExposeNumericValues;
options.snapshot_mode = HeapProfiler::HeapSnapshotMode::kExposeInternals;
heap::WriteSnapshot(env(), filename_.c_str(), options);
// 采集完快照,停止 watchdog
return false;
}
return true;
}

TimeoutHandler 就是獲取主線程的內存信息,并判斷是否超過了我們配置的閾值,是的話則采集堆快照并停止 watchdog,防止采集過多的重復信息,我們也可以改成隔久一點再開始重新監控,而內存如果沒有超過閾值,則重啟定時器,等待下一輪判斷。從前面的代碼可以看到,如果沒有達到閾值,我們會調用 AddTask 往子線程插入一個任務。

watchdog->AddTask([watchdog = std::move(watchdog)]() { 
watchdog->SetTimeout();
});

看一下 AddTask 的實現。

template <typename Fn>
void ProfileWatchdog::AddTask(Fn&& cb, CallbackFlags::Flags flags) {
auto callback = tasks_.CreateCallback(std::move(cb), flags);
{
Mutex::ScopedLock lock(task_mutex_);
// 追加一個任務
tasks_.Push(std::move(callback));
}
// 通知子線程有任務處理
uv_async_send(&async_);
}

AddTask 往子線程的任務隊列中插入一個任務,并通知子線程處理,接著看看子線程如何處理任務。

void ProfileWatchdog::HandleTasks() {
while (tasks_.size() > 0) {
CallbackQueue<void> queue;
{
Mutex::ScopedLock lock(task_mutex_);
queue.ConcatMove(std::move(tasks_));
}
while (auto head = queue.Shift()) head->Call();
}
}

HandleTasks 會逐個任務處理,也就是執行一個個函數,我們剛才插入的函數如下。

void ProfileWatchdog::SetTimeout() {
uv_timer_start(&timer_, &ProfileWatchdog::Timer, interval_, 0);
}

也就是重啟定時器,這樣就開始等待下次超時,直到觸發了閾值。

這就是 APM watchdog 的實現原理,核心思想是利用子線程和 env->RequestInterrupt 機制,保證我們對目的線程進行相對實時的監控(取決于設置的輪詢時間),并在發現問題采集相關信息來協助我們排查問題,利用這個思路,我們可以實現不同類型的 watchdog 來解決不同的問題,比如 CPU watchdog 可以在 JS 死循環時采集 CPU Profile 信息幫助我們找到有問題的代碼,本文就分享到這里,最后貼上目前的實現 PR(見文章末尾)。因為涉及到多線程和 Node.js 內部的一些知識,實現起來有很多地方需要考慮的,希望后面有時間繼續推進。

PR:https://github.com/nodejs/node/pull/45714

責任編輯:武曉燕 來源: 編程雜技
相關推薦

2022-03-05 23:29:18

LibuvwatchdogNode.js

2024-06-21 08:15:25

2024-04-01 08:13:59

排行榜MySQL持久化

2021-10-04 09:29:41

對象池線程池

2024-06-19 09:47:21

2022-06-16 07:50:35

數據結構鏈表

2023-09-19 08:03:50

rebase?merge

2023-04-27 08:42:50

效果

2022-02-08 09:09:45

智能指針C++

2024-07-29 10:35:44

KubernetesCSI存儲

2024-01-19 08:25:38

死鎖Java通信

2023-01-10 08:43:15

定義DDD架構

2024-02-04 00:00:00

Effect數據組件

2023-07-26 13:11:21

ChatGPT平臺工具

2025-04-01 03:25:00

2022-11-30 09:54:57

網絡令牌身份驗證

2021-05-19 14:22:46

代碼開發項目

2024-01-02 12:05:26

Java并發編程

2023-08-01 12:51:18

WebGPT機器學習模型

2024-09-26 09:10:08

點贊
收藏

51CTO技術棧公眾號

欧美日韩一区二区三区 | 不卡视频免费播放| 欧美性受xxxx黑人猛交| 国产传媒国产传媒| 免费观看亚洲视频大全| 狠狠操狠狠色综合网| 亚洲精品永久www嫩草| 亚洲精品综合网| 三级在线观看一区二区| 欧美老少做受xxxx高潮| 美女洗澡无遮挡| 国产亚洲久久| 日本丰满少妇一区二区三区| 先锋影音男人资源| 日本v片在线免费观看| 国内精品久久久久影院色| 97免费中文视频在线观看| 国产黄色片在线| 米奇精品关键词| 这里是久久伊人| aa在线免费观看| 2024短剧网剧在线观看| 国产女人18毛片水真多成人如厕 | 看欧美ab黄色大片视频免费 | 一区二区三区在线视频观看| 青青草成人网| 四季av日韩精品一区| 国产在线看一区| 国产精品99导航| 日韩 欧美 中文| 狠狠综合久久av一区二区老牛| 揄拍成人国产精品视频| 日本xxxx裸体xxxx| 精品深夜福利视频| 欧美成人在线直播| 国产5g成人5g天天爽| 日本成人福利| 色综合一个色综合亚洲| 国产不卡一区二区视频| 伊人在我在线看导航| 中文字幕亚洲成人| 午夜老司机精品| 蜜桃视频在线观看视频| 972aa.com艺术欧美| 国产精品久久国产三级国电话系列| www五月天com| 久久精品亚洲| 欧美与欧洲交xxxx免费观看| www.av视频在线观看| 欧美一区二区| 欧美成在线观看| 成年人二级毛片| 久久成人综合| 精品国产一区av| 久久久久久国产免费a片| 特黄特色欧美大片| 亚洲国产精品va在看黑人| 日韩久久久久久久久久久| 欧美aaaaaaaa| 6080亚洲精品一区二区| 亚洲涩涩在线观看| 99久久99九九99九九九| 91精品欧美久久久久久动漫| 99久久99精品| 国产伦精品一区二区三区在线播放 | 精品国产一区三区| 涩涩视频在线| 欧美综合欧美视频| 最新天堂在线视频| 国产一区 二区| 日韩一本二本av| 中文字幕天堂av| 真实原创一区二区影院| 中文字幕成人精品久久不卡| 97精品在线播放| 一区二区免费不卡在线| 久久久噜噜噜久久中文字免| 欧美亚洲精品天堂| 蜜桃一区二区三区在线观看| 92国产精品视频| 免费激情视频网站| 久久婷婷一区二区三区| 亚洲精品一区二区三| 永久免费网站在线| 欧美色播在线播放| 亚洲欧美日韩一级| 亚洲欧洲国产精品一区| 亚洲精品视频网上网址在线观看| 91成人精品一区二区| 欧美va天堂在线| 日韩av高清不卡| 亚洲一卡二卡在线观看| 高清国产午夜精品久久久久久| 久久精品一区二区三区不卡免费视频| 触手亚洲一区二区三区| 亚洲精品少妇30p| 日本精品一区在线观看| 在线视频成人| 亚洲精品电影久久久| 国产精品69久久久久孕妇欧美| 欧美激情日韩| 国产成人精品在线| 亚洲国产剧情在线观看| 国产欧美一区二区在线观看| 日韩精品综合在线| 欧美极品在线| 国产偷亚洲偷欧美偷精品| 黄色一级大片在线免费观看| 亚洲精品乱码久久久久久蜜桃麻豆| 国产精品av在线播放| 国产日韩欧美中文字幕| 久久久久久99精品| 精品国产一区二区三区无码| 久久久久久久性潮| 亚洲精品日韩丝袜精品| 欧美日韩在线观看免费| 免费高清在线一区| 看高清中日韩色视频| 少女频道在线观看免费播放电视剧| 色88888久久久久久影院按摩| 色哟哟在线观看视频| 精品一区二区三| 97精品国产97久久久久久免费| 国产精品久久久久久免费播放| 久久色在线视频| 国产 日韩 欧美在线| 精品国产一区二| 丝袜美腿精品国产二区| 久久久精品毛片| 91麻豆免费观看| 九九爱精品视频| 国产成人aa在线观看网站站| 欧美二区在线播放| 国产熟女精品视频| 最好看的中文字幕久久| 91日韩视频在线观看| 狠狠色狠狠色综合婷婷tag| 91av国产在线| 三级网站在线看| 亚洲一二三专区| 色婷婷一区二区三区在线观看| 凹凸成人精品亚洲精品密奴| 国产成人精品电影久久久| 性高潮久久久久久久久久| 亚洲夂夂婷婷色拍ww47| 免费看的av网站| 欧美激情第8页| 3d蒂法精品啪啪一区二区免费| 欧美日韩视频在线播放| 88在线观看91蜜桃国自产| www.97视频| 国产一区二区免费视频| 日韩精品久久一区二区| 1204国产成人精品视频| 久久免费视频在线观看| 亚州视频一区二区三区| 欧美三级免费观看| 国产三级黄色片| 国产一区二区不卡在线| 欧美做暖暖视频| 国内精品国产成人国产三级粉色 | 欧美做受777cos| 日本一区二区三区播放| 午夜精品一区二区三区在线播放| 日本激情一区二区| 色狠狠色狠狠综合| 国产成人精品视频免费| 国产美女一区二区三区| youjizz.com在线观看| 国内精品麻豆美女在线播放视频| 68精品国产免费久久久久久婷婷| 色香蕉在线视频| 色香蕉久久蜜桃| 男人在线观看视频| 国产在线日韩欧美| 成人网站免费观看入口| 国产精品一国产精品| 91热福利电影| aaa在线播放视频| 一本久久综合亚洲鲁鲁| 国产精品午夜福利| 午夜精品一区在线观看| 日韩av片在线| 国产精选一区二区三区| 亚洲 高清 成人 动漫| 日韩国产专区| 国产免费一区| 欧美a一级片| 97精品国产97久久久久久免费| porn视频在线观看| 精品噜噜噜噜久久久久久久久试看| 毛片视频网站在线观看| 国产精品乱码一区二区三区软件 | 日日摸天天爽天天爽视频| 天天做天天爱天天综合网2021| 国产日韩欧美综合精品 | 豆国产97在线| 亚洲综合av一区二区三区| 欧美另类精品xxxx孕妇| 国产中文在线| 精品免费一区二区三区| 艳妇乳肉豪妇荡乳av无码福利| 夜夜亚洲天天久久| 亚洲图片第一页| 99久久99精品久久久久久| 天堂视频免费看| 亚洲精品偷拍| 日本一本草久p| 国产综合久久久| 国产在线精品一区| 日本一区二区三区播放| 国产女同一区二区| 成人欧美大片| 久久久久久伊人| 黄色网页在线观看| 一区二区三区亚洲| 日韩福利一区二区| 精品国产亚洲在线| 国产黄色片网站| 欧美日韩mp4| 亚洲色成人www永久网站| 亚洲成人午夜电影| www青青草原| 自拍偷拍国产精品| 91麻豆制片厂| 久久精品亚洲麻豆av一区二区 | 国产欧美一区二区精品久导航| 黄色免费视频网站| 成人综合婷婷国产精品久久免费| 三年中文在线观看免费大全中国| 免费美女久久99| 国产精品天天av精麻传媒| 午夜综合激情| 日韩av片在线看| 性久久久久久| 成人小视频在线看| 久久国产高清| 国内外成人免费激情视频| 亚洲人成高清| 国产 福利 在线| 亚洲欧美久久久| 男女午夜激情视频| 羞羞答答国产精品www一本| 成人一对一视频| 国产亚洲综合精品| 欧美亚洲另类色图| 香蕉av777xxx色综合一区| 成年人视频网站免费观看| 亚洲免费综合| 日本999视频| 蜜桃在线一区二区三区| 在线观看国产一级片| 九九热在线视频观看这里只有精品| www.日本一区| 国产一区二区毛片| 一区二区三区人妻| 成人免费毛片片v| 日韩免费高清一区二区| 93久久精品日日躁夜夜躁欧美| 国产精品伦子伦| 久久久另类综合| 夫妇交换中文字幕| 《视频一区视频二区| 校园春色 亚洲| 亚洲国产成人tv| 亚洲视频 欧美视频| 欧美日韩在线不卡| 亚洲成熟女性毛茸茸| 日韩精品一二三四区| 激情福利在线| 久久国内精品一国内精品| 秋霞在线视频| 欧美在线xxx| 日韩综合久久| 国产精品国产三级欧美二区| 日本在线中文字幕一区| 日韩精品最新在线观看| 久久久久久久久免费视频| 久久精品视频在线免费观看| 中文字幕一区二区三区乱码不卡| 99视频国产精品| 久久久精品成人| 亚洲国产人成综合网站| 男人的天堂av网站| 91精品国产aⅴ一区二区| 欧美 日韩 国产 成人 在线 91| 亚洲乱码一区二区| av毛片在线免费| 日韩美女免费观看| 在线播放一区二区精品视频| 欧美人与性禽动交精品| 欧美va亚洲va日韩∨a综合色| 国产主播在线看| 国产一区视频网站| 中文字字幕码一二三区| 亚洲人成伊人成综合网小说| 日本五十熟hd丰满| 欧美日韩美女一区二区| 天堂中文字幕av| 久久久国产一区| 欧美gay囗交囗交| 国产精品久久国产精品| 91精品综合久久久久久久久久久 | 国产高清视频色在线www| 国产精品日韩欧美综合| 欧美黑白配在线| 日本一区二区免费高清视频| 午夜在线视频观看日韩17c| 91丨porny丨九色| 中文av一区特黄| 久久久精品福利| 精品成人一区二区| 国产写真视频在线观看| 国产精品视频中文字幕91| 小说区图片区色综合区| 欧美黑人在线观看| 国产一区视频在线看| 欧日韩不卡视频| 欧美丝袜第三区| 欧洲综合视频| 97视频在线看| 99精品在免费线中文字幕网站一区| 一区二区精品国产| 日日夜夜免费精品| 少妇光屁股影院| 精品久久久精品| 亚洲精品国产精品国| 欧美大奶子在线| 综合久久伊人| 亚洲综合激情五月| 免费看欧美美女黄的网站| 人妻熟人中文字幕一区二区| 日韩欧美在线观看| 亚洲 欧美 自拍偷拍| 69视频在线播放| 国产精品自在| 成人在线观看你懂的| 成人免费视频视频在线观看免费| 性色av无码久久一区二区三区| 欧美人狂配大交3d怪物一区| 亚洲xxxxxx| 国产在线精品自拍| 911久久香蕉国产线看观看| 天天干天天色天天干| 1区2区3区精品视频| 一区二区三区午夜| 少妇久久久久久| 只有精品亚洲| 色一情一乱一乱一区91| 国产成a人无v码亚洲福利| 久久久久久久国产精品毛片| 精品成人一区二区| 麻豆免费在线| 日韩av一区二区三区美女毛片| 久久性色av| 日日操免费视频| 91精品国产综合久久精品| 毛片在线网址| 国产精品一区二区不卡视频| 亚洲精品人人| 337人体粉嫩噜噜噜| 欧美情侣在线播放| 色图在线观看| 久久狠狠久久综合桃花| 久久久久.com| 国产第一页浮力| 日韩欧美123| 伊人久久综合一区二区| 日韩高清av电影| 国产综合色在线视频区| 久久精品欧美一区二区| 亚洲欧美一区二区三区情侣bbw | 欧美视频精品在线观看| 好操啊在线观看免费视频| 国产乱码精品一区二区三区中文| 久久av最新网址| 肉色超薄丝袜脚交69xx图片| 精品精品国产高清一毛片一天堂| 末成年女av片一区二区下载| 日韩欧美精品久久| 国产91露脸合集magnet| caoporn国产| 欧美成人在线免费| 久久99视频| 国产裸体视频网站| 日韩欧美在线视频免费观看| 国产精品实拍| 久久亚洲高清| 国产一区二区免费在线| 综合激情网五月| 久久成人人人人精品欧| 日韩高清三区| 亚洲国产日韩在线一区| 色综合色狠狠天天综合色| 在线免费av导航| 日本精品免费| av日韩在线网站| 97免费观看视频| 欧美诱惑福利视频| 午夜精品久久久久99热蜜桃导演 |