SiamCafe.net Blog
Technology

Healthchecks.io Scaling Strategy วิธี Scale

healthchecksio scaling strategy วธ scale
Healthchecks.io Scaling Strategy วิธี Scale | SiamCafe Blog
2025-09-01· อ. บอม — SiamCafe.net· 8,719 คำ

Healthchecks.io คืออะไร

Healthchecks.io เป็นบริการ Cron Job Monitoring ที่ช่วยตรวจสอบว่า Scheduled Tasks ทำงานตามเวลาหรือไม่ หลักการคือ Cron Job ส่ง HTTP GET/POST ไปยัง Healthchecks.io เมื่อทำงานเสร็จ (Ping) ถ้าไม่ได้รับ Ping ภายในเวลาที่กำหนดจะแจ้งเตือน

เมื่อใช้ร่วมกับ Scaling Strategy ช่วยตรวจจับว่า Jobs เริ่มช้าลง (Duration เพิ่ม) หรือ Timeout เป็นสัญญาณว่าต้อง Scale Resources เพิ่ม

Setup Healthchecks.io

# === Healthchecks.io Setup ===

# 1. สมัครที่ https://healthchecks.io (Free: 20 Checks)
# หรือ Self-hosted ด้วย Docker

# === Self-hosted ด้วย Docker Compose ===
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
  healthchecks:
    image: healthchecks/healthchecks:latest
    ports:
      - "8000:8000"
    environment:
      - DB=postgres
      - DB_HOST=postgres
      - DB_NAME=healthchecks
      - DB_USER=hc
      - DB_PASSWORD=SecurePass123
      - SECRET_KEY=your-secret-key-here
      - ALLOWED_HOSTS=*
      - SITE_ROOT=https://hc.example.com
      - DEFAULT_FROM_EMAIL=alerts@example.com
      - EMAIL_HOST=smtp.gmail.com
      - EMAIL_PORT=587
      - EMAIL_USE_TLS=True
      - EMAIL_HOST_USER=your@gmail.com
      - EMAIL_HOST_PASSWORD=app-password
      - SLACK_CLIENT_ID=xxx
      - SLACK_CLIENT_SECRET=xxx
    depends_on:
      - postgres
    restart: unless-stopped

  postgres:
    image: postgres:16-alpine
    environment:
      - POSTGRES_DB=healthchecks
      - POSTGRES_USER=hc
      - POSTGRES_PASSWORD=SecurePass123
    volumes:
      - pg-data:/var/lib/postgresql/data
    restart: unless-stopped

volumes:
  pg-data:
EOF

docker compose up -d

# 2. Cron Job Integration
# แต่ละ Check มี UUID เฉพาะ เช่น:
# https://hc-ping.com/abc123-def456

# === Bash — Ping เมื่อ Job เสร็จ ===
# Backup Script
#!/bin/bash
set -e
CHECK_URL="https://hc-ping.com/abc123-def456"

# แจ้งเริ่มต้น
curl -fsS -m 10 --retry 5 "$CHECK_URL/start" > /dev/null

# ทำงาน
pg_dump mydb | gzip > /backups/mydb_$(date +%Y%m%d).sql.gz

# แจ้งเสร็จ (Ping)
curl -fsS -m 10 --retry 5 "$CHECK_URL" > /dev/null

# ถ้า Error — แจ้ง Fail
# curl -fsS -m 10 --retry 5 "$CHECK_URL/fail" > /dev/null

# 3. Crontab
# 0 2 * * * /opt/scripts/backup.sh 2>&1 | curl -fsS -m 10 \
#   --retry 5 --data-binary @- https://hc-ping.com/abc123-def456/log

# 4. Python Integration
# import requests
# CHECK_URL = "https://hc-ping.com/abc123-def456"
# requests.get(f"{CHECK_URL}/start")
# # ... do work ...
# requests.get(CHECK_URL)  # Success
# # requests.get(f"{CHECK_URL}/fail")  # Failure

echo "Healthchecks.io setup complete"

Scaling Strategy Script

# scaling_strategy.py — Auto-scaling ตาม Healthchecks.io Metrics
import requests
import json
import subprocess
from datetime import datetime, timedelta
from dataclasses import dataclass
from typing import List, Dict, Optional

class HealthchecksClient:
    """Healthchecks.io API Client"""

    def __init__(self, api_key, base_url="https://healthchecks.io"):
        self.base_url = base_url
        self.headers = {"X-Api-Key": api_key}

    def list_checks(self):
        """ดู Checks ทั้งหมด"""
        resp = requests.get(f"{self.base_url}/api/v3/checks/",
                           headers=self.headers)
        return resp.json().get("checks", [])

    def get_check(self, uuid):
        """ดู Check เฉพาะ"""
        resp = requests.get(f"{self.base_url}/api/v3/checks/{uuid}",
                           headers=self.headers)
        return resp.json()

    def get_pings(self, uuid, limit=50):
        """ดู Ping History"""
        resp = requests.get(
            f"{self.base_url}/api/v3/checks/{uuid}/pings/",
            headers=self.headers,
        )
        return resp.json().get("pings", [])[:limit]

    def get_flips(self, uuid):
        """ดู Status Changes"""
        resp = requests.get(
            f"{self.base_url}/api/v3/checks/{uuid}/flips/",
            headers=self.headers,
        )
        return resp.json().get("flips", [])

class ScalingAdvisor:
    """วิเคราะห์ Metrics และแนะนำ Scaling"""

    def __init__(self, hc_client: HealthchecksClient):
        self.hc = hc_client

    def analyze_job_durations(self, uuid):
        """วิเคราะห์ Duration ของ Job"""
        pings = self.hc.get_pings(uuid)

        durations = []
        start_time = None

        for ping in reversed(pings):
            if ping.get("type") == "start":
                start_time = ping.get("date")
            elif ping.get("type") == "success" and start_time:
                start = datetime.fromisoformat(start_time.replace("Z", "+00:00"))
                end = datetime.fromisoformat(ping["date"].replace("Z", "+00:00"))
                duration = (end - start).total_seconds()
                durations.append(duration)
                start_time = None

        if not durations:
            return None

        avg = sum(durations) / len(durations)
        latest = durations[-1] if durations else 0
        trend = "increasing" if len(durations) >= 3 and \
                durations[-1] > durations[-3] * 1.2 else "stable"

        return {
            "avg_seconds": round(avg),
            "latest_seconds": round(latest),
            "min_seconds": round(min(durations)),
            "max_seconds": round(max(durations)),
            "samples": len(durations),
            "trend": trend,
        }

    def scaling_recommendation(self, checks_analysis):
        """สร้างคำแนะนำ Scaling"""
        recommendations = []

        for name, analysis in checks_analysis.items():
            if not analysis:
                continue

            if analysis["trend"] == "increasing":
                recommendations.append({
                    "job": name,
                    "action": "SCALE UP",
                    "reason": f"Duration increasing: "
                              f"{analysis['latest_seconds']}s "
                              f"(avg: {analysis['avg_seconds']}s)",
                    "priority": "high",
                })
            elif analysis["latest_seconds"] > analysis["avg_seconds"] * 2:
                recommendations.append({
                    "job": name,
                    "action": "INVESTIGATE",
                    "reason": f"Latest run 2x slower than average",
                    "priority": "medium",
                })

        return recommendations

    def print_report(self, checks):
        """แสดง Scaling Report"""
        print(f"\n{'='*55}")
        print(f"Scaling Analysis Report — {datetime.now():%Y-%m-%d %H:%M}")
        print(f"{'='*55}")

        analyses = {}
        for check in checks:
            name = check.get("name", "Unknown")
            uuid = check.get("ping_url", "").split("/")[-1]

            if uuid:
                analysis = self.analyze_job_durations(uuid)
                analyses[name] = analysis

                if analysis:
                    trend_icon = "UP" if analysis["trend"] == "increasing" else "OK"
                    print(f"\n  [{trend_icon}] {name}")
                    print(f"    Latest: {analysis['latest_seconds']}s | "
                          f"Avg: {analysis['avg_seconds']}s | "
                          f"Max: {analysis['max_seconds']}s")

        recs = self.scaling_recommendation(analyses)
        if recs:
            print(f"\n  Recommendations:")
            for r in recs:
                print(f"    [{r['priority'].upper()}] {r['job']}: "
                      f"{r['action']} — {r['reason']}")

# hc = HealthchecksClient("your-api-key")
# advisor = ScalingAdvisor(hc)
# checks = hc.list_checks()
# advisor.print_report(checks)

Kubernetes HPA Integration

# === Kubernetes Auto-scaling ตาม Job Metrics ===
# hpa-config.yaml

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: worker-hpa
  namespace: production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: worker
  minReplicas: 2
  maxReplicas: 20
  metrics:
    # Scale ตาม CPU
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 60
    # Scale ตาม Queue Length (Custom Metric)
    - type: Pods
      pods:
        metric:
          name: job_queue_length
        target:
          type: AverageValue
          averageValue: "10"
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
        - type: Percent
          value: 50
          periodSeconds: 60
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
        - type: Percent
          value: 25
          periodSeconds: 120
---
# === CronJob ที่ส่ง Ping ไป Healthchecks.io ===
apiVersion: batch/v1
kind: CronJob
metadata:
  name: data-sync
  namespace: production
spec:
  schedule: "*/30 * * * *"
  concurrencyPolicy: Forbid
  jobTemplate:
    spec:
      template:
        spec:
          containers:
            - name: sync
              image: myapp/data-sync:latest
              command:
                - /bin/sh
                - -c
                - |
                  curl -fsS -m 10 "$HC_PING_URL/start"
                  python sync.py
                  EXIT_CODE=$?
                  if [ $EXIT_CODE -eq 0 ]; then
                    curl -fsS -m 10 "$HC_PING_URL"
                  else
                    curl -fsS -m 10 "$HC_PING_URL/fail"
                  fi
              env:
                - name: HC_PING_URL
                  valueFrom:
                    secretKeyRef:
                      name: healthchecks
                      key: data-sync-url
          restartPolicy: OnFailure

Best Practices

Healthchecks.io คืออะไร

บริการ Cron Job Monitoring ตรวจสอบ Scheduled Tasks ทำงานตามเวลาหรือไม่ Cron Job ส่ง HTTP Ping เมื่อเสร็จ ถ้าไม่ได้รับ Ping แจ้งเตือน Email Slack PagerDuty Free Plan 20 Checks

Scaling Strategy คืออะไร

แผนขยายระบบรองรับ Load เพิ่ม Vertical Scaling เพิ่ม CPU/RAM Server เดิม Horizontal Scaling เพิ่มจำนวน Server ใช้ Metrics เช่น CPU Usage Request Count Queue Length ตัดสินใจ

Healthchecks.io ช่วย Scaling อย่างไร

ตรวจจับ Jobs ช้าลงหรือ Timeout สัญญาณต้อง Scale ติดตาม Job Duration เห็นแนวโน้ม Duration เพิ่มแสดงว่า Resources ไม่พอ ใช้ร่วมกับ Auto-scaling Scale เมื่อ Jobs เริ่มช้า

Self-hosted Healthchecks.io ทำได้ไหม

ได้ Open-source BSD License ติดตั้งด้วย Docker Compose ต้องมี PostgreSQL ไม่จำกัด Checks ข้อมูลอยู่ Server เอง เหมาะองค์กรที่ต้องการ Data Privacy

สรุป

Healthchecks.io เป็นเครื่องมือ Cron Job Monitoring ที่ช่วยตรวจสอบ Scheduled Tasks และเมื่อใช้ร่วมกับ Scaling Strategy ช่วยตรวจจับปัญหา Performance ก่อนกระทบผู้ใช้ ใช้ Start/Success Pattern วัด Duration ติดตาม Trends ถ้า Duration เพิ่มต่อเนื่องต้อง Scale ใช้ Kubernetes HPA สำหรับ Auto-scaling Self-hosted ด้วย Docker ถ้าต้องการ Data Privacy

📖 บทความที่เกี่ยวข้อง

CDK Construct Scaling Strategy วิธี Scaleอ่านบทความ → AWS Step Functions Scaling Strategy วิธี Scaleอ่านบทความ → BigQuery Scheduled Query Scaling Strategy วิธี Scaleอ่านบทความ → Java GraalVM Scaling Strategy วิธี Scaleอ่านบทความ → AlmaLinux Setup Scaling Strategy วิธี Scaleอ่านบทความ →

📚 ดูบทความทั้งหมด →