<?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>Rds-Proxy on Tarragon</title><link>https://tarrragon.github.io/blog/tags/rds-proxy/</link><description>Recent content in Rds-Proxy on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Tue, 02 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/rds-proxy/index.xml" rel="self" type="application/rss+xml"/><item><title>Aurora RDS Proxy 與連線管理：connection multiplexing、pinning 陷阱與 failover 加速</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/aurora/rds-proxy-connection-pooling/</link><pubDate>Tue, 02 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/aurora/rds-proxy-connection-pooling/</guid><description>&lt;p>Lambda 函式在流量尖峰被同時拉起幾百個實例、每個各自開一條到 Aurora 的連線、Aurora 的 connection 上限瞬間被打爆、新請求拿不到連線、整批失敗。根因是 &lt;em>連線管理&lt;/em> 缺位、Aurora 容量本身夠用——serverless 與高並發短連線 workload 製造的連線數遠超過資料庫該同時維持的後端連線。RDS Proxy 在 application 與 Aurora 之間做 connection multiplexing，把大量 client 連線收斂成少量後端連線。但它不是「連上去就自動省」——某些 session 操作會讓連線被 pin 住、multiplexing 失效。&lt;/p>
&lt;p>本文不是 Aurora overview（請看 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&amp;#43;75% 效能改善的 production 證據">Aurora vendor 頁&lt;/a>）— 而是 RDS Proxy 連線管理機制與陷阱的實作層教學。&lt;/p>
&lt;h2 id="核心機制connection-multiplexing">核心機制：connection multiplexing&lt;/h2>
&lt;p>RDS Proxy 維護一個到 Aurora 的後端連線池，多個 client 連線共享這些後端連線。當 client 連線閒置（交易之間沒有活動），proxy 可以把對應的後端連線釋放回池子給其他 client 用：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>沒有 proxy&lt;/th>
 &lt;th>有 RDS Proxy&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>每個 client 連線 = 一條後端連線&lt;/td>
 &lt;td>多個 client 連線共享少量後端連線&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Lambda 並發 N → 後端 N 條連線&lt;/td>
 &lt;td>Lambda 並發 N → 後端遠少於 N 條&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>failover 時 client 連線斷、要重連&lt;/td>
 &lt;td>proxy 保持 client 連線、後端切換對 client 透明&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>連線建立開銷由 application 承擔&lt;/td>
 &lt;td>proxy 維持暖連線池、省去反覆建立&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>multiplexing 生效的前提是 client 連線「閒置時可以被借走」。這只在連線處於 &lt;em>交易之間&lt;/em> 的乾淨狀態時成立——一旦連線帶了交易內狀態，proxy 不能把它借給別人，這就是 pinning。&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Scope warning&lt;/strong>：「RDS Proxy 支援的 engine / 連線數上限 / IAM 認證細節」屬 AWS vendor 規格、實作時 cross-verify 官方 doc 當前值。本文不含 production case 揭露的 proxy 配置數字。&lt;/p>&lt;/blockquote>
&lt;p>對應 knowledge card：&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool&lt;/a>。&lt;/p>
&lt;h2 id="pinningmultiplexing-失效的主因">Pinning：multiplexing 失效的主因&lt;/h2>
&lt;p>Pinning 是 RDS Proxy 最常被忽略、卻直接決定省連線效果的機制。當 client 在連線上做了「跨交易持續的 session 狀態」操作，proxy 無法安全地把這條後端連線借給其他 client，於是把它 &lt;em>pin&lt;/em>（綁定）到該 client 直到連線關閉——這條後端連線在 pin 期間不參與 multiplexing。&lt;/p>
&lt;p>常見觸發 pinning 的操作：&lt;/p>
&lt;ul>
&lt;li>session 層級的變數設定（&lt;code>SET&lt;/code> 某些 session variable）&lt;/li>
&lt;li>建立 temp table&lt;/li>
&lt;li>prepared statement（某些情況）&lt;/li>
&lt;li>advisory lock、保持開啟的交易&lt;/li>
&lt;li>部分 session 層級的設定語句&lt;/li>
&lt;/ul>
&lt;p>pinning 的後果是「明明裝了 RDS Proxy、後端連線數卻沒降下來」。若大量 client 都觸發 pinning，等於退化回「一個 client 一條後端連線」、proxy 白裝。&lt;/p>
&lt;p>&lt;strong>判讀與修法方向&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>監控 &lt;code>DatabaseConnectionsCurrentlySessionPinned&lt;/code>，看 pinning 比例&lt;/li>
&lt;li>application 端避免不必要的 session 狀態（少用 session variable、temp table；改用交易內可清理的方式）&lt;/li>
&lt;li>真的需要 session 狀態的 workload，接受該連線會 pin、或評估這類 workload 是否適合走 proxy&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>&lt;strong>Scope warning&lt;/strong>：「哪些具體語句觸發 pinning」隨 RDS Proxy 版本與 engine 演進、實作時以 AWS doc 當前清單為準；本段列舉是常見類型、非完整或固定清單。&lt;/p></description><content:encoded><![CDATA[<p>Lambda 函式在流量尖峰被同時拉起幾百個實例、每個各自開一條到 Aurora 的連線、Aurora 的 connection 上限瞬間被打爆、新請求拿不到連線、整批失敗。根因是 <em>連線管理</em> 缺位、Aurora 容量本身夠用——serverless 與高並發短連線 workload 製造的連線數遠超過資料庫該同時維持的後端連線。RDS Proxy 在 application 與 Aurora 之間做 connection multiplexing，把大量 client 連線收斂成少量後端連線。但它不是「連上去就自動省」——某些 session 操作會讓連線被 pin 住、multiplexing 失效。</p>
<p>本文不是 Aurora overview（請看 <a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor 頁</a>）— 而是 RDS Proxy 連線管理機制與陷阱的實作層教學。</p>
<h2 id="核心機制connection-multiplexing">核心機制：connection multiplexing</h2>
<p>RDS Proxy 維護一個到 Aurora 的後端連線池，多個 client 連線共享這些後端連線。當 client 連線閒置（交易之間沒有活動），proxy 可以把對應的後端連線釋放回池子給其他 client 用：</p>
<table>
  <thead>
      <tr>
          <th>沒有 proxy</th>
          <th>有 RDS Proxy</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>每個 client 連線 = 一條後端連線</td>
          <td>多個 client 連線共享少量後端連線</td>
      </tr>
      <tr>
          <td>Lambda 並發 N → 後端 N 條連線</td>
          <td>Lambda 並發 N → 後端遠少於 N 條</td>
      </tr>
      <tr>
          <td>failover 時 client 連線斷、要重連</td>
          <td>proxy 保持 client 連線、後端切換對 client 透明</td>
      </tr>
      <tr>
          <td>連線建立開銷由 application 承擔</td>
          <td>proxy 維持暖連線池、省去反覆建立</td>
      </tr>
  </tbody>
</table>
<p>multiplexing 生效的前提是 client 連線「閒置時可以被借走」。這只在連線處於 <em>交易之間</em> 的乾淨狀態時成立——一旦連線帶了交易內狀態，proxy 不能把它借給別人，這就是 pinning。</p>
<blockquote>
<p><strong>Scope warning</strong>：「RDS Proxy 支援的 engine / 連線數上限 / IAM 認證細節」屬 AWS vendor 規格、實作時 cross-verify 官方 doc 當前值。本文不含 production case 揭露的 proxy 配置數字。</p></blockquote>
<p>對應 knowledge card：<a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool</a>。</p>
<h2 id="pinningmultiplexing-失效的主因">Pinning：multiplexing 失效的主因</h2>
<p>Pinning 是 RDS Proxy 最常被忽略、卻直接決定省連線效果的機制。當 client 在連線上做了「跨交易持續的 session 狀態」操作，proxy 無法安全地把這條後端連線借給其他 client，於是把它 <em>pin</em>（綁定）到該 client 直到連線關閉——這條後端連線在 pin 期間不參與 multiplexing。</p>
<p>常見觸發 pinning 的操作：</p>
<ul>
<li>session 層級的變數設定（<code>SET</code> 某些 session variable）</li>
<li>建立 temp table</li>
<li>prepared statement（某些情況）</li>
<li>advisory lock、保持開啟的交易</li>
<li>部分 session 層級的設定語句</li>
</ul>
<p>pinning 的後果是「明明裝了 RDS Proxy、後端連線數卻沒降下來」。若大量 client 都觸發 pinning，等於退化回「一個 client 一條後端連線」、proxy 白裝。</p>
<p><strong>判讀與修法方向</strong>：</p>
<ul>
<li>監控 <code>DatabaseConnectionsCurrentlySessionPinned</code>，看 pinning 比例</li>
<li>application 端避免不必要的 session 狀態（少用 session variable、temp table；改用交易內可清理的方式）</li>
<li>真的需要 session 狀態的 workload，接受該連線會 pin、或評估這類 workload 是否適合走 proxy</li>
</ul>
<blockquote>
<p><strong>Scope warning</strong>：「哪些具體語句觸發 pinning」隨 RDS Proxy 版本與 engine 演進、實作時以 AWS doc 當前清單為準；本段列舉是常見類型、非完整或固定清單。</p></blockquote>
<h2 id="failover-加速">Failover 加速</h2>
<p>RDS Proxy 的第二個價值是縮短 failover 對 application 的中斷。沒有 proxy 時，writer failover 會讓所有 client 連線斷掉、application 要偵測、重連、重建連線池；有 proxy 時，proxy 保持與 client 的連線、在後端把流量切到新 writer，client 端感知到的中斷時間縮短。</p>
<p>這對連線建立成本高、或 failover 期間不能大量重連的 workload 特別有價值。但 proxy 不消除 failover 本身——in-flight 的交易仍會失敗、application 仍要有 retry；proxy 縮短的是「重建連線」這段，不是「交易不中斷」。</p>
<h2 id="操作流程">操作流程</h2>
<p>從連線壓力判讀到上線的 6 步流程。</p>
<h4 id="step-1確認是不是連線問題">Step 1：確認是不是連線問題</h4>
<p>先區分「Aurora 容量不夠」vs「連線管理問題」。看 <code>DatabaseConnections</code> 是否逼近上限、且 CPU/IOPS 還有餘量——後者是典型的連線數問題、proxy 能解；若是 CPU/IOPS 飽和，proxy 不解。</p>
<h4 id="step-2判斷-workload-是否適合-proxy">Step 2：判斷 workload 是否適合 proxy</h4>
<ul>
<li>serverless / Lambda / 高並發短連線 → 適合（連線爆炸是主問題）</li>
<li>少量長連線、穩定的 application server → proxy 效益有限（連線數本就可控）</li>
<li>大量 session 狀態 workload → pinning 會吃掉 multiplexing 效益、要先評估</li>
</ul>
<h4 id="step-3建立-proxy">Step 3：建立 proxy</h4>





<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">aws rds create-db-proxy <span class="se">\
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="se"></span>  --db-proxy-name my-aurora-proxy <span class="se">\
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="se"></span>  --engine-family POSTGRESQL <span class="se">\
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="se"></span>  --auth ... <span class="se">\
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="se"></span>  --role-arn ... <span class="se">\
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="se"></span>  --vpc-subnet-ids ...</span></span></code></pre></div><p>application 連到 proxy endpoint 而非直連 cluster endpoint。</p>
<h4 id="step-4減少-pinning">Step 4：減少 pinning</h4>
<p>review application 的 session 狀態使用、移除不必要的 <code>SET</code> / temp table；連線池設定避免長時間持有閒置連線。</p>
<h4 id="step-5驗證-multiplexing-生效">Step 5：驗證 multiplexing 生效</h4>





<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"># 對照後端連線數：裝 proxy 後 Aurora 的 DatabaseConnections 應顯著低於 client 並發數
</span></span><span class="line"><span class="ln">2</span><span class="cl"># 看 DatabaseConnectionsCurrentlySessionPinned：pinning 比例高代表 multiplexing 沒發揮</span></span></code></pre></div><h4 id="step-6驗證-failover-行為">Step 6：驗證 failover 行為</h4>
<p>主動觸發一次 failover、測量 application 感知到的中斷時間、確認 retry 邏輯能吸收 in-flight 交易失敗。</p>
<p><strong>Rollback boundary</strong>：application 可在 proxy endpoint 與直連 cluster endpoint 間切換、proxy 出問題時改回直連（但直連會回到連線爆炸風險，要先確認後端撐得住）。</p>
<h2 id="失敗模式">失敗模式</h2>
<p>production 常見的 5 個踩雷：</p>
<h4 id="case-1裝了-proxy-但-pinning-比例高連線沒降">Case 1：裝了 proxy 但 pinning 比例高、連線沒降</h4>
<p>application 大量用 session variable / temp table、多數連線被 pin、後端連線數沒降、proxy 白裝。修法：監控 pinning 比例、減少 session 狀態；理解 proxy 的省連線前提是連線可被借走。</p>
<h4 id="case-2把-proxy-當aurora-容量擴充">Case 2：把 proxy 當「Aurora 容量擴充」</h4>
<p>連線數沒問題、是 CPU/IOPS 飽和、卻裝 proxy 期待變快。修法：proxy 解連線管理、不解運算容量；容量問題要擴 instance / 加 replica。</p>
<h4 id="case-3以為-proxy-讓-failover-零中斷">Case 3：以為 proxy 讓 failover 零中斷</h4>
<p>裝了 proxy 就拿掉 application 的 retry、failover 時 in-flight 交易失敗沒處理。修法：proxy 縮短重連時間、不保證交易不中斷；application 仍要 retry in-flight 交易。</p>
<h4 id="case-4少量長連線-workload-強裝-proxy">Case 4：少量長連線 workload 強裝 proxy</h4>
<p>穩定的 application server 連線數本就可控、裝 proxy 多一跳延遲、效益有限。修法：proxy 的價值在連線爆炸場景（serverless / 高並發短連線）；連線可控的 workload 不必加。</p>
<h4 id="case-5proxy-與自管-pooler-疊加未理清責任">Case 5：proxy 與自管 pooler 疊加未理清責任</h4>
<p>application 已有自管連線池（如語言層 pool）、又加 RDS Proxy、兩層 pool 互相打架、連線數行為難預測。修法：理清兩層職責——application 層 pool 管「app 到 proxy」、proxy 管「proxy 到 Aurora」；兩層設定要協調、不是各設各的。</p>
<p><strong>Anti-recommendation</strong>：連線數本就可控的少量長連線 workload、或 workload 大量依賴 session 狀態（pinning 會吃掉效益）→ 不必上 RDS Proxy；它的價值集中在 serverless / Lambda / 高並發短連線的連線爆炸場景。</p>
<h2 id="容量與觀測">容量與觀測</h2>
<p>CloudWatch metric：</p>
<ul>
<li><code>DatabaseConnections</code>（Aurora 端）：裝 proxy 後應顯著低於 client 並發數</li>
<li><code>DatabaseConnectionsCurrentlySessionPinned</code>：pinning 數、判斷 multiplexing 效益</li>
<li><code>ClientConnections</code>（proxy 端）：client 側連線數、對照後端收斂比例</li>
<li><code>QueryDatabaseResponseLatency</code>：proxy 多一跳的延遲影響</li>
</ul>
<p><strong>判讀</strong>：</p>
<ul>
<li>後端連線數沒因 proxy 下降 → pinning 比例高或 workload 不適合</li>
<li>pinning 數持續高 → application session 狀態過多、需 review</li>
<li>proxy 延遲明顯 → 評估這一跳對延遲敏感路徑是否值得</li>
</ul>
<blockquote>
<p><strong>Scope warning</strong>：本文未引用 production case 的 proxy metric 數字；上述指標與判讀屬 vendor 規格 + 通用連線管理工程。</p></blockquote>
<p>接回 <a href="/blog/backend/09-performance-capacity/bottleneck-localization/" data-link-title="9.5 瓶頸定位流程" data-link-desc="從 app 到 DB / cache / broker / 第三方 quota 的逐層瓶頸定位">9.5 瓶頸定位流程</a>、<a href="/blog/backend/01-database/high-concurrency-access/" data-link-title="1.1 高併發下的 SQL 讀寫邊界" data-link-desc="說明高併發服務如何共用資料庫 client、控制 transaction、管理 connection pool、避免資料庫成為瓶頸">1.1 高併發下的 SQL 讀寫邊界</a>。</p>
<h2 id="邊界與整合">邊界與整合</h2>
<h3 id="rds-proxy-vs-自管-pgbouncer">RDS Proxy vs 自管 pgbouncer</h3>
<p>兩者都是 connection pooler，責任切分在「managed vs 自管」：</p>
<ul>
<li><strong>RDS Proxy</strong>：AWS managed、跟 Aurora / IAM / Secrets Manager 整合、零運維、含 failover 加速；綁 AWS</li>
<li><strong>自管 pgbouncer / pgcat</strong>：自己部署運維、pooling 模式（session / transaction / statement）可細調、跨雲可攜；運維責任自負</li>
</ul>
<p>PostgreSQL 的通用連線池機制與 pgbouncer 細節主寫於 <a href="/blog/backend/01-database/vendors/postgresql/pgbouncer-config/" data-link-title="PostgreSQL pgBouncer 配置 &#43; 連線池治理" data-link-desc="pgBouncer transaction pooling 配置、跟 application connection pool 的分層、production 故障演練（pool exhaustion / stale connection / DNS failover）跟容量規劃">pgbouncer-config</a> 與 <a href="/blog/backend/01-database/vendors/postgresql/connection-pooler-comparison/" data-link-title="PostgreSQL Connection Pooler Comparison" data-link-desc="PostgreSQL PgBouncer、Odyssey、RDS Proxy、application pool 與 transaction pooling 的選型比較">connection-pooler-comparison</a>；本篇聚焦 RDS Proxy 這個 AWS managed 方案的機制與 pinning 陷阱。要細調 pooling 模式、或需要跨雲可攜 → 評估自管 pooler；要零運維 + Aurora 原生整合 + failover 加速 → RDS Proxy。</p>
<h3 id="sibling-與-cross-link">Sibling 與 cross-link</h3>
<ul>
<li><a href="/blog/backend/01-database/vendors/aurora/serverless-v2-scaling/" data-link-title="Aurora Serverless v2 適用判斷：ACU 自動擴縮、混合 cluster 與何時不該用" data-link-desc="Aurora Serverless v2 不是「比較便宜的 Aurora」；本文展開 ACU 計費粒度、秒級自動擴縮機制、min/max ACU 設定、serverless 與 provisioned 同 cluster 混用，以及穩定高負載下 serverless 反而更貴的成本 crossover 邊界">serverless-v2-scaling</a> — serverless + Lambda 場景的連線管理常與 RDS Proxy 一起出現</li>
<li><a href="/blog/backend/01-database/vendors/aurora/cross-az-failover-rto/" data-link-title="Aurora Cross-AZ Failover：RTO 量測、endpoint routing 與 application reconnect 契約" data-link-desc="Aurora cross-AZ failover lifecycle（detection / promotion / DNS update）、&lt; 30 秒 RTO、application DNS cache 跟 connection pool 對齊、Standard Chartered 受監管場景為什麼用獨立 cluster 而非 Global Database failover">cross-az-failover-rto</a> — proxy 縮短 failover 重連時間、與 RTO 目標結合</li>
<li><a href="/blog/backend/01-database/vendors/postgresql/pgbouncer-config/" data-link-title="PostgreSQL pgBouncer 配置 &#43; 連線池治理" data-link-desc="pgBouncer transaction pooling 配置、跟 application connection pool 的分層、production 故障演練（pool exhaustion / stale connection / DNS failover）跟容量規劃">pgbouncer-config</a> / <a href="/blog/backend/01-database/vendors/postgresql/connection-pooler-comparison/" data-link-title="PostgreSQL Connection Pooler Comparison" data-link-desc="PostgreSQL PgBouncer、Odyssey、RDS Proxy、application pool 與 transaction pooling 的選型比較">connection-pooler-comparison</a> — 通用連線池 SSoT、自管方案對照</li>
<li><a href="/blog/backend/01-database/high-concurrency-access/" data-link-title="1.1 高併發下的 SQL 讀寫邊界" data-link-desc="說明高併發服務如何共用資料庫 client、控制 transaction、管理 connection pool、避免資料庫成為瓶頸">1.1 高併發下的 SQL 讀寫邊界</a> — 連線池與 transaction 範圍控制</li>
<li>替代路由：需要細調 pooling 模式 / 跨雲 → 自管 pgbouncer</li>
</ul>
]]></content:encoded></item></channel></rss>