<?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>Push-Pull on Tarragon</title><link>https://tarrragon.github.io/blog/tags/push-pull/</link><description>Recent content in Push-Pull on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Tue, 16 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/push-pull/index.xml" rel="self" type="application/rss+xml"/><item><title>Google Pub/Sub push vs pull：不是實作偏好，是下游容量的判讀</title><link>https://tarrragon.github.io/blog/backend/03-message-queue/vendors/google-pubsub/push-pull-ack-flow-control/</link><pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/03-message-queue/vendors/google-pubsub/push-pull-ack-flow-control/</guid><description>&lt;blockquote>
&lt;p>本文是 &lt;a href="https://tarrragon.github.io/blog/backend/03-message-queue/vendors/google-pubsub/" data-link-title="Google Cloud Pub/Sub" data-link-desc="GCP managed pub/sub、global routing、push/pull">Google Cloud Pub/Sub&lt;/a> overview 的 implementation-layer deep article。選型層（Pub/Sub vs Kafka / SQS）見 overview；本文只處理「決定用 Pub/Sub 後，subscription 與 ack 怎麼設」。Pub/Sub 是 managed SaaS、無法本機 docker 驗證，本文 config 依 &lt;a href="https://cloud.google.com/pubsub/docs/subscriber">Pub/Sub 官方文件&lt;/a> 與下列 production case、最後檢查日 2026-06-16；引數與計費以官方為準。&lt;/p>&lt;/blockquote>
&lt;h2 id="push-vs-pull-不是實作偏好">push vs pull 不是實作偏好&lt;/h2>
&lt;p>把 Pub/Sub 的 subscription 設成 push 還是 pull，常被當成「看團隊習慣」的實作選擇。但它其實是一個關於下游容量的判讀。差別在流量控制權在誰手上：push subscription 由 Pub/Sub 主動把訊息 HTTP POST 到目標 endpoint——流量節奏由 Pub/Sub 決定，尖峰時瞬間打過來；pull subscription 由 consumer 主動拉，要拉多少、多快由 consumer 自己控制。&lt;/p>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/backend/03-message-queue/cases/pubsub-mercari-line-flow-control/" data-link-title="3.C65 Mercari LINE：Pull subscription 對齊外部 RPS" data-link-desc="Mercari LINE webhook 轉 Pub/Sub、worker pull subscription 精確控制 RPS、應 LINE API 限制。">Mercari 的 LINE 整合&lt;/a>把這個判讀講得很具體：Braze webhook 進來轉成 Pub/Sub event，下游要呼叫 LINE API——而 &lt;strong>LINE API 有 RPS 限制&lt;/strong>。如果用 push，Pub/Sub 會把訊息瞬間打到 worker、worker 再打 LINE、直接超過 LINE 的 RPS 上限。所以他們用 pull subscription，worker「精確控制每秒處理訊息數」來對齊 LINE 的限制。這個案例揭露的原則是——&lt;strong>push vs pull 不是實作偏好，是「下游能不能承受 push 的流量衝擊」的判讀&lt;/strong>：下游有速率限制、處理能力有限、或需要平滑流量，就走 pull 自我節流。&lt;/p>
&lt;p>本文展開 subscription 模型、ack deadline、flow control 與 dead-letter topic——這些決定了訊息怎麼被可靠地、以下游能承受的速度消費。&lt;/p>
&lt;h2 id="核心概念subscriptionack-deadline-與-flow-control">核心概念：subscription、ack deadline 與 flow control&lt;/h2>
&lt;p>Pub/Sub 把「topic（發布）」跟「subscription（訂閱）」分開，可靠消費的旋鈕都在 subscription 上。&lt;/p>
&lt;p>&lt;strong>一個 topic、多個 subscription、各自獨立&lt;/strong>。發布者發到 topic，每個 subscription 收到一份完整的訊息流、各自維護消費進度。這天然支援 fanout（多個服務各建一個 subscription）。&lt;a href="https://tarrragon.github.io/blog/backend/03-message-queue/cases/pubsub-mercari-item-feed-dlt/" data-link-title="3.C64 Mercari Item Feed：DLT 防 poison message 阻塞" data-link-desc="Mercari 商品 feed 同步、ack 整批 / nack 重送、重試多次仍失敗送 DLT、topic 同時當 load-leveling buffer。">Mercari 的另一個案例&lt;/a>還揭露 topic 的雙重角色——它同時是「dispatch」跟「load-leveling buffer」，突發流量先進 topic 緩衝、consumer 按自己節奏消化。&lt;/p>
&lt;p>&lt;strong>ack deadline 是 Pub/Sub 版的可見性逾時&lt;/strong>。consumer 收到訊息後，有一段 ack deadline 來處理並 &lt;code>ack&lt;/code>。在 deadline 內沒 ack，Pub/Sub 重新投遞（at-least-once）。跟 &lt;a href="https://tarrragon.github.io/blog/backend/03-message-queue/vendors/aws-sqs/visibility-polling-lambda-cost/" data-link-title="AWS SQS：Visibility timeout、long polling 與 Lambda event source 的成本與失敗形狀" data-link-desc="SQS deep article：visibility timeout 對齊 consumer 處理時間（ChangeMessageVisibility）、long vs short polling 的 cost 取捨（WaitTimeSeconds）、SQS &amp;#43; Lambda event source mapping（batch size / batch window / 並行 ramp-up）、DLQ &amp;#43; redrive policy（maxReceiveCount）、message size 與 extended client、per-request cost 模型；含 5 個 production 故障演練（VT &amp;lt; 處理時間 redelivery、polling 設定省成本、Lambda 部分失敗整批重投、DLQ maxReceiveCount、FIFO 吞吐上限）">SQS visibility timeout&lt;/a> 同樣是雙邊風險：太短→處理中就重投、太長→失敗後恢復慢。處理中可用 &lt;code>modifyAckDeadline&lt;/code>（client library 通常自動 lease extension）延長。&lt;/p></description><content:encoded><![CDATA[<blockquote>
<p>本文是 <a href="/blog/backend/03-message-queue/vendors/google-pubsub/" data-link-title="Google Cloud Pub/Sub" data-link-desc="GCP managed pub/sub、global routing、push/pull">Google Cloud Pub/Sub</a> overview 的 implementation-layer deep article。選型層（Pub/Sub vs Kafka / SQS）見 overview；本文只處理「決定用 Pub/Sub 後，subscription 與 ack 怎麼設」。Pub/Sub 是 managed SaaS、無法本機 docker 驗證，本文 config 依 <a href="https://cloud.google.com/pubsub/docs/subscriber">Pub/Sub 官方文件</a> 與下列 production case、最後檢查日 2026-06-16；引數與計費以官方為準。</p></blockquote>
<h2 id="push-vs-pull-不是實作偏好">push vs pull 不是實作偏好</h2>
<p>把 Pub/Sub 的 subscription 設成 push 還是 pull，常被當成「看團隊習慣」的實作選擇。但它其實是一個關於下游容量的判讀。差別在流量控制權在誰手上：push subscription 由 Pub/Sub 主動把訊息 HTTP POST 到目標 endpoint——流量節奏由 Pub/Sub 決定，尖峰時瞬間打過來；pull subscription 由 consumer 主動拉，要拉多少、多快由 consumer 自己控制。</p>
<p><a href="/blog/backend/03-message-queue/cases/pubsub-mercari-line-flow-control/" data-link-title="3.C65 Mercari LINE：Pull subscription 對齊外部 RPS" data-link-desc="Mercari LINE webhook 轉 Pub/Sub、worker pull subscription 精確控制 RPS、應 LINE API 限制。">Mercari 的 LINE 整合</a>把這個判讀講得很具體：Braze webhook 進來轉成 Pub/Sub event，下游要呼叫 LINE API——而 <strong>LINE API 有 RPS 限制</strong>。如果用 push，Pub/Sub 會把訊息瞬間打到 worker、worker 再打 LINE、直接超過 LINE 的 RPS 上限。所以他們用 pull subscription，worker「精確控制每秒處理訊息數」來對齊 LINE 的限制。這個案例揭露的原則是——<strong>push vs pull 不是實作偏好，是「下游能不能承受 push 的流量衝擊」的判讀</strong>：下游有速率限制、處理能力有限、或需要平滑流量，就走 pull 自我節流。</p>
<p>本文展開 subscription 模型、ack deadline、flow control 與 dead-letter topic——這些決定了訊息怎麼被可靠地、以下游能承受的速度消費。</p>
<h2 id="核心概念subscriptionack-deadline-與-flow-control">核心概念：subscription、ack deadline 與 flow control</h2>
<p>Pub/Sub 把「topic（發布）」跟「subscription（訂閱）」分開，可靠消費的旋鈕都在 subscription 上。</p>
<p><strong>一個 topic、多個 subscription、各自獨立</strong>。發布者發到 topic，每個 subscription 收到一份完整的訊息流、各自維護消費進度。這天然支援 fanout（多個服務各建一個 subscription）。<a href="/blog/backend/03-message-queue/cases/pubsub-mercari-item-feed-dlt/" data-link-title="3.C64 Mercari Item Feed：DLT 防 poison message 阻塞" data-link-desc="Mercari 商品 feed 同步、ack 整批 / nack 重送、重試多次仍失敗送 DLT、topic 同時當 load-leveling buffer。">Mercari 的另一個案例</a>還揭露 topic 的雙重角色——它同時是「dispatch」跟「load-leveling buffer」，突發流量先進 topic 緩衝、consumer 按自己節奏消化。</p>
<p><strong>ack deadline 是 Pub/Sub 版的可見性逾時</strong>。consumer 收到訊息後，有一段 ack deadline 來處理並 <code>ack</code>。在 deadline 內沒 ack，Pub/Sub 重新投遞（at-least-once）。跟 <a href="/blog/backend/03-message-queue/vendors/aws-sqs/visibility-polling-lambda-cost/" data-link-title="AWS SQS：Visibility timeout、long polling 與 Lambda event source 的成本與失敗形狀" data-link-desc="SQS deep article：visibility timeout 對齊 consumer 處理時間（ChangeMessageVisibility）、long vs short polling 的 cost 取捨（WaitTimeSeconds）、SQS &#43; Lambda event source mapping（batch size / batch window / 並行 ramp-up）、DLQ &#43; redrive policy（maxReceiveCount）、message size 與 extended client、per-request cost 模型；含 5 個 production 故障演練（VT &lt; 處理時間 redelivery、polling 設定省成本、Lambda 部分失敗整批重投、DLQ maxReceiveCount、FIFO 吞吐上限）">SQS visibility timeout</a> 同樣是雙邊風險：太短→處理中就重投、太長→失敗後恢復慢。處理中可用 <code>modifyAckDeadline</code>（client library 通常自動 lease extension）延長。</p>
<p><strong>flow control 限制 client 端同時持有的未 ack 量</strong>。pull subscription 的 client library 可設 <code>max_outstanding_messages</code> / <code>max_outstanding_bytes</code>——consumer 最多同時持有多少未 ack 訊息。這是 consumer 端自我節流的旋鈕，避免一次拉太多撐爆自己或下游。Mercari 對齊 LINE RPS 靠的就是這層控制。</p>
<p><strong>dead-letter topic（DLT）給毒訊息出口</strong>。subscription 設 dead-letter policy（<code>maxDeliveryAttempts</code> + dead-letter topic）後，重投超過上限的訊息被轉到 DLT，不再阻塞後續。Mercari item feed 正是「重試多次仍失敗送 DLT、後續訊息優先處理」——避免 poison message 卡住 pipeline。</p>
<h2 id="配置subscription--ack-deadline--dlt依官方文件">配置：subscription + ack deadline + DLT（依官方文件）</h2>
<p>Pub/Sub 是 managed、以下 gcloud 依官方文件（未本機 docker 驗證、引數以官方為準）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 建 topic + dead-letter topic</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">gcloud pubsub topics create orders
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">gcloud pubsub topics create orders-dlt
</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"><span class="c1"># 2. pull subscription：ack deadline + dead-letter policy</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">gcloud pubsub subscriptions create orders-worker <span class="se">\
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="se"></span>  --topic<span class="o">=</span>orders <span class="se">\
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="se"></span>  --ack-deadline<span class="o">=</span><span class="m">60</span> <span class="se">\
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="se"></span>  --dead-letter-topic<span class="o">=</span>orders-dlt <span class="se">\
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="se"></span>  --max-delivery-attempts<span class="o">=</span><span class="m">5</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1"># 3. consumer 端 flow control（client library、以 Python 為例、概念跨語言一致）</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c1">#    flow_control = FlowControl(max_messages=100, max_bytes=10*1024*1024)</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="c1">#    subscriber.subscribe(sub_path, callback=handle, flow_control=flow_control)</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="c1">#    handle 內：處理成功 message.ack()、失敗 message.nack()</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="c1"># push subscription（僅當下游能承受 Pub/Sub 主動推的流量時）：</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="c1"># gcloud pubsub subscriptions create orders-push \</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="c1">#   --topic=orders --push-endpoint=https://my-svc/handler --ack-deadline=60</span></span></span></code></pre></div><p>判讀：</p>
<ul>
<li>下游有 RPS 限制 / 處理能力有限 → pull + flow control（self-throttle，Mercari 模式）</li>
<li>下游能吸收推送尖峰、要 serverless 簡單 → push</li>
<li><code>ack-deadline</code> 略高於處理時間；長任務靠 client library 的 lease extension</li>
<li><code>max-delivery-attempts</code> + DLT 給毒訊息出口</li>
</ul>
<h2 id="production-故障演練">Production 故障演練</h2>
<h3 id="case-1用-push下游被瞬間流量打爆">Case 1：用 push、下游被瞬間流量打爆</h3>
<p><strong>徵兆</strong>：流量尖峰時下游 endpoint 5xx 暴增、或下游的第三方 API 回 429（rate limited），訊息大量重投惡化。</p>
<p><strong>根因</strong>：用 push subscription，Pub/Sub 把訊息瞬間 POST 到 endpoint，超過下游（或下游依賴的外部 API）的處理 / 速率上限。正是 <a href="/blog/backend/03-message-queue/cases/pubsub-mercari-line-flow-control/" data-link-title="3.C65 Mercari LINE：Pull subscription 對齊外部 RPS" data-link-desc="Mercari LINE webhook 轉 Pub/Sub、worker pull subscription 精確控制 RPS、應 LINE API 限制。">Mercari LINE</a> 要避開的情形。</p>
<p><strong>修法</strong>：</p>
<ol>
<li>下游有速率限制改用 pull subscription + flow control，由 consumer 自我節流</li>
<li>flow control 的 <code>max_outstanding_messages</code> 對齊下游能承受的並發</li>
<li>push 只用在下游能吸收推送尖峰的場景</li>
<li>push 場景下游要自己擋（rate limit / 佇列），不能假設 Pub/Sub 會幫你平滑</li>
</ol>
<h3 id="case-2ack-deadline-太短訊息處理中就被重投">Case 2：ack deadline 太短、訊息處理中就被重投</h3>
<p><strong>徵兆</strong>：同一則訊息被處理多次，尤其處理較慢時；訂閱的 redelivery 指標偏高。</p>
<p><strong>根因</strong>：ack deadline 設得比處理時間短，訊息在處理途中 deadline 到期、Pub/Sub 重投。跟 SQS visibility timeout 太短同類。</p>
<p><strong>修法</strong>：</p>
<ol>
<li>ack deadline 設成略高於處理時間 p99</li>
<li>用 client library 的自動 lease extension（modifyAckDeadline）處理長尾任務</li>
<li>消費端冪等——at-least-once 本來就可能重投（見 <a href="/blog/backend/06-reliability/idempotency-replay/" data-link-title="6.12 Idempotency 與 Replay 驗證" data-link-desc="把重試、重播與冪等性從口頭約定變成可驗證屬性">6.12 idempotency</a>）</li>
<li>監控 redelivery 率，偏高代表 deadline 偏短或處理變慢</li>
</ol>
<h3 id="case-3沒設-dlt毒訊息一直重投阻塞">Case 3：沒設 DLT、毒訊息一直重投阻塞</h3>
<p><strong>徵兆</strong>：某則訊息一直失敗、一直被重投，後續訊息處理被拖慢。</p>
<p><strong>根因</strong>：subscription 沒設 dead-letter policy。處理失敗（nack 或沒 ack）的訊息一再重投、沒有上限與出口，毒訊息反覆消耗 consumer。</p>
<p><strong>修法</strong>：</p>
<ol>
<li>設 dead-letter policy（<code>max-delivery-attempts</code> + DLT），重投達上限轉 DLT</li>
<li>DLT 是另一個 topic，要有處理 / 告警流程（Mercari「送 DLT、後續訊息優先處理」）</li>
<li><code>max-delivery-attempts</code> 平衡暫時性失敗重試與毒訊息隔離</li>
<li>對照 <a href="/blog/backend/03-message-queue/vendors/aws-sqs/visibility-polling-lambda-cost/" data-link-title="AWS SQS：Visibility timeout、long polling 與 Lambda event source 的成本與失敗形狀" data-link-desc="SQS deep article：visibility timeout 對齊 consumer 處理時間（ChangeMessageVisibility）、long vs short polling 的 cost 取捨（WaitTimeSeconds）、SQS &#43; Lambda event source mapping（batch size / batch window / 並行 ramp-up）、DLQ &#43; redrive policy（maxReceiveCount）、message size 與 extended client、per-request cost 模型；含 5 個 production 故障演練（VT &lt; 處理時間 redelivery、polling 設定省成本、Lambda 部分失敗整批重投、DLQ maxReceiveCount、FIFO 吞吐上限）">SQS redrive</a>：兩者都是 managed 原生 DLQ/DLT、比自建省事</li>
</ol>
<h3 id="case-4flow-control-沒設consumer-一次拉太多撐爆">Case 4：flow control 沒設、consumer 一次拉太多撐爆</h3>
<p><strong>徵兆</strong>：consumer 記憶體暴增 / OOM，或一次拉太多把下游打爆。</p>
<p><strong>根因</strong>：pull subscription 沒設 flow control，client library 預設可能持有大量未 ack 訊息，consumer 端記憶體與下游壓力失控。</p>
<p><strong>修法</strong>：</p>
<ol>
<li>設 <code>max_outstanding_messages</code> / <code>max_outstanding_bytes</code> 限制同時持有量</li>
<li>對齊 consumer 處理能力與下游容量（Mercari 對齊 LINE RPS）</li>
<li>監控 consumer 記憶體與未 ack 數，調 flow control 參數</li>
<li>flow control 是 pull 自我節流的核心，不設等於放棄背壓</li>
</ol>
<h3 id="case-5誤用-ordering-key吞吐受限">Case 5：誤用 ordering key、吞吐受限</h3>
<p><strong>徵兆</strong>：開了 message ordering 後吞吐明顯下降、特定 ordering key 的訊息處理變慢。</p>
<p><strong>根因</strong>：Pub/Sub 的順序保證是 per-ordering-key 的——同一個 ordering key 的訊息嚴格按序、必須序列處理（前一則 ack 才處理下一則）。把所有訊息塞同一個 ordering key 等於序列化整條流、吞吐崩。</p>
<p><strong>修法</strong>：</p>
<ol>
<li>ordering key 用細粒度（per-entity，如 per-user），讓不同 key 可並行</li>
<li>不需要嚴格順序的就別開 ordering（預設無序、吞吐高）</li>
<li>評估順序需求的真實範圍——多數場景只需 per-entity 順序，不是全域</li>
<li>嚴格全域順序 + 高吞吐有本質衝突，重新審視需求或走 <a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Kafka</a> 的 partition 模型</li>
</ol>
<h2 id="capacity--cost-邊界">Capacity / cost 邊界</h2>
<p>Pub/Sub 的容量判讀（managed、無 broker 運維）：</p>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>健康區間</th>
          <th>警戒與動作</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>subscription backlog（未 ack 數 / 最舊訊息 age）</td>
          <td>在 SLA 內</td>
          <td>持續成長 → consumer 跟不上、加 consumer / 調 flow control</td>
      </tr>
      <tr>
          <td>redelivery 率</td>
          <td>低</td>
          <td>偏高 → ack deadline 太短 / 下游失敗</td>
      </tr>
      <tr>
          <td>DLT 深度</td>
          <td>低且有處理流程</td>
          <td>成長 → 上游系統性失敗</td>
      </tr>
      <tr>
          <td>consumer 記憶體 / 未 ack 量</td>
          <td>在 flow control 限制內</td>
          <td>暴增 → flow control 沒設好</td>
      </tr>
      <tr>
          <td>訊息量（計費基礎）</td>
          <td>對齊預算</td>
          <td>暴增 → 評估 throughput 計費、batch / 壓縮</td>
      </tr>
  </tbody>
</table>
<p>撞牆後的路由判斷：</p>
<ul>
<li><strong>需要長期保留 + 任意 replay</strong>：Pub/Sub 有 retention（可設、seek 到時間點）但事件流長期 replay + 生態走 <a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Kafka</a>。</li>
<li><strong>嚴格全域順序 + 高吞吐</strong>：Pub/Sub ordering 是 per-key 序列化，全域順序高吞吐走 Kafka partition 設計。</li>
<li><strong>不在 GCP 生態</strong>：Pub/Sub 綁 GCP，跨雲走 <a href="/blog/backend/03-message-queue/vendors/kafka/" data-link-title="Apache Kafka" data-link-desc="Distributed event streaming platform、log-based 模型">Kafka</a> / <a href="/blog/backend/03-message-queue/vendors/nats/" data-link-title="NATS" data-link-desc="Lightweight messaging、JetStream 加持久化與 streams">NATS</a> 或對應雲的 managed（<a href="/blog/backend/03-message-queue/vendors/aws-sqs/" data-link-title="AWS SQS" data-link-desc="AWS managed queue、簡單可靠、無 ordering（standard）">SQS</a>）。</li>
<li><strong>複雜 routing（topic exchange 式）</strong>：Pub/Sub 是 topic→subscription 扇出，複雜 routing 規則走 <a href="/blog/backend/03-message-queue/vendors/rabbitmq/" data-link-title="RabbitMQ" data-link-desc="Classic message broker、AMQP routing 為主">RabbitMQ</a> exchange。</li>
</ul>
<h2 id="整合--下一步">整合 / 下一步</h2>
<p>push/pull 判讀與 ack 是 Pub/Sub 可靠消費的核心，它跟其他議題交織：</p>
<ul>
<li><strong>跟 <a href="/blog/backend/03-message-queue/consumer-design/" data-link-title="3.4 consumer 設計與去重" data-link-desc="整理 consumer、checkpoint 與 replay safety">3.4 consumer design</a></strong>：push/pull、ack deadline、flow control 是 consumer 設計的具體選項。</li>
<li><strong>跟 <a href="/blog/backend/06-reliability/idempotency-replay/" data-link-title="6.12 Idempotency 與 Replay 驗證" data-link-desc="把重試、重播與冪等性從口頭約定變成可驗證屬性">6.12 idempotency / replay</a></strong>：at-least-once + 重投要求消費冪等。</li>
<li><strong>跟 <a href="/blog/backend/03-message-queue/vendors/aws-sqs/visibility-polling-lambda-cost/" data-link-title="AWS SQS：Visibility timeout、long polling 與 Lambda event source 的成本與失敗形狀" data-link-desc="SQS deep article：visibility timeout 對齊 consumer 處理時間（ChangeMessageVisibility）、long vs short polling 的 cost 取捨（WaitTimeSeconds）、SQS &#43; Lambda event source mapping（batch size / batch window / 並行 ramp-up）、DLQ &#43; redrive policy（maxReceiveCount）、message size 與 extended client、per-request cost 模型；含 5 個 production 故障演練（VT &lt; 處理時間 redelivery、polling 設定省成本、Lambda 部分失敗整批重投、DLQ maxReceiveCount、FIFO 吞吐上限）">SQS visibility timeout</a></strong>：ack deadline 對應 visibility timeout、DLT 對應 redrive，兩個 managed queue 的可靠消費模型高度對位、可對照閱讀。</li>
<li><strong>跟 webhook buffer 模式</strong>：Pub/Sub topic 當 load-leveling buffer（Mercari）對應 <a href="/blog/backend/03-message-queue/cases/sqs-twilio-webhook-buffer/" data-link-title="3.C58 Twilio：SQS 緩衝高流量 webhook" data-link-desc="Twilio 教用 SQS 緩衝 SMS / status callback webhook、分 queue（SMS vs callback）、long polling 減 cost、FIFO 300 TPS 上限要分片。">SQS Twilio webhook buffer</a>——把不可控的外部 webhook 流量先緩衝再按自己節奏消化。</li>
</ul>
<h2 id="相關連結">相關連結</h2>
<ul>
<li>上游 vendor 頁：<a href="/blog/backend/03-message-queue/vendors/google-pubsub/" data-link-title="Google Cloud Pub/Sub" data-link-desc="GCP managed pub/sub、global routing、push/pull">Google Cloud Pub/Sub</a></li>
<li>對照 vendor：<a href="/blog/backend/03-message-queue/vendors/aws-sqs/visibility-polling-lambda-cost/" data-link-title="AWS SQS：Visibility timeout、long polling 與 Lambda event source 的成本與失敗形狀" data-link-desc="SQS deep article：visibility timeout 對齊 consumer 處理時間（ChangeMessageVisibility）、long vs short polling 的 cost 取捨（WaitTimeSeconds）、SQS &#43; Lambda event source mapping（batch size / batch window / 並行 ramp-up）、DLQ &#43; redrive policy（maxReceiveCount）、message size 與 extended client、per-request cost 模型；含 5 個 production 故障演練（VT &lt; 處理時間 redelivery、polling 設定省成本、Lambda 部分失敗整批重投、DLQ maxReceiveCount、FIFO 吞吐上限）">AWS SQS visibility timeout</a>、<a href="/blog/backend/03-message-queue/vendors/rabbitmq/dlq-retry-escalation/" data-link-title="RabbitMQ DLQ 與分層 retry：別把失敗訊息 requeue 回隊首" data-link-desc="RabbitMQ 處理失敗訊息最常見的錯是直接 requeue 回原隊列——它回到隊首、反覆失敗、把後面的訊息全卡住（head-of-line blocking）。正解是用 dead-letter exchange &#43; TTL 組出 work → delay → DLQ 的分層 escalation。本文展開 DLX 求值模型、實機驗證的三層拓樸、5 個把 retry 寫成無限迴圈與隊列阻塞的 production 踩坑，以及 retry 拓樸的容量邊界">RabbitMQ DLQ</a></li>
<li>對應案例：<a href="/blog/backend/03-message-queue/cases/pubsub-mercari-line-flow-control/" data-link-title="3.C65 Mercari LINE：Pull subscription 對齊外部 RPS" data-link-desc="Mercari LINE webhook 轉 Pub/Sub、worker pull subscription 精確控制 RPS、應 LINE API 限制。">3.C65 Mercari LINE flow control</a>、<a href="/blog/backend/03-message-queue/cases/pubsub-mercari-item-feed-dlt/" data-link-title="3.C64 Mercari Item Feed：DLT 防 poison message 阻塞" data-link-desc="Mercari 商品 feed 同步、ack 整批 / nack 重送、重試多次仍失敗送 DLT、topic 同時當 load-leveling buffer。">3.C64 Mercari item feed DLT</a></li>
<li>上游概念：<a href="/blog/backend/03-message-queue/consumer-design/" data-link-title="3.4 consumer 設計與去重" data-link-desc="整理 consumer、checkpoint 與 replay safety">3.4 consumer design</a></li>
</ul>
]]></content:encoded></item></channel></rss>