精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

欧美fxxxxxx另类| 国产精品论坛| 日韩不卡手机在线v区| 最近2019中文字幕在线高清| 不卡中文字幕在线观看| 日本不卡影院| 99re热这里只有精品免费视频| 欧洲美女免费图片一区| 婷婷激情四射网| 日韩精品免费一区二区三区竹菊| 91成人看片片| 久久av高潮av| 国产尤物视频在线| 国产精品88888| 国产97免费视| 久久国产精品波多野结衣| 国产性一乱一性一伧一色| 国产高清免费观看| 久久综合影音| 欧美激情奇米色| 在线观看国产精品一区| 亚洲一区二区电影| 欧美日韩亚洲不卡| 少妇无码av无码专区在线观看| 大片免费播放在线视频| 成人黄页在线观看| 91亚洲精华国产精华| 久久久久久久久久久影院| 永久91嫩草亚洲精品人人| 亚洲人成网在线播放| 久久久男人的天堂| 国产精品99久久免费| 日韩欧美在线免费观看| 黄色一级片黄色| 日本高清视频在线播放| 久久久噜噜噜久久中文字幕色伊伊 | 欧美福利影院| 日韩在线高清视频| 人人妻人人澡人人爽| 偷窥自拍亚洲色图精选| 日韩精品在线看片z| 欧美一级视频在线| 欧美成人福利| 色狠狠一区二区| 国产男女无遮挡| 91视频欧美| 欧美大片高清| 国产91露脸合集magnet| 国产中文字幕91| 欧美激情一区二区三区免费观看| 在线亚洲观看| 3344国产精品免费看| 一区二区三区免费高清视频| 欧美 日韩 国产一区二区在线视频| 在线中文字幕日韩| www中文在线| 99久久精品费精品国产| 色老头一区二区三区在线观看| 美女被到爽高潮视频| 中文字幕伦av一区二区邻居| 精品在线观看国产| 国产毛片久久久久久久| 美女亚洲一区| 在线播放精品一区二区三区 | 国产精品不卡一区二区三区| 亚洲巨乳在线观看| 免费在线观看黄色网| 国产精品久久网站| 一级黄色免费在线观看| 伊人精品影院| 精品色蜜蜜精品视频在线观看| 精品久久一二三| 成人免费看视频网站| 91久久国产最好的精华液| 亚洲综合欧美激情| 国产精品一区免费在线| 欧美大片免费久久精品三p| 天天躁日日躁狠狠躁av麻豆男男 | 色噜噜狠狠色综合网| 老司机午夜在线视频| 亚洲免费av观看| 国产精品久久中文字幕| 中文字幕在线官网| 欧美人体做爰大胆视频| 香蕉视频在线观看黄| 久久悠悠精品综合网| 亚洲香蕉在线观看| 91杏吧porn蝌蚪| 亚洲精品男同| 国产精品视频成人| 丰满人妻妇伦又伦精品国产| 91在线一区二区三区| 亚洲国产成人不卡| 免费在线观看的电影网站| 色综合色狠狠天天综合色| 久久久精品麻豆| 91成人短视频| 亚洲一区二区国产| 久久久久久久九九九九| 老**午夜毛片一区二区三区| 亚洲一区二区自拍| 青青操视频在线| 亚洲女人小视频在线观看| 伊人成色综合网| 国产精品成人**免费视频| 精品视频在线导航| 久久国产波多野结衣| 国产偷自视频区视频一区二区| 国产人妖伪娘一区91| 四虎精品一区二区三区| 最新热久久免费视频| 亚洲 高清 成人 动漫| av成人在线网站| 欧美理论在线播放| 欧美妇女性影城| 中文字幕精品视频在线| 97视频精品| 日本久久久久久久| 亚洲精华国产精华精华液网站| 久久久国产精华| 久久艹国产精品| www 久久久| 国产亚洲日本欧美韩国| 日韩精品一卡二卡| 国产精品888| 伊人av成人| 欧美最新精品| 亚洲美女精品成人在线视频| 免费看一级一片| 精品一区二区三区在线播放视频 | 精品国产99久久久久久宅男i | 少妇高潮一区二区三区喷水| 先锋影音久久久| y111111国产精品久久婷婷| 91网页在线观看| 在线看日本不卡| av黄色免费网站| 欧美综合二区| 免费成人深夜夜行视频| 51精品在线| 日韩免费电影网站| 91视频综合网| 韩国成人在线视频| 在线不卡视频一区二区| 国产福利亚洲| 99精品视频在线免费播放| 亚洲欧美激情另类校园| 国产欧美日韩另类| 成人妖精视频yjsp地址| 日韩小视频网站| 99a精品视频在线观看| 色综合导航网站| 亚洲国产精品suv| 亚洲女厕所小便bbb| 韩国三级丰满少妇高潮| 午夜日韩激情| 成人av影视在线| 国产偷倩在线播放| 亚洲精品suv精品一区二区| a v视频在线观看| 粉嫩一区二区三区性色av| 又大又硬又爽免费视频| 菁菁伊人国产精品| 欧美中文在线观看| 精品久久久久一区二区三区| 欧美在线你懂的| 黄色免费一级视频| 国内精品视频一区二区三区八戒| 桥本有菜av在线| 亚洲欧美日本国产| 午夜精品久久久久久久白皮肤| 亚洲aaaaaaa| 在线区一区二视频| 东方av正在进入| 岛国一区二区在线观看| 国产精品久久久久久久久| 3d动漫精品啪啪一区二区下载| 久久精品女人| 亚洲一一在线| 88久久精品| 日本久久久久久| 久草免费在线| 精品成人在线观看| 自拍偷拍18p| 亚洲美女淫视频| 亚洲精品乱码久久| 日韩国产高清在线| 日韩视频 中文字幕| 久久影视三级福利片| 国产精品第2页| 四虎亚洲成人| 亚洲视频日韩精品| 国产视频在线观看免费| 精品免费在线观看| 免费看裸体网站| 成人网在线免费视频| 国产一区二区视频免费在线观看 | 在线观看国产精品日韩av| 国产美女免费视频| 色综合天天综合网天天狠天天| 午夜激情视频在线播放| www.欧美日韩| 亚洲妇熟xx妇色黄蜜桃| 亚洲综合激情| 欧洲精品视频在线| 精品国产99| 国产乱码精品一区二区三区日韩精品| 日韩一区二区三区在线免费观看 | 国产精品迅雷| 欧美成人免费全部| 福利在线午夜| 天天干在线视频论坛| 欧美日韩一级黄| 日本天堂网在线观看| 亚洲少妇屁股交4| 一区二区三区四区免费| 成人性生交大片免费看中文 | 欧美日韩亚洲国产| 国语自产精品视频在线看抢先版图片| 在线观看完整版免费| 日韩经典第一页| 精品人妻午夜一区二区三区四区 | 欧美人妖视频| 俄罗斯精品一区二区| 精品国产亚洲一区二区三区大结局 | 日韩欧美精品在线视频| 最近日韩免费视频| 欧美午夜美女看片| 国产午夜精品无码一区二区| 亚洲人123区| 欧美人与禽zoz0善交| 久久老女人爱爱| 国产ts丝袜人妖系列视频 | 99国产精品久久久久久久成人热| 欧洲xxxxx| 外国成人免费视频| 亚洲一区不卡在线| 日韩在线观看一区 | 欧美肉大捧一进一出免费视频| 国产在线播放一区| 午夜精品久久久久久久白皮肤| 亚洲精品国产成人av在线| 日本va欧美va瓶| 欧美两根一起进3p做受视频| 欧美一级网站| 你懂的av在线| 性欧美精品高清| 无码aⅴ精品一区二区三区浪潮| 91久久久久| 久草热视频在线观看| 99精品国产福利在线观看免费| www.在线观看av| 亚洲成人中文| 日韩一级性生活片| 国产精品五区| 成年人免费在线播放| 久久久水蜜桃av免费网站| 久草精品在线播放| 奇米亚洲午夜久久精品| 日韩精品视频一二三| 精品在线一区二区三区| 久久久久久久久久久影视| 成人免费黄色大片| 狠狠人妻久久久久久综合蜜桃| 91麻豆国产精品久久| av电影在线不卡| 国产精品高潮呻吟久久| 91嫩草|国产丨精品入口| 亚洲高清一区二区三区| www.国产高清| 欧美自拍丝袜亚洲| 国产老妇伦国产熟女老妇视频| 欧美一卡2卡3卡4卡| 蜜桃av鲁一鲁一鲁一鲁俄罗斯的| 日韩大陆欧美高清视频区| 久青草国产在线| 久久网福利资源网站| brazzers在线观看| 国产98色在线| 国产精品视频首页| 精品视频一区在线| 日韩欧美1区| www.夜夜爱| 天堂久久久久va久久久久| 天天色天天综合网| 99久久免费精品| 91视频最新网址| 五月婷婷综合网| 五月天婷亚洲天综合网鲁鲁鲁| 黄网站免费在线播放| 色综合久久悠悠| 国模冰冰炮一区二区| 成人情趣片在线观看免费| 国产精品男女| 中文字幕一区二区三区最新| 亚洲免费精品| 99九九精品视频| 久久久夜色精品亚洲| 国产高潮流白浆| 在线免费观看日本欧美| 蜜桃久久一区二区三区| 日韩在线视频一区| 色是在线视频| 亚洲bt天天射| 日本不卡电影| 青青艹视频在线| 国产麻豆视频一区二区| 国产精品无码无卡无需播放器| 午夜免费久久看| 国产又粗又长又大视频| 亚洲日本欧美中文幕| 久久大胆人体| 成人av电影天堂| 日本久久精品| 亚洲国产精品久久久久婷蜜芽| 国产麻豆91精品| 欧美巨胸大乳hitomi| 日韩欧美成人精品| 黄频在线免费观看| 久久久国产一区| 欧美日韩女优| 欧美日韩在线观看一区二区三区| 激情久久中文字幕| 亚洲av无码久久精品色欲| 国产精品久线观看视频| 一级片免费在线播放| 亚洲国产精品国自产拍av秋霞| 午夜伦理大片视频在线观看| 国产日韩av在线| 久久av免费看| 男人的天堂99| 99国产精品久久久| 亚洲精品77777| 精品国产91洋老外米糕| 日本动漫理论片在线观看网站| 国产日韩欧美综合| 四虎成人av| 欧美成人精品三级在线观看| 国产精品无码久久av| 这里只有精品视频在线| 666av成人影院在线观看| 日本不卡一区二区三区视频| 成人开心激情| 国产精品嫩草在线观看| 一区二区三区毛片免费| 国产精品久久久久久9999| 国产精品高清亚洲| 一级黄色大片免费观看| 中文日韩在线视频| 欧美性生活一级| 一区二区三区视频在线播放| 久久精品二区亚洲w码| 呻吟揉丰满对白91乃国产区| 欧美精品久久久久久久久老牛影院| 不卡在线视频| 成人国产精品久久久久久亚洲| 国产精品x453.com| 激情成人在线观看| 一区二区三区四区不卡在线| 高h震动喷水双性1v1| 7777免费精品视频| 亚洲婷婷影院| 天天干天天玩天天操| 亚洲天堂2014| 亚洲免费成人在线| 69久久夜色精品国产69乱青草| 美女久久久久| 国产九九在线观看| 一区二区三区蜜桃网| 人妻妺妺窝人体色www聚色窝 | 97在线观看免费高| 日韩精品一区二区三区在线播放| 国产www视频在线观看| 蜜桃麻豆91| 久久精品99久久久| 国产精品久久久精品四季影院| 亚洲成人三级在线| 高清成人在线| 丰满人妻一区二区三区53号| 99精品桃花视频在线观看| 亚洲一级在线播放| 欧美国产视频日韩| 欧美伦理在线视频| 亚洲三级在线视频| 色综合天天综合网天天狠天天| 日本在线观看视频| 国产福利久久精品| 天堂午夜影视日韩欧美一区二区| 91高清免费观看| 日韩二区三区在线| 疯狂欧洲av久久成人av电影| 野外做受又硬又粗又大视频√| 国产亚洲一二三区| 国产熟女一区二区丰满| 91sa在线看| 在线中文字幕亚洲| 久久精品老司机| 日韩欧美视频一区| 成人在线视频免费| 国产午夜福利100集发布|