iT邦幫忙

2025 iThome 鐵人賽

DAY 16
0
自我挑戰組

IT工具與自我學IT的過程分享系列 第 16

Day 7|升級路線圖與壓軸總整理(附部署檔清單)

  • 分享至 

  • xImage
  •  

Day 7|升級路線圖與壓軸總整理(附部署檔清單)

把「能用」升級成「耐用、好維運、可擴充」;今天一次幫你收尾打包 ✅

這篇是系列最終回:把前面 Day 1–6 的重點串起來,給你一條龍的部署 runbook升級 Roadmap、以及實用檔案清單(Dockerfile / requirements.txt / .env / gcloud 指令)。
另外也附上圖表(部署流程、間隔 vs 請求量、Roadmap 清單)讓你貼文更有梗。


一圖秒懂:部署 Runbook(從打包到監控)

[部署 Runbook]
https://ithelp.ithome.com.tw/upload/images/20250930/20178823j9sun9rcDv.png

口訣:先打包 → 再部署 → 接 webhook/cron → 開監控。

步驟重點:

  1. 準備程式app.pyrequirements.txtDockerfile
  2. 申請 LINE Channel:拿到 CHANNEL_ACCESS_TOKEN / CHANNEL_SECRET
  3. 建立 GCP 專案:啟用 Artifact Registry、Cloud Run、Firestore、Cloud Scheduler、Secret Manager
  4. 打包 & 推送docker build → 推至 Artifact Registry
  5. 部署 Cloud Run:帶環境變數、設定最小實例(0 或 1),並開 public invoker(或用 IAM)
  6. 初始化 Firestore(Native 模式)
  7. 排程:Cloud Scheduler 每 60s 呼叫 /cron/tick
  8. Webhook:把 LINE Webhook 指向 /webhook
  9. 監控:Cloud Logging/Monitoring 設定錯誤率與延遲告警

成本心法:間隔 vs 請求量(估算)

[間隔 vs 請求數(估算)]
https://ithelp.ithome.com.tw/upload/images/20250930/20178823OV0vhqZMWP.png

曲線只示意:間隔越短、任務越多,請求數越高。以此選擇你的「抗吵」與「資源」平衡點。

  • 每小時請求數 ≈ 3600 / 間隔 × 任務數
  • 建議入門:60s;手刀模式:20–30s;夜間可放寬到 120–300s
  • 若擔心噪音:採用 Day 5 的合併視窗(coalesce)只在變化時通知 策略

升級 Roadmap(短中長期)

[Roadmap(中文)]
https://ithelp.ithome.com.tw/upload/images/20250929/20178823B5hYSphKzp.png
短期(1–2 週):

  • ✅ 文字推播穩定化、快取與錯誤重試(requests timeout/backoff)
  • ✅ 任務分批與軟性截止(避免爆衝)
  • ⏳ 偏好過濾(價位/區域/關鍵字),訊息截斷更友善
  • ⏳ 告警門檻:延遲/錯誤率超標推送到 LINE/Admin

中期(1–2 月):

  • ⏳ Flex Message 卡片+座位圖縮圖(Day 6)
  • ⏳ 夜間/白天動態調頻(節省資源)
  • ⏳ 支援更多平台(KKTIX / tixCraft)

長期(3–6 月):

  • ⏳ 多通道(Email/App Push)
  • ⏳ 預估「熱賣中」張數(啟發式或行為學習)
  • ⏳ 以任務表現自動調整頻率(事件驅動 / 自適應排程)

部署檔清單(可直接複製用)

1) requirements.txt

flask==3.0.3
gunicorn==21.2.0
requests==2.32.3
beautifulsoup4==4.12.3
lxml==5.2.1
google-cloud-firestore==2.16.1
google-cloud-logging==3.10.0
line-bot-sdk==3.11.0

2) Dockerfile

FROM python:3.11-slim
WORKDIR /app

# 安裝系統套件(若需)

RUN apt-get update && apt-get install -y --no-install-recommends \
    ca-certificates curl && rm -rf /var/lib/apt/lists/*

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .
ENV PORT=8080
# 用 gunicorn 啟動 Flask app: 模組為 app.py 內的 app 物件
CMD exec gunicorn -b :$PORT -w 2 --timeout 90 app:app

3).env(本地測試範例)

LINE_CHANNEL_ACCESS_TOKEN=your_line_token
LINE_CHANNEL_SECRET=your_line_secret
DEFAULT_PERIOD_SEC=60
ALWAYS_NOTIFY=0
MAX_PER_TICK=5
TICK_SOFT_DEADLINE_SEC=25

4) Cloud Run(gcloud 示意)

# 建 Artifact Registry(若尚未建立)
gcloud artifacts repositories create ibon-repo \
  --repository-format=docker --location=asia-east1

# 建鏡像
PROJECT_ID=$(gcloud config get-value project)
REGION=asia-east1
IMAGE=asia-east1-docker.pkg.dev/$PROJECT_ID/ibon-repo/ibon-watch:latest

docker build -t "$IMAGE" .
docker push "$IMAGE"

# 部署 Cloud Run
# 建 Artifact Registry(若尚未建立)
gcloud artifacts repositories create ibon-repo \
  --repository-format=docker --location=asia-east1

# 建鏡像
PROJECT_ID=$(gcloud config get-value project)
REGION=asia-east1
IMAGE=asia-east1-docker.pkg.dev/$PROJECT_ID/ibon-repo/ibon-watch:latest

docker build -t "$IMAGE" .
docker push "$IMAGE"

# 部署 Cloud Run

gcloud run deploy ibon-watch \
  --image "$IMAGE" \
  --platform managed \
  --region $REGION \
  --allow-unauthenticated \
  --set-env-vars "DEFAULT_PERIOD_SEC=60,ALWAYS_NOTIFY=0,MAX_PER_TICK=5,TICK_SOFT_DEADLINE_SEC=25" \
  --set-env-vars "LINE_CHANNEL_ACCESS_TOKEN=YOUR_TOKEN,LINE_CHANNEL_SECRET=YOUR_SECRET"

5) Cloud Scheduler(每 60 秒呼叫一次)

SERVICE_URL=$(gcloud run services describe ibon-watch --region $REGION --format='value(status.url)')
gcloud scheduler jobs create http ibon-cron \
  --schedule="* * * * *" \
  --uri="$SERVICE_URL/cron/tick" \
  --http-method=POST

企業環境可改用 OIDC 觸發(設定 --oidc-service-account-email)避免公開端點。

6) Firestore 結構(最小可用)

// collection: jobs
{
  id: "W123456",
  user_id: "Uxxxxx",
  url: "https://tickets.ibon.com/Show/Index/...",
  interval: 60,
  enabled: true,
  last_run: 1737800000,
  areas_cache: [
    { code: "B09P2J33", name: "5F B區 3800", status: "25" },
    { code: "C02X...",  name: "3F C區 2800", status: "熱賣中" }
  ]
}

監控與可靠度(SRE 小抄)

  • Logging:記錄每次 tick 的 processed/elapsed_ms/errors;webhook 指令與錯誤碼

  • Metrics:通知次數、通知延遲、抓取失敗率、ibon 解析錯誤率

  • 告警:

    • 5 分鐘內錯誤率 > X%

    • 單次 tick > 30s(疑似卡住)

    • 通知連續 0 次 > N 小時(可能排程停了)

安全與禮貌

  • 保持合理頻率(例 60s),避免造成網站負擔

  • 僅做提醒與資訊整理;購票仍需你親自完成

  • Token/Secret 請用 Secret Manager 管理,避免硬編在程式裡

QA:三個常見陷阱

  • Webhook 沒回 200:LINE 會重試 → 記得回 {"ok":true} 類的成功訊息

  • 排程命中 403/401:若關閉公開存取,請改用 OIDC 呼叫

  • 火力不足:把通知策略改成「只在變化時 + 合併視窗」,或把間隔適度放長

完結撒花 🎉

如果你一路追到這裡,恭喜擁有一個可維運的「ibon 票數自動偵測 + LINE 推播」系統。
接下來就看你要走美化派(Flex 卡片、圖像化)或猛攻派(多平台、動態調頻)啦!

下一篇後記

下一篇是心得,敬請期待 🎉


上一篇
Day 6|把訊息變好懂:LINE 推播排版(含座位圖與區塊)
系列文
IT工具與自我學IT的過程分享16
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言