<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Kairo Blog</title><description>一個分享網站開發、程式實作、自動化工具與技術經驗的博客，作者Kairo</description><link>https://kairo.qzz.io/</link><language>zh_TW</language><item><title>Astro 新手部署全攻略：避免常見設定錯誤與踩雷指南</title><link>https://kairo.qzz.io/posts/astro/</link><guid isPermaLink="true">https://kairo.qzz.io/posts/astro/</guid><description>針對新手在 Astro 部署時容易遇到的各種錯誤，提供詳細分析、實例與解決方案，讓你少踩坑，快速上手。</description><pubDate>Sun, 04 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Astro 新手部署全攻略：避免常見設定錯誤與踩雷指南&lt;/h1&gt;
&lt;p&gt;對新手來說，部署 Astro 專案到 Cloudflare Pages 或使用 GitHub Actions 可能會遇到各種錯誤和困惑。&lt;br /&gt;
即使你只是搬官方範例，也可能因環境不同或設定疏漏而踩坑。本指南將帶你&lt;strong&gt;一步步檢查常見問題、分析原因、提供解決方案，並給出實務建議&lt;/strong&gt;，保證你少走冤枉路。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;1. Node / Deno 版本不匹配&lt;/h2&gt;
&lt;h3&gt;錯誤現象&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Build 過程中出現警告或錯誤&lt;/li&gt;
&lt;li&gt;部署成功，但網頁行為異常或無法啟動&lt;/li&gt;
&lt;li&gt;第三方套件報錯或不兼容&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;為什麼會出現&lt;/h3&gt;
&lt;p&gt;Astro 官方文檔會建議使用特定 Node 版本，但：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;本地開發環境可能版本過舊或過新&lt;/li&gt;
&lt;li&gt;CI/CD 預設 Node 環境與本地不同&lt;/li&gt;
&lt;li&gt;第三方套件可能需要特定版本支持&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;解決方案（Step by Step）&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# 確認本地 Node 版本
node -v

# 安裝官方建議版本
nvm install 20
nvm use 20

# 確認 Deno 版本（如使用）
deno --version
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在 &lt;code&gt;package.json&lt;/code&gt; 明確指定 Node 版本：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;engines&quot;: {
  &quot;node&quot;: &quot;&amp;gt;=20&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;延伸問題&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Node 版本過舊會導致部分套件編譯失敗&lt;/li&gt;
&lt;li&gt;CI/CD pipeline 未同步版本，可能 build 成功，但部署失敗&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;實務建議&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;在 CI/CD workflow 中固定 Node 版本&lt;/li&gt;
&lt;li&gt;每篇文章或專案都記錄使用的 Node/Deno 版本&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;2. 靜態資源路徑設定錯誤&lt;/h2&gt;
&lt;h3&gt;錯誤現象&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;部署後 CSS / JS 無法載入&lt;/li&gt;
&lt;li&gt;圖片路徑錯誤，頁面顯示破圖&lt;/li&gt;
&lt;li&gt;在本地正常，但部署到 Cloudflare Pages 失敗&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;為什麼會出現&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Astro 預設靜態資源路徑為根目錄 &lt;code&gt;/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;部署到子路徑或 CDN 時，未設定 &lt;code&gt;base&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;相對路徑使用不當&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;解決方案（Step by Step）&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;// astro.config.mjs
export default defineConfig({
  base: &apos;/你的路徑/&apos;
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或使用相對路徑：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&quot;stylesheet&quot; href=&quot;./styles/main.css&quot;&amp;gt;
&amp;lt;script src=&quot;./scripts/app.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;延伸問題&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;多環境部署（本地 / Preview / Production）路徑不一致&lt;/li&gt;
&lt;li&gt;瀏覽器快取導致資源載入舊版本&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;實務建議&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;部署前先本地 build 測試&lt;/li&gt;
&lt;li&gt;對不同環境設置環境變數管理 base path&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;3. GitHub Actions 部署設定缺失&lt;/h2&gt;
&lt;h3&gt;錯誤現象&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Workflow 跑通，但 deploy 失敗&lt;/li&gt;
&lt;li&gt;權限錯誤、Token 不存在&lt;/li&gt;
&lt;li&gt;專案預覽成功，但正式部署失敗&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;為什麼會出現&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;直接 fork 官方 workflow，未設定環境變數或 Secret&lt;/li&gt;
&lt;li&gt;branch 指向錯誤或 target 不正確&lt;/li&gt;
&lt;li&gt;token 過期或權限不足&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;解決方案（Step by Step）&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# .github/workflows/deploy.yml
env:
  CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;確保 Secret 設定正確&lt;/li&gt;
&lt;li&gt;workflow branch 對應 main / production&lt;/li&gt;
&lt;li&gt;驗證 token 是否具有必要權限&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;延伸問題&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;部署到不同環境需要不同 token&lt;/li&gt;
&lt;li&gt;Workflow 設計不合理可能 silent fail&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;實務建議&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;每篇文章或專案都註明 token / secret 用途&lt;/li&gt;
&lt;li&gt;CI/CD log 必須檢查部署成功訊息&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;4. Cloudflare Pages 特定設定問題&lt;/h2&gt;
&lt;h3&gt;錯誤現象&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;部署成功，但功能不完整
&lt;ul&gt;
&lt;li&gt;Functions 路徑錯誤&lt;/li&gt;
&lt;li&gt;Edge config 未正確設定&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;預覽正常，正式部署失敗&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;為什麼會出現&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;新手依官方快速 start，忽略 production 設定&lt;/li&gt;
&lt;li&gt;Edge function 或 environment variable 未正確設置&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;解決方案（Step by Step）&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;檢查 &lt;code&gt;functions&lt;/code&gt; 路徑，確保 Cloudflare Pages 可識別&lt;/li&gt;
&lt;li&gt;確認 Edge config 對應環境變數&lt;/li&gt;
&lt;li&gt;本地測試 production build&lt;/li&gt;
&lt;li&gt;部署前檢查 log&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;延伸問題&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;多地區部署差異&lt;/li&gt;
&lt;li&gt;不同 Node 版本兼容性問題&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;實務建議&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;建立不同環境的設定檔&lt;/li&gt;
&lt;li&gt;每次部署前先做本地 build&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;5. 內部連結與主題權威感&lt;/h2&gt;
&lt;h3&gt;錯誤現象&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;新文章沒連到舊文章&lt;/li&gt;
&lt;li&gt;相同主題散落，Google 難以理解主題權威&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;解決方案&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;每篇文章至少連 2 篇舊文章&lt;/li&gt;
&lt;li&gt;舊文章補連到新文章&lt;/li&gt;
&lt;li&gt;使用長尾關鍵字作 anchor text，例如：
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Astro 部署到 Cloudflare Pages&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GitHub Actions workflow 配置錯誤&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;實務建議&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;強制每篇文章檢查內部連結&lt;/li&gt;
&lt;li&gt;建立站內「主題樹狀圖」，方便後續文章拓展&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;6. 更新文章與長期維護&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;隨著 Astro / Cloudflare / GitHub Actions 更新，補充文章內容&lt;/li&gt;
&lt;li&gt;每 1–3 個月檢查文章環境資訊&lt;/li&gt;
&lt;li&gt;更新後重新提交 sitemap&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;結論&lt;/h2&gt;
&lt;p&gt;即使你是「搬範例」的新手，只要：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;測試每個流程&lt;/li&gt;
&lt;li&gt;記錄環境與版本&lt;/li&gt;
&lt;li&gt;聚焦一件事、長尾主題&lt;/li&gt;
&lt;li&gt;做好內部連結&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Google 就會開始把你當「值得推薦的技術內容」。&lt;/p&gt;
&lt;p&gt;長篇文章不只是 SEO，也能讓讀者&lt;strong&gt;學到真正操作過程與原理&lt;/strong&gt;，減少踩坑、快速上手。&lt;/p&gt;
</content:encoded></item><item><title>Web 應用安全：XSS、CSRF 與注入攻擊防護</title><link>https://kairo.qzz.io/posts/xss-csrf/</link><guid isPermaLink="true">https://kairo.qzz.io/posts/xss-csrf/</guid><description>系統性說明 Web 應用三大常見攻擊（XSS、CSRF、注入攻擊）的原理、判別、以及開發與運維層面的實務防護措施與檢測流程。</description><pubDate>Sun, 04 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;概覽與目標&lt;/h2&gt;
&lt;p&gt;Web 應用最常見、也最致命的安全問題經常源於「外界輸入未被妥善處理」或「驗證與授權邏輯不完善」。本文聚焦三個高頻攻擊類型——&lt;strong&gt;XSS（跨站指令碼）&lt;/strong&gt;、&lt;strong&gt;CSRF（跨站請求偽造）&lt;strong&gt;與廣義的&lt;/strong&gt;注入攻擊（SQL、命令、LDAP、XPath 等）&lt;/strong&gt;。我們會說明每種攻擊的本質、如何在程式碼或系統層面判別脆弱點、以及能立即採取的防護措施與測試方法，重點放在「實務可用、能落地」的防護策略。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;一、通用原則（先說結論）&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;永遠把外界資料當成不可信&lt;/strong&gt;：所有來自使用者、第三方、上游系統的資料，都必須驗證、淨化或轉義（視情境）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;最小權限與最小資訊暴露&lt;/strong&gt;：程式與帳戶僅賦予必要權限；錯誤訊息避免洩露內部細節。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;輸入驗證 ≠ 輸出編碼&lt;/strong&gt;：前者是過濾或拒絕不合法輸入；後者是在輸出到 HTML/SQL/OS 等上下文時做安全轉義。兩者都需要。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用現代框架 &amp;amp; 內建防護&lt;/strong&gt;：多數成熟框架提供安全 API（prepared statements、templating 的 auto-escape、CSRF token support），善用它們比自己重寫更安全。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;持續測試&lt;/strong&gt;：整合 SAST、DAST、依賴掃描與例行滲透測試（或使用自動化工具）納入 CI/CD。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;二、XSS（Cross-Site Scripting）&lt;/h2&gt;
&lt;h3&gt;1) 本質與類型快速回顧&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Stored XSS（儲存型）&lt;/strong&gt;：惡意腳本被儲存在伺服器（如資料庫、留言板）並在其他使用者載入頁面時執行。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reflected XSS（反射型）&lt;/strong&gt;：惡意輸入透過 URL 或表單即時反映在回應中，攻擊者誘導受害者點擊特製 URL。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DOM-based XSS&lt;/strong&gt;：攻擊在客戶端 JavaScript 操作 DOM 時發生，原始伺服器回應本身看似安全，但前端處理不當導致執行惡意程式。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2) 常見觸發場景&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;把使用者內容直接插入 innerHTML、document.write、eval 等 API。&lt;/li&gt;
&lt;li&gt;在未轉義的情況下把使用者輸入放到 HTML 屬性、事件處理器（onclick）、或 &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; 中。&lt;/li&gt;
&lt;li&gt;動態構成 HTML 字串並插入 DOM（client-side templating 未做 escape）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3) 防護策略（實務可執行）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;輸出編碼（Output Encoding）&lt;/strong&gt;：在把資料輸出到 HTML、HTML attribute、JavaScript、CSS 或 URL 不同上下文時，採用對應的編碼函式。
&lt;ul&gt;
&lt;li&gt;HTML body → escape HTML（&lt;code&gt;&amp;amp;&lt;/code&gt;、&lt;code&gt;&amp;lt;&lt;/code&gt;、&lt;code&gt;&amp;gt;&lt;/code&gt;、&lt;code&gt;&quot;&lt;/code&gt; 等）&lt;/li&gt;
&lt;li&gt;HTML attribute → attribute-encoding（避免破壞引號）&lt;/li&gt;
&lt;li&gt;JavaScript context → 使用安全接口或 JSON 序列化（不要直接拼字串）&lt;/li&gt;
&lt;li&gt;URL context → URL-encode&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用框架的自動 escaping&lt;/strong&gt;：例如大多數模板引擎（Mustache、Handlebars、Jinja2、React 的 JSX）會在輸出時自動 escape。不要關閉這些保護，除非非常必要並且清楚風險。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;避免危險 API&lt;/strong&gt;：盡量不要用 &lt;code&gt;innerHTML&lt;/code&gt;, &lt;code&gt;dangerouslySetInnerHTML&lt;/code&gt;, &lt;code&gt;eval&lt;/code&gt;, &lt;code&gt;new Function&lt;/code&gt; 等；若必要則在輸入經過嚴格白名單淨化。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Content Security Policy (CSP)&lt;/strong&gt;：透過 CSP 限制可執行的來源（script-src），並啟用 &lt;code&gt;nonce&lt;/code&gt; 或 &lt;code&gt;hash&lt;/code&gt; 機制來允許可信內嵌程式碼。CSP 不是萬靈丹，但能大幅降低成功攻擊面。範例 header：&lt;pre&gt;&lt;code&gt;Content-Security-Policy: default-src &apos;self&apos;; script-src &apos;self&apos; &apos;nonce-&amp;lt;RANDOM&amp;gt;&apos;;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HttpOnly 與 Secure Cookie&lt;/strong&gt;：把 session cookie 設為 &lt;code&gt;HttpOnly&lt;/code&gt; 避免被 JavaScript 讀取（降低 XSS 竊取 session 的風險）；&lt;code&gt;Secure&lt;/code&gt; 強制僅在 HTTPS 傳輸。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;輸入白名單（for rich text）&lt;/strong&gt;：若允許富文本（HTML），使用安全的 HTML sanitizer（例如 DOMPurify、Bleach 等），並僅允許特定標籤/屬性與 URL schemes。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4) 範例（安全 vs 不安全，前端示意）&lt;/h3&gt;
&lt;p&gt;不安全（示意）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Don&apos;t do this:
const container = document.getElementById(&apos;msg&apos;);
container.innerHTML = userInput; // userInput 含腳本 -&amp;gt; XSS
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;安全（示意）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Safer: use textContent or escape before inserting
const container = document.getElementById(&apos;msg&apos;);
container.textContent = userInput; // 不會當作 HTML 解析
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或若必須插入 HTML，先用 sanitizer：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import DOMPurify from &apos;dompurify&apos;;
container.innerHTML = DOMPurify.sanitize(userInput);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;5) 偵測與測試&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;在開發階段加入自動化測試（SAST 與 unit tests for output encoding）。&lt;/li&gt;
&lt;li&gt;使用 DAST 工具（OWASP ZAP、Burp）對輸入點做掃描（注意：僅在測試/授權環境執行）。&lt;/li&gt;
&lt;li&gt;在瀏覽器 console 模擬 payload（安全情況下使用無害字串）確認應用如何處理特殊字符。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;三、CSRF（Cross-Site Request Forgery）&lt;/h2&gt;
&lt;h3&gt;1) 本質&lt;/h3&gt;
&lt;p&gt;CSRF 的攻擊者利用使用者已登入的瀏覽器權限（cookie、HTTP 認證等），誘導其瀏覽器向受信任網站發送未經授權的請求（例如轉帳、修改設定）。關鍵在於伺服器端無法分辨該請求是由真實使用者交互觸發還是外部網頁發起。&lt;/p&gt;
&lt;h3&gt;2) 被利用的常見場景&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;任何以 cookie 認證的 state-changing action（POST/PUT/DELETE）如果沒有 CSRF 防護就容易被利用。&lt;/li&gt;
&lt;li&gt;圖像/表單/GET 請求可能被當作觸發方式（例如 &lt;code&gt;&amp;lt;img src=&quot;https://bank/transfer?to=...&quot;&amp;gt;&lt;/code&gt;）。現代 RESTful 設計通常要求 state change 使用非 GET 方法，但仍要防護。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3) 防護策略（實務明單）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CSRF Token（同源驗證 token）&lt;/strong&gt;：在 server-rendered 或 SPA 與 server 互動時，對所有 state-changing 請求附帶不可預測的 token（伺服器驗證）；token 存於伺服器端 session 或在 cookie 與 request header 中雙向比對。
&lt;ul&gt;
&lt;li&gt;例如：伺服器在表單頁面 embed 隱藏欄位 &lt;code&gt;&amp;lt;input type=&quot;hidden&quot; name=&quot;_csrf&quot; value=&quot;...&quot;&amp;gt;&lt;/code&gt;。提交時伺服器檢查 token 是否正確。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SameSite Cookie&lt;/strong&gt;：把 cookie 的 &lt;code&gt;SameSite&lt;/code&gt; 設為 &lt;code&gt;Lax&lt;/code&gt; 或 &lt;code&gt;Strict&lt;/code&gt;。&lt;code&gt;Lax&lt;/code&gt; 在大多數情境對跨站 GET 請求有保護，而 &lt;code&gt;Strict&lt;/code&gt; 更嚴格。此為簡單且高成效的保護。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Double Submit Cookie&lt;/strong&gt;：把隨機 token 同時放在 cookie 與 request body/header，伺服器端比較兩者是否一致（注意對 XSS 無效，因為 XSS 可讀 cookie）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;驗證 Referer/Origin&lt;/strong&gt;：對於敏感請求，檢查 &lt;code&gt;Origin&lt;/code&gt; 或 &lt;code&gt;Referer&lt;/code&gt; header 是否屬於你的域（較可靠）。注意某些情況 referer 可能被瀏覽器隱藏或省略。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;避免把敏感操作綁在 GET&lt;/strong&gt;：務必把會改變狀態的操作用 POST/PUT/DELETE 並要求 CSRF token。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4) 範例（Express + csurf）&lt;/h3&gt;
&lt;p&gt;伺服器端（Node/Express）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import csurf from &apos;csurf&apos;;
const csrfProtection = csurf({ cookie: true });
app.use(cookieParser());
app.get(&apos;/form&apos;, csrfProtection, (req, res) =&amp;gt; {
  res.render(&apos;form&apos;, { csrfToken: req.csrfToken() });
});
app.post(&apos;/process&apos;, csrfProtection, (req, res) =&amp;gt; {
  // csurf 已驗證 token
});
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;四、注入攻擊（以 SQL Injection 為代表，但概念適用於命令注入、LDAP、XPath 等）&lt;/h2&gt;
&lt;h3&gt;1) 本質&lt;/h3&gt;
&lt;p&gt;注入攻擊是指把惡意資料注入到原本應該是資料（而非指令）的位置，導致伺服器將資料錯誤當作程式或查詢的一部分執行。最常見的是 SQL 注入（攻擊者能操控查詢語句），但類似問題也發生在 shell command、LDAP、XML/XPath 操作等。&lt;/p&gt;
&lt;h3&gt;2) 常見場景&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;直接把使用者輸入拼接成 SQL 字串：&lt;code&gt;&quot;SELECT * FROM users WHERE id = &quot; + req.query.id&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;用輸入建構系統命令、shell 執行字串。&lt;/li&gt;
&lt;li&gt;在動態構造 XPath、LDAP filter 時未過濾特殊字元。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3) 防護重點（實務面）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;使用參數化查詢 / Prepared Statements&lt;/strong&gt;（最重要）：不要拼字串，使用 DB 驅動提供的 bind parameter 機制。資料會被視為參數而非 SQL code。
&lt;ul&gt;
&lt;li&gt;SQL 範例（Node + pg）：&lt;pre&gt;&lt;code&gt;const res = await client.query(&apos;SELECT * FROM users WHERE email = $1&apos;, [email]);
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Java（JDBC）：&lt;pre&gt;&lt;code&gt;PreparedStatement ps = conn.prepareStatement(&quot;SELECT * FROM users WHERE id = ?&quot;);
ps.setInt(1, id);
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用 ORM 並了解其生成的 SQL&lt;/strong&gt;：ORM 可以降低寫 raw SQL 的錯誤，但仍需留意動態 where clause 的拼接與 raw query 使用情況。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;避免直接把使用者輸入傳給系統命令&lt;/strong&gt;：若必須，使用安全 API（例如 spawn with args array 而非 shell string），並在可能時做白名單限制。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;限制資料庫權限&lt;/strong&gt;：應用使用的 DB 帳戶只給必要操作權限（SELECT/INSERT/UPDATE on specific tables），不要用 root 或 admin 帳戶執行日常查詢。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;參考最小化表達式&lt;/strong&gt;：避免把敏感查詢結果直接回傳至使用者，防止錯誤回傳洩露結構資訊。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4) 命令注入（Shell Injection）與防護&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;不要把使用者輸入透過字串拼接放進 &lt;code&gt;exec&lt;/code&gt;、&lt;code&gt;system&lt;/code&gt; 等 shell command。改用參數化的 process spawn 或 libraries 並將不可信輸入當作資料傳入。&lt;/li&gt;
&lt;li&gt;對於必須執行外部程序的情境，使用白名單與最小權限策略，並進行輸入長度及格式限制。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;五、驗證、授權與會話管理（與上述攻擊交互）&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;強化認證流程&lt;/strong&gt;：使用多因素（MFA）對高權限操作。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;會話安全&lt;/strong&gt;：短期 session TTL、定期輪換 session id（重要操作後），以及 &lt;code&gt;HttpOnly/ Secure/ SameSite&lt;/code&gt; cookie。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;細緻化授權檢查&lt;/strong&gt;：在 server 端對每一個重要 API 進行授權，而非僅依賴前端 UI 隱藏。使用基於角色（RBAC）或屬性的授權（ABAC）視複雜度而定。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;輸入最小化&lt;/strong&gt;：在校驗成功後只保留必要欄位到後端邏輯，避免把多餘欄位直接轉給下游系統。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;六、測試與偵測（SAST / DAST / IAST / RASP）&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;SAST（Static Application Security Testing）&lt;/strong&gt;：把靜態漏洞掃描（例如 SQL 注入敏感模式、不安全 API 使用）整合到 PR pipeline（例：Semgrep、SonarQube）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DAST（Dynamic Application Security Testing）&lt;/strong&gt;：執行時模擬攻擊行為（OWASP ZAP、Burp Intruder 等）找出 runtime 的漏洞（注意需在授權環境執行）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IAST / RASP&lt;/strong&gt;：在應用內嵌入式偵測（如在測試環境偵測即時的注入嘗試與不當資料處理）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;依賴掃描（SCA）&lt;/strong&gt;：使用 Dependabot、Snyk 等工具檢查第三方套件的已知弱點。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自動化安全測試用例&lt;/strong&gt;：把常見注入/XSS/CSRF 測試做成自動化測試（非惡意 payload，使用可控測試字串）並納入 CI。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;七、例行運維與事件處理&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;日誌&lt;/strong&gt;：詳細記錄關鍵事件（驗證失敗、授權拒絕、異常操作），並把敏感資訊遮掩或匿名化。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;警示&lt;/strong&gt;：為大量失敗登入、異常流量或非預期的資料變更設置告警。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;備援與回復&lt;/strong&gt;：定期備份資料庫，並演練回滾流程。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;滲透測試與紅隊演練&lt;/strong&gt;：每季或每半年進行一次滲透測試，並把發現納入優先修復清單。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;披露與補丁流程&lt;/strong&gt;：建立第三方或用戶漏洞通報管道，並設定緊急修補（hotfix）作業。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;八、實務檢查清單（部署前後可用）&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[ ] 所有輸出到 HTML / JS / URL / Attribute 的動態資料都有適當的 output-encoding 或使用框架 auto-escape。&lt;/li&gt;
&lt;li&gt;[ ] 所有 state-changing 的請求都受 CSRF token 或同等防護（或 cookie 設為 SameSite=strict/lax 並做 double submit 驗證）。&lt;/li&gt;
&lt;li&gt;[ ] 所有資料庫查詢使用 parameterized queries / prepared statements 或 ORM 安全 API。&lt;/li&gt;
&lt;li&gt;[ ] Cookie 設置：&lt;code&gt;Secure&lt;/code&gt;, &lt;code&gt;HttpOnly&lt;/code&gt;, &lt;code&gt;SameSite&lt;/code&gt;（視需求選 Lax/Strict）。&lt;/li&gt;
&lt;li&gt;[ ] CSP header 已評估並逐步導入（先報告模式，再強制模式）。&lt;/li&gt;
&lt;li&gt;[ ] 第三方 action/套件做 SCA 掃描並定期升級重大修補。&lt;/li&gt;
&lt;li&gt;[ ] CI pipeline 包含 SAST/DAST（或 nightly DAST）、依賴掃描與基本自動化攻擊測試。&lt;/li&gt;
&lt;li&gt;[ ] 重要日誌上傳到集中化系統並設定告警門檻。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;九、結語（工程取向的實用建議）&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;「安全」不是一次性任務，而是開發、測試與運維的持續工作。把安全檢查整合到日常開發流程（PR、CI）中，能夠「早發現、早修復」。&lt;/li&gt;
&lt;li&gt;優先把&lt;strong&gt;簡單、高回報&lt;/strong&gt;的措施做起：output encoding、prepared statements、CSRF token、SameSite cookies、CSP 的逐步引入。這些能立即降低大多數常見攻擊的風險。&lt;/li&gt;
&lt;li&gt;當你使用第三方框架或庫時，先確認它們有良好的安全實踐與更新頻率；必要時選較受信任的替代方案。&lt;/li&gt;
&lt;li&gt;最後，建立應變流程：出事時快速識別受影響範圍、回滾部署、通知使用者與法遵部門，這些都比事後手忙腳亂更重要。&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>加入聊天群</title><link>https://kairo.qzz.io/posts/join-chat/</link><guid isPermaLink="true">https://kairo.qzz.io/posts/join-chat/</guid><description>ᕙ⁠(⁠＠⁠°⁠▽⁠°⁠＠⁠)⁠ᕗ</description><pubDate>Thu, 01 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;🔹 加入我的社群 🔹&lt;/h1&gt;
&lt;p&gt;想跟我一起聊天、討論或者分享資源嗎？快來加入以下社群吧！🎉&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;💬 Telegram 聊天群&lt;/h2&gt;
&lt;p&gt;加入我們的 Telegram 群組，一起交流最新資訊與心得。&lt;br /&gt;
點擊下面的按鈕即可加入：
&lt;a href=&quot;https://t.me/+jHzf0NVwFx02ZjNl&quot;&gt;&lt;img src=&quot;https://t.me/+jHzf0NVwFx02ZjNl&quot; alt=&quot;點我點我點我&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;🎮 Discord&lt;/h2&gt;
&lt;p&gt;想要更即時的互動？歡迎來 Discord 跟我聊天！&lt;br /&gt;
&lt;a href=&quot;https://discord.com/users/1433736270311587910&quot;&gt;&lt;img src=&quot;https://discord.com/users/1433736270311587910&quot; alt=&quot;點我點我點我&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;💡 小提示：加入後記得查看群規，保持友善互動哦！😊&lt;/p&gt;
</content:encoded></item><item><title>GitHub Actions 自動化 CI/CD</title><link>https://kairo.qzz.io/posts/github-actions/</link><guid isPermaLink="true">https://kairo.qzz.io/posts/github-actions/</guid><description>完整、實務導向的 GitHub Actions CI/CD 教學：工作流程架構、範例 YAML、最佳實務、安全性與進階技巧，帶你從單機測試到自動部署、監控與擴展。</description><pubDate>Wed, 31 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;前言&lt;/h2&gt;
&lt;p&gt;GitHub Actions 已經從一個方便的自動化工具，演變成完整的 CI/CD 平台。它把工作流程（workflows）直接綁在 Git 倉庫上，讓代碼的測試、建置、驗證與部署可以在同一個地方自動化完成。本文以實務角度出發，從概念說明到範例、再到最佳實務與安全性考量，逐步帶你把 GitHub Actions 用到位：不只是跑測試，而是把整個交付流程做得穩健、可觀測、可擴展。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;一、核心概念快速說明（不要笨重定義）&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Workflow（工作流程）&lt;/strong&gt;：以 YAML 檔放在 &lt;code&gt;.github/workflows/&lt;/code&gt;。它定義了觸發時機（on）、要做的工作（jobs）與邏輯。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Job（工作）&lt;/strong&gt;：工作由多個步驟（steps）組成，在 runner 上執行。每個 job 預設在獨立的 runner（container 或 VM）上執行，job 之間可以並行或依賴。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Step（步驟）&lt;/strong&gt;：單一執行單位，可以是 shell 指令，也可以是 action（重複使用的封裝）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Action&lt;/strong&gt;：可重複使用的模組（JavaScript、Docker 或 composite action），用來封裝常見任務。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Runner&lt;/strong&gt;：執行 job 的主機，分為 GitHub 提供的 hosted runners（Linux/Windows/macOS）或你自建的 self-hosted runners。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Artifact / Cache&lt;/strong&gt;：用來在 job 間傳遞檔案（artifacts）或加快依賴安裝（cache）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Secrets / Environments&lt;/strong&gt;：安全儲存機密資訊與環境級別保護（例如需人工審核才可部署到 production）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;理解這些關鍵字就能閱讀任一 workflow，下面開始用實例把它拼起來。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;二、從最簡單的 CI 開始：Node.js 範例（一步到位）&lt;/h2&gt;
&lt;p&gt;一個實際的 Node.js 專案，典型的 CI 流程包含：安裝依賴、執行 lint、跑測試、產生報告並上傳 artifact。這是一個標準範例：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [ &quot;main&quot;, &quot;staging&quot; ]
  pull_request:
    branches: [ &quot;main&quot; ]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [16.x, 18.x]
    steps:
      - uses: actions/checkout@v4
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - name: Install dependencies (cache)
        uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles(&apos;**/package-lock.json&apos;) }}
          restore-keys: |
            ${{ runner.os }}-node-${{ matrix.node-version }}-
      - run: npm ci
      - run: npm run lint
      - run: npm test -- --ci --reporter=mocha-junit-reporter
      - name: Upload test results
        uses: actions/upload-artifact@v4
        with:
          name: junit-results
          path: test-results.xml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;說明要點：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用 &lt;code&gt;strategy.matrix&lt;/code&gt; 並行在多個 Node 版本上跑測試，驗證相容性。&lt;/li&gt;
&lt;li&gt;使用 &lt;code&gt;actions/cache&lt;/code&gt; 快取 npm，顯著減少安裝時間。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;upload-artifact&lt;/code&gt; 可讓後續 job 或 GitHub UI 下載測試報告。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;三、把 CI 接上 CD：部署範例（Docker → Registry → K8s / VPS / Serverless）&lt;/h2&gt;
&lt;p&gt;CI 做完後通常會把產物（artifact / container image）推到 registry，接著觸發部署。以下範例示範建置 Docker 映像並推到 Docker Hub，然後示範如何用另外的 job 或 workflow 做部署。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Build &amp;amp; Push Image&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# .github/workflows/docker-build.yml
name: Build and Publish Docker Image

on:
  push:
    branches:
      - main
  workflow_dispatch:

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v2
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
      - name: Login to DockerHub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      - name: Build and push
        uses: docker/build-push-action@v4
        with:
          context: .
          push: true
          tags: myorg/myapp:${{ github.sha }}
          platforms: linux/amd64,linux/arm64
      - name: Upload image tag artifact
        uses: actions/upload-artifact@v4
        with:
          name: image-tag
          path: image-tag.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;部署（例：在另一個 workflow 觸發，或使用 environment 與保護）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;部署可在同一 workflow 以 &lt;code&gt;needs:&lt;/code&gt; 依賴順序執行，或用 &lt;code&gt;workflow_run&lt;/code&gt; 觸發。示例：把映像部署到 Kubernetes（kubectl + k8s manifest）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# .github/workflows/deploy.yml
name: Deploy to K8s

on:
  workflow_run:
    workflows: [&quot;Build and Publish Docker Image&quot;]
    types:
      - completed

jobs:
  deploy:
    if: ${{ github.event.workflow_run.conclusion == &apos;success&apos; }}
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://your-app.example.com
    steps:
      - uses: actions/checkout@v4
      - name: Download image tag
        uses: actions/download-artifact@v4
        with:
          name: image-tag
      - name: Set kubectl
        uses: azure/setup-kubectl@v4
        with:
          version: &apos;1.26.0&apos;
      - name: Deploy to k8s
        env:
          IMAGE_TAG: ${{ steps.download-artifact.outputs.path }}/image-tag.txt
          KUBECONFIG: ${{ secrets.KUBE_CONFIG }}
        run: |
          kubectl set image deployment/my-app my-app=myorg/myapp:${{ github.sha }}
          kubectl rollout status deployment/my-app -n default
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意事項：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;secrets&lt;/strong&gt;（例如 DockerHub token、Kubeconfig）不要放在 repo 中，要用 GitHub Secrets。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;environment&lt;/strong&gt; 可以搭配保護規則（required reviewers）來做準入控制。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;workflow_run&lt;/strong&gt; 用於把 build 完成後的自動部署分離成不同 workflow，使 CI 與 CD 更清晰。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;四、常見 CI/CD 模式與工作流設計建議&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;分層 workflow&lt;/strong&gt;：把「測試/建置」和「部署」拆成不同 workflow，用 &lt;code&gt;workflow_run&lt;/code&gt; 串接，降低耦合。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;短、快、可回覆的 job&lt;/strong&gt;：把大任務拆成多個小 job（lint、unit tests、integration tests、build），方便並行與重試。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;只在必要時部署&lt;/strong&gt;：使用 &lt;code&gt;paths&lt;/code&gt;、branch policy 或專門的 release tag 來控制何時部署。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用 artifacts 傳遞建置產物&lt;/strong&gt;：binary 或 build output 儘量透過 artifacts 保留，部署時直接下載使用。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Matrix 建構但有限度&lt;/strong&gt;：Matrix 很方便驗證多環境，但同時啟動過多會增加 runner/費用與配額風險。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用 concurrency 與 cancel-in-progress&lt;/strong&gt;：避免多次 push 觸發排隊部署，&lt;code&gt;concurrency&lt;/code&gt; 能保證同一分支只有一個在跑的 workflow。例：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;五、加速 CI 的實務技巧（節省時間就是節省錢）&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;善用 cache&lt;/strong&gt;（actions/cache）：node_modules、pip cache、maven repo、go modules、composer 等都該 cache，但 key 設計要保守（key 包括 lockfile hash）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;依賴分層&lt;/strong&gt;：把依賴安裝放到獨立 job 或預先產出 artifact，以便後續 job 使用。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用 self-hosted runners（有強需求）&lt;/strong&gt;：若需要特定硬體（GPU）或更高效能，self-hosted runner 可降低啟動時間，但需維護安全與穩定。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;利用 composite actions / reusable workflows&lt;/strong&gt;：把共通步驟抽成 action 或 reusable workflow，減少重複、提高一致性。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;按需執行較重測試&lt;/strong&gt;：把 Unit tests、Integration tests、E2E 分層，PR 時先跑 Unit tests，merge 或 nightly 再跑 E2E。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;六、安全性實務（不能偷懶）&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Secrets 管理&lt;/strong&gt;：所有憑證、token、kubeconfig 一律放入 GitHub Secrets；不要在 workflows 直接 echo secrets（會在 log 洩漏）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;環境保護&lt;/strong&gt;：把 production environment 設為需要人工審核或多重審核（required reviewers）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;避免在 PR 中使用寫入權限的 token&lt;/strong&gt;：&lt;code&gt;GITHUB_TOKEN&lt;/code&gt; 有 repo 權限，若有 fork PR，預設會保護性限制；對外部 PR 請小心。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;最小權限原則&lt;/strong&gt;：只授予 action 或 runner 需要的權限（用 &lt;code&gt;permissions:&lt;/code&gt; 限制 scope）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;第三方 action 風險&lt;/strong&gt;：使用 community action 時檢查 source code（不要盲用），prefer 指定具備維護紀錄與信任度高的 action並鎖定版本（不可用 &lt;code&gt;@master&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;依賴掃描與秘密掃描&lt;/strong&gt;：把 Dependabot、secret scanning、或 SCA 工具整合到 workflow 中，提早攔截安全問題。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;七、Debug、可觀測性與報告&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;在 workflow 中輸出詳細日誌（但不輸出 secrets）&lt;/strong&gt;：對失敗的 step 使用 &lt;code&gt;run: |&lt;/code&gt; 方式抓取更多上下文。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;利用 artifacts 保存 log 與報表&lt;/strong&gt;：測試報告、coverages、bundle stats 都上傳 artifacts 以便分析與回溯。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用 annotations&lt;/strong&gt;：GitHub Actions 支援註解（warning/error）直接貼到 Pull Request，改善開發者體驗。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Metrics 與告警&lt;/strong&gt;：把關鍵指標（成功率、平均執行時間、失敗趨勢）匯到外部監控（Datadog、Prometheus）以偵測異常。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用 &lt;code&gt;if: failure()&lt;/code&gt; 與重試策略&lt;/strong&gt;：針對網路不穩或外部服務的臨時錯誤加入重試（retry loops）或 &lt;code&gt;continue-on-error&lt;/code&gt;（慎用）。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;八、進階功能與常用 patterns&lt;/h2&gt;
&lt;h3&gt;1. Reusable workflows（可重用 workflow）&lt;/h3&gt;
&lt;p&gt;把常用流水線抽成 reusable workflow，供不同 repo 呼叫，減少維護負擔。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# .github/workflows/reusable-ci.yml
name: Reusable CI
on:
  workflow_call:
    inputs:
      node-version:
        required: true
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ inputs.node-version }}
      - run: npm ci
      - run: npm test
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;呼叫方：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;jobs:
  call-reusable:
    uses: your-org/your-repo/.github/workflows/reusable-ci.yml@main
    with:
      node-version: 18.x
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. Composite Actions（組合 action）&lt;/h3&gt;
&lt;p&gt;把多個步驟封裝成一個 action（版本控制、可在多個 workflow 重複使用）。&lt;/p&gt;
&lt;h3&gt;3. Concurrency 與 Workflow Dispatch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;workflow_dispatch&lt;/code&gt; 可手動觸發（常用於 release 或 hotfix）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;concurrency&lt;/code&gt; 能防止重複排隊與浪費 runner。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. Scheduled Workflows（Cron）&lt;/h3&gt;
&lt;p&gt;例：每天夜間跑 E2E 測試或定期掃描：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;on:
  schedule:
    - cron: &quot;0 2 * * *&quot; # 每日 02:00 UTC
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;九、Self-hosted runners：何時才適合？&lt;/h2&gt;
&lt;p&gt;優點：自訂環境、較低延遲（依網路）、可使用特殊硬體（GPU、專用網卡）、無需排隊受限於 GitHub hosted runner 配額。&lt;br /&gt;
缺點：需要維護（OS patch、security)、曝光風險（若 runner 在公網）、必須小心 secrets 管理（避免在 runner 上被盜用）。&lt;br /&gt;
實務建議：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;將 self-hosted runner 放在安全網段（VPC / private subnet）且使用自動化管理（Ansible/Terraform），定期 patch。&lt;/li&gt;
&lt;li&gt;使用 ephemeral runner（短期啟動、完成即關）降低攻擊面。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;十、成本與配額考量&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;GitHub-hosted runners 的執行時間會計費（依帳戶類型與 runner OS 不同）。&lt;/li&gt;
&lt;li&gt;除了 runner 時間，artifact 存儲、package storage 也可能有額外費用。&lt;/li&gt;
&lt;li&gt;使用 matrix、大量並行 job 會快速增加成本；用 &lt;code&gt;concurrency&lt;/code&gt;、job 並行度與 cache 設計來優化使用率。&lt;/li&gt;
&lt;li&gt;如果大流量 CI（每日數千次 workflow），考慮 self-hosted 或混合策略（部分工作放 public hosted，重度計算放 self-hosted）。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;十一、常見問題與排查清單&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Workflow 沒有觸發？&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;檢查 &lt;code&gt;on:&lt;/code&gt; 設定（push、pull_request、workflow_dispatch、schedule）與 branch 名稱。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Secrets 不能在 fork PR 中使用？&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;這是預設安全措施，外部貢獻者的 workflow 不會被授權取用 repository secrets。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cache 不命中？&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;核心問題是 key 設計；建議 key 包含 lockfile hash（如 &lt;code&gt;package-lock.json&lt;/code&gt;）或依需求採分層 key 以提高穩定性。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;artifact 太大 / retention 過短？&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;調整 artifact 的 retentionDays 或清理政策，避免佔用儲存配額。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;部署失敗且沒有明確錯誤？&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;開啟詳細 log，確保敏感資訊以 masked 方式處理，並把部署步驟拆解成更小步驟便於定位。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;十二、實務檢查清單（部署前後必做）&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;部署前&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;所有敏感資訊已放入 Secrets 且經過審核。&lt;/li&gt;
&lt;li&gt;workflows 使用最小必要權限（&lt;code&gt;permissions&lt;/code&gt; 限制）。&lt;/li&gt;
&lt;li&gt;key 的 cache 設計與 purge 流程可控。&lt;/li&gt;
&lt;li&gt;測試 coverage 與自動化測試門檻設置（PR 必通過測試才能 merge）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;部署中&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用 environment 與 required reviewers 控制 production 上線。&lt;/li&gt;
&lt;li&gt;監控 deploy duration 與 rollback 機制（health check）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;部署後&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Release notes / changelog 自動生成（例如使用 conventional commits + action 產生 release）。&lt;/li&gt;
&lt;li&gt;觀察 SLO / error rate 與自動化告警。&lt;/li&gt;
&lt;li&gt;定期清理 artifacts、冷資料與舊 runner。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;十三、實戰案例速覽（簡要）&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;小型專案&lt;/strong&gt;：使用單一 workflow，PR 試跑測試，merge 到 &lt;code&gt;main&lt;/code&gt; 才 build image 並部署到 Vercel / Netlify（serverless）— 成本低、維護簡單。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;中型企業&lt;/strong&gt;：拆分 CI / CD，使用 reusable workflows、environment 保護、並把 E2E 在 nightly 或 staging 執行。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;高頻交易/高依賴專案&lt;/strong&gt;：自建 runner、嚴格的權限管理、並把敏感部署步驟放在內部網路的 runner 執行。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;十四、總結：把 GitHub Actions 當成團隊的自動化中樞&lt;/h2&gt;
&lt;p&gt;GitHub Actions 的價值不僅是把單一任務自動化，而是把開發、測試、建置、發佈、監控串成一條可靠的交付鏈。好的 CI/CD 流程能讓你：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;更早發現錯誤（shift-left）&lt;/li&gt;
&lt;li&gt;減少人工步驟與人為失誤&lt;/li&gt;
&lt;li&gt;快速回應市場與使用者需求&lt;/li&gt;
&lt;li&gt;在必要時快速回滾與回復服務&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最後給你一個最實用的 checklist（複製貼上）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[. ] workflow 有清楚的觸發條件與分支策略&lt;/li&gt;
&lt;li&gt;[. ] secrets 與 environment 已正確設定&lt;/li&gt;
&lt;li&gt;[. ] job 被拆分為可並行與可重試的小步驟&lt;/li&gt;
&lt;li&gt;[. ] cache 與 artifact 設計合理、key 有版本化或 lockfile hash&lt;/li&gt;
&lt;li&gt;[. ] reusable workflows / composite actions 被用於共通流程&lt;/li&gt;
&lt;li&gt;[. ] production environment 有保護與審核流程&lt;/li&gt;
&lt;li&gt;[. ] 日誌、報表、與指標被上傳並納入監控&lt;/li&gt;
&lt;li&gt;[. ] 成本預估與配額檢查已完成&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;把這些元素落實在你的 GitHub Actions 中，CI/CD 就不再是麻煩的工程，而是你可依賴的交付引擎。&lt;/p&gt;
</content:encoded></item><item><title>介紹 Astro Fuwari 主題</title><link>https://kairo.qzz.io/posts/fuwari-theme/</link><guid isPermaLink="true">https://kairo.qzz.io/posts/fuwari-theme/</guid><description>完整介紹 Fuwari：功能特色、安裝方式、設定結構與部署建議，適合用於技術與個人部落格。</description><pubDate>Tue, 23 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;什麼是 Astro Fuwari&lt;/h2&gt;
&lt;p&gt;Fuwari 是一款基於 Astro 建構的靜態部落格主題，設計目標是提供乾淨、輕量且現代化的寫作與閱讀體驗。它將部落格常見需求直接整合進模板中，讓使用者可以專注在內容本身，而不是從零處理版型與架構。
Fuwari 並不是單純的樣式套件，而是一個可直接建立專案的完整模板，包含文章系統、頁面結構、搜尋、動畫與主題設定。&lt;/p&gt;
&lt;h2&gt;核心技術架構&lt;/h2&gt;
&lt;p&gt;Fuwari 的核心技術組成如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Astro：負責靜態生成與頁面架構&lt;/li&gt;
&lt;li&gt;Tailwind CSS：處理版面、色彩與響應式設計&lt;/li&gt;
&lt;li&gt;Pagefind：靜態全文搜尋&lt;/li&gt;
&lt;li&gt;Swup（或同類方案）：頁面切換過場動畫  這樣的組合讓網站在保持高度可讀性的同時，仍然具備良好的效能與可維護性。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;主要功能特色：&lt;/h2&gt;
&lt;h3&gt;靜態生成與高效能&lt;/h3&gt;
&lt;p&gt;Fuwari 完全採用 Astro 的靜態輸出模式，建置後產生純靜態檔案，部署到任何 CDN 或靜態主機都能有極快的載入速度，且不依賴後端伺服器。&lt;/p&gt;
&lt;h3&gt;Markdown 文章系統&lt;/h3&gt;
&lt;p&gt;文章以 Markdown 撰寫，支援 Frontmatter，用來定義標題、日期、標籤、分類與是否為草稿。這使得文章管理與版本控制變得非常直覺。&lt;/p&gt;
&lt;h3&gt;內建搜尋功能&lt;/h3&gt;
&lt;p&gt;透過 Pagefind，Fuwari 能在建置階段產生搜尋索引，瀏覽器端即可進行全文搜尋，不需要外部服務，也不會增加伺服器成本。&lt;/p&gt;
&lt;h3&gt;主題與深色模式&lt;/h3&gt;
&lt;p&gt;Fuwari 內建亮色與深色模式切換，並透過 Tailwind CSS 的設定檔集中管理配色，方便進行整體風格調整。&lt;/p&gt;
&lt;h3&gt;頁面過場動畫&lt;/h3&gt;
&lt;p&gt;頁面切換時不會整頁刷新，而是透過過場動畫進行內容替換，使閱讀體驗更加流暢，接近傳統 SPA 的手感，但不犧牲靜態站點的效能。&lt;/p&gt;
&lt;h2&gt;專案結構說明&lt;/h2&gt;
&lt;p&gt;Fuwari 的專案結構清楚，適合長期維護：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;src/config.ts&lt;/code&gt;：站台基本設定，如站名、描述、社群連結&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src/content/posts/&lt;/code&gt;：所有文章內容&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src/pages/&lt;/code&gt;：額外頁面（關於頁、標籤頁等）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tailwind.config.cjs&lt;/code&gt;：樣式與主題設定&lt;/li&gt;
&lt;li&gt;&lt;code&gt;astro.config.mjs&lt;/code&gt;：Astro 建置與部署設定  多數客製化需求都能在這些檔案中完成，而不需要大幅改動核心邏輯。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;安裝與啟動流程&lt;/h2&gt;
&lt;p&gt;Fuwari 提供官方建立指令，可快速建立新專案：  &lt;code&gt;bash pnpm create fuwari@latest cd my-blog pnpm install pnpm dev &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;啟動後即可在本機預覽完整部落格功能。&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;部署方式建議&lt;/h2&gt;
&lt;p&gt;由於 Fuwari 是純靜態網站，可部署至多種平台：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vercel&lt;/li&gt;
&lt;li&gt;Netlify&lt;/li&gt;
&lt;li&gt;GitHub Pages&lt;/li&gt;
&lt;li&gt;Cloudflare Pages&lt;/li&gt;
&lt;li&gt;任意支援靜態檔案的伺服器或 CDN&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;部署時只需上傳建置後的輸出目錄即可，不需要後端環境。&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;適合哪些人使用&lt;/h2&gt;
&lt;p&gt;Fuwari 特別適合以下族群：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;技術部落客&lt;/li&gt;
&lt;li&gt;開發者筆記網站&lt;/li&gt;
&lt;li&gt;個人知識庫&lt;/li&gt;
&lt;li&gt;不想維護後端的寫作者&lt;/li&gt;
&lt;li&gt;希望版型乾淨、不被 UI 干擾內容的人&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;限制與注意事項&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;若需要即時互動或高度動態功能，需要額外整合 API 或第三方服務&lt;/li&gt;
&lt;li&gt;頁面過場動畫在特殊情境下需注意瀏覽器相容性&lt;/li&gt;
&lt;li&gt;對完全不熟 Astro 的使用者仍有一定學習曲線&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;總結&lt;/h2&gt;
&lt;p&gt;Astro Fuwari 是一款定位明確、完成度高的靜態部落格主題。它在效能、外觀與可維護性之間取得良好平衡，非常適合作為長期寫作與技術分享的平台。如果你想要一個不用從零設計、又能持續擴充的部落格架構，Fuwari 會是一個非常穩定且安心的選擇。&lt;/p&gt;
</content:encoded></item><item><title>CPU 在忙什麼？多核心運作原理詳解</title><link>https://kairo.qzz.io/posts/cpu/</link><guid isPermaLink="true">https://kairo.qzz.io/posts/cpu/</guid><description>深入解析 CPU 的組成、工作流程、多核心協作及現代技術特性，幫助你理解效能優化與系統設計。</description><pubDate>Mon, 22 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;CPU 的基本組成&lt;/h2&gt;
&lt;p&gt;CPU（中央處理器）是電腦的核心運算單元，負責解讀指令、處理資料並協調硬體。主要組件包括：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;控制單元（Control Unit, CU）&lt;/strong&gt;&lt;br /&gt;
負責指令解碼與流程控制，決定何時讀取記憶體、執行運算或寫入暫存器。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;算術邏輯單元（Arithmetic Logic Unit, ALU）&lt;/strong&gt;&lt;br /&gt;
執行算術運算（加減乘除）和邏輯運算（AND、OR、XOR、NOT）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;暫存器（Registers）&lt;/strong&gt;&lt;br /&gt;
高速內部記憶體，用於存放臨時數據和指令位址，包括通用暫存器、程式計數器（PC）、指令暫存器（IR）與狀態暫存器。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;快取（Cache）&lt;/strong&gt;&lt;br /&gt;
小容量高速記憶體，分 L1、L2、L3，減少對主記憶體的存取延遲。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;總線與介面（Bus &amp;amp; Interface）&lt;/strong&gt;&lt;br /&gt;
負責 CPU 與記憶體及周邊設備的資料傳輸，包括資料匯流排、地址匯流排與控制匯流排。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;CPU 的工作流程&lt;/h2&gt;
&lt;p&gt;CPU 執行指令遵循 &lt;strong&gt;取指-解碼-執行-寫回（Fetch-Decode-Execute-Write Back）&lt;/strong&gt; 四階段：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;取指（Fetch）&lt;/strong&gt;：控制單元從記憶體抓取指令，程式計數器提供地址。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;解碼（Decode）&lt;/strong&gt;：將指令轉換成 CPU 可執行的微操作。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;執行（Execute）&lt;/strong&gt;：ALU 根據解碼結果進行運算或邏輯操作。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;寫回（Write Back）&lt;/strong&gt;：將運算結果寫回暫存器或記憶體，更新狀態。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在多核心 CPU 中，多條指令可同時在不同核心或管線中運行，提高並行處理能力。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;多核心 CPU 的運作原理&lt;/h2&gt;
&lt;h3&gt;核心與線程（Core &amp;amp; Thread）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;核心（Core）&lt;/strong&gt;：實體運算單元，可獨立執行指令。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;線程（Thread）&lt;/strong&gt;：核心內的虛擬運算單位。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;超執行緒（Hyper-Threading）&lt;/strong&gt;：單核心模擬多線程，提高資源利用率。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;工作分配&lt;/h3&gt;
&lt;p&gt;操作系統將程式拆成多個執行緒，分配給不同核心：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;調度器決定核心分配。&lt;/li&gt;
&lt;li&gt;各核心維護自己的暫存器、快取與管線。&lt;/li&gt;
&lt;li&gt;多核心協作透過共享記憶體或訊息傳遞同步。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;核心內管線（Pipeline）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;CPU 將指令拆成多個階段並行運行，提升吞吐量。&lt;/li&gt;
&lt;li&gt;管線停滯可能因分支跳轉或資料依賴發生。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;快取與記憶體層級&lt;/h2&gt;
&lt;p&gt;CPU 速度遠快於 RAM，因此快取至關重要：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;L1 Cache&lt;/strong&gt;：核心內建，最快、容量最小。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;L2 Cache&lt;/strong&gt;：每核心專屬，稍慢。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;L3 Cache&lt;/strong&gt;：多核心共享，最大容量。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;主記憶體（RAM）&lt;/strong&gt;：延遲高於快取。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;磁碟（SSD/HDD）&lt;/strong&gt;：延遲最高，不直接被 CPU 使用。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;快取命中率高，可大幅提升實際運算效率。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;CPU 調度與多核心協作&lt;/h2&gt;
&lt;p&gt;操作系統管理核心資源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;搶佔式調度（Preemptive Scheduling）&lt;/strong&gt;：隨時切換線程，保證公平性。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多核心負載均衡&lt;/strong&gt;：平均分配工作，避免閒置。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;親和性（Affinity）設置&lt;/strong&gt;：綁定線程到特定核心，提高快取命中率。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;協作挑戰：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;同步與鎖（Lock/Mutex）&lt;/strong&gt;：避免資料競爭。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;記憶體一致性&lt;/strong&gt;：確保多核心讀寫資料正確。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;快取一致性&lt;/strong&gt;：避免不同核心快取資料衝突。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;現代 CPU 技術特性&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;超執行緒（Hyper-Threading / SMT）&lt;/strong&gt;：模擬多線程，提高管線利用率。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多級快取（L1/L2/L3）&lt;/strong&gt;：速度與容量平衡，減少記憶體延遲。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分支預測（Branch Prediction）&lt;/strong&gt;：預測條件跳轉方向，避免管線停滯。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;向量指令集（SIMD）&lt;/strong&gt;：單指令多資料，適合科學運算與圖形處理。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;動態頻率與節能（Turbo Boost / Power Throttling）&lt;/strong&gt;：自動調整頻率，提升效能或降低功耗。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;CPU 效能分析&lt;/h2&gt;
&lt;p&gt;效能指標：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;時脈頻率（Clock Frequency）&lt;/strong&gt;：每秒運算速度。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IPC（Instructions Per Cycle）&lt;/strong&gt;：每個時鐘週期可執行指令數。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;核心數（Cores）&lt;/strong&gt;：並行能力。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;快取命中率&lt;/strong&gt;：影響實際吞吐量。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;功耗與發熱&lt;/strong&gt;：過熱會自動降頻。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;瓶頸來源：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;運算密集型&lt;/strong&gt;：ALU、FPU 處理能力不足。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;記憶體密集型&lt;/strong&gt;：頻繁存取 RAM，快取命中率低。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;I/O 密集型&lt;/strong&gt;：磁碟或網路阻塞 CPU。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;CPU 與現代應用&lt;/h2&gt;
&lt;p&gt;多核心 CPU 應用場景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;多工處理（同時執行多程式）&lt;/li&gt;
&lt;li&gt;並行計算（科學運算、圖形渲染）&lt;/li&gt;
&lt;li&gt;虛擬化（VM 或容器核心分配）&lt;/li&gt;
&lt;li&gt;多線程伺服器（Web、遊戲伺服器）&lt;/li&gt;
&lt;li&gt;資料分析與機器學習（矩陣運算受益於 SIMD 與多核心）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;總結&lt;/h2&gt;
&lt;p&gt;CPU 是運算的心臟，其效能取決於：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;控制單元、ALU、暫存器與快取的協作&lt;/li&gt;
&lt;li&gt;多核心與多線程的並行運作&lt;/li&gt;
&lt;li&gt;管線、分支預測與向量指令集的優化&lt;/li&gt;
&lt;li&gt;效能指標：時脈、IPC、核心數與快取命中率&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;理解 CPU 運作與多核心協作原理，有助於：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析系統瓶頸&lt;/li&gt;
&lt;li&gt;優化程式效能&lt;/li&gt;
&lt;li&gt;設計高效能軟體與系統架構&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>什麼是 CDN？原理與應用場景</title><link>https://kairo.qzz.io/posts/what-is-cdn/</link><guid isPermaLink="true">https://kairo.qzz.io/posts/what-is-cdn/</guid><description>這篇文章將帶大家理解什麼是 CDN 以及有什麼功效！</description><pubDate>Fri, 28 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;什麼是 CDN？原理與應用場景（詳盡技術指南）&lt;/h1&gt;
&lt;p&gt;內容分為：CDN 基本概念 → 核心原理與架構 → 快取策略與 HTTP 標頭實作 → 進階功能（安全、串流、邊緣運算）→ 部署與 DNS 設定步驟 → 性能/監控/測試實務 → 成本與選型考量 → 常見問題與排查。想全面理解 CDN、實際上線、以及如何最佳化它，這篇把你需要的都攤開講清楚。&lt;/p&gt;
&lt;h2&gt;一、CDN 是什麼？為什麼要用 CDN&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;CDN（Content Delivery Network）&lt;/strong&gt; 是分散式的伺服器網路，目的是把靜態或可快取的內容（例如圖片、影片、CSS、JS、字型、甚至動態 API 的快取結果）放到離最終使用者更近的節點（edge / POP），以降低延遲（latency）、提高吞吐（throughput）、減少原始伺服器（origin server）負載並提升可用性與抗攻擊能力。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心目標：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;減少使用者到伺服器的網路距離（降低 RTT）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;把流量分散到邊緣節點（節省來源伺服器資源）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;加速靜態資產與大檔案傳輸（更快的 TTFB / 首包）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;提供安全功能（DDoS 緩解、WAF、TLS 終止）&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;二、CDN 的核心架構與運作原理&lt;/h2&gt;
&lt;h3&gt;1. 核心組件&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Origin（來源伺服器）&lt;/strong&gt;：放原始內容的伺服器（你的主機或雲端 storage）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Edge / POP（Point of Presence）&lt;/strong&gt;：遍佈全球的緩存節點，用於回應終端使用者請求。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;DNS / Anycast&lt;/strong&gt;：全局流量導向機制，通常使用 Anycast IP 或地理 DNS（GeoDNS）將使用者解析到最近的 POP。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;控制平面（Control Plane）&lt;/strong&gt;：管理規則、快取策略、憑證、WAF 規則等。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;管理與監控介面&lt;/strong&gt;：供運維調整、查看流量、設定快取失效（purge）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. 基本請求流程（簡化）&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;使用者在瀏覽器輸入網址（或載入資源）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DNS 解析把該域名解析到 CDN 的 IP（通常是最近的 POP）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;使用者發送 HTTP(S) 請求到該 POP。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;POP 檢查是否有快取命中（Hit）：&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;若命中（HIT）→ 直接回應快取內容。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;若未命中（MISS）→ POP 向 Origin 請求內容，然後回傳給使用者，並可將內容快取起來以便後續命中。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;POP 可根據快取規則（Cache-Control、Vary、Cookie、Query string）決定是否快取與如何快取。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;3. Anycast 與 GeoDNS 的差異&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Anycast&lt;/strong&gt;：同一 IP 在多個地點宣告，由 BGP 路由決定最短路徑到最近 POP。優點是透明且迅速。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;GeoDNS（基於地理位置的 DNS）&lt;/strong&gt;：DNS 回傳不同 IP/CNAME 給不同地理位置的查詢者。可更精細，但多一步解析流程。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;三、快取策略（Cache）與 HTTP 標頭的關鍵實作&lt;/h2&gt;
&lt;p&gt;快取是 CDN 的核心。理解 HTTP 標頭如何影響 CDN 行為，是把 CDN 用得好與用得爛的差別。&lt;/p&gt;
&lt;h3&gt;1. 重要 HTTP Cache 標頭&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;Cache-Control&lt;/code&gt;（最重要）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;public&lt;/code&gt; / &lt;code&gt;private&lt;/code&gt;：&lt;code&gt;public&lt;/code&gt; 允許公用快取；&lt;code&gt;private&lt;/code&gt; 只給私人快取（例如瀏覽器）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;max-age=SECONDS&lt;/code&gt;：快取有效期。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;s-maxage=SECONDS&lt;/code&gt;：為 shared caches（CDN、代理）專用，優先於 max-age。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;must-revalidate&lt;/code&gt;：到期後需再次向 origin 驗證。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;no-cache&lt;/code&gt;：需要向 origin 驗證才可使用（但可用作 conditional request）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;no-store&lt;/code&gt;：不允許任何快取。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;stale-while-revalidate=SECONDS&lt;/code&gt;：允許返回過期資源，同時在後台重新刷新。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;stale-if-error=SECONDS&lt;/code&gt;：當 origin 發生錯誤時允許返回過期內容。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;Expires&lt;/code&gt;：舊式（基於絕對時間）。可與 Cache-Control 並用，但 Cache-Control 優先。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;ETag&lt;/code&gt;：資源標識（內容變更檢測），可用於 conditional requests（If-None-Match）。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;Last-Modified&lt;/code&gt; / &lt;code&gt;If-Modified-Since&lt;/code&gt;：基於最後修改時間的快取驗證。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;Vary&lt;/code&gt;：指定快取依賴哪些請求標頭（例如 &lt;code&gt;Vary: Accept-Encoding&lt;/code&gt; 表示壓縮後的差異），若設錯會造成快取分裂或錯誤命中。&lt;/p&gt;
&lt;h3&gt;2. 快取層級與鍵（cache key）&lt;/h3&gt;
&lt;p&gt;CDN 會用一個「快取鍵」來辨識同一資源，常見的組成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;protocol（http/https）、host、path、query string（可選）、headers（可選）、cookies（可選）。 設定常見策略：&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;包含 query string&lt;/strong&gt;：若你的資源用 query string 做版本或參數，則包含。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;忽略 query string&lt;/strong&gt;：對於不影響資源的 query，忽略可以提高命中率。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Vary 與 Accept-Encoding&lt;/strong&gt;：務必設定 &lt;code&gt;Vary: Accept-Encoding&lt;/code&gt; 以區分壓縮與未壓縮版本。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. Cache Invalidation（快取失效）策略&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;TTL 依賴&lt;/strong&gt;：自然過期，等待 max-age 到期。簡單但延遲更新。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Purge API / Cache-Busting&lt;/strong&gt;：呼叫 CDN 的 purge API 清除指定物件，或採用版本化 URL（例如 &lt;code&gt;/app.v1.js&lt;/code&gt; → &lt;code&gt;/app.v2.js&lt;/code&gt;）來避免 purge。版本化是最穩健的做法。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Stale-while-revalidate + background refresh&lt;/strong&gt;：在不影響使用者的情況下延長可使用過期資源，同時在後台刷新。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. 快取粒度設計&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;大檔案（影片、軟體、圖片）&lt;/strong&gt;：長 TTL，強快取。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;變動頻繁資源（API、認證相關）&lt;/strong&gt;：短 TTL 或不快取，且用 &lt;code&gt;Cache-Control: no-cache&lt;/code&gt; 與 &lt;code&gt;ETag&lt;/code&gt; 做 conditional request。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;HTML&lt;/strong&gt;：通常較短 TTL 或不快取，因為經常包含最新動態；也可用 Edge Side Includes（ESI）或 HTML 只快取靜態片段。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;四、CDN 的進階功能與應用場景&lt;/h2&gt;
&lt;h3&gt;1. 靜態資產加速（最常見）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;圖片、JS、CSS、字型等透過 POP 分散到全球，加快首次繪製（first paint）與首包時間（TTFB）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. 視訊串流（VOD / Live）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;VOD（Video On Demand）&lt;/strong&gt;：使用 HTTP 節流並支援分段（HLS、DASH）＋ ABR（自適應位元率）。CDN 用於分段快取與分發。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Live Streaming&lt;/strong&gt;：低延遲直播需要較短分段與特殊加速策略（LL-HLS、WebRTC 等）。專業 CDN 支援直播傳輸、回跳（origination）與錄製快取。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. API 加速與邊緣快取（Edge Caching for APIs）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;非個人化、可快取的 API 結果（如公開數據、產品目錄）可以放在 edge，減少 origin 負載並縮短延遲。建議配合 &lt;code&gt;s-maxage&lt;/code&gt; 與 &lt;code&gt;stale-while-revalidate&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. 安全功能（WAF、DDoS 緩解、TLS 終止）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;WAF&lt;/strong&gt;（Web Application Firewall）：在 edge 層過濾 SQLi、XSS 等攻擊。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;DDoS 保護&lt;/strong&gt;：透過全球 POP 吸收與速率限制保護 origin。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;TLS 終止&lt;/strong&gt;：CDN 在 edge 先解 TLS（減少 origin CPU），並提供自動憑證（Let&apos;s Encrypt / 商業憑證）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;5. 動態內容路由（Reverse Proxy、Load Balancing）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;CDN 可當作全局負載平衡器，結合健康檢查將流量路由到多 region origin 或多 datacenter。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;6. 邊緣運算（Edge Computing / Edge Workers）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;例如 Cloudflare Workers、Fastly VCL、AWS Lambda@Edge，使你能在 edge 執行程式碼：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;動態改寫回應、A/B 測試、Auth 驗證、圖像處理、個性化內容（有狀態挑戰）等。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;優勢：把輕量運算移到離使用者最近的位置，降低延遲並縮短回覆時間。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;7. 影像與媒體最佳化（Image Optimization）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;自動調整尺寸、格式轉換（WebP/AVIF）、延遲載入（lazy loading）與響應式圖片，節省頻寬並提高效能。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;8. IoT / 大量小檔分發&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;固件更新、軟體分發等，透過 CDN 分發可大幅降低 origin 壓力並提升分發穩定性。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;五、部署 CDNs：實作步驟（以自有域名與 HTTPS 為例）&lt;/h2&gt;
&lt;h3&gt;步驟總覽&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;註冊 CDN 服務（Cloudflare / Fastly / Akamai / AWS CloudFront / GCP Cloud CDN / Bunny / Netlify 等）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;設定 origin（你的來源伺服器）URL 與埠號。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;設定快取政策（TTL、cache key、忽略 query、Vary 等）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;設定 SSL/TLS（自動憑證或上傳自有憑證）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;設定 CNAME 或使用 CDN 提供的域名。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;測試（curl、瀏覽器、trace）與監控。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;設定 purge 與發佈流程（版本化最佳）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;DNS 與 CNAME：&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;常見做法：把 &lt;code&gt;static.example.com&lt;/code&gt; 或 &lt;code&gt;www.example.com&lt;/code&gt; CNAME 指向 CDN 提供的 host（例如 &lt;code&gt;your-site.cdnprovider.net&lt;/code&gt;）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;若使用 apex/root domain（example.com），需檢查 CDN 是否支援 ANAME/ALIAS 或提供 DNS 承諾；Cloudflare 則採用代理模式，直接替換 Name Server。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;SSL 相關：&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;CDN 通常提供自動 TLS（Let&apos;s Encrypt）或讓你上傳自有憑證（包含中繼憑證）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;設定 &lt;code&gt;Edge TLS&lt;/code&gt; 要注意 &lt;code&gt;Full&lt;/code&gt; / &lt;code&gt;Full (strict)&lt;/code&gt; / &lt;code&gt;Flexible&lt;/code&gt; 模式，&lt;strong&gt;推薦使用 strict（edge 與 origin 皆驗證憑證）&lt;/strong&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;六、測試、監控與效能驗證（實務指令與方法）&lt;/h2&gt;
&lt;h3&gt;1. 基礎測試（命令行）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;檢查 DNS 解析到哪個 IP：
&lt;code&gt;dig +short yourcdn.example.com &lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;看 HTTP 標頭與快取狀態：
&lt;code&gt;curl -I https://yourcdn.example.com/path/to/resource &lt;/code&gt;
關注標頭：&lt;code&gt;Cache-Control&lt;/code&gt;、&lt;code&gt;Age&lt;/code&gt;、&lt;code&gt;Via&lt;/code&gt;、&lt;code&gt;X-Cache&lt;/code&gt;、&lt;code&gt;X-Cache-Status&lt;/code&gt;、&lt;code&gt;CF-Cache-Status&lt;/code&gt;（Cloudflare）等。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;路徑追蹤（traceroute / mtr）看網路路徑到 POP：
&lt;code&gt;traceroute yourcdn.example.com mtr --report yourcdn.example.com &lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;2. 性能測試&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;使用 &lt;code&gt;curl -w&lt;/code&gt; 來量化 TTFB： &lt;code&gt;curl -o /dev/null -s -w &quot;%{time_starttransfer}\n&quot; https://yourcdn.example.com/path &lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;用 WebPageTest 或 Lighthouse（Chrome DevTools）來做前端端到端測試（首次載入與快取載入差異）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. 壓力測試（注意對 origin 保護）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;使用負載測試工具（k6、wrk、hey）測試 CDN 命中率與 origin 退避情況，但在正式測試前必須通知 CDN 或做好流量限制，以免被視為攻擊。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. 監控指標&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cache HIT ratio&lt;/strong&gt;（命中率）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Requests/s&lt;/strong&gt; 與流量（Mbps）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Origin bandwidth&lt;/strong&gt;（origin 被拉流量）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Error rate（4xx/5xx）&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Latency (P50/P95/P99)&lt;/strong&gt; 使用 CDN 的分析與外部監控（Prometheus / Grafana / Datadog / New Relic）來搭配。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;七、成本與選型考量&lt;/h2&gt;
&lt;h3&gt;成本構成&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;流量費用（egress）&lt;/strong&gt;：通常是主要成分，依區域與供應商不同價差甚大。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;請求數量（requests）&lt;/strong&gt;：大量小檔案（favicon、icons）會增加請求成本。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;功能費&lt;/strong&gt;：WAF、DDoS、邊緣運算、圖片最佳化等附加服務。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cache hit ratio&lt;/strong&gt;：高命中率能有效降低 origin 流量成本。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;選 CDN 的重點&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;地域覆蓋&lt;/strong&gt;：你的使用者在哪裡？美國/歐洲/亞太/新興市場的 POP 覆蓋率與延遲表現不同。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;流量費用&lt;/strong&gt;：大流量場景（影片、分發）要看 egress 價格。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;功能需求&lt;/strong&gt;：是否需要 WAF、DDoS、edge compute、媒體處理。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;API / 管理介面&lt;/strong&gt;：是否有 purge API、版本化支援、部署自動化。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SLA 與企業支援&lt;/strong&gt;：商業等級需求是否需要 24/7 支援與 SLA。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;整合能力&lt;/strong&gt;：是否與雲端（AWS/GCP/Azure）高度整合、或可插入現有 CI/CD 流程。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;八、最佳實踐總結（實務清單）&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;資源版本化（cache-busting）&lt;/strong&gt;：靜態資產使用內容哈希或版本號（app.a1b2c3.js），避免頻繁 purge。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;合理設定 Cache-Control 與 s-maxage&lt;/strong&gt;：靜態長 TTL、HTML 短 TTL 或 edge-only caching。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;用 &lt;code&gt;Vary&lt;/code&gt; 小心&lt;/strong&gt;：只對真正需要的 header 設定 Vary（例如 &lt;code&gt;Accept-Encoding&lt;/code&gt;）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;啟用壓縮（gzip / brotli）與 HTTP/2（或 HTTP/3）&lt;/strong&gt;：提高載入效率。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;圖片與媒體優化&lt;/strong&gt;：使用響應式圖片、格式轉換（WebP/AVIF）、延遲載入與 CDN 自動轉換功能。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;監控 cache hit rate&lt;/strong&gt;：目標是提高命中、降低 origin 依賴。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;使用 purge 與 invalidation API 有節制&lt;/strong&gt;：盡量採版本化避免大量 purge。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;在預期高流量時先暖機（pre-warm）或預熱熱門內容&lt;/strong&gt;：避免突發流量命中率低。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;邊緣運算要有退路&lt;/strong&gt;：把關鍵邏輯留給 origin，edge 適合做輕量化處理。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;安全性第一&lt;/strong&gt;：強制 HTTPS、WAF 規則、限制來源 IP 或使用 signed URLs（安全短鏈）做保護敏感內容。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;九、常見問題與排查 (Troubleshooting)&lt;/h2&gt;
&lt;h3&gt;問題：&lt;code&gt;Cache-Control: max-age&lt;/code&gt; 設了還是不命中？&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;檢查 CDN 配置是否被 override（某些 CDN 有自己的設定優先）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;檢查回應 header 是否在經過 CDN 時被改寫。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;檢查 &lt;code&gt;Vary&lt;/code&gt; 與 &lt;code&gt;Cookie&lt;/code&gt; 是否導致大量快取分裂。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;問題：圖片載入緩慢但 HTML 快？&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;檢查圖片是否被 origin 重新生成（慢）；或 POP 未快取圖片（可能因為 &lt;code&gt;no-cache&lt;/code&gt; 或 query string）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;檢查是否啟用影像優化（自動轉檔）導致邊緣延遲。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;問題：使用者在某地區連不上 CDN？&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;檢查 DNS 是否解析到正確 POP（dig +trace）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;檢查 CDN 在該地是否有 POP（供應商文件）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;檢查防火牆或 ISP 是否封鎖特定 IP。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;問題：Origin 被突發流量打爆&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;啟用或調整 &lt;strong&gt;origin shielding&lt;/strong&gt;（讓某一 region 的 POP 做 origin gateway），提高 cache hit。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;提升 cache TTL 或預熱熱門內容。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;考慮增加多 region origin 與全局負載平衡。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;十、結語（要點回顧）&lt;/h2&gt;
&lt;p&gt;CDN 不只是「把東西丟到別處」，而是一整套優化網路交付、提升使用者體驗、保護 origin 與降低成本的系統。掌握以下幾點，你就可以把 CDN 用到刀口上：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;設計合適的 &lt;strong&gt;快取策略&lt;/strong&gt;（Cache-Control / s-maxage / ETag / Vary）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;版本化資源&lt;/strong&gt; 避免頻繁 purge，提升命中率&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;根據使用者地理分布挑選有良好 POP 覆蓋的供應商&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;使用 &lt;strong&gt;edge 功能&lt;/strong&gt;（image optimization / workers / WAF）來提升使用者體驗與安全&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;持續 &lt;strong&gt;監控 cache hit、origin bandwidth、latency&lt;/strong&gt; 並調整策略&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;把 CDN 視為你系統的一個「全球代理層」，正確設定與管理它，能讓網站更快、更穩、更省錢，也更能抵抗網路上常見的攻擊與突發流量。&lt;/p&gt;
</content:encoded></item><item><title>API Gateway 用途與設計</title><link>https://kairo.qzz.io/posts/api-gateway-purpose-and-design/</link><guid isPermaLink="true">https://kairo.qzz.io/posts/api-gateway-purpose-and-design/</guid><description>這篇文章主要是帶大家理解 API 以及用途並如何設計。</description><pubDate>Thu, 27 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;&lt;strong&gt;API Gateway 的用途與設計：核心概念、運作方式與常見架構解析&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;API Gateway 是現代服務架構中不可或缺的核心組件，特別是在微服務、分散式後端與大型系統中，它負責統一對外入口、跨服務協作、安全管理與流量控制。理解 API Gateway 的角色，有助於在設計 API、部署服務與建立高可擴展系統時做出更好的架構決策。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;一、API Gateway 的核心用途&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;1. 統一入口（Single Entry Point）&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;在微服務架構下，如果前端需要呼叫多個後端服務，會造成複雜的請求流程。 API Gateway 可以作為唯一的入口，統一接收所有外部請求，再根據邏輯分派到不同服務，大幅簡化前端流程。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;2. 請求轉發與路由（Routing）&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;API Gateway 根據路由規則，把不同的 API 請求轉送到不同的服務：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;/auth/*&lt;/code&gt; → 身分驗證服務&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;/user/*&lt;/code&gt; → 使用者服務&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;/order/*&lt;/code&gt; → 訂單服務 這讓後端能保持乾淨、獨立且高度模組化。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;3. 安全管理（Authentication &amp;amp; Authorization）&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;API Gateway 可攔截請求並執行：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Token 驗證&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;API Key 驗證&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;OAuth 2.0 / JWT&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;IP 限制 這樣後端各服務就不用反覆實作相同的鑑權邏輯。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;4. 流量控制（Rate Limiting）&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;為防止惡意流量、暴力攻擊或大量請求壓垮服務，API Gateway 可提供：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;每秒請求上限&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;每 IP 限流&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;API 使用配額&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;全局流量管理&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;確保系統在高流量下依然穩定。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;5. 負載平衡（Load Balancing）&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;API Gateway 可以自動在多台服務間分配請求，提高：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;併發能力&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;穩定性&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;可用性&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;並能在某服務異常時自動切換節點。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;6. 日誌與監控（Logging &amp;amp; Monitoring）&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;API Gateway 是所有流量的第一站，可以統一記錄：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;API 使用率&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;回應時間&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;錯誤率&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;流量來源&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這些資訊對除錯與維運至關重要。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;二、API Gateway 的工作流程&lt;/strong&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;使用者從前端或客戶端發送請求&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;API Gateway 接收到請求&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;進行 Token 驗證、安全檢查、參數過濾等&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;根據路由規則分派到目標後端服務&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;後端回傳資料給 Gateway&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Gateway 進行格式處理或統一回應格式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;回傳給使用者&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;這讓整個系統的 API 行為更一致、更安全。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;三、常見的 API Gateway 功能模組&lt;/strong&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;認證模組&lt;/strong&gt;：處理身份與權限&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;路由模組&lt;/strong&gt;：決定請求的目標服務&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;緩存模組&lt;/strong&gt;：加速熱門 API 回應&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;流量管理模組&lt;/strong&gt;：限流、配額、排隊&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;轉換模組&lt;/strong&gt;：Header、Query、Body 格式調整&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;日誌模組&lt;/strong&gt;：統一記錄所有請求&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;監控模組&lt;/strong&gt;：提供圖表化統計&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;strong&gt;四、API Gateway 的常見架構模式&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;1. 單一 Gateway（最常見）&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;所有外部請求都通過同一個 API Gateway。 適合一般網站或小型微服務。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;2. 多層 Gateway（大型系統）&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;外部 Gateway：負責公開 API&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;內部 Gateway：負責服務間通訊 適合大型企業架構與高複雜度系統。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;3. Sidecar 模式（Service Mesh）&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;在 Istio 等 Service Mesh 中，API Gateway 的功能部分分散在各 Proxy 中，由 Mesh 控制中心統一配置。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;五、API Gateway 的優點與限制&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;優點&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;強化 API 安全性&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;提升架構清晰度&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;降低前端負擔&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;改善整體效能與容錯能力&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;API 一致化管理更加簡單&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;限制&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;增加系統複雜度&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;可能成為單點瓶頸（需搭配高可用部署）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;初期設定較繁瑣&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;高流量下需要搭配快取與分散部署&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;strong&gt;六、適合採用 API Gateway 的情況&lt;/strong&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;使用微服務架構&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;多端（Web、App、小程式）共用 API&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;系統需要統一流量管理&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;各系統團隊需要解耦&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;API 數量龐大並需要集中管理&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;strong&gt;七、總結&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;API Gateway 是現代系統的流量中樞，它統一管理安全、路由、流量、快取與監控，讓後端服務得以保持專注與模組化。雖然需要額外維運成本，但在中大型應用中，它能有效提升整體架構品質、可擴展性與可靠性。&lt;/p&gt;
&lt;p&gt;如果搭配負載平衡、快取與服務網格，它甚至能成為整個後端架構的主要控制中心，是現代雲端與微服務不可或缺的一環。&lt;/p&gt;
</content:encoded></item><item><title>Nginx 與 Apache 的差異分析：架構、效能與使用場景完整比較</title><link>https://kairo.qzz.io/posts/nginx-and-apache/</link><guid isPermaLink="true">https://kairo.qzz.io/posts/nginx-and-apache/</guid><description>這篇文將分析 Nginx 與 Apache 的差異。</description><pubDate>Wed, 26 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;&lt;strong&gt;Nginx 與 Apache 的差異分析：架構、效能與使用場景完整比較&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;Nginx 與 Apache 是兩大主流 Web 伺服器，雖然目的相同，但在架構設計、效能模式與使用場景上有明顯差異。理解兩者的特性，能讓你在建置服務時做出更合適的技術選擇。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;一、核心架構差異&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;Nginx：事件驅動、非阻塞架構&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Nginx 使用 event-driven 模型，一個 Worker Process 就能處理大量連線，並透過非阻塞 I/O 提高效率。 &lt;strong&gt;優勢：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;高併發處理能力&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;記憶體占用極低&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;高流量環境穩定性極佳&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;Apache：以進程／執行緒為中心的傳統架構&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Apache 提供 Prefork、Worker、Event 等 MPM，但本質仍偏向「一連線對一執行緒」。 &lt;strong&gt;缺點：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;高併發時資源消耗會快速上升&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;大量連線可能造成 CPU 或 RAM 壓力&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;strong&gt;二、效能與併發能力&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;Nginx&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;靜態檔案輸出速度極快&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;面對突發流量更穩定&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;適合作為反向代理、快取、負載平衡器&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;Apache&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;適合大量動態內容（尤其 PHP）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;透過 mod_php 部署相當直覺&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在舊系統、WordPress 佈建中相容性極高&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;strong&gt;三、設定彈性與架站習慣&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;Nginx&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;不支援 &lt;code&gt;.htaccess&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;所有設定集中在主設定檔，需 reload 才生效&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;適合團隊、容器化、標準化部署&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;Apache&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;支援 &lt;code&gt;.htaccess&lt;/code&gt;，可在每個目錄獨立設定&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;適合共享主機、舊式網站、頻繁修改設定的環境&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;小型站或不熟伺服器者更容易上手&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;strong&gt;四、使用場景建議&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;Nginx 適合：&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;高流量、高併發的網站&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;CDN、反向代理、API Gateway&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;微服務架構、Docker、K8s&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;大量靜態資源輸出的網站&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;Apache 適合：&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;PHP 為主的傳統架構&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;WordPress、Laravel 等依賴 &lt;code&gt;.htaccess&lt;/code&gt; 的系統&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;處理大量模組、複雜 Rewrite 規則的環境&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;strong&gt;五、總結&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Nginx 與 Apache 各有擅長領域，並不存在誰完全取代誰的問題。 &lt;strong&gt;Nginx&lt;/strong&gt; 強在效能、併發量與現代化架構； &lt;strong&gt;Apache&lt;/strong&gt; 強在相容性、動態內容處理與高度彈性設定。&lt;/p&gt;
&lt;p&gt;最好的做法，是根據專案類型而選擇使用何者，甚至在某些架構中，兩者可以同時存在並互補角色。&lt;/p&gt;
</content:encoded></item><item><title>資料庫索引是什麼？為什麼能讓查詢變快？</title><link>https://kairo.qzz.io/posts/what-is-database-index/</link><guid isPermaLink="true">https://kairo.qzz.io/posts/what-is-database-index/</guid><description>這篇將介紹資料庫索引是什麼以及有什麼用處！</description><pubDate>Mon, 24 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;資料庫索引是什麼？為什麼能讓查詢變快&lt;/h1&gt;
&lt;p&gt;在資料量變大之後，資料庫效能的關鍵往往不在硬體，而在「查詢怎麼做」。索引（Index）就是資料庫用來加速查詢的核心機制。如果沒有索引，資料庫幾乎只能一筆一筆掃描資料；有了索引，查詢速度可以從「秒級」直接降到「毫秒級」。&lt;/p&gt;
&lt;h2&gt;一、什麼是資料庫索引&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;資料庫索引&lt;/strong&gt;是一種額外建立的資料結構，用來快速定位資料在資料表中的位置。 它的本質不是資料本身，而是「資料的對照表」。&lt;/p&gt;
&lt;p&gt;可以把索引想成書本最後的目錄：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;書的內容 = 資料表（Table）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;章節與頁碼 = 索引&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;查頁碼 = 查詢資料&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果沒有目錄，你只能從第一頁一路翻到最後一頁；有目錄，你可以直接跳到指定頁數。&lt;/p&gt;
&lt;h2&gt;二、沒有索引時，資料庫怎麼查資料&lt;/h2&gt;
&lt;p&gt;假設有一個使用者資料表 &lt;code&gt;users&lt;/code&gt;：
&lt;code&gt;SELECT * FROM users WHERE email = &apos;test@example.com&apos;; &lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;沒有索引的情況&lt;/h3&gt;
&lt;p&gt;資料庫只能執行 &lt;strong&gt;全表掃描（Full Table Scan）&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;從第一筆資料開始&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;一筆一筆比對 &lt;code&gt;email&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;直到找到符合條件的資料或掃完整張表&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;時間複雜度接近 &lt;strong&gt;O(n)&lt;/strong&gt;，資料越多，查詢越慢。&lt;/p&gt;
&lt;h2&gt;三、有索引之後，查詢為什麼會變快&lt;/h2&gt;
&lt;h3&gt;1. 索引本身是有結構的&lt;/h3&gt;
&lt;p&gt;多數關聯式資料庫（MySQL、PostgreSQL）使用的索引結構是 &lt;strong&gt;B-Tree 或 B+Tree&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;B-Tree 的特性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;資料是排序過的&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;查詢時可以「一層一層縮小範圍」&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;時間複雜度接近 &lt;strong&gt;O(log n)&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這讓資料庫能快速定位資料位置，而不是全部掃過。&lt;/p&gt;
&lt;h3&gt;2. 索引的實際查詢流程&lt;/h3&gt;
&lt;p&gt;建立索引後：
&lt;code&gt;CREATE INDEX idx_users_email ON users(email); &lt;/code&gt;
查詢流程會變成：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;到索引樹中查找 &lt;code&gt;test@example.com&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;直接取得該值對應的資料位置（Row ID）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;依位置讀取資料&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;資料量越大，差距越明顯。&lt;/p&gt;
&lt;h2&gt;四、索引到底存了什麼&lt;/h2&gt;
&lt;p&gt;一個索引通常包含：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;索引欄位的值（如 email）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;對應資料列的位置（主鍵或指標）&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;索引不一定包含整筆資料&lt;/strong&gt;，而是「怎麼快速找到那筆資料」。&lt;/p&gt;
&lt;h2&gt;五、常見索引類型&lt;/h2&gt;
&lt;h3&gt;1. 主鍵索引（Primary Key Index）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;自動建立&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;唯一且不可為 NULL&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;查詢效率最高&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;PRIMARY KEY (id) &lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;2. 唯一索引（Unique Index）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;確保欄位值不重複&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;同時具備查詢加速功能&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;CREATE UNIQUE INDEX idx_users_email ON users(email); &lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;3. 一般索引（Non-Unique Index）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;最常見&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;可重複值&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;用於加速查詢&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;CREATE INDEX idx_users_name ON users(name); &lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;4. 複合索引（Composite Index）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;多個欄位組成&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;依「欄位順序」生效&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;CREATE INDEX idx_users_city_age ON users(city, age); &lt;/code&gt;
查詢生效：
&lt;code&gt;WHERE city = &apos;Taipei&apos; WHERE city = &apos;Taipei&apos; AND age = 18 &lt;/code&gt;
不生效：
&lt;code&gt;WHERE age = 18 &lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;六、索引為什麼不是越多越好&lt;/h2&gt;
&lt;p&gt;索引不是免費的。&lt;/p&gt;
&lt;h3&gt;1. 影響寫入效能&lt;/h3&gt;
&lt;p&gt;每次 &lt;code&gt;INSERT&lt;/code&gt;、&lt;code&gt;UPDATE&lt;/code&gt;、&lt;code&gt;DELETE&lt;/code&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;資料表要更新&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;所有相關索引也要更新&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;索引越多，寫入成本越高。&lt;/p&gt;
&lt;h3&gt;2. 佔用額外空間&lt;/h3&gt;
&lt;p&gt;索引本身是獨立的資料結構，會吃磁碟與記憶體。&lt;/p&gt;
&lt;h3&gt;3. 錯誤索引反而沒用&lt;/h3&gt;
&lt;p&gt;以下情況索引可能無法使用：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;對索引欄位使用函式&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;WHERE DATE(created_at) = &apos;2025-01-01&apos; &lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用前置萬用字元&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;WHERE name LIKE &apos;%abc&apos; &lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;資料選擇性太低（例如性別）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;七、什麼欄位適合建立索引&lt;/h2&gt;
&lt;p&gt;適合：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;常用於 &lt;code&gt;WHERE&lt;/code&gt; 條件&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;常用於 &lt;code&gt;JOIN&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;常用於 &lt;code&gt;ORDER BY&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;高選擇性（值分布廣）&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;不適合：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;經常變動的欄位&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;值種類很少的欄位&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;很少被查詢的欄位&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;八、索引與查詢優化的關係&lt;/h2&gt;
&lt;p&gt;索引只是查詢優化的一部分。&lt;/p&gt;
&lt;p&gt;良好的查詢效能還需要：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;合理的 SQL 寫法&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;避免不必要的 &lt;code&gt;SELECT *&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;善用 &lt;code&gt;EXPLAIN&lt;/code&gt; 查看查詢計畫&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;正確設計資料表結構&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;索引是工具，不是萬靈丹。&lt;/p&gt;
&lt;h2&gt;九、總結&lt;/h2&gt;
&lt;p&gt;資料庫索引的本質，是用空間換時間。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;沒索引 → 全表掃描 → 線性時間&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;有索引 → 樹狀結構 → 對數時間&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;索引用得好 → 查詢快數十倍&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;索引用錯 → 寫入變慢、空間浪費&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;理解索引的運作原理，才能在資料量成長時，讓系統依然保持穩定與高效。&lt;/p&gt;
</content:encoded></item><item><title>Lavalink 介紹與架設教學：完整技術指南</title><link>https://kairo.qzz.io/posts/introduction-to-lavalink/</link><guid isPermaLink="true">https://kairo.qzz.io/posts/introduction-to-lavalink/</guid><description>讓大家了解 Lavalink 是什麼以及教大家如何簡單部署</description><pubDate>Sun, 23 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;&lt;strong&gt;Lavalink 介紹與架設教學：完整技術指南&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;Lavalink 是一套高效能的音訊轉送與解碼系統，專門設計來處理 Discord Bot 的語音串流。它以獨立伺服器的形式運作，將音訊搜尋、解碼、回傳、狀態管理等高負載工作全部集中處理，避免 Bot 本體因大量運算而受到限制。對任何需要穩定音樂播放、低延遲音訊傳輸與高使用量負載的 Discord Bot 專案而言，Lavalink 幾乎是標準且必要的核心組件。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;一、Lavalink 的核心功能與架構概念&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Lavalink 建構於 WebSocket 與 REST API 之上，提供兩種主要的通信方式：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;REST API：&lt;/strong&gt; 用於搜尋音樂、取得資訊、加載音源。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;WebSocket：&lt;/strong&gt; 用於傳送播放狀態、事件、音訊控制命令等。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;它在整個音訊系統中扮演「集中式音訊工作站」的角色，Bot 只需送出指令，而整個音訊的技術流程都由 Lavalink 負責。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;主要處理內容包括：&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;音訊解碼（尤其是 YouTube、SoundCloud 等壓縮格式）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;音訊流式傳輸（Streaming）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;播放隊列管理&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;音訊事件回傳&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;多音源平台支援&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;連線重試、語音重連、失敗恢復&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這項架構在多 Bot、多伺服器、多語音頻道環境下具備極高穩定性。如果 Bot 在大量語音頻道播放音樂，Lavalink 可以輕鬆分攤高運算量，並同時處理數千條音訊流。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;二、Lavalink 的優勢與適用場景&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;1. 高效穩定的音訊處理能力&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Discord Bot 若自身處理 YouTube 或 SoundCloud 的音訊轉碼，會承受巨量 CPU 負載，而 Lavalink 以 Java 與 Lavaplayer 為基礎提供高效率解碼，顯著提升穩定性。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;2. 可水平擴充的架構&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;可部署多個 Lavalink 節點，並透過 Bot 的負載平衡策略進行調度，適合大型機器人與多地區音訊節點。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;3. 避免 Discord 的語音限制或延遲問題&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Lavalink 處理語音傳輸的重連與同步，降低 Bot 在流量高峰時遭遇語音 Channel 凍結或延遲的機率。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;4. 清晰的 API 與極高相容性&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;支援幾乎所有主流 Discord 音訊框架，例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Erela.js&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Poru&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Discord Player（部分版本）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Wavelink（Python）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Moonlink（JS）&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;strong&gt;三、架設 Lavalink 的系統需求&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;最低需求：&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Java 17 或以上&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;1GB RAM（建議 2GB）&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;能對外開放指定 Port 的伺服器（例如 2333）&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;建議系統：&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Ubuntu 20.04 / 22.04&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Debian 11 / 12&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;使用 systemd 運行守護程序&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;搭配 Nginx 進行反向代理與安全保護（可選）&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;strong&gt;四、下載並準備 Lavalink&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;從官方 GitHub Releases 下載最新版本的 Lavalink：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/lavalink-devs/Lavalink/releases&quot;&gt;https://github.com/lavalink-devs/Lavalink/releases&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;將 &lt;code&gt;Lavalink.jar&lt;/code&gt; 放在你的資料夾內，例如：
&lt;code&gt;/home/lavalink/ &lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;五、撰寫 application.yml（完整設定示範與解說）&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Lavalink 的運作完全依賴 &lt;code&gt;application.yml&lt;/code&gt;，以下是可直接使用的完整配置：
&lt;code&gt;server:   port: 2333 lavalink:   server:     password: &quot;yourStrongPassword&quot;     sources:       youtube: true       bandcamp: true       soundcloud: true       twitch: true       vimeo: true       http: true       local: false     bufferDurationMs: 400     frameBufferDurationMs: 5000     trackStuckThresholdMs: 10000     soundcloudClientId: null     youtubeConfig:       playlistLoadLimit: 6     ratelimit:       ipBlocks: []        strategy: RotateOnBan logging:   file:     path: ./logs/   level:     root: INFO     lavalink: INFO     lavaplayer: WARN &lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;關鍵設定解說&lt;/strong&gt;&lt;/h3&gt;
&lt;h4&gt;&lt;strong&gt;1. server.port&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Lavalink 對外提供服務的端口，預設為 2333。&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;2. password&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Bot 連線 WebSocket 時必須使用的密碼。 務必設定成複雜字串以避免被第三方占用。&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;3. sources&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;決定是否啟用各平台音源。 若不需要某些來源，可關閉以減少不必要的 API 操作。&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;4. bufferDurationMs / frameBufferDurationMs&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;影響音訊延遲與流暢度。 一般建議保持預設，除非遇到延遲問題再做調整。&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;5. logging&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;用來控制輸出日誌細節，多數情況下 INFO 足夠。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;六、啟動 Lavalink&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;在存放 jar 的目錄執行：
&lt;code&gt;java -jar Lavalink.jar &lt;/code&gt;
若看到：
&lt;code&gt;Started Launcher in X.XXX seconds &lt;/code&gt;
表示 Lavalink 已成功運行，並在指定 port 等待 Bot 的連線。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;七、Linux 伺服器必要設定：開放防火牆&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;如果使用 UFW（Ubuntu 常見）：
&lt;code&gt;sudo ufw allow 2333/tcp &lt;/code&gt;
確認：
&lt;code&gt;sudo ufw status &lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;八、建立 systemd 服務（正式部署必備）&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;創建：
&lt;code&gt;/etc/systemd/system/lavalink.service &lt;/code&gt;
內容：
&lt;code&gt;[Unit] Description=Lavalink Audio Node After=network.target  [Service] User=ubuntu WorkingDirectory=/home/lavalink ExecStart=/usr/bin/java -jar Lavalink.jar Restart=always RestartSec=10  [Install] WantedBy=multi-user.target &lt;/code&gt;
啟動：
&lt;code&gt;sudo systemctl enable lavalink sudo systemctl start lavalink &lt;/code&gt;
查看狀態：
&lt;code&gt;systemctl status lavalink &lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;九、在 Discord Bot 中串接 Lavalink（以 Erela.js 為例）&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;以下為 Node.js 的標準連線方式：
&lt;code&gt;const { Manager } = require(&quot;erela.js&quot;);  const manager = new Manager({   nodes: [     {       host: &quot;你的伺服器IP&quot;,       port: 2333,       password: &quot;yourStrongPassword&quot;,       secure: false     }   ],   send(id, payload) {     const guild = client.guilds.cache.get(id);     if (guild) guild.shard.send(payload);   } }); &lt;/code&gt;
只需改：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;host&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;port&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;password&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;即可成功連線 Lavalink。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;十、常見錯誤與技術排查&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;1. Unable to connect&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;檢查：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;密碼是否正確&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Port 是否開放&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;防火牆是否阻擋&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;SSL 是否被強制啟用&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;2. YouTube 加載失敗&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;可能原因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;IP 遭 YouTube 限制&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;使用公共 VPS 被風控&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;未啟用 youtube: true&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;未更新到最新版 Lavalink&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;3. 聲音延遲或卡頓&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;可調整：
&lt;code&gt;bufferDurationMs: 400 frameBufferDurationMs: 5000 &lt;/code&gt;
或提升 VPS 性能。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;十一、部署與架構建議&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;為確保長期穩定：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;每個 Bot 至少配置一個專用 Lavalink 節點&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;大型架構使用多節點分散流量&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;搭配 Nginx 與 IP 白名單保護通訊安全&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;使用 systemd 讓 Lavalink 自動重啟與守護&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;定期更新 JDK 與 Lavalink 版本&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;對於高使用量 Bot，建議採用歐洲或北美較穩定 VPS，並避免使用廉價共享主機。&lt;/p&gt;
&lt;h1&gt;&lt;strong&gt;結語&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;Lavalink 為 Discord 音樂系統提供高效、穩定、可擴充的音訊服務架構，透過集中式音訊解碼與 WebSocket 事件管理，大幅減輕 Bot 主程式的負擔。無論是單機個人 Bot 還是大型跨伺服器音樂平台，Lavalink 都能提供成熟可靠的音訊支援。透過正確配置 application.yml、建立 systemd 守護程序以及保持版本更新，即可建立穩定高效的音訊節點並投入正式運作。&lt;/p&gt;
</content:encoded></item><item><title>Nginx 反向代理的優缺點</title><link>https://kairo.qzz.io/posts/reverse-proxy/</link><guid isPermaLink="true">https://kairo.qzz.io/posts/reverse-proxy/</guid><description>帶你一起挖掘 Nginx 反向代理的優缺點。</description><pubDate>Sun, 23 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Nginx 反向代理的優缺點&lt;/h1&gt;
&lt;p&gt;**Nginx（Engine X）**長久以來被廣泛用作反向代理（reverse proxy）與負載平衡器。本文從原理、優點、缺點、實務考量與最佳實踐等面向做深入說明，並提供實用的設定範例與監控、調校建議，讓你在設計系統時能有清晰的判斷與可操作步驟。&lt;/p&gt;
&lt;h2&gt;一、什麼是反向代理（簡要原理）&lt;/h2&gt;
&lt;p&gt;反向代理是介於客戶端（瀏覽器、API 客戶端）與一或多個後端伺服器之間的伺服器。客戶端發送請求到反向代理，反向代理再將請求轉發（proxy）到內部的後端伺服器，將後端回應再返還給客戶端。對外表現為單一入口（single entry point），而內部可做路由、分流、快取、SSL 終止等功能。&lt;/p&gt;
&lt;p&gt;Nginx 的事件驅動模型（epoll/kqueue + 非阻塞 I/O）使其在高併發場景下表現優異，因此成為常見的反向代理選擇。&lt;/p&gt;
&lt;h2&gt;二、Nginx 做為反向代理的主要優點&lt;/h2&gt;
&lt;h3&gt;1. 高效能與高併發處理&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Nginx 採用非阻塞事件循環（event loop）與 worker-process 架構，善於處理大量短連線與高併發請求，能以較少資源維持高吞吐。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;對靜態資源、簡單代理請求的效能通常優於同功能的傳統阻塞式伺服器（例如舊版 Apache in prefork）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. 負載平衡（多種策略）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;支援輪詢（round-robin）、最少連線（least_conn）、IP hash、加權（weight）等策略。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;可搭配健康檢查（active/passive health checks）或第三方模組實現更精細的健康檢測（注意：部分健康檢查需商業或第三方模組）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. 快取（proxy_cache）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Nginx 支援 proxy_cache，可在反向代理層快取後端回應以減少後端負載、降低延遲。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;支援快取過期策略、快取鍵（cache key）自訂、快取控制標頭（Cache-Control、Expires）等。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. SSL/TLS 終止（SSL termination）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;反向代理可在前端終止 TLS，後端伺服器可用內部 HTTP 通信，減少後端負擔並統一證書管理。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;可配合 OCSP stapling、HTTP/2 與 TLS 參數調校提升安全性與效能。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;5. 安全性提升&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;可用作 Web Application Firewall（WAF）規則前置（例如 ModSecurity + nginx connector），過濾惡意請求、阻擋常見攻擊。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;隱藏後端 IP 與架構細節，降低直接攻擊後端的風險。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;支援 rate limiting、connection limiting、限制 request body 大小、限制 header 長度等防護措施。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;6. 請求路由與 URL 重寫&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;可以根據路徑、主機名稱、標頭，或正則式路由到不同後端服務，適合多服務或微服務架構。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;支援 rewrite、redirect 與 internal location 等機制來調整 URL 與路由邏輯。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;7. 動態擴展與灰度部署支援&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;搭配後端服務的動態註冊（如服務發現）與 Nginx 重載或 API（nginx-plus、有第三方模組）可無痛新增/移除後端進行滾動更新或灰度發布。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;配合 upstream 的權重可做流量分流，方便 A/B test 或漸進釋出。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;8. 支援多種協議與功能（WebSocket、gRPC、HTTP/2）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;新版 Nginx 支援 WebSocket proxy、HTTP/2、gRPC 等現代協議（在某些情況需啟用相應模組或編譯選項）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;能在反向代理層解決跨域、長連線代理等問題。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;9. 配置靈活且生態豐富&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Nginx 配置語法清晰，社群模組豐富（cache、auth、rewrite、lua 等）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;有 Nginx Plus（商業版）提供更多企業級特性，例如動態上游、活躍健康檢查、監控 API 等。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;三、Nginx 做為反向代理的主要缺點與限制&lt;/h2&gt;
&lt;h3&gt;1. 單點故障（Single Point of Failure）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;若只有一台 Nginx 作為反向代理，該節點故障則整個服務不可用。必須搭配多個反向代理節點與負載分擔（例如 DNS Round Robin、L4 負載均衡器、Anycast、云供應商的 Load Balancer）或 HA 解決方案（keepalived + VRRP）來避免單點故障。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. 配置錯誤風險高（安全與邏輯漏洞）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Nginx 配置錯誤（例如錯誤的 proxy_set_header、漏掉 proxy_redirect、緩存鍵設定不當）會導致安全風險（洩漏 headers、host header 欺騙）、緩存污染或功能錯誤。複雜路由/快取邏輯會增加維運難度。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. SSL/TLS 管理負擔&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;雖然 TLS 終止集中化方便，但證書數量多或需要自動更新（Let&apos;s Encrypt）時，仍需管理 ACME 自動化、Renew failure 的監控。大規模多域名（SNI）情況也需注意性能與記憶體消耗。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. 動態內容處理不是最佳場所&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Nginx 本身適合靜態與代理，對複雜動態處理（例如應用層邏輯、長時間運行的同步計算）仍應交給後端應用伺服器。若將過多邏輯塞在 Nginx（使用 Lua、embedded scripts）會增加複雜性與 debug 成本。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;5. WebSocket / 長連線限制與調校&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;雖然支援 WebSocket，但若未正確設定 proxy_buffering、timeout、keepalive 參數，會遭遇延遲、連線中斷或資源耗盡問題。長連線大量存在時，Nginx 要妥善調整 worker_connections、ulimit 等系統參數。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;6. 快取一致性與過期控制複雜&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;代理快取若未正確處理 Cache-Control、Vary、Cookie、副本失效（cache purge）等問題，會導致舊內容被回傳或不當的私人資料被快取。實務上需要設計快取鍵、過期策略與歸檔/失效機制（purge）來避免資料一致性風險。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;7. 資源瓶頸（記憶體與 I/O）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;在高吞吐且啟用大量緩存/SSL 的環境，Nginx 的記憶體與 I/O 使用會顯著上升。尤其是 proxy buffering 與 SSL session cache，需監控與調校。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;8. 監控與可觀測性較原始&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;開源 Nginx 的監控界面較簡陋（相比 nginx-plus 的 API），需要依靠日誌（access/error）、第三方 exporter（如 nginx-exporter）與外部監控系統（Prometheus/Grafana）來觀察狀況。排查問題時通常需要綜合 log 與 system metrics 分析。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;9. 部分進階功能需商業版或第三方模組&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;像動態 upstream（無需 reload）或高級健康檢查、基於指標的流量控制、API 可視化等功能在 Nginx 開源版有限，需要 Nginx Plus 或第三方模組來補足。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;四、常見實務情境（優缺點體現）&lt;/h2&gt;
&lt;h3&gt;情境 A：靜態站 + 高併發&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;優點：Nginx 能直接提供靜態檔案、使用 gzip、HTTP/2，大幅降低延遲與後端負載。proxy_cache 可減少動態請求，效能優。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;缺點：需設計正確的快取策略與 purge 流程。若缺乏 CDN，單機仍可能成為瓶頸。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;情境 B：微服務 API Gateway&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;優點：統一定義路由、認證、速率限制、SSL 終止，方便管理與安全性提升。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;缺點：API Gateway 會成為關鍵路徑，需要高可用設計與監控，配置錯誤會導致整體系統故障。部分高級流量控制可能需外部系統（如 envoy、kong）來補強。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;情境 C：WebSocket 即時應用&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;優點：Nginx 支援 proxying WebSocket，可以作為入口節點。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;缺點：需正確設定 proxy_buffering off、proxy_read_timeout 與系統資源，以免大量長連線造成 connection 泄漏或 worker 被阻塞。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;五、實用 Nginx 反向代理設定範例&lt;/h2&gt;
&lt;h3&gt;1. 最基本的反向代理&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;server {   listen 80;   server_name example.com;    location / {     proxy_pass http://127.0.0.1:8080;     proxy_set_header Host $host;     proxy_set_header X-Real-IP $remote_addr;     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;     proxy_set_header X-Forwarded-Proto $scheme;   } } &lt;/code&gt;
說明：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;proxy_set_header&lt;/code&gt; 保留原始 header 資訊給後端。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;proxy_pass&lt;/code&gt; 指向後端 HTTP 服務。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. 加入快取（proxy_cache）&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;  server {   listen 80;   server_name example.com;    location /api/ {     proxy_pass http://backend_pool;     proxy_cache my_cache;     proxy_cache_valid 200 302 10m;     proxy_cache_valid 404 1m;     proxy_cache_key &quot;$scheme$request_method$host$request_uri&quot;;     add_header X-Cache-Status $upstream_cache_status;     proxy_set_header Host $host;   } } &lt;/code&gt;
說明：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;proxy_cache_path&lt;/code&gt; 定義快取空間與大小。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;proxy_cache_key&lt;/code&gt; 自訂快取鍵避免衝突。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;add_header X-Cache-Status&lt;/code&gt; 可在回應看到命中情況（HIT/MISS/BYPASS）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. SSL 終止與反向代理&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;server {   listen 80;   server_name example.com;   return 301 https://$host$request_uri; }  server {   listen 443 ssl http2;   server_name example.com;    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;   ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;   ssl_protocols TLSv1.2 TLSv1.3;   ssl_ciphers HIGH:!aNULL:!MD5;   ssl_prefer_server_ciphers on;   ssl_session_cache shared:SSL:10m;   ssl_session_timeout 10m;    location / {     proxy_pass http://127.0.0.1:8080;     proxy_set_header Host $host;     proxy_set_header X-Forwarded-Proto https;     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;     proxy_buffering off;   } } &lt;/code&gt;
說明：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;TLS 終止在 Nginx；後端以 HTTP 溝通（或用內部 mTLS 若需保護）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;proxy_buffering off&lt;/code&gt; 若處理即時流或 SSE 可能需要關閉。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. 負載平衡（upstream）&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;upstream backend_pool {   least_conn;   server 10.0.0.11:8080 max_fails=3 fail_timeout=30s;   server 10.0.0.12:8080 max_fails=3 fail_timeout=30s;   server 10.0.0.13:8080 max_fails=3 fail_timeout=30s; }  server {   listen 80;   server_name api.example.com;    location / {     proxy_pass http://backend_pool;     proxy_set_header Host $host;     proxy_set_header X-Real-IP $remote_addr;   } } &lt;/code&gt;
說明：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;least_conn&lt;/code&gt; 讓連線較少的後端優先分配，適合長連線情況。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;5. WebSocket 代理&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;server {   listen 80;   server_name ws.example.com;    location /ws/ {     proxy_pass http://127.0.0.1:9000;     proxy_http_version 1.1;     proxy_set_header Upgrade $http_upgrade;     proxy_set_header Connection &quot;Upgrade&quot;;     proxy_set_header Host $host;     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;     proxy_read_timeout 3600s;     proxy_send_timeout 3600s;   } } &lt;/code&gt;
說明：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;必要的 &lt;code&gt;Upgrade&lt;/code&gt; 與 &lt;code&gt;Connection&lt;/code&gt; header 用於 WebSocket 握手。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;延長 timeout 以避免長連線被切斷。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;六、監控指標與調校建議&lt;/h2&gt;
&lt;h3&gt;監控指標（建議納入監控系統）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Nginx access log metrics：requests per second、4xx/5xx 比例、latency（request time）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Worker connections / active connections / accepted / handled。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;upstream 5xx、連線錯誤率。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;proxy_cache hit ratio。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;CPU、memory、network I/O、disk I/O（若使用本地 cache）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;SSL/TLS 鍵協商失敗率（handshake errors）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;系統層級：ulimit（open files）、file descriptors、tcp_tw_reuse、somaxconn。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;調校建議&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;worker_processes&lt;/code&gt; 設為 &lt;code&gt;auto&lt;/code&gt;（或等於 CPU 核心數），&lt;code&gt;worker_connections&lt;/code&gt; 設為能支撐的最大連線數。理論最大並發 = worker_processes × worker_connections。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;調整系統參數 &lt;code&gt;fs.file-max&lt;/code&gt;、&lt;code&gt;ulimit -n&lt;/code&gt;、&lt;code&gt;net.core.somaxconn&lt;/code&gt;、&lt;code&gt;net.ipv4.tcp_tw_reuse&lt;/code&gt; 等，以支援大量連線。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;若使用 proxy_cache，啟用 &lt;code&gt;use_temp_path=off&lt;/code&gt; 可以減少 I/O 頻繁操作（但視情況而定）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;SSL：啟用 HTTP/2、使用 Nagle 相關設置與 TLSv1.3 優先，並合理配置 session cache。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在 WebSocket 或長連線場景關閉 proxy_buffering。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;七、安全性最佳實踐（實務要點）&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;僅開必要的公開 port（80/443），後端服務放於私有網路或內網。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;統一在反向代理啟用 WAF 規則（或使用雲廠商的 DDoS 與 WAF）來過濾已知攻擊向量。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;強制 HTTPS，使用 HSTS（慎用，需確認配置正確再啟用）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;避免在快取中保存帶有敏感 Cookie 或 Authorization 的回應；使用 &lt;code&gt;proxy_cache_bypass&lt;/code&gt; 與 &lt;code&gt;proxy_set_header&lt;/code&gt; 控制快取行為。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;正確設定 &lt;code&gt;X-Forwarded-*&lt;/code&gt; headers，後端使用這些 header 來判斷原始客戶端資訊（並驗證其合理性）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;限制請求速率（rate limiting）與連線數保護（limit_req、limit_conn）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;定期更新 Nginx 與相關模組，避免已知漏洞。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;八、與其他代理/負載均衡器比較（簡述）&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;HAProxy&lt;/strong&gt;：在純 TCP/HTTP 負載平衡與高可用性場景，HAProxy 擅長低延遲、精細的負載策略與豐富的 health check，對 L4/L7 負載平衡非常成熟。Nginx 在靜態內容與反向代理 + web 服務整合上更方便。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Envoy&lt;/strong&gt;：現代化的代理，對微服務、可觀測性、動態路由、服務網格（service mesh）支持優秀；功能更現代但學習曲線與運維複雜度較高。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Apache httpd&lt;/strong&gt;：傳統 web server，模組豐富但在高併發情境通常不如 Nginx 高效，且配置風格與事件模型不同。 選擇依使用場景：需要高效靜態服務與簡單反向代理 → Nginx 非常合適；需要進階 L7 控制與服務網格功能 → Envoy 或其他解決方案可能更好；大量 TCP 負載均衡與精密健康檢查 → HAProxy 是強項。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;九、總結與決策要點&lt;/h2&gt;
&lt;h3&gt;適合使用 Nginx 反向代理的場景&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;需要高效處理大量短連線與靜態資源的系統。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;需要集中進行 TLS 終止、統一安全策略、速率限制、簡單的負載平衡與快取。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;希望用較低資源達到高效能（尤其是與 proxy_cache 結合）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;需謹慎評估的點（或考慮替代方案）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;若反向代理承擔多項企業級流量控制與動態 upstream 管理，且需無縫動態調整，可能需要 Nginx Plus 或 Envoy、Kong 等更專業方案。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;長連線或大量 WebSocket 時需特別調校或考慮專門的即時通訊架構（如基於專門的長連線伺服器或使用 L4 負載均衡）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;若系統要求極高的可用性，必須設計多個反向代理節點與高可用（VRRP、雲端 LB）層級來避免單點故障。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;十、實務檢查清單（部署前後）&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;部署前&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;檢查 proxy headers（Host、X-Real-IP、X-Forwarded-For）是否正確傳遞。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;設計好快取鍵、快取失效（purge）策略與敏感資訊過濾。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;設定 TLS 與憑證自動續期機制（Let&apos;s Encrypt + Certbot / ACME 客戶端）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;設定基本 rate limit、conn limit、防止 DOS。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;部署後&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;監控：Requests/s、Latency、5xx rate、cache hit rate、worker connections。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;壓力測試（非生產）驗證設定（慢查、突發流量、長連線模擬）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;定期審視 access / error log，設定 alert（5xx 爆、cache hit 下降、TLS handshake error 上升等）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以上是針對 &lt;strong&gt;Nginx 作為反向代理&lt;/strong&gt; 的全面說明：原理、優勢、潛在缺點、實戰設定、調校與監控要點，以及與其他方案的比較。依照你的實際需求（例如是否需大量長連線、是否重度依賴快取、是否要求零停機動態配置），可以決定採用 Nginx 開源版、Nginx Plus 或其它代理解決方案。若需要，我可以直接幫你產生針對你的流量模型的 Nginx 參數建議（worker/connection、proxy_buffer、ssl 設定、cache 大小）與壓力測試腳本。&lt;/p&gt;
</content:encoded></item><item><title>從零開始：做出你的第一個網頁</title><link>https://kairo.qzz.io/posts/create-first-web/</link><guid isPermaLink="true">https://kairo.qzz.io/posts/create-first-web/</guid><description>教你如何簡單的做出一個自己的網頁</description><pubDate>Sun, 23 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;《從零開始：做出你的第一個網頁》&lt;/h1&gt;
&lt;p&gt;如果你完全沒有寫過網頁，別緊張 —— 做出你的第一個網站其實比想像中更簡單。你只需要一個資料夾，再新增一個叫做 index.html 的檔案，然後把下面這段程式碼貼進去，立刻就能看到你的第一個網頁誕生。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
    &amp;lt;title&amp;gt;我的第一個網頁&amp;lt;/title&amp;gt;
    &amp;lt;style&amp;gt;
      body {
        font-family: sans-serif;
        padding: 40px;
      }
      h1 {
        color: #333;
      }
    &amp;lt;/style&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;哈囉，世界！&amp;lt;/h1&amp;gt;
    &amp;lt;p&amp;gt;這是我做出的第一個網頁。&amp;lt;/p&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h1&gt;每一段程式碼在做什麼？&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;它的作用只有一句話：
➡️ 告訴瀏覽器這是一份 HTML5 文件。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;沒有它瀏覽器也能開，但可能用較舊的模式解析，導致跑版或怪怪的行為。&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;：整個網頁的最外層&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;所有內容都包在 &lt;code&gt;&amp;lt;html&amp;gt; ... &amp;lt;/html&amp;gt;&lt;/code&gt; 裡。
可以把它想成網站的整個房子外框。&lt;/p&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;：放設定、不會直接顯示&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;裡面有幾個重要的小設定：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;&lt;/code&gt;
避免中文顯示成亂碼。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt;
控制瀏覽器分頁（tab）的名稱。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt;
這是 CSS，它負責調整網頁的外觀。例如：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;body {
  font-family: sans-serif;
  padding: 40px;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;讓整體字體更自然、頁面四周有舒服的留白。
h1 的深灰色也是在這裡設定：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;h1 {
  color: #333;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt;：真正會顯示的內容&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;所有使用者看得到的文字、圖片、按鈕都放在這裡：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;h1&amp;gt;哈囉，世界！&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;這是我做出的第一個網頁。&amp;lt;/p&amp;gt;

&amp;lt;h1&amp;gt; 是主標題，&amp;lt;p&amp;gt; 是一般文字段落。
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h1&gt;如何查看你的網頁？&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;存檔。&lt;/li&gt;
&lt;li&gt;在資料夾裡找到 index.html。&lt;/li&gt;
&lt;li&gt;直接雙擊它。&lt;/li&gt;
&lt;li&gt;瀏覽器就會把你的作品開起來。✨&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;你第一個網頁就這樣完成了。&lt;/strong&gt;&lt;/em&gt;
沒有框架、沒有工具，只靠一個檔案就能開始 —— 超純粹、超經典。&lt;/p&gt;
</content:encoded></item><item><title>歡迎來到我的博客</title><link>https://kairo.qzz.io/posts/welcome/</link><guid isPermaLink="true">https://kairo.qzz.io/posts/welcome/</guid><description>這裡是我的新博客！</description><pubDate>Sat, 22 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;你好！&lt;/h1&gt;
&lt;h2&gt;這裡是我的新博客2.0！&lt;/h2&gt;
&lt;h1&gt;這裡即將發布新文章！&lt;/h1&gt;
&lt;h1&gt;盡請期待哦！🤓👍&lt;/h1&gt;
</content:encoded></item></channel></rss>