<?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>Burst-Traffic on Tarragon</title><link>https://tarrragon.github.io/blog/tags/burst-traffic/</link><description>Recent content in Burst-Traffic on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Sat, 20 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/burst-traffic/index.xml" rel="self" type="application/rss+xml"/><item><title>突發流量的分類</title><link>https://tarrragon.github.io/blog/devops/07-burst-traffic/burst-classification/</link><pubDate>Sat, 20 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/devops/07-burst-traffic/burst-classification/</guid><description>&lt;p>突發流量按可預測性分成兩類。可預期的突發（行銷活動、新聞發佈）可以事前準備容量；不可預期的突發（病毒傳播、error storm）只能靠架構設計吸收衝擊。&lt;/p>
&lt;h2 id="可預期突發">可預期突發&lt;/h2>
&lt;p>事前知道流量會增加，有時間準備。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>來源&lt;/th>
 &lt;th>流量倍率&lt;/th>
 &lt;th>持續時間&lt;/th>
 &lt;th>特徵&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>行銷活動（促銷、限時折扣）&lt;/td>
 &lt;td>5-50x&lt;/td>
 &lt;td>數小時～數天&lt;/td>
 &lt;td>流量集中在活動開始的前幾分鐘&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>新聞曝光（媒體報導、社群爆紅）&lt;/td>
 &lt;td>10-100x&lt;/td>
 &lt;td>數小時&lt;/td>
 &lt;td>不可控的流量曲線、峰值在發佈後 1-2 小時&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>定時推播（每日報表、週報）&lt;/td>
 &lt;td>2-10x&lt;/td>
 &lt;td>分鐘級&lt;/td>
 &lt;td>短暫但可精確預測時間&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>新版本推送（app store 更新）&lt;/td>
 &lt;td>3-10x&lt;/td>
 &lt;td>數天（逐漸擴散）&lt;/td>
 &lt;td>流量緩慢上升、峰值在推送後 24-48 小時&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>可預期突發的應對核心是&lt;strong>容量預備&lt;/strong> — 活動前擴容、活動後縮回。&lt;/p>
&lt;h3 id="預備清單">預備清單&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>項目&lt;/th>
 &lt;th>做什麼&lt;/th>
 &lt;th>何時做&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>容量估算&lt;/td>
 &lt;td>歷史峰值 × 安全係數（1.5-2x）&lt;/td>
 &lt;td>活動前 1 週&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>擴容&lt;/td>
 &lt;td>加實例 / 加資源 / 預熱 cache&lt;/td>
 &lt;td>活動前 1 天&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>降級預案&lt;/td>
 &lt;td>設定動態取樣的觸發閾值&lt;/td>
 &lt;td>活動前 1 天&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>壓力測試&lt;/td>
 &lt;td>模擬預期流量打 staging&lt;/td>
 &lt;td>活動前 3 天&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>值班&lt;/td>
 &lt;td>安排值班人員監控 dashboard&lt;/td>
 &lt;td>活動期間&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="不可預期突發">不可預期突發&lt;/h2>
&lt;p>事前不知道流量會增加，只能靠架構設計吸收。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>來源&lt;/th>
 &lt;th>流量倍率&lt;/th>
 &lt;th>持續時間&lt;/th>
 &lt;th>特徵&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>病毒傳播（社群分享爆量）&lt;/td>
 &lt;td>10-1000x&lt;/td>
 &lt;td>數小時&lt;/td>
 &lt;td>完全無法預測、可能超過任何預備容量&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>DDoS 攻擊&lt;/td>
 &lt;td>100-10000x&lt;/td>
 &lt;td>不定&lt;/td>
 &lt;td>惡意流量、需要 WAF / CDN 擋在前面&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Error storm（app bug 觸發大量 error）&lt;/td>
 &lt;td>依 bug 影響範圍&lt;/td>
 &lt;td>直到 hotfix&lt;/td>
 &lt;td>每個受影響的使用者都在送 error 事件&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>外部依賴復原（積壓請求一次湧入）&lt;/td>
 &lt;td>2-5x&lt;/td>
 &lt;td>分鐘級&lt;/td>
 &lt;td>依賴恢復後積壓的 retry 一起到達&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>不可預期突發的應對核心是&lt;strong>降級&lt;/strong> — 系統在超載時自動犧牲非核心功能，保住核心功能。&lt;/p>
&lt;h3 id="監控系統的-error-storm">監控系統的 error storm&lt;/h3>
&lt;p>Error storm 是監控系統特有的突發場景：被監控的 app 出了 bug，每個受影響的使用者都在送 error 事件。如果有 10 萬使用者同時遇到同一個 bug，collector 瞬間收到 10 萬筆 error 事件。&lt;/p>
&lt;p>Error storm 的矛盾：error 事件是 debug 最需要的資料，但 storm 時的大量 error 可能打垮 collector。處理策略是&lt;strong>保留前 N 筆完整 error（含 stack trace）、後續的 error 只計數不存原始資料&lt;/strong>。第一筆 error 的 stack trace 足夠 debug，後續的 10 萬筆只是確認影響範圍。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>突發時的降級策略 → &lt;a href="https://tarrragon.github.io/blog/devops/07-burst-traffic/degradation-strategy/" data-link-title="降級策略" data-link-desc="系統超載時犧牲什麼保住什麼 — 動態取樣、事件優先級、功能降級、聚合前移四種策略">降級策略&lt;/a>&lt;/li>
&lt;li>Queue 做 burst 緩衝 → &lt;a href="https://tarrragon.github.io/blog/devops/07-burst-traffic/queue-buffering/" data-link-title="Queue 緩衝" data-link-desc="在 ingestion 和 processing 之間加 message queue 做 burst 緩衝 — Kafka / NATS / Redis Streams 的選型和引入條件">Queue 緩衝&lt;/a>&lt;/li>
&lt;li>不同規模的應對方案 → &lt;a href="https://tarrragon.github.io/blog/devops/07-burst-traffic/scale-tier-response/" data-link-title="規模分級應對表" data-link-desc="自用級 → 中型 → 大型 → 商業網站級的四級應對方案 — 每級的觸發條件、架構組成和成本">規模分級應對表&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>突發流量按可預測性分成兩類。可預期的突發（行銷活動、新聞發佈）可以事前準備容量；不可預期的突發（病毒傳播、error storm）只能靠架構設計吸收衝擊。</p>
<h2 id="可預期突發">可預期突發</h2>
<p>事前知道流量會增加，有時間準備。</p>
<table>
  <thead>
      <tr>
          <th>來源</th>
          <th>流量倍率</th>
          <th>持續時間</th>
          <th>特徵</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>行銷活動（促銷、限時折扣）</td>
          <td>5-50x</td>
          <td>數小時～數天</td>
          <td>流量集中在活動開始的前幾分鐘</td>
      </tr>
      <tr>
          <td>新聞曝光（媒體報導、社群爆紅）</td>
          <td>10-100x</td>
          <td>數小時</td>
          <td>不可控的流量曲線、峰值在發佈後 1-2 小時</td>
      </tr>
      <tr>
          <td>定時推播（每日報表、週報）</td>
          <td>2-10x</td>
          <td>分鐘級</td>
          <td>短暫但可精確預測時間</td>
      </tr>
      <tr>
          <td>新版本推送（app store 更新）</td>
          <td>3-10x</td>
          <td>數天（逐漸擴散）</td>
          <td>流量緩慢上升、峰值在推送後 24-48 小時</td>
      </tr>
  </tbody>
</table>
<p>可預期突發的應對核心是<strong>容量預備</strong> — 活動前擴容、活動後縮回。</p>
<h3 id="預備清單">預備清單</h3>
<table>
  <thead>
      <tr>
          <th>項目</th>
          <th>做什麼</th>
          <th>何時做</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>容量估算</td>
          <td>歷史峰值 × 安全係數（1.5-2x）</td>
          <td>活動前 1 週</td>
      </tr>
      <tr>
          <td>擴容</td>
          <td>加實例 / 加資源 / 預熱 cache</td>
          <td>活動前 1 天</td>
      </tr>
      <tr>
          <td>降級預案</td>
          <td>設定動態取樣的觸發閾值</td>
          <td>活動前 1 天</td>
      </tr>
      <tr>
          <td>壓力測試</td>
          <td>模擬預期流量打 staging</td>
          <td>活動前 3 天</td>
      </tr>
      <tr>
          <td>值班</td>
          <td>安排值班人員監控 dashboard</td>
          <td>活動期間</td>
      </tr>
  </tbody>
</table>
<h2 id="不可預期突發">不可預期突發</h2>
<p>事前不知道流量會增加，只能靠架構設計吸收。</p>
<table>
  <thead>
      <tr>
          <th>來源</th>
          <th>流量倍率</th>
          <th>持續時間</th>
          <th>特徵</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>病毒傳播（社群分享爆量）</td>
          <td>10-1000x</td>
          <td>數小時</td>
          <td>完全無法預測、可能超過任何預備容量</td>
      </tr>
      <tr>
          <td>DDoS 攻擊</td>
          <td>100-10000x</td>
          <td>不定</td>
          <td>惡意流量、需要 WAF / CDN 擋在前面</td>
      </tr>
      <tr>
          <td>Error storm（app bug 觸發大量 error）</td>
          <td>依 bug 影響範圍</td>
          <td>直到 hotfix</td>
          <td>每個受影響的使用者都在送 error 事件</td>
      </tr>
      <tr>
          <td>外部依賴復原（積壓請求一次湧入）</td>
          <td>2-5x</td>
          <td>分鐘級</td>
          <td>依賴恢復後積壓的 retry 一起到達</td>
      </tr>
  </tbody>
</table>
<p>不可預期突發的應對核心是<strong>降級</strong> — 系統在超載時自動犧牲非核心功能，保住核心功能。</p>
<h3 id="監控系統的-error-storm">監控系統的 error storm</h3>
<p>Error storm 是監控系統特有的突發場景：被監控的 app 出了 bug，每個受影響的使用者都在送 error 事件。如果有 10 萬使用者同時遇到同一個 bug，collector 瞬間收到 10 萬筆 error 事件。</p>
<p>Error storm 的矛盾：error 事件是 debug 最需要的資料，但 storm 時的大量 error 可能打垮 collector。處理策略是<strong>保留前 N 筆完整 error（含 stack trace）、後續的 error 只計數不存原始資料</strong>。第一筆 error 的 stack trace 足夠 debug，後續的 10 萬筆只是確認影響範圍。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>突發時的降級策略 → <a href="/blog/devops/07-burst-traffic/degradation-strategy/" data-link-title="降級策略" data-link-desc="系統超載時犧牲什麼保住什麼 — 動態取樣、事件優先級、功能降級、聚合前移四種策略">降級策略</a></li>
<li>Queue 做 burst 緩衝 → <a href="/blog/devops/07-burst-traffic/queue-buffering/" data-link-title="Queue 緩衝" data-link-desc="在 ingestion 和 processing 之間加 message queue 做 burst 緩衝 — Kafka / NATS / Redis Streams 的選型和引入條件">Queue 緩衝</a></li>
<li>不同規模的應對方案 → <a href="/blog/devops/07-burst-traffic/scale-tier-response/" data-link-title="規模分級應對表" data-link-desc="自用級 → 中型 → 大型 → 商業網站級的四級應對方案 — 每級的觸發條件、架構組成和成本">規模分級應對表</a></li>
</ul>
]]></content:encoded></item><item><title>降級策略</title><link>https://tarrragon.github.io/blog/devops/07-burst-traffic/degradation-strategy/</link><pubDate>Sat, 20 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/devops/07-burst-traffic/degradation-strategy/</guid><description>&lt;p>降級策略的核心決策是「超載時犧牲什麼保住什麼」。犧牲的是精度、延遲或非核心功能；保住的是核心功能的可用性。沒有降級策略的系統在超載時整體崩潰 — 所有功能同時不可用。&lt;/p>
&lt;h2 id="動態取樣">動態取樣&lt;/h2>
&lt;p>流量超過閾值時自動降低取樣率。平時 100% 收集、超載時降到 10% — 仍有資料可分析，只是精度下降。&lt;/p>
&lt;h3 id="觸發條件">觸發條件&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>訊號&lt;/th>
 &lt;th>動作&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Collector 回 429 次數 &amp;gt; N / 分鐘&lt;/td>
 &lt;td>SDK 降低取樣率 50%&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>連續 429 超過 M 分鐘&lt;/td>
 &lt;td>SDK 再降到 10%&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>429 消失且 buffer 清空&lt;/td>
 &lt;td>SDK 恢復 100%&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="取樣的公平性">取樣的公平性&lt;/h3>
&lt;p>動態取樣不應該只丟新事件保留舊事件（FIFO 丟棄）— 這會讓取樣偏向「burst 初期的事件」。更好的策略是隨機取樣（每個事件有 sampling_rate 的機率被保留），讓取樣後的資料仍然能代表整體分佈。&lt;/p>
&lt;p>取樣後的事件帶 &lt;code>_sampling_rate&lt;/code> 欄位，分析時用 &lt;code>1 / sampling_rate&lt;/code> 做加權還原。&lt;/p>
&lt;h2 id="事件優先級">事件優先級&lt;/h2>
&lt;p>不同事件類型的 debug 價值不同。超載時先丟價值低的，保留價值高的。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>優先級&lt;/th>
 &lt;th>事件類型&lt;/th>
 &lt;th>理由&lt;/th>
 &lt;th>超載時處理&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>最高&lt;/td>
 &lt;td>error&lt;/td>
 &lt;td>debug 核心 — 丟了就查不到問題&lt;/td>
 &lt;td>全部保留&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>高&lt;/td>
 &lt;td>lifecycle&lt;/td>
 &lt;td>session 邊界 — 影響 session 分析&lt;/td>
 &lt;td>全部保留&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>中&lt;/td>
 &lt;td>metric&lt;/td>
 &lt;td>趨勢可從取樣還原&lt;/td>
 &lt;td>降低取樣率&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>低&lt;/td>
 &lt;td>event&lt;/td>
 &lt;td>行為分析可接受精度損失&lt;/td>
 &lt;td>降低取樣率或暫停&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>優先級的判斷原則：「這個事件丟了、要花多少時間從其他來源補回相同資訊」。Error 的 stack trace 丟了幾乎不可能從其他來源補回；event 的 click 計數可以從後續資料的趨勢推測。&lt;/p>
&lt;h2 id="功能降級">功能降級&lt;/h2>
&lt;p>非核心功能暫時關閉或降低更新頻率，把資源留給核心功能。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>功能&lt;/th>
 &lt;th>正常模式&lt;/th>
 &lt;th>降級模式&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Dashboard 即時刷新&lt;/td>
 &lt;td>每秒查詢&lt;/td>
 &lt;td>每 30 秒查詢&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Rule engine 評估&lt;/td>
 &lt;td>每筆事件即時評估&lt;/td>
 &lt;td>累積 10 筆批次評估&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>JSONL 匯出&lt;/td>
 &lt;td>隨時可匯出&lt;/td>
 &lt;td>暫停（避免 I/O 競爭）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>降採樣 job&lt;/td>
 &lt;td>每小時跑&lt;/td>
 &lt;td>延後到流量恢復後補跑&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>降級的觸發和恢復應該自動化 — 用 collector 的內部 metric（goroutine pool 使用率、寫入延遲）作為訊號。&lt;/p>
&lt;h2 id="聚合前移">聚合前移&lt;/h2>
&lt;p>讓 SDK 端做預聚合，減少送到 collector 的事件數量。&lt;/p>
&lt;p>平時：每次 click 送一筆 &lt;code>button.clicked&lt;/code> 事件 → 100 次 click = 100 筆事件。
聚合前移：SDK 累積 10 秒內的 click → 送一筆 &lt;code>button.clicked&lt;/code> 帶 &lt;code>count: 17&lt;/code> → 100 次 click = ~10 筆事件。&lt;/p>
&lt;p>聚合前移犧牲的是事件粒度（失去每次 click 的精確時間戳），換取的是 10x 的事件量減少。適用於高頻但單筆資訊量低的事件（click、scroll、mousemove）。&lt;/p>
&lt;p>聚合前移的觸發也可以是動態的 — collector 回 429 時 SDK 自動啟用聚合前移，流量恢復後關閉。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>突發流量的分類 → &lt;a href="https://tarrragon.github.io/blog/devops/07-burst-traffic/burst-classification/" data-link-title="突發流量的分類" data-link-desc="可預期 vs 不可預期的突發流量 — 不同來源、持續時間和倍率決定不同的應對策略">突發流量的分類&lt;/a>&lt;/li>
&lt;li>Queue 做更大規模的緩衝 → &lt;a href="https://tarrragon.github.io/blog/devops/07-burst-traffic/queue-buffering/" data-link-title="Queue 緩衝" data-link-desc="在 ingestion 和 processing 之間加 message queue 做 burst 緩衝 — Kafka / NATS / Redis Streams 的選型和引入條件">Queue 緩衝&lt;/a>&lt;/li>
&lt;li>不同規模的應對方案 → &lt;a href="https://tarrragon.github.io/blog/devops/07-burst-traffic/scale-tier-response/" data-link-title="規模分級應對表" data-link-desc="自用級 → 中型 → 大型 → 商業網站級的四級應對方案 — 每級的觸發條件、架構組成和成本">規模分級應對表&lt;/a>&lt;/li>
&lt;li>背壓和 rate limit 的基礎 → &lt;a href="https://tarrragon.github.io/blog/devops/03-traffic-management/" data-link-title="模組三：流量管控" data-link-desc="收到的流量超過處理能力時怎麼辦 — 背壓、rate limit、熔斷、bulkhead 四種防護機制">模組三 流量管控&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>降級策略的核心決策是「超載時犧牲什麼保住什麼」。犧牲的是精度、延遲或非核心功能；保住的是核心功能的可用性。沒有降級策略的系統在超載時整體崩潰 — 所有功能同時不可用。</p>
<h2 id="動態取樣">動態取樣</h2>
<p>流量超過閾值時自動降低取樣率。平時 100% 收集、超載時降到 10% — 仍有資料可分析，只是精度下降。</p>
<h3 id="觸發條件">觸發條件</h3>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>動作</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Collector 回 429 次數 &gt; N / 分鐘</td>
          <td>SDK 降低取樣率 50%</td>
      </tr>
      <tr>
          <td>連續 429 超過 M 分鐘</td>
          <td>SDK 再降到 10%</td>
      </tr>
      <tr>
          <td>429 消失且 buffer 清空</td>
          <td>SDK 恢復 100%</td>
      </tr>
  </tbody>
</table>
<h3 id="取樣的公平性">取樣的公平性</h3>
<p>動態取樣不應該只丟新事件保留舊事件（FIFO 丟棄）— 這會讓取樣偏向「burst 初期的事件」。更好的策略是隨機取樣（每個事件有 sampling_rate 的機率被保留），讓取樣後的資料仍然能代表整體分佈。</p>
<p>取樣後的事件帶 <code>_sampling_rate</code> 欄位，分析時用 <code>1 / sampling_rate</code> 做加權還原。</p>
<h2 id="事件優先級">事件優先級</h2>
<p>不同事件類型的 debug 價值不同。超載時先丟價值低的，保留價值高的。</p>
<table>
  <thead>
      <tr>
          <th>優先級</th>
          <th>事件類型</th>
          <th>理由</th>
          <th>超載時處理</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>最高</td>
          <td>error</td>
          <td>debug 核心 — 丟了就查不到問題</td>
          <td>全部保留</td>
      </tr>
      <tr>
          <td>高</td>
          <td>lifecycle</td>
          <td>session 邊界 — 影響 session 分析</td>
          <td>全部保留</td>
      </tr>
      <tr>
          <td>中</td>
          <td>metric</td>
          <td>趨勢可從取樣還原</td>
          <td>降低取樣率</td>
      </tr>
      <tr>
          <td>低</td>
          <td>event</td>
          <td>行為分析可接受精度損失</td>
          <td>降低取樣率或暫停</td>
      </tr>
  </tbody>
</table>
<p>優先級的判斷原則：「這個事件丟了、要花多少時間從其他來源補回相同資訊」。Error 的 stack trace 丟了幾乎不可能從其他來源補回；event 的 click 計數可以從後續資料的趨勢推測。</p>
<h2 id="功能降級">功能降級</h2>
<p>非核心功能暫時關閉或降低更新頻率，把資源留給核心功能。</p>
<table>
  <thead>
      <tr>
          <th>功能</th>
          <th>正常模式</th>
          <th>降級模式</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Dashboard 即時刷新</td>
          <td>每秒查詢</td>
          <td>每 30 秒查詢</td>
      </tr>
      <tr>
          <td>Rule engine 評估</td>
          <td>每筆事件即時評估</td>
          <td>累積 10 筆批次評估</td>
      </tr>
      <tr>
          <td>JSONL 匯出</td>
          <td>隨時可匯出</td>
          <td>暫停（避免 I/O 競爭）</td>
      </tr>
      <tr>
          <td>降採樣 job</td>
          <td>每小時跑</td>
          <td>延後到流量恢復後補跑</td>
      </tr>
  </tbody>
</table>
<p>降級的觸發和恢復應該自動化 — 用 collector 的內部 metric（goroutine pool 使用率、寫入延遲）作為訊號。</p>
<h2 id="聚合前移">聚合前移</h2>
<p>讓 SDK 端做預聚合，減少送到 collector 的事件數量。</p>
<p>平時：每次 click 送一筆 <code>button.clicked</code> 事件 → 100 次 click = 100 筆事件。
聚合前移：SDK 累積 10 秒內的 click → 送一筆 <code>button.clicked</code> 帶 <code>count: 17</code> → 100 次 click = ~10 筆事件。</p>
<p>聚合前移犧牲的是事件粒度（失去每次 click 的精確時間戳），換取的是 10x 的事件量減少。適用於高頻但單筆資訊量低的事件（click、scroll、mousemove）。</p>
<p>聚合前移的觸發也可以是動態的 — collector 回 429 時 SDK 自動啟用聚合前移，流量恢復後關閉。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>突發流量的分類 → <a href="/blog/devops/07-burst-traffic/burst-classification/" data-link-title="突發流量的分類" data-link-desc="可預期 vs 不可預期的突發流量 — 不同來源、持續時間和倍率決定不同的應對策略">突發流量的分類</a></li>
<li>Queue 做更大規模的緩衝 → <a href="/blog/devops/07-burst-traffic/queue-buffering/" data-link-title="Queue 緩衝" data-link-desc="在 ingestion 和 processing 之間加 message queue 做 burst 緩衝 — Kafka / NATS / Redis Streams 的選型和引入條件">Queue 緩衝</a></li>
<li>不同規模的應對方案 → <a href="/blog/devops/07-burst-traffic/scale-tier-response/" data-link-title="規模分級應對表" data-link-desc="自用級 → 中型 → 大型 → 商業網站級的四級應對方案 — 每級的觸發條件、架構組成和成本">規模分級應對表</a></li>
<li>背壓和 rate limit 的基礎 → <a href="/blog/devops/03-traffic-management/" data-link-title="模組三：流量管控" data-link-desc="收到的流量超過處理能力時怎麼辦 — 背壓、rate limit、熔斷、bulkhead 四種防護機制">模組三 流量管控</a></li>
</ul>
]]></content:encoded></item><item><title>Queue 緩衝</title><link>https://tarrragon.github.io/blog/devops/07-burst-traffic/queue-buffering/</link><pubDate>Sat, 20 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/devops/07-burst-traffic/queue-buffering/</guid><description>&lt;p>Message queue 放在 ingestion（接收事件）和 processing（寫入 storage）之間，把兩者解耦。Ingestion 只負責驗證和寫入 queue，processing 按自己的速度從 queue 消費。Queue 做 burst 的時間緩衝 — 高峰時 queue 積壓、低峰時 worker 追上。&lt;/p>
&lt;h2 id="為什麼不直接寫-db">為什麼不直接寫 DB&lt;/h2>
&lt;p>直接寫 DB（SQLite / PostgreSQL）的問題是 ingestion 速度被 DB 寫入速度限制。DB 寫入慢（鎖定、WAL flush、索引更新）時，HTTP handler 的 goroutine 等在 &lt;code>Storage.Store()&lt;/code> 上 — goroutine 積壓 → 記憶體上升 → 最終 OOM 或 response timeout。&lt;/p>
&lt;p>Queue 的解決方式是把「接收」和「寫入」分開：接收端只做 JSON 驗證 + 寫入 queue（微秒級），處理端從 queue 讀取 + 寫入 DB（毫秒級）。接收端的吞吐量不再受 DB 限制。&lt;/p>
&lt;h3 id="取捨">取捨&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>直接寫 DB&lt;/th>
 &lt;th>經過 Queue&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>延遲&lt;/td>
 &lt;td>事件寫完 DB 即可查詢&lt;/td>
 &lt;td>事件要等 worker 消費後才可查詢&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>吞吐&lt;/td>
 &lt;td>受 DB 寫入速度限制&lt;/td>
 &lt;td>受 queue 寫入速度限制（通常遠高於 DB）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>複雜度&lt;/td>
 &lt;td>一個元件&lt;/td>
 &lt;td>三個元件（collector + queue + worker）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>故障模式&lt;/td>
 &lt;td>DB 掛了事件丟失（除非有背壓）&lt;/td>
 &lt;td>Queue 做持久化，DB 掛了事件在 queue 等待&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>自用工具場景不需要 queue — 單 collector + SQLite 的直接寫入足夠。Queue 的引入條件是「直接寫 DB 的背壓開始頻繁觸發」。&lt;/p>
&lt;h2 id="候選類型">候選類型&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Queue&lt;/th>
 &lt;th>特點&lt;/th>
 &lt;th>適用場景&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;strong>Kafka&lt;/strong>&lt;/td>
 &lt;td>高吞吐、持久化、消費者群組&lt;/td>
 &lt;td>大規模（&amp;gt; 10 萬 events/sec）、多消費者&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>NATS JetStream&lt;/strong>&lt;/td>
 &lt;td>輕量、低延遲、Go 原生&lt;/td>
 &lt;td>中型（千 ~ 萬 events/sec）、Go 生態&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>Redis Streams&lt;/strong>&lt;/td>
 &lt;td>用既有 Redis、XADD/XREAD API&lt;/td>
 &lt;td>中型、已有 Redis 基礎設施&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="選型判斷">選型判斷&lt;/h3>
&lt;p>已有 Redis → 先用 Redis Streams（零新增元件）。Go 為主的技術棧 → NATS JetStream（Go 原生 client、單 binary 部署）。需要跨消費者群組或日誌級持久化 → Kafka。&lt;/p>
&lt;h3 id="引入條件">引入條件&lt;/h3>
&lt;p>Queue 的引入是架構複雜度的顯著上升（一個元件變三個）。明確的觸發條件：&lt;/p>
&lt;ul>
&lt;li>背壓（429 回應）頻繁觸發（每天 &amp;gt; 100 次）且持續（不只是瞬間 burst）&lt;/li>
&lt;li>寫入延遲的 P95 超過 500ms（DB 成為瓶頸）&lt;/li>
&lt;li>需要多個 consumer（同一批事件要送到不同的下游 — analytics DB、alert engine、archive）&lt;/li>
&lt;/ul>
&lt;h2 id="監控系統的-queue-架構">監控系統的 Queue 架構&lt;/h2>





&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">SDK ──→ Collector (ingestion only)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> ├─ 驗證 JSON Schema
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> ├─ Redaction
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> └─ 寫入 Queue
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> ├── Worker A → PostgreSQL（主 storage）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl"> ├── Worker B → 降採樣 → Summary tables
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl"> └── Worker C → Rule engine → Alert&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Collector 瘦身為 ingestion-only — 只做接收、驗證、redaction 和寫入 queue。Storage 寫入、降採樣、rule engine 都移到 worker 群。Collector 的吞吐瓶頸從 DB 寫入變成 queue 寫入（queue 的寫入吞吐通常是 DB 的 10-100 倍）。&lt;/p></description><content:encoded><![CDATA[<p>Message queue 放在 ingestion（接收事件）和 processing（寫入 storage）之間，把兩者解耦。Ingestion 只負責驗證和寫入 queue，processing 按自己的速度從 queue 消費。Queue 做 burst 的時間緩衝 — 高峰時 queue 積壓、低峰時 worker 追上。</p>
<h2 id="為什麼不直接寫-db">為什麼不直接寫 DB</h2>
<p>直接寫 DB（SQLite / PostgreSQL）的問題是 ingestion 速度被 DB 寫入速度限制。DB 寫入慢（鎖定、WAL flush、索引更新）時，HTTP handler 的 goroutine 等在 <code>Storage.Store()</code> 上 — goroutine 積壓 → 記憶體上升 → 最終 OOM 或 response timeout。</p>
<p>Queue 的解決方式是把「接收」和「寫入」分開：接收端只做 JSON 驗證 + 寫入 queue（微秒級），處理端從 queue 讀取 + 寫入 DB（毫秒級）。接收端的吞吐量不再受 DB 限制。</p>
<h3 id="取捨">取捨</h3>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>直接寫 DB</th>
          <th>經過 Queue</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>延遲</td>
          <td>事件寫完 DB 即可查詢</td>
          <td>事件要等 worker 消費後才可查詢</td>
      </tr>
      <tr>
          <td>吞吐</td>
          <td>受 DB 寫入速度限制</td>
          <td>受 queue 寫入速度限制（通常遠高於 DB）</td>
      </tr>
      <tr>
          <td>複雜度</td>
          <td>一個元件</td>
          <td>三個元件（collector + queue + worker）</td>
      </tr>
      <tr>
          <td>故障模式</td>
          <td>DB 掛了事件丟失（除非有背壓）</td>
          <td>Queue 做持久化，DB 掛了事件在 queue 等待</td>
      </tr>
  </tbody>
</table>
<p>自用工具場景不需要 queue — 單 collector + SQLite 的直接寫入足夠。Queue 的引入條件是「直接寫 DB 的背壓開始頻繁觸發」。</p>
<h2 id="候選類型">候選類型</h2>
<table>
  <thead>
      <tr>
          <th>Queue</th>
          <th>特點</th>
          <th>適用場景</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>Kafka</strong></td>
          <td>高吞吐、持久化、消費者群組</td>
          <td>大規模（&gt; 10 萬 events/sec）、多消費者</td>
      </tr>
      <tr>
          <td><strong>NATS JetStream</strong></td>
          <td>輕量、低延遲、Go 原生</td>
          <td>中型（千 ~ 萬 events/sec）、Go 生態</td>
      </tr>
      <tr>
          <td><strong>Redis Streams</strong></td>
          <td>用既有 Redis、XADD/XREAD API</td>
          <td>中型、已有 Redis 基礎設施</td>
      </tr>
  </tbody>
</table>
<h3 id="選型判斷">選型判斷</h3>
<p>已有 Redis → 先用 Redis Streams（零新增元件）。Go 為主的技術棧 → NATS JetStream（Go 原生 client、單 binary 部署）。需要跨消費者群組或日誌級持久化 → Kafka。</p>
<h3 id="引入條件">引入條件</h3>
<p>Queue 的引入是架構複雜度的顯著上升（一個元件變三個）。明確的觸發條件：</p>
<ul>
<li>背壓（429 回應）頻繁觸發（每天 &gt; 100 次）且持續（不只是瞬間 burst）</li>
<li>寫入延遲的 P95 超過 500ms（DB 成為瓶頸）</li>
<li>需要多個 consumer（同一批事件要送到不同的下游 — analytics DB、alert engine、archive）</li>
</ul>
<h2 id="監控系統的-queue-架構">監控系統的 Queue 架構</h2>





<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">SDK ──→ Collector (ingestion only)
</span></span><span class="line"><span class="ln">2</span><span class="cl">           │
</span></span><span class="line"><span class="ln">3</span><span class="cl">           ├─ 驗證 JSON Schema
</span></span><span class="line"><span class="ln">4</span><span class="cl">           ├─ Redaction
</span></span><span class="line"><span class="ln">5</span><span class="cl">           └─ 寫入 Queue
</span></span><span class="line"><span class="ln">6</span><span class="cl">                 │
</span></span><span class="line"><span class="ln">7</span><span class="cl">                 ├── Worker A → PostgreSQL（主 storage）
</span></span><span class="line"><span class="ln">8</span><span class="cl">                 ├── Worker B → 降採樣 → Summary tables
</span></span><span class="line"><span class="ln">9</span><span class="cl">                 └── Worker C → Rule engine → Alert</span></span></code></pre></div><p>Collector 瘦身為 ingestion-only — 只做接收、驗證、redaction 和寫入 queue。Storage 寫入、降採樣、rule engine 都移到 worker 群。Collector 的吞吐瓶頸從 DB 寫入變成 queue 寫入（queue 的寫入吞吐通常是 DB 的 10-100 倍）。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>突發流量的分類 → <a href="/blog/devops/07-burst-traffic/burst-classification/" data-link-title="突發流量的分類" data-link-desc="可預期 vs 不可預期的突發流量 — 不同來源、持續時間和倍率決定不同的應對策略">突發流量的分類</a></li>
<li>降級策略 → <a href="/blog/devops/07-burst-traffic/degradation-strategy/" data-link-title="降級策略" data-link-desc="系統超載時犧牲什麼保住什麼 — 動態取樣、事件優先級、功能降級、聚合前移四種策略">降級策略</a></li>
<li>規模分級的完整應對 → <a href="/blog/devops/07-burst-traffic/scale-tier-response/" data-link-title="規模分級應對表" data-link-desc="自用級 → 中型 → 大型 → 商業網站級的四級應對方案 — 每級的觸發條件、架構組成和成本">規模分級應對表</a></li>
<li>Queue 的選型和操作實務 → <a href="/blog/backend/03-message-queue/" data-link-title="模組三：訊息佇列與事件傳遞" data-link-desc="整理 durable queue、broker、retry、outbox 與 idempotency 的後端實務">backend 非同步佇列</a></li>
</ul>
]]></content:encoded></item><item><title>規模分級應對表</title><link>https://tarrragon.github.io/blog/devops/07-burst-traffic/scale-tier-response/</link><pubDate>Sat, 20 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/devops/07-burst-traffic/scale-tier-response/</guid><description>&lt;p>突發流量的應對方案隨服務規模分成四級。每一級在前一級的基礎上增加元件，複雜度和成本同步上升。選擇哪一級取決於「預期的峰值流量」和「可接受的降級程度」。&lt;/p>
&lt;h2 id="四級分級">四級分級&lt;/h2>
&lt;h3 id="tier-1自用級-100-eventssec">Tier 1：自用級（&amp;lt; 100 events/sec）&lt;/h3>





&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">SDK ──→ Collector (單 binary + SQLite)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>設定&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>架構&lt;/td>
 &lt;td>單 Go binary、SQLite embedded&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>流量控制&lt;/td>
 &lt;td>背壓（channel buffer 10000 + 429）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>突發應對&lt;/td>
 &lt;td>SDK 離線 buffer 吸收短暫 burst&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>降級&lt;/td>
 &lt;td>無（流量不會到需要降級的程度）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>成本&lt;/td>
 &lt;td>零（自有主機、零外部依賴）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>適用&lt;/td>
 &lt;td>自用工具、開發期測試、小型團隊&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Tier 1 的假設是峰值流量不超過 SQLite WAL mode 的寫入能力（每秒數千筆）。自用場景下這個假設幾乎永遠成立。&lt;/p>
&lt;h3 id="tier-2中型100-10000-eventssec">Tier 2：中型（100-10000 events/sec）&lt;/h3>





&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"> ┌─ Collector A ──→ PostgreSQL
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">SDK ──→ LB ─┤
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> └─ Collector B ──→ PostgreSQL&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>設定&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>架構&lt;/td>
 &lt;td>多 collector + load balancer + PostgreSQL&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>流量控制&lt;/td>
 &lt;td>背壓 + per-SDK rate limit&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>突發應對&lt;/td>
 &lt;td>LB 分散流量 + collector 水平擴展&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>降級&lt;/td>
 &lt;td>動態取樣（超載時 SDK 降到 10%）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>成本&lt;/td>
 &lt;td>PostgreSQL + LB 的維護（可用 managed service 降低維護成本）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>適用&lt;/td>
 &lt;td>使用者數百到數千、有付費能力&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Tier 1 → Tier 2 的觸發：SQLite 的 &lt;code>database is locked&lt;/code> 頻繁出現，或 dashboard 的聚合查詢需要 PostgreSQL 的能力。&lt;/p>
&lt;h3 id="tier-3大型10000-100000-eventssec">Tier 3：大型（10000-100000 events/sec）&lt;/h3>





&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"> ┌─ Collector A ─┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">SDK ──→ LB ─┤ ├─→ Queue ──→ Worker 群 ──→ PostgreSQL
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> └─ Collector B ─┘&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>設定&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>架構&lt;/td>
 &lt;td>Collector 群 + queue（NATS / Kafka）+ worker 群 + PostgreSQL&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>流量控制&lt;/td>
 &lt;td>背壓 + rate limit + bulkhead&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>突發應對&lt;/td>
 &lt;td>Queue 做時間緩衝（積壓 → 追趕）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>降級&lt;/td>
 &lt;td>動態取樣 + 事件優先級 + 功能降級&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>成本&lt;/td>
 &lt;td>Queue + worker 的基礎設施（顯著上升）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>適用&lt;/td>
 &lt;td>中大型 SaaS、使用者數萬&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Tier 2 → Tier 3 的觸發：直接寫 PostgreSQL 的背壓頻繁觸發（即使有多個 collector 寫入）。&lt;/p>
&lt;h3 id="tier-4商業網站級-100000-eventssec">Tier 4：商業網站級（&amp;gt; 100000 events/sec）&lt;/h3>





&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">SDK ──→ CDN/Edge ──→ LB ──→ Collector 群 ──→ Kafka ──→ Worker 群 ──→ 分層 DB
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> ├─ 即時查詢 DB（ClickHouse / TimescaleDB）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> └─ 歸檔 DB（S3 + Athena）&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>設定&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>架構&lt;/td>
 &lt;td>CDN edge 收集 + Kafka + 分層存儲&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>流量控制&lt;/td>
 &lt;td>CDN rate limit + 全鏈路背壓&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>突發應對&lt;/td>
 &lt;td>Kafka partition 水平擴展 + auto-scaling worker&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>降級&lt;/td>
 &lt;td>全套（動態取樣 + 優先級 + 聚合前移 + 功能降級）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>成本&lt;/td>
 &lt;td>基礎設施團隊級別的投入&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>適用&lt;/td>
 &lt;td>大型 SaaS、電商、社群平台&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Tier 3 → Tier 4 的觸發：Kafka 單 cluster 的吞吐不夠、或查詢需要跨日誌級的時間序列分析。&lt;/p></description><content:encoded><![CDATA[<p>突發流量的應對方案隨服務規模分成四級。每一級在前一級的基礎上增加元件，複雜度和成本同步上升。選擇哪一級取決於「預期的峰值流量」和「可接受的降級程度」。</p>
<h2 id="四級分級">四級分級</h2>
<h3 id="tier-1自用級-100-eventssec">Tier 1：自用級（&lt; 100 events/sec）</h3>





<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">SDK ──→ Collector (單 binary + SQLite)</span></span></code></pre></div><table>
  <thead>
      <tr>
          <th>維度</th>
          <th>設定</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>架構</td>
          <td>單 Go binary、SQLite embedded</td>
      </tr>
      <tr>
          <td>流量控制</td>
          <td>背壓（channel buffer 10000 + 429）</td>
      </tr>
      <tr>
          <td>突發應對</td>
          <td>SDK 離線 buffer 吸收短暫 burst</td>
      </tr>
      <tr>
          <td>降級</td>
          <td>無（流量不會到需要降級的程度）</td>
      </tr>
      <tr>
          <td>成本</td>
          <td>零（自有主機、零外部依賴）</td>
      </tr>
      <tr>
          <td>適用</td>
          <td>自用工具、開發期測試、小型團隊</td>
      </tr>
  </tbody>
</table>
<p>Tier 1 的假設是峰值流量不超過 SQLite WAL mode 的寫入能力（每秒數千筆）。自用場景下這個假設幾乎永遠成立。</p>
<h3 id="tier-2中型100-10000-eventssec">Tier 2：中型（100-10000 events/sec）</h3>





<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">         ┌─ Collector A ──→ PostgreSQL
</span></span><span class="line"><span class="ln">2</span><span class="cl">SDK ──→ LB ─┤
</span></span><span class="line"><span class="ln">3</span><span class="cl">         └─ Collector B ──→ PostgreSQL</span></span></code></pre></div><table>
  <thead>
      <tr>
          <th>維度</th>
          <th>設定</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>架構</td>
          <td>多 collector + load balancer + PostgreSQL</td>
      </tr>
      <tr>
          <td>流量控制</td>
          <td>背壓 + per-SDK rate limit</td>
      </tr>
      <tr>
          <td>突發應對</td>
          <td>LB 分散流量 + collector 水平擴展</td>
      </tr>
      <tr>
          <td>降級</td>
          <td>動態取樣（超載時 SDK 降到 10%）</td>
      </tr>
      <tr>
          <td>成本</td>
          <td>PostgreSQL + LB 的維護（可用 managed service 降低維護成本）</td>
      </tr>
      <tr>
          <td>適用</td>
          <td>使用者數百到數千、有付費能力</td>
      </tr>
  </tbody>
</table>
<p>Tier 1 → Tier 2 的觸發：SQLite 的 <code>database is locked</code> 頻繁出現，或 dashboard 的聚合查詢需要 PostgreSQL 的能力。</p>
<h3 id="tier-3大型10000-100000-eventssec">Tier 3：大型（10000-100000 events/sec）</h3>





<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">         ┌─ Collector A ─┐
</span></span><span class="line"><span class="ln">2</span><span class="cl">SDK ──→ LB ─┤               ├─→ Queue ──→ Worker 群 ──→ PostgreSQL
</span></span><span class="line"><span class="ln">3</span><span class="cl">         └─ Collector B ─┘</span></span></code></pre></div><table>
  <thead>
      <tr>
          <th>維度</th>
          <th>設定</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>架構</td>
          <td>Collector 群 + queue（NATS / Kafka）+ worker 群 + PostgreSQL</td>
      </tr>
      <tr>
          <td>流量控制</td>
          <td>背壓 + rate limit + bulkhead</td>
      </tr>
      <tr>
          <td>突發應對</td>
          <td>Queue 做時間緩衝（積壓 → 追趕）</td>
      </tr>
      <tr>
          <td>降級</td>
          <td>動態取樣 + 事件優先級 + 功能降級</td>
      </tr>
      <tr>
          <td>成本</td>
          <td>Queue + worker 的基礎設施（顯著上升）</td>
      </tr>
      <tr>
          <td>適用</td>
          <td>中大型 SaaS、使用者數萬</td>
      </tr>
  </tbody>
</table>
<p>Tier 2 → Tier 3 的觸發：直接寫 PostgreSQL 的背壓頻繁觸發（即使有多個 collector 寫入）。</p>
<h3 id="tier-4商業網站級-100000-eventssec">Tier 4：商業網站級（&gt; 100000 events/sec）</h3>





<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">SDK ──→ CDN/Edge ──→ LB ──→ Collector 群 ──→ Kafka ──→ Worker 群 ──→ 分層 DB
</span></span><span class="line"><span class="ln">2</span><span class="cl">                                                                      ├─ 即時查詢 DB（ClickHouse / TimescaleDB）
</span></span><span class="line"><span class="ln">3</span><span class="cl">                                                                      └─ 歸檔 DB（S3 + Athena）</span></span></code></pre></div><table>
  <thead>
      <tr>
          <th>維度</th>
          <th>設定</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>架構</td>
          <td>CDN edge 收集 + Kafka + 分層存儲</td>
      </tr>
      <tr>
          <td>流量控制</td>
          <td>CDN rate limit + 全鏈路背壓</td>
      </tr>
      <tr>
          <td>突發應對</td>
          <td>Kafka partition 水平擴展 + auto-scaling worker</td>
      </tr>
      <tr>
          <td>降級</td>
          <td>全套（動態取樣 + 優先級 + 聚合前移 + 功能降級）</td>
      </tr>
      <tr>
          <td>成本</td>
          <td>基礎設施團隊級別的投入</td>
      </tr>
      <tr>
          <td>適用</td>
          <td>大型 SaaS、電商、社群平台</td>
      </tr>
  </tbody>
</table>
<p>Tier 3 → Tier 4 的觸發：Kafka 單 cluster 的吞吐不夠、或查詢需要跨日誌級的時間序列分析。</p>
<p>多數自架開源工具不需要超過 Tier 2。Tier 3 和 Tier 4 是商業 SaaS 的領域。</p>
<h2 id="規模遷移路徑">規模遷移路徑</h2>
<table>
  <thead>
      <tr>
          <th>遷移</th>
          <th>改什麼</th>
          <th>停機</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Tier 1 → 2</td>
          <td>Storage backend 切 PostgreSQL + 加 LB + 加 collector</td>
          <td>config change + 資料遷移（分鐘級停機）</td>
      </tr>
      <tr>
          <td>Tier 2 → 3</td>
          <td>加 queue + 改 collector 為 ingestion-only + 加 worker</td>
          <td>架構重構（需要開發時間）</td>
      </tr>
      <tr>
          <td>Tier 3 → 4</td>
          <td>加 CDN edge + 分層 DB + auto-scaling</td>
          <td>基礎設施工程（需要專職團隊）</td>
      </tr>
  </tbody>
</table>
<p>每一級的遷移成本遞增。Tier 1 → 2 是 config change 級、Tier 2 → 3 是架構重構級、Tier 3 → 4 是團隊級。選擇起始 tier 時選最低的足夠 tier — 過早引入高 tier 的複雜度是浪費。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>流量管控的四種機制 → <a href="/blog/devops/03-traffic-management/" data-link-title="模組三：流量管控" data-link-desc="收到的流量超過處理能力時怎麼辦 — 背壓、rate limit、熔斷、bulkhead 四種防護機制">模組三 流量管控</a></li>
<li>容量預備和壓力測試 → <a href="/blog/devops/05-capacity-planning/" data-link-title="模組五：容量規劃與壓力測試" data-link-desc="要準備多少資源才夠 — 壓力測試方法、峰值估算、成本模型、規模拐點的判斷">模組五 容量規劃</a></li>
<li>Collector 的可插拔 storage 架構 → <a href="/blog/monitoring/04-collector/scaling-evolution/" data-link-title="規模演進" data-link-desc="可插拔 Storage Backend 架構 — SQLite 預設、PostgreSQL 觸發切換、時間序列 DB 長期演進">monitoring 模組四 規模演進</a></li>
<li>Queue 的選型 → <a href="/blog/backend/03-message-queue/" data-link-title="模組三：訊息佇列與事件傳遞" data-link-desc="整理 durable queue、broker、retry、outbox 與 idempotency 的後端實務">backend 非同步佇列</a></li>
</ul>
]]></content:encoded></item><item><title>模組七：突發流量應對</title><link>https://tarrragon.github.io/blog/devops/07-burst-traffic/</link><pubDate>Sat, 20 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/devops/07-burst-traffic/</guid><description>&lt;p>回答「流量突然暴增時怎麼不掛」。突發流量和穩定高流量的處理策略不同 — 突發有時間限制，撐過去就恢復正常。&lt;/p>
&lt;h2 id="待寫章節">待寫章節&lt;/h2>
&lt;ul>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> 突發流量的分類（可預期 vs 不可預期、持續時間和倍率）&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> 降級策略（動態取樣、事件優先級、功能降級、聚合前移）&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> Queue 緩衝（Kafka / NATS / Redis Streams 做 burst buffer）&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> 規模分級應對表（自用 → 中型 → 大型 → 商業網站）&lt;/li>
&lt;/ul>
&lt;h2 id="跨分類引用">跨分類引用&lt;/h2>
&lt;ul>
&lt;li>← &lt;a href="https://tarrragon.github.io/blog/devops/03-traffic-management/" data-link-title="模組三：流量管控" data-link-desc="收到的流量超過處理能力時怎麼辦 — 背壓、rate limit、熔斷、bulkhead 四種防護機制">devops 模組三 流量管控&lt;/a>：背壓和 rate limit 是突發應對的基礎元件&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/monitoring/04-collector/" data-link-title="模組四：Collector 設計" data-link-desc="收 → 驗 → 存 → 查 → 觸發的完整鏈路 — Go 單一 binary、可插拔 Storage Backend、rule engine">monitoring 模組四 Collector&lt;/a>：Collector 的 ingestion scaling 是本模組的應用場景&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/backend/03-message-queue/" data-link-title="模組三：訊息佇列與事件傳遞" data-link-desc="整理 durable queue、broker、retry、outbox 與 idempotency 的後端實務">backend 非同步佇列&lt;/a>：Queue 的選型和操作實務&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/devops/05-capacity-planning/" data-link-title="模組五：容量規劃與壓力測試" data-link-desc="要準備多少資源才夠 — 壓力測試方法、峰值估算、成本模型、規模拐點的判斷">devops 模組五 容量規劃&lt;/a>：預期突發的容量預備&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/monitoring/04-collector/data-integrity/" data-link-title="端到端資料完整性" data-link-desc="從 SDK 到 storage 的資料損失地圖 — 每個環節的損失類型、控制策略、完整性指標、被自己 SDK DDoS 的防護">端到端資料完整性&lt;/a>：被自己 SDK DDoS 的三種場景&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>回答「流量突然暴增時怎麼不掛」。突發流量和穩定高流量的處理策略不同 — 突發有時間限制，撐過去就恢復正常。</p>
<h2 id="待寫章節">待寫章節</h2>
<ul>
<li><input checked="" disabled="" type="checkbox"> 突發流量的分類（可預期 vs 不可預期、持續時間和倍率）</li>
<li><input checked="" disabled="" type="checkbox"> 降級策略（動態取樣、事件優先級、功能降級、聚合前移）</li>
<li><input checked="" disabled="" type="checkbox"> Queue 緩衝（Kafka / NATS / Redis Streams 做 burst buffer）</li>
<li><input checked="" disabled="" type="checkbox"> 規模分級應對表（自用 → 中型 → 大型 → 商業網站）</li>
</ul>
<h2 id="跨分類引用">跨分類引用</h2>
<ul>
<li>← <a href="/blog/devops/03-traffic-management/" data-link-title="模組三：流量管控" data-link-desc="收到的流量超過處理能力時怎麼辦 — 背壓、rate limit、熔斷、bulkhead 四種防護機制">devops 模組三 流量管控</a>：背壓和 rate limit 是突發應對的基礎元件</li>
<li>→ <a href="/blog/monitoring/04-collector/" data-link-title="模組四：Collector 設計" data-link-desc="收 → 驗 → 存 → 查 → 觸發的完整鏈路 — Go 單一 binary、可插拔 Storage Backend、rule engine">monitoring 模組四 Collector</a>：Collector 的 ingestion scaling 是本模組的應用場景</li>
<li>→ <a href="/blog/backend/03-message-queue/" data-link-title="模組三：訊息佇列與事件傳遞" data-link-desc="整理 durable queue、broker、retry、outbox 與 idempotency 的後端實務">backend 非同步佇列</a>：Queue 的選型和操作實務</li>
<li>→ <a href="/blog/devops/05-capacity-planning/" data-link-title="模組五：容量規劃與壓力測試" data-link-desc="要準備多少資源才夠 — 壓力測試方法、峰值估算、成本模型、規模拐點的判斷">devops 模組五 容量規劃</a>：預期突發的容量預備</li>
<li>→ <a href="/blog/monitoring/04-collector/data-integrity/" data-link-title="端到端資料完整性" data-link-desc="從 SDK 到 storage 的資料損失地圖 — 每個環節的損失類型、控制策略、完整性指標、被自己 SDK DDoS 的防護">端到端資料完整性</a>：被自己 SDK DDoS 的三種場景</li>
</ul>
]]></content:encoded></item></channel></rss>