效能、可靠性、安全性——技術品質的硬指標

一句話總結:使用者看不見你的程式碼,但他們感受得到你的效能、可靠性和安全性。這些是「看起來能用」和「真正好用」之間的鴻溝。

結論先講:技術品質不是工程師的自嗨指標。效能差使用者會離開,可靠性差使用者會不信任,安全性差使用者的資料會外洩。這三個做不好,其他做再好也沒用。

效能:100 毫秒和 10 秒之間的世界

效能不是技術 KPI,是使用者體驗的一部分。研究反覆證實:

  • 100ms 以內:使用者覺得是「即時」的
  • 100ms - 1s:有點延遲,但可接受
  • 1s - 10s:流暢感消失,需要進度指示
  • 超過 10s:使用者離開

你可能覺得「我的 API 回應時間才 2 秒,還好吧?」不好。2 秒在使用者感知裡已經是「這東西有點慢」。加上網路延遲、前端渲染,使用者實際等待時間可能接近 4 秒。

「看起來能用」和「真正好用」的差距:

指標「看起來能用」「真正好用」
首次內容繪製(FCP)< 5s< 1.5s
最大內容繪製(LCP)< 4s< 2.5s
首次輸入延遲(FID)< 300ms< 100ms
累積版面位移(CLS)< 0.25< 0.1
API P95 回應時間< 3s< 500ms
API P99 回應時間< 10s< 1s

看到了嗎?差距不是一點半點,是好幾倍。而且注意,要看 P95 和 P99,不是平均值。平均值是最會騙人的指標——你的平均回應時間 200ms,但如果 1% 的請求要 15 秒,那 1% 的使用者每次都會想摔手機。

可靠性:系統不掛比什麼都重要

可靠性衡量的是系統在各種條件下持續正常運作的能力。你的功能再強大,掛了就什麼都不是。

指標「能用」「好用」「出色」
Uptime95%(每月 36 小時停機)99.9%(每月 43 分鐘)99.99%(每月 4.3 分鐘)
Error Rate< 5%< 0.5%< 0.1%
MTTR< 24 小時< 1 小時< 15 分鐘
MTBF> 1 天> 30 天> 90 天

95% 的 Uptime 聽起來不錯?每個月停機 36 小時。換算一下,大概每天都會掛一個多小時。你的使用者一定會崩潰。

可靠性的問題通常出在「沒有防禦性程式設計」。你的 API 呼叫沒有 retry、沒有 timeout、沒有 circuit breaker。外部服務一掛,你的服務跟著掛。

// 沒有防禦——外部服務一慢你就跟著慢
async function fetchUserData(userId) {
  const response = await fetch(`/api/users/${userId}`);
  return response.json();
}
 
// 有防禦——timeout + retry + exponential backoff
async function fetchUserData(userId, { maxRetries = 3, timeoutMs = 5000 } = {}) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const controller = new AbortController();
      const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
      const response = await fetch(`/api/users/${userId}`, {
        signal: controller.signal,
      });
      clearTimeout(timeoutId);
      if (!response.ok) throw new Error(`HTTP ${response.status}`);
      return response.json();
    } catch (error) {
      if (attempt === maxRetries) {
        logger.error('Failed after retries', { userId, attempts: maxRetries });
        throw error;
      }
      await sleep(Math.pow(2, attempt) * 100); // exponential backoff
    }
  }
}

第一種寫法三行搞定,看起來很簡潔。第二種寫法多了十幾行。但第一種在生產環境會讓你半夜被叫起來,第二種不會。你選哪個?

安全性:不是事後加的功能

安全性不是「功能做完了再來補」的東西。它是產品品質的基本要求。你不會蓋完一棟大樓再來裝門鎖吧?

OWASP Top 10 對應的最低要求:

風險你至少要做到
Injectionparameterized query / ORM,絕不拼接 SQL
Broken Authentication密碼 bcrypt 雜湊、JWT 有過期時間、支援 MFA
Sensitive Data ExposureHTTPS everywhere、敏感資料加密、log 不記錄 PII
Broken Access Control每個 API 端點都有權限檢查,不只靠前端隱藏按鈕
Security Misconfiguration關閉 debug mode、移除預設帳號、定期更新依賴
XSS輸出編碼、CSP header、避免 innerHTML
Known Vulnerabilities定期跑 npm audit / snyk test

「靠前端隱藏按鈕」這件事我要特別講。我見過太多系統,管理員功能只是前端把按鈕藏起來,API 端點完全沒有權限檢查。你用 curl 打一下就能做任何事。這不是安全,這是自欺欺人。

可擴展性:現在不需要,但改動成本有多大?

可擴展性不是「現在就要能撐百萬用戶」,而是「未來需要的時候,改動的成本有多大」。

擴展方式做法優點缺點
垂直擴展(Scale Up)升級硬體簡單、不用改架構有上限、成本指數增長
水平擴展(Scale Out)增加實例理論上無上限需要無狀態設計

設計時就該問自己這些問題:

  • Session:存在 server memory 裡?還是 Redis?前者無法水平擴展
  • 檔案:存在 local disk?還是 S3?前者加機器時檔案不會跟著走
  • 背景任務:在 API server 裡跑?還是有獨立 worker?前者會阻塞 API 請求
  • 資料庫:有 connection pool 嗎?有讀寫分離嗎?

你不需要現在就做到所有這些。但你需要知道:如果現在 session 存在 memory 裡,哪天要水平擴展的時候,你要改的東西會有多少?如果答案是「需要重寫整個認證模組」,那你可能要提前想一想。

這篇的重點回顧

技術品質有四個面向:效能(使用者能感知的速度)、可靠性(系統不掛的能力)、安全性(基本衛生要求)、可擴展性(未來變更的成本)。不要追求完美,但要知道底線在哪裡。

系列文章:

「效能優化跟減肥一樣——量之前你永遠覺得自己還可以。」