API Migration 上線與剩餘 API 盤點計畫

更新日期:2026-08-03

目標

這份計畫要回答四個問題:

  1. getlancer legacy 一共有多少支公開 API?
  2. 多少已存在於 pro360_api_82,而且 production 流量真的已導向新機器?
  3. 還有多少正在被正式環境呼叫、但尚未搬移?
  4. 哪些 legacy API 長期沒有流量,可以評估不搬?

第一輪 30 天盤點已完成,結果與限制見:

完成後應留下:

evidence/YYYY-MM-DD/
├── production_lb_rules.json       # 原始檔不進 git
├── staging_lb_rules.json          # 原始檔不進 git
├── legacy_api_inventory.csv
├── new_api_inventory.csv
├── api_gap_inventory.csv
├── production_traffic.csv
├── lb_route_inventory.csv
└── rollout_batches.md

判斷模型

Legacy/New 程式盤點 ──確認 endpoint 是否存在、route 是否相容

Load Balancer rules ──確認目前實際導向 legacy 或 PHP 8.2 target group

Production ALB logs ──確認呼叫量、最後呼叫時間、狀態碼與實際 target group

Postman + Web/App ────確認 response contract 與真實使用者流程

LB 規則只能說明「符合某條規則後送去哪裡」,不能單獨列出 catch-all 規則底下的所有 API;完整盤點必須同時對照程式 route 與 production access log。

一、匯出 production 與 staging Load Balancer

環境必須分開保存

項目ProductionStaging
Hostapi.pro360.com.twapi-staging.pro360.com.tw
ALBpro360-apiALB-PRO360-Staging
ALB resource idapp/pro360-api/d3898ad14c394f67app/ALB-PRO360-Staging/22d9e3275ff14d23
Legacy target grouppro360-getlancer-target-groupstaging-php7
PHP 8.2 target groupec2-pro360-api-prod-php8pro360-api-staging-php82
Default actionpro360-getlancer-target-groupTG-PRO360-Staging
Access log S3 prefixs3://pro360-alb-logs/web/待獨立確認

不要直接把 staging 的 ARN、rule priority 或 target group 複製到 production。ALB listener rule 依 priority 由小到大比對,精確 endpoint rule 必須排在 catch-all/default rule 之前。

執行文件

實際指令、變數意義、輸出檔案與逐步確認方式獨立放在:

先逐段執行 production,再更換 profile/ALB name 另跑 staging。這些指令不修改 AWS,但會在本機建立或覆蓋 JSON;原始檔可能包含 ARN、內部 IP 與環境資訊,不放進共用 git。

二、列出 getlancer 有、pro360_api 沒有的 API

Legacy inventory

不能只找 controller method。至少盤點:

  • CakePHP routes、plugin routes 與 convention route。
  • 對外 public controller actions,排除 admin/internal-only method。
  • .json、REST helper、webhook、callback 與 cron 入口。
  • umbrella endpoint 依實際 actionfiltertype 或 routing key 拆開。

每筆標準化為:

HTTP method + normalized path + behavior-changing named parameters

動態 id 統一成 {id}、移除純追蹤 query string;會改變行為的 named parameter 不可移除。

New inventory

盤點 pro360_api_82 的:

  • Endpoint method。
  • Route mapping。
  • Origin/File fallback 與實際可到達的 URL。

只有 method、但 production/staging URL 無法 route 到它,也算尚未完成。

狀態分類

狀態意義
MIGRATED_LIVE新程式存在,production LB 已導入且有驗證證據
MIGRATED_NOT_LIVE新程式存在,但 production 尚未導入
LEGACY_ACTIVE_GAPproduction 仍有流量,新程式缺少或 route 不相容
LEGACY_DORMANT_CANDIDATE觀察期零流量,待確認是否可不搬
NO_MIGRATION_APPROVEDreviewer/product 已明確同意不搬
NEW_METHOD_ROUTE_GAPnew method 已寫,但外部 route 到不了
OUT_OF_SCOPE非公開 API,例如管理或純內部入口;需註明理由

api_gap_inventory.csv 至少要有:

method,path,legacy_source,new_source,current_target_group,
calls_7d,calls_30d,calls_90d,last_seen,status,owner,decision_note

三、用 production ALB logs 計算正式呼叫量

應分析「進入分流前」的 production ALB access log,不只看單台 legacy Apache/Nginx log。ALB log 可提供 request URL、target group ARN、matched rule priority、狀態碼與處理時間。

現有 Endpoint/V1/In.php::load_api_logs() / ApiMonitorHelper 可作為 parser 參考,但目前有兩個限制:

  • S3 prefix 寫死在特定日期。
  • 匯入前會刪除 alb_log2s 指定時間範圍資料。

因此不要直接用原方法跑全 production 盤點。先做參數化、唯讀 importer,或以 Athena external table 查 S3 原始 log。

完整權限、建表、查詢、匯出、成本控制與錯誤排查見:

每支 API 要統計

  • 7 / 30 / 90 天 business request 數。
  • OPTIONS 數量另列,不混入主要呼叫量。
  • 最後呼叫時間。
  • 2xx / 4xx / 5xx 分布。
  • peak requests/min、RPS、p50 / p95 / p99 latency。
  • caller:Web、iOS、Android、internal/unknown。
  • 實際 target group 與 matched rule priority。

ALB access log 是 best-effort delivery,所以「90 天為 0」只能標為 LEGACY_DORMANT_CANDIDATE,還要檢查:

  • 是否有繞過此 ALB 的內網/direct call。
  • webhook、callback、cron 或 queue consumer。
  • 舊版 App 或季節性功能。
  • URL normalization 是否把不同 endpoint 錯誤合併。

參考:ALB access logs

核心數字

Code gap
= legacy 公開 API 總數
- route 相容的新 API
- 已核准不搬的 API
 
Active gap
= status = LEGACY_ACTIVE_GAP 的 API 數
 
Traffic coverage
= 已送到 PHP 8.2 的 production business requests
/ 全部 production business API requests

2026-08-03 已完成 Production ALB logs 2026-06-042026-08-02 UTC 的 60 天重跑。以下目前狀態取最近完整 30 天,並排除 HEAD 探測與 malformed path:

指標結果
可操作的 GET/POST/DELETE endpoint 組153
新程式存在,正式已切62;parity 另驗
指定 API Key 走 PHP 8,其餘走 Legacy(搬移中)1
新程式存在但正式仍走 Legacy59
新程式缺少且正式有流量30
已走新 target,但 route/method 待確認1
尚未全部走 PHP 890
排除的 HEAD/malformed 組45/1

完整口徑與證據見 2026-08-03 Production API 60 天盤點。7/28 的 90 天零流量候選仍保留為歷史 snapshot,未用本次 60 天資料改寫。

90 組尚未全走 PHP 8 的 API 已依 caller、使用流程、side effect 與 rollback 範圍分為 22 批;只先建立 B001 的詳細 QA 文件,其餘批次目前只保留範圍。見 PHP 8 API 搬移批次

route/method 存在不等於 migration 完成;response、DB write、log、queue、header、cookie 與 side effect 仍要逐支完成 legacy parity 驗證。

四、Postman 結合 Web / App 實際操作

Postman 用來保存可重複的 API contract/regression test;Web/App 實際操作用來證明真實 caller、headers、request body、route 與畫面流程。兩者不能互相取代。

建立可重複測試

  1. 在 staging 操作真實 Web 或 App。
  2. Web 從 DevTools Network 選 request,使用 Copy as cURL
  3. App 可在已授權的 staging 使用 Charles/Proxyman;若 TLS pinning 無法攔截,改用 App debug log 與 server access log,不繞過 production 安全限制。
  4. 在 Postman 使用 Import → Raw text 匯入 cURL。
  5. 把環境相關值改成變數:
{{base_url}}
{{api_key}}
{{session_token}}
{{quote_bid_id}}

建立兩個 environment:

  • pro360-staging:允許經審查的資料異動測試。
  • pro360-production-smoke:只允許已確認安全的 read-only / idempotent smoke test。

API key、session token、password、id_token、Authorization 與 cookie 不可寫進文件、collection 或共用 environment;只放 local value、Postman Vault 或團隊核准的 secret storage。

參考:Postman 匯入 cURLenvironment variables

Collection 結構

每支 API 至少包含:

API name/
├── Happy path
├── Missing or invalid input
├── Owner / non-owner
├── Duplicate / retry
├── Legacy baseline vs new staging
└── Production smoke(安全時才建立)

回應測試不能只確認 HTTP 200 或 error = 0,還要驗證 response shape、欄位型別與不應多出的欄位:

pm.test('HTTP 200', () => pm.response.to.have.status(200));
 
const body = pm.response.json();
 
pm.test('legacy response shape and types', () => {
  pm.expect(body).to.be.an('array');
  pm.expect(body[0]).to.have.keys([
    'QuoteService',
    'QuoteFeedback',
    'QuoteBid',
    'QuoteFeedbackComment',
    'FeedbackAttachment'
  ]);
  pm.expect(body[0].QuoteFeedback.id).to.be.a('string');
});

依 endpoint 再驗證 headers、cookie、error shape、排序、空陣列/null 與 legacy 不回傳的欄位。可用 Collection Runner 搭配 CSV/JSON data 測多組 id、sort 與 guard input;production 不跑大量或會寫 DB 的 runner。

參考:Postman test scriptspm.response reference

回到真實前端 / App 驗證

每個 caller 平台都要獨立留下證據,不能因 Web 成功就推論 iOS/Android 也成功:

  1. 操作前 snapshot 相關 DB、queue 與 application log。
  2. 從 Web/iOS/Android 完成一次真實操作。
  3. 由 Network/server access log 確認 method、path、request 與 response。
  4. 用 ALB log/header 確認實際命中新 PHP 8.2 target group。
  5. 確認 UI 狀態與 response contract。
  6. 查 DB write、activity、transaction、queue/log、notification 等 side effects。
  7. reload 或重試一次,確認 duplicate/retry 行為與 legacy 一致。
  8. 還原 staging 測試資料。

每支 API 維護驗證矩陣:

APIPostmanWebiOSAndroidDBQueue/LogProd smoke
{method} {path}待測待測/N/A待測/N/A待測/N/A待測待測待測/N/A

N/A 必須寫理由,例如該功能只有 Web caller。

五、每批 API 的切換流程

Staging

  1. 先保存 LB rules、target health 與部署 config snapshot。
  2. 加入精確 host/path rule,導向 PHP 8.2 staging target group。
  3. 跑 PHPUnit、legacy baseline、Postman collection 與實際 Web/App flow。
  4. 比對 response、DB、queue/log、cookie/header、config 與 error path。
  5. 保存測試 id、時間、response 與 side-effect 證據。

Production

  1. 確認 target health、deployment config、dashboard 與 rollback action。
  2. 保存變更前 LB rules。
  3. 使用精確 endpoint path 切換,不先改 broad catch-all。
  4. 執行安全 smoke test,並確認請求命中新 target group。
  5. 監看 30–60 分鐘,再觀察 24 小時的流量、latency、4xx/5xx 與 application log。
  6. 確認穩定後更新 MIGRATED_LIVE 與 production evidence。

Rollback 必須是可立即恢復到原 legacy target group 的已審查 LB action。若使用 weighted target groups,不能假設某一 target group unhealthy 時 ALB 會自動把權重轉給另一組;切換前必須有監控與人工/自動 rollback 設計。

參考:ALB weighted forward actions

六、何時需要增加新機器

不能用「已搬幾支 API」判斷機器數量,要以 peak load 與單機安全容量計算:

Projected peak RPS
= 目前 PHP 8.2 peak RPS
+ 下一批 endpoint 在相同尖峰時段的 legacy peak RPS
 
Required capacity
= Projected peak RPS × headroom
/ 單台經壓測確認的 safe RPS

切換前確認:

  • Auto Scaling Group 是否可直接擴容;優先使用既有 ASG,不先手動建立孤立 EC2。
  • 各 AZ 至少有健康 target,且能承受一台故障。
  • CPU、memory、PHP-FPM workers、DB connections、network。
  • ALB RequestCountTargetResponseTimeHTTPCode_Target_5XX_CountHealthyHostCount
  • queue worker、Redis、DB 與外部服務是否也會成為瓶頸。

可先用 30% headroom 當討論起點,實際門檻仍要由壓測與 production baseline 決定。若下一批預估流量會吃掉安全餘裕,或任一 instance 故障後無法承受 projected peak,就在切換前擴容。

參考:ALB CloudWatch metrics

七、執行順序

  1. 取得 AWS read-only 權限。
  2. 匯出 production/staging ALB、listener、rules、target groups 與 access-log 設定。
  3. 產生 legacy/new 全量 API inventory。
  4. 查 90 天 production ALB log,normalize method/path 並統計流量。
  5. 合併成 api_gap_inventory.csv,取得可信的剩餘數量。
  6. 從真實 Web/App request 建 Postman collection 與驗證矩陣。
  7. 以「正式流量 × parity/side-effect 風險」安排 rollout batches。
  8. 建立 PHP 8.2 單機容量 baseline,判斷是否先擴容。
  9. 每批依 staging → production → 監控 → 文件更新完成切換。

第一個實際工作不是修改 LB,而是先完成 production/staging LB 唯讀快照 + 90 天 API inventory。這兩份證據完成後,才能回答還剩多少 API、哪些已無流量,以及下一批是否需要增加機器。