系列:30 天用 Google AI 打造臺灣防災速報 App(Day 28/30)
後端 9/25 上線,到今天兩週多。今天算兩件事:錢花在哪裡,以及怎麼防止服務被濫用。費用用帳單的實際數字;資安只寫已經做好的部分,限流門檻這類可能幫到攻擊者的細節不公開。
帳單匯出到 BigQuery,用 SQL 依服務和日期加總。下面是 10/1 到 10/9 這個專案的金額。帳單以新臺幣計,美元用帳單欄位裡的匯率平均值 31.775 換算。
| 用途 | 新臺幣 | 約美元 |
|---|---|---|
| Demo 影片製作(影片、圖片、配樂、語音) | 555.92 | 17.49 |
| 評測與本機測試(Day 27 的評審模型等) | 48.99 | 1.54 |
| App:Gemini(含本機測試) | 46.11 | 1.45 |
| App:Cloud Functions(五支函式) | 11.21 | 0.35 |
| App:Cloud DNS | 1.21 | 0.04 |
| App:Firestore、Hosting、Scheduler、Secret Manager 等 12 項 | 0 | 0 |
目前帳單由試用抵免額抵掉。這篇算的是用量本身的金額。
gemini_usage.py 把正式函式日誌記下的 token 數乘上官方單價。10/1 到 10/9 每天 0.0068 到 0.168 美元,合計 0.527 美元;帳單上 App 的 Gemini 1.45 美元,其餘約 0.9 美元是本機測試。
| 項目 | 10/1–10/9(9 天) | 換算 30 天 |
|---|---|---|
| Gemini(日誌估算) | 0.53 美元 | 約 1.8 美元 |
| Cloud Functions | 0.35 美元 | 約 1.2 美元 |
| Cloud DNS | 0.04 美元 | 約 0.1 美元 |
| 合計 | 約 0.92 美元 | 約 3.1 美元 |
這個數字不含網域年費(攤到每月約 1 美元)和開發測試。這段期間使用者很少,正式上架後用量會增加。
meta/quake_status 只在有新地震、剛恢復或滿 10 分鐘時寫。App 監聽這份文件,每寫一次,每個監聽中的 App 就多一次讀取。用量檢查。 本機排程每天 09:00 跑 gemini_usage.py,統計前一天正式環境的 Gemini 呼叫數、token、推估花費和錯誤碼。另外檢查:出現 402(預付餘額不足)或餘額撐不到 3 天、外語回答殘留民國年、錯字校正逾時率超過 5%。任一項成立就寄示警信給我。
App Check 統計。 appcheck_monitor.py 依函式、用戶端和 HTTP 狀態統計最近 3 小時的請求,加上 Firestore 的驗證結果和 reCAPTCHA 評估;網頁版被擋超過 2% 就通知。
排程紀錄。 10/1 到 10/9 每天示警 144 輪、地震 720 輪都有執行,10/10 上午也沒有漏跑。沒有漏跑只代表每一輪都有跑,錯誤另外算:10/10 09:30 之前有 6 輪以錯誤結束,原因是連 NCDR 或中央氣象署逾時,以及 NCDR 回 429,都在下一輪自動恢復。9/25 到 9/30 的 4 輪 Day 21 寫過。
以下是臺灣時間。
poll_alerts 一再以錯誤結束,原因都是 NCDR 回 429 Too Many Requests,到 11:10 共 9 輪失敗。本機實測也一樣:連續兩次請求,第二次就被擋。meta/sync_status 記下失敗,App 顯示同步失敗,最後一次成功是 10:50。推播和既有的示警不受影響。11 點多部署修正:
Retry-After 就照它,上限 30 秒;整輪總時間 75 秒內。本機實測 429 後等 25 秒,成功抓到 182 筆。3-59/10)。修正後的 11:23、11:33 兩輪都正常,沒有觸發重試,同步狀態恢復。之後再遇到 429,日誌會記一筆 ncdr_retry,只記狀態碼、等待秒數和第幾次,用來統計重試頻率。
程式裡依平台設定:Android 正式版用 Play Integrity,網頁版用 reCAPTCHA Enterprise,除錯版用 debug provider;iOS 正式版設定為 App Attest,要等 Apple 開發者帳號核准後才會實際用到。10/4 起問答 ask 和回報 report_answer 強制 App Check,不帶權杖回 401;10/7 起 Firestore 也強制。
開強制前,先查清無效權杖的來源:模擬器上的 profile 版、背景沒關的本機測試頁,都是開發流量。Firestore 強制後 24 小時的統計:Android 481 筆、iOS 184 筆、網頁 86 筆請求都通過,被拒的 29 筆全是開發測試和後端自測。
權杖到期不會自己換新。 實測時,權杖到期後 Android 約 35 分鐘、iOS 超過 13 分鐘都是無效狀態。修法是開啟 SDK 的自動換新,再加上到期前 10 分鐘主動換新並讓 Firestore 重連;行動版和網頁版(背景分頁)都改了。修正後連續 85 分鐘前景驗證,無效 0 次。
alerts、history、earthquakes、meta 公開可讀;寫入一律拒絕,只有後端用 Admin SDK 寫;其他集合讀寫全拒,內部資料用戶端讀不到。Retry-After 並設總時間上限,排程錯開整十分。明天 Day 29:成果展示與上架進度。