<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Node-Js on 技術、遊戲、生活通俗易懂的解釋</title><link>https://takao.blog/zh-tw/tags/node-js/</link><description>Recent content in Node-Js on 技術、遊戲、生活通俗易懂的解釋</description><generator>Hugo -- gohugo.io</generator><language>zh-tw</language><copyright>Commentary of Takao</copyright><lastBuildDate>Wed, 18 Dec 2024 00:00:00 +0900</lastBuildDate><atom:link href="https://takao.blog/zh-tw/tags/node-js/index.xml" rel="self" type="application/rss+xml"/><item><title>Node.js 效能監控：重要的指標</title><link>https://takao.blog/zh-tw/web/nodejs-performance/</link><pubDate>Wed, 18 Dec 2024 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/nodejs-performance/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/nodejs-performance-zh-tw.png" alt="Featured image of post Node.js 效能監控：重要的指標" /&gt;&lt;p&gt;Node.js 效能監控需要採用與傳統伺服器環境不同的方法。單線程事件循環、垃圾收集記憶體模型和非同步 I/O 創建了通用 CPU 和記憶體指標無法單獨捕獲的獨特故障模式。本文介紹了保持 Node.js 應用程式在生產環境中平穩運行所需的基本指標和工具。&lt;/p&gt;
&lt;h2 id="為什麼-nodejs-效能監控有所不同"&gt;為什麼 Node.js 效能監控有所不同
&lt;/h2&gt;&lt;p&gt;與多執行緒伺服器中緩慢的操作僅阻塞一個執行緒不同，Node.js 中的單一 CPU 密集型操作會阻塞整個事件循環，從而停止所有並發請求。垃圾收集暫停可能會導致不可預測的延遲高峰。常見的失敗模式包括事件循環飢餓、未清理的閉包導致的記憶體洩漏、回調抖動以及未處理的承諾拒絕默默吞下錯誤。了解這些特徵是有效監控的第一步。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="事件循環滯後"&gt;事件循環滯後
&lt;/h2&gt;&lt;p&gt;事件循環延遲測量調度計時器回呼與其實際執行之間的延遲。這是 Node.js 進程最重要的健康指標。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;monitorEventLoopDelay&lt;/span&gt; } &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;perf_hooks&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;histogram&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;monitorEventLoopDelay&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;histogram&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;enable&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// In your health check endpoint:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;setInterval&lt;/span&gt;(() =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;lag&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;histogram&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;mean&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1e6&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// Convert nanoseconds to milliseconds
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;histogram&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;reset&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;lag&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;50&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;logger&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;warn&lt;/span&gt;({ &lt;span style="color:#a6e22e"&gt;eventLoopLag&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;lag&lt;/span&gt; }, &lt;span style="color:#e6db74"&gt;&amp;#34;Event loop lag detected&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}, &lt;span style="color:#ae81ff"&gt;10000&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;滯後&lt;/th&gt;
					&lt;th&gt;解讀&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&amp;lt; 10 毫秒&lt;/td&gt;
					&lt;td&gt;健康&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;10–50 毫秒&lt;/td&gt;
					&lt;td&gt;關於 — 調查&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&amp;gt; 50 毫秒&lt;/td&gt;
					&lt;td&gt;關鍵－需要立即採取行動&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;常見原因包括同步 CPU 密集型操作、大負載上的過多 JSON 解析以及主執行緒中執行的資料庫查詢最佳化不佳。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="垃圾收集指標"&gt;垃圾收集指標
&lt;/h2&gt;&lt;p&gt;V8 的垃圾收集器分兩個階段運行：快速的清理（年輕代）和較慢的標記-清除-壓縮（老年代）。長時間或頻繁的 GC 暫停會直接影響 p99 延遲。&lt;/p&gt;</description></item><item><title>Node.js Logging 最佳 Practices: 架構d and Scalable</title><link>https://takao.blog/zh-tw/web/nodejs-logging/</link><pubDate>Tue, 06 Aug 2024 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/nodejs-logging/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/nodejs-logging-zh-tw.png" alt="Featured image of post Node.js Logging 最佳 Practices: 架構d and Scalable" /&gt;&lt;p&gt;Production-grade logging is one of the most overlooked aspects of Node.js application development. While &lt;code&gt;console.log&lt;/code&gt; works for debugging locally, it falls apart in distributed environments where logs must be searchable, structured, and actionable. This article covers the essential patterns for building a logging strategy that scales.&lt;/p&gt;
&lt;h2 id="why-structured-logging"&gt;Why Structured Logging
&lt;/h2&gt;&lt;p&gt;Traditional unstructured logging outputs plain text that is difficult to parse programmatically. Consider &lt;code&gt;console.log(&amp;quot;User logged in:&amp;quot;, userId)&lt;/code&gt;. Grepping this across hundreds of service instances is slow and error-prone. Structured logging outputs each log event as a JSON object, making it machine-readable and queryable by log aggregation systems.&lt;/p&gt;</description></item><item><title>Node.js 工作執行緒：平行處理實踐</title><link>https://takao.blog/zh-tw/web/nodejs-worker-threads/</link><pubDate>Tue, 23 Apr 2024 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/nodejs-worker-threads/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/nodejs-worker-threads-zh-tw.png" alt="Featured image of post Node.js 工作執行緒：平行處理實踐" /&gt;&lt;p&gt;Node.js 傳統上是單線程的，並依賴非同步 I/O 來實現並發。雖然此模型擅長處理 I/O 密集型工作負載，但 CPU 密集型操作會阻止事件循環並降低應用程式回應能力。在 Node.js 12 中穩定的工作執行緒透過在單獨的 V8 隔離中執行 JavaScript 來在單一進程中提供真正的平行執行。本文介紹了在生產中使用工作執行緒的實用模式。&lt;/p&gt;
&lt;h2 id="工人生命週期和溝通"&gt;工人生命週期和溝通
&lt;/h2&gt;&lt;p&gt;建立工作執行緒需要一個單獨的 JavaScript 文件，該文件在自己的 V8 隔離中執行，並具有自己的堆和事件循環。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// main.js
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;Worker&lt;/span&gt; } &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;worker_threads&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;worker&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Worker&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;./worker.js&amp;#34;&lt;/span&gt;, {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;workerData&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;input&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;largeDataset&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;worker&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;on&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;, (&lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;logger&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;info&lt;/span&gt;({ &lt;span style="color:#a6e22e"&gt;result&lt;/span&gt; }, &lt;span style="color:#e6db74"&gt;&amp;#34;Worker completed&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;worker&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;on&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;, (&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;logger&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;error&lt;/span&gt;({ &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; }, &lt;span style="color:#e6db74"&gt;&amp;#34;Worker failed&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;worker&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;on&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;exit&amp;#34;&lt;/span&gt;, (&lt;span style="color:#a6e22e"&gt;code&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;code&lt;/span&gt; &lt;span style="color:#f92672"&gt;!==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;logger&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;error&lt;/span&gt;({ &lt;span style="color:#a6e22e"&gt;exitCode&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;code&lt;/span&gt; }, &lt;span style="color:#e6db74"&gt;&amp;#34;Worker crashed&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// worker.js
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;parentPort&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;workerData&lt;/span&gt; } &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;worker_threads&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;result&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;processData&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;workerData&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;input&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;parentPort&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;postMessage&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;工作人員透過結構化克隆進行通信，該克隆支援物件、陣列、Map、Sets、RegExp、Date 和 ArrayBuffers。對於大型二進位數據，請使用可傳輸物件來避免複製開銷 - 來源緩衝區在傳輸後會被中和。&lt;/p&gt;</description></item><item><title>Node.js Streams: Practical 指南 for Data Processing</title><link>https://takao.blog/zh-tw/web/nodejs-streams/</link><pubDate>Wed, 20 Dec 2023 00:00:00 +0900</pubDate><guid>https://takao.blog/zh-tw/web/nodejs-streams/</guid><description>&lt;img src="https://takao.blog/img/thumbnail/nodejs-streams-zh-tw.png" alt="Featured image of post Node.js Streams: Practical 指南 for Data Processing" /&gt;&lt;p&gt;Node.js streams are one of the most powerful yet underutilized features of the platform. They enable processing data piece by piece as it arrives, rather than loading entire datasets into memory. This makes them essential for working with large files, network communication, and real-time data transformation. This guide covers stream fundamentals and practical patterns for building robust data pipelines.&lt;/p&gt;
&lt;h2 id="understanding-stream-types"&gt;Understanding Stream Types
&lt;/h2&gt;&lt;p&gt;Node.js provides four fundamental stream types, each serving a distinct role in data processing pipelines.&lt;/p&gt;</description></item></channel></rss>