<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Wrk on Tarragon</title><link>https://tarrragon.github.io/blog/tags/wrk/</link><description>Recent content in Wrk on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Fri, 03 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/wrk/index.xml" rel="self" type="application/rss+xml"/><item><title>壓力測試工具與方法</title><link>https://tarrragon.github.io/blog/devops/05-capacity-planning/load-testing-tools/</link><pubDate>Fri, 03 Jul 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/devops/05-capacity-planning/load-testing-tools/</guid><description>&lt;p>壓測要回答的問題是「這個服務在什麼負載下開始撐不住」，不是「跑一次看會不會掛」。有價值的壓測是階梯加壓、觀察系統行為在哪個點從穩定轉為劣化，把 &lt;a href="https://tarrragon.github.io/blog/devops/05-capacity-planning/traffic-model/" data-link-title="流量模型建立" data-link-desc="要把「這個服務會收到什麼樣的流量」量化成容量規劃的輸入時，釐清該量哪幾個維度、峰均比為什麼是最關鍵的單一指標、以及怎麼從 production log 抽出可信的模型">流量模型&lt;/a> 的假設拿到真實負載下驗證。工具選對，這個劣化點測得準；工具選錯，測到的是工具自己的極限、不是被測系統的。&lt;/p>
&lt;p>工具選型的核心不是「哪個最強」，是「哪個最貼合本團隊的 workload model 表達能力與 CI 整合需求」。同樣一組流量，能不能用工具複製出來，決定壓測結果可不可信。&lt;/p>
&lt;h2 id="選型看六個維度">選型看六個維度&lt;/h2>
&lt;p>選壓測工具要按六個維度評估，只看「能不能發 HTTP 請求」會選錯：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>腳本表達能力&lt;/strong>：能不能寫完整的用戶動線（登入到瀏覽到結帳），而不只是打單一端點。複雜系統的瓶頸常在跨端點的資源競爭，單端點壓測看不到。&lt;/li>
&lt;li>&lt;strong>協議支援&lt;/strong>：HTTP、WebSocket、gRPC、TCP。現代後端常用 WebSocket 與 gRPC，有些老工具要靠外掛才支援。&lt;/li>
&lt;li>&lt;strong>規模能力&lt;/strong>：單機能發多少 RPS、能不能分散式擴容。單機 wrk 能發一到五萬 RPS，分散式部署的工具能到百萬級。&lt;/li>
&lt;li>&lt;strong>CI 整合&lt;/strong>：能不能在 PR 上跑輕量效能檢查、結果能不能機器可讀、能不能跟 baseline 比對。沒有 CI 整合的工具只能做事件型壓測，做不了持續的效能治理。&lt;/li>
&lt;li>&lt;strong>結果分析&lt;/strong>：原生儀表板、或整進既有的 metric 系統、或純文字輸出。&lt;/li>
&lt;li>&lt;strong>學習曲線&lt;/strong>：腳本語言與團隊熟悉度。工具再好、團隊不會用，就會變成一兩個人的孤島技能。&lt;/li>
&lt;/ul>
&lt;p>主流開源工具的定位大致是：k6（JavaScript 腳本、CI 友善、現代專案首選）、Locust（Python、適合複雜業務邏輯、單機吞吐受限要靠分散式）、Gatling（Scala、報表精美、學習曲線陡）、JMeter（協議廣、腳本是 XML 難版控、已在用的團隊再續用）、wrk 與 Vegeta（單機極限壓測、找天花板用）。選型的完整維度與雲端託管服務見 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/load-test-tooling/" data-link-title="9.3 壓測工具選型" data-link-desc="k6 / JMeter / Gatling / Locust / Vegeta / Production Replay 的工程選型">backend 壓測工具選型&lt;/a>，這一章聚焦怎麼實際跑一次、怎麼讀結果。&lt;/p>
&lt;h2 id="用-k6-實際跑一次">用 k6 實際跑一次&lt;/h2>
&lt;p>k6 的壓測腳本是一段 JavaScript，定義加壓的階段（stages）與通過標準（thresholds）。下面這段腳本把虛擬用戶（VU）在 5 秒內拉到 20、維持 10 秒、再 5 秒降回 0，並設一條「p95 延遲要低於 500 毫秒」的通過線：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kr">import&lt;/span> &lt;span class="nx">http&lt;/span> &lt;span class="nx">from&lt;/span> &lt;span class="s1">&amp;#39;k6/http&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kr">import&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nx">check&lt;/span> &lt;span class="p">}&lt;/span> &lt;span class="nx">from&lt;/span> &lt;span class="s1">&amp;#39;k6&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="kr">export&lt;/span> &lt;span class="kr">const&lt;/span> &lt;span class="nx">options&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> &lt;span class="nx">stages&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="p">{&lt;/span> &lt;span class="nx">duration&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;5s&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">target&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="mi">20&lt;/span> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> &lt;span class="p">{&lt;/span> &lt;span class="nx">duration&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;10s&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">target&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="mi">20&lt;/span> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="p">{&lt;/span> &lt;span class="nx">duration&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;5s&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">target&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> &lt;span class="nx">thresholds&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nx">http_req_duration&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;p(95)&amp;lt;500&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="kr">export&lt;/span> &lt;span class="k">default&lt;/span> &lt;span class="kd">function&lt;/span> &lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">res&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">http&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;http://target/&amp;#39;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="nx">check&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">res&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="s1">&amp;#39;status is 200&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nx">r&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="nx">r&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">status&lt;/span> &lt;span class="o">===&lt;/span> &lt;span class="mi">200&lt;/span> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>對一個 nginx 目標實跑這段腳本，輸出的關鍵段落是：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl"> █ THRESHOLDS
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> http_req_duration
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> ✓ &amp;#39;p(95)&amp;lt;500&amp;#39; p(95)=1.3ms
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> █ TOTAL RESULTS
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> checks_succeeded...: 100.00% 637011 out of 637011
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> http_req_duration..: avg=403µs min=11µs med=126µs max=562ms p(90)=749µs p(95)=1.3ms
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl"> http_req_failed....: 0.00% 0 out of 637011
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl"> http_reqs..........: 637011 30971/s&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>讀這份輸出的順序是：先看 &lt;code>THRESHOLDS&lt;/code> 有沒有通過（打勾代表 p95 通過了 500 毫秒的線），再看 &lt;code>http_req_failed&lt;/code> 確認錯誤率（0% 代表沒有失敗請求），接著看 &lt;code>http_reqs&lt;/code> 的每秒數（這次是 30971 RPS）。真正的判讀重點在 &lt;code>http_req_duration&lt;/code> 那一行的分布：平均 403 微秒沒什麼資訊量，要看的是 p90、p95 跟 max 之間的差距。這次 p95 是 1.3 毫秒、max 卻是 562 毫秒——絕大多數請求很快，但有極少數慢了三個數量級。這種「平均漂亮、尾巴很長」正是只看平均會漏掉的問題，也是壓測要看 percentile 而非平均的理由。&lt;/p>
&lt;p>這次測出的 sub-millisecond 延遲有一個前提：壓測機跟被測的 nginx 跑在同一台主機的容器網路裡，沒有真實的網路往返。這正好示範了下一節第一個反模式——壓測機跟被測機太近，延遲會被嚴重低估、p99 比 production 樂觀。&lt;/p>
&lt;h2 id="wrk-找單機天花板">wrk 找單機天花板&lt;/h2>
&lt;p>wrk 的定位跟 k6 不同：它不寫複雜動線，專門對單一端點灌到極限、找這個服務的天花板。saturation discovery 的第一輪常用它——&lt;code>wrk -t4 -c100 -d30s --latency http://target/&lt;/code> 開 4 個執行緒、100 條連線、壓 30 秒，回報 RPS 與延遲分布。k6 適合驗證「這條用戶動線在預期負載下的行為」，wrk 適合回答「這個端點的絕對上限在哪」，兩者常搭配：wrk 先找到天花板的量級，k6 再在天花板以下驗證真實動線。&lt;/p></description><content:encoded><![CDATA[<p>壓測要回答的問題是「這個服務在什麼負載下開始撐不住」，不是「跑一次看會不會掛」。有價值的壓測是階梯加壓、觀察系統行為在哪個點從穩定轉為劣化，把 <a href="/blog/devops/05-capacity-planning/traffic-model/" data-link-title="流量模型建立" data-link-desc="要把「這個服務會收到什麼樣的流量」量化成容量規劃的輸入時，釐清該量哪幾個維度、峰均比為什麼是最關鍵的單一指標、以及怎麼從 production log 抽出可信的模型">流量模型</a> 的假設拿到真實負載下驗證。工具選對，這個劣化點測得準；工具選錯，測到的是工具自己的極限、不是被測系統的。</p>
<p>工具選型的核心不是「哪個最強」，是「哪個最貼合本團隊的 workload model 表達能力與 CI 整合需求」。同樣一組流量，能不能用工具複製出來，決定壓測結果可不可信。</p>
<h2 id="選型看六個維度">選型看六個維度</h2>
<p>選壓測工具要按六個維度評估，只看「能不能發 HTTP 請求」會選錯：</p>
<ul>
<li><strong>腳本表達能力</strong>：能不能寫完整的用戶動線（登入到瀏覽到結帳），而不只是打單一端點。複雜系統的瓶頸常在跨端點的資源競爭，單端點壓測看不到。</li>
<li><strong>協議支援</strong>：HTTP、WebSocket、gRPC、TCP。現代後端常用 WebSocket 與 gRPC，有些老工具要靠外掛才支援。</li>
<li><strong>規模能力</strong>：單機能發多少 RPS、能不能分散式擴容。單機 wrk 能發一到五萬 RPS，分散式部署的工具能到百萬級。</li>
<li><strong>CI 整合</strong>：能不能在 PR 上跑輕量效能檢查、結果能不能機器可讀、能不能跟 baseline 比對。沒有 CI 整合的工具只能做事件型壓測，做不了持續的效能治理。</li>
<li><strong>結果分析</strong>：原生儀表板、或整進既有的 metric 系統、或純文字輸出。</li>
<li><strong>學習曲線</strong>：腳本語言與團隊熟悉度。工具再好、團隊不會用，就會變成一兩個人的孤島技能。</li>
</ul>
<p>主流開源工具的定位大致是：k6（JavaScript 腳本、CI 友善、現代專案首選）、Locust（Python、適合複雜業務邏輯、單機吞吐受限要靠分散式）、Gatling（Scala、報表精美、學習曲線陡）、JMeter（協議廣、腳本是 XML 難版控、已在用的團隊再續用）、wrk 與 Vegeta（單機極限壓測、找天花板用）。選型的完整維度與雲端託管服務見 <a href="/blog/backend/09-performance-capacity/load-test-tooling/" data-link-title="9.3 壓測工具選型" data-link-desc="k6 / JMeter / Gatling / Locust / Vegeta / Production Replay 的工程選型">backend 壓測工具選型</a>，這一章聚焦怎麼實際跑一次、怎麼讀結果。</p>
<h2 id="用-k6-實際跑一次">用 k6 實際跑一次</h2>
<p>k6 的壓測腳本是一段 JavaScript，定義加壓的階段（stages）與通過標準（thresholds）。下面這段腳本把虛擬用戶（VU）在 5 秒內拉到 20、維持 10 秒、再 5 秒降回 0，並設一條「p95 延遲要低於 500 毫秒」的通過線：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kr">import</span> <span class="nx">http</span> <span class="nx">from</span> <span class="s1">&#39;k6/http&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">check</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;k6&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  <span class="nx">stages</span><span class="o">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="p">{</span> <span class="nx">duration</span><span class="o">:</span> <span class="s1">&#39;5s&#39;</span><span class="p">,</span> <span class="nx">target</span><span class="o">:</span> <span class="mi">20</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="p">{</span> <span class="nx">duration</span><span class="o">:</span> <span class="s1">&#39;10s&#39;</span><span class="p">,</span> <span class="nx">target</span><span class="o">:</span> <span class="mi">20</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="p">{</span> <span class="nx">duration</span><span class="o">:</span> <span class="s1">&#39;5s&#39;</span><span class="p">,</span> <span class="nx">target</span><span class="o">:</span> <span class="mi">0</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  <span class="p">],</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  <span class="nx">thresholds</span><span class="o">:</span> <span class="p">{</span> <span class="nx">http_req_duration</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;p(95)&lt;500&#39;</span><span class="p">]</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="kr">export</span> <span class="k">default</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">  <span class="kr">const</span> <span class="nx">res</span> <span class="o">=</span> <span class="nx">http</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;http://target/&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">  <span class="nx">check</span><span class="p">(</span><span class="nx">res</span><span class="p">,</span> <span class="p">{</span> <span class="s1">&#39;status is 200&#39;</span><span class="o">:</span> <span class="p">(</span><span class="nx">r</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">r</span><span class="p">.</span><span class="nx">status</span> <span class="o">===</span> <span class="mi">200</span> <span class="p">});</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>對一個 nginx 目標實跑這段腳本，輸出的關鍵段落是：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">  █ THRESHOLDS
</span></span><span class="line"><span class="ln">2</span><span class="cl">    http_req_duration
</span></span><span class="line"><span class="ln">3</span><span class="cl">    ✓ &#39;p(95)&lt;500&#39; p(95)=1.3ms
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl">  █ TOTAL RESULTS
</span></span><span class="line"><span class="ln">6</span><span class="cl">    checks_succeeded...: 100.00% 637011 out of 637011
</span></span><span class="line"><span class="ln">7</span><span class="cl">    http_req_duration..: avg=403µs min=11µs med=126µs max=562ms p(90)=749µs p(95)=1.3ms
</span></span><span class="line"><span class="ln">8</span><span class="cl">    http_req_failed....: 0.00%  0 out of 637011
</span></span><span class="line"><span class="ln">9</span><span class="cl">    http_reqs..........: 637011 30971/s</span></span></code></pre></div><p>讀這份輸出的順序是：先看 <code>THRESHOLDS</code> 有沒有通過（打勾代表 p95 通過了 500 毫秒的線），再看 <code>http_req_failed</code> 確認錯誤率（0% 代表沒有失敗請求），接著看 <code>http_reqs</code> 的每秒數（這次是 30971 RPS）。真正的判讀重點在 <code>http_req_duration</code> 那一行的分布：平均 403 微秒沒什麼資訊量，要看的是 p90、p95 跟 max 之間的差距。這次 p95 是 1.3 毫秒、max 卻是 562 毫秒——絕大多數請求很快，但有極少數慢了三個數量級。這種「平均漂亮、尾巴很長」正是只看平均會漏掉的問題，也是壓測要看 percentile 而非平均的理由。</p>
<p>這次測出的 sub-millisecond 延遲有一個前提：壓測機跟被測的 nginx 跑在同一台主機的容器網路裡，沒有真實的網路往返。這正好示範了下一節第一個反模式——壓測機跟被測機太近，延遲會被嚴重低估、p99 比 production 樂觀。</p>
<h2 id="wrk-找單機天花板">wrk 找單機天花板</h2>
<p>wrk 的定位跟 k6 不同：它不寫複雜動線，專門對單一端點灌到極限、找這個服務的天花板。saturation discovery 的第一輪常用它——<code>wrk -t4 -c100 -d30s --latency http://target/</code> 開 4 個執行緒、100 條連線、壓 30 秒，回報 RPS 與延遲分布。k6 適合驗證「這條用戶動線在預期負載下的行為」，wrk 適合回答「這個端點的絕對上限在哪」，兩者常搭配：wrk 先找到天花板的量級，k6 再在天花板以下驗證真實動線。</p>
<h2 id="讓結果失真的反模式">讓結果失真的反模式</h2>
<p>壓測最大的風險是測出一個看起來漂亮、但不能外推到 production 的數字。幾個常見的失真來源：</p>
<ul>
<li><strong>只測單一 API、不測用戶動線</strong>：找不到跨端點的資源競爭、也累積不出真實的 session 狀態。</li>
<li><strong>壓測機跟被測機在同一網段</strong>：網路延遲被低估，p99 比 production 樂觀——上一節的 sub-millisecond 結果就是這個例子。</li>
<li><strong>壓測時 throttle 到自己的工具</strong>：測出的是工具的極限、不是被測系統的，訊號是壓測機自己的 CPU 先滿。</li>
<li><strong>只看平均延遲</strong>：尾延遲看不到，p99 的劣化被平均值蓋掉。</li>
<li><strong>壓測環境跟 production 硬體不一致</strong>：CPU 型號、網路、磁碟 IOPS 差很多，結果不可外推。</li>
<li><strong>跑了壓測卻沒驗證模型</strong>：沒拿結果跟 production metric 比對，不知道壓測用的流量模型貼不貼近真實。</li>
</ul>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>壓測用的流量模型怎麼建、怎麼驗證 → <a href="/blog/devops/05-capacity-planning/traffic-model/" data-link-title="流量模型建立" data-link-desc="要把「這個服務會收到什麼樣的流量」量化成容量規劃的輸入時，釐清該量哪幾個維度、峰均比為什麼是最關鍵的單一指標、以及怎麼從 production log 抽出可信的模型">流量模型建立</a></li>
<li>用階梯加壓找飽和點、讀哪些訊號 → <a href="/blog/devops/05-capacity-planning/scaling-inflection-point/" data-link-title="規模拐點判斷" data-link-desc="判斷什麼訊號代表該擴容、什麼代表可縮容、以及該往垂直還水平擴時，用飽和曲線的三段區間、膝點的早期訊號與 ramp-up 方法回來讀">規模拐點判斷</a></li>
<li>工具選型的完整維度、雲端託管壓測、production 流量重播 → <a href="/blog/backend/09-performance-capacity/load-test-tooling/" data-link-title="9.3 壓測工具選型" data-link-desc="k6 / JMeter / Gatling / Locust / Vegeta / Production Replay 的工程選型">backend 壓測工具選型</a></li>
</ul>
]]></content:encoded></item></channel></rss>