DevOps & Skalabilitas

Azure Functions + CaptchaAI: Integrasi Cloud

Azure Functions menyediakan penyelesaian CAPTCHA serverless dengan integrasi erat ke dalam ekosistem Azure – Key Vault untuk secrets, Queue Storage untuk distribusi tugas, dan Application Insights untuk pemantauan.


Fungsi yang Dipicu HTTP

# function_app.py
import json
import time
import os
import logging
import urllib.request
import urllib.parse
import azure.functions as func

app = func.FunctionApp()


@app.route(route="solve", methods=["POST"])
def solve_captcha(req: func.HttpRequest) -> func.HttpResponse:
    """HTTP trigger for CAPTCHA solving."""
    try:
        body = req.get_json()
    except ValueError:
        return func.HttpResponse(
            json.dumps({"error": "JSON body required"}),
            status_code=400,
            mimetype="application/json",
        )

    method = body.get("method", "userrecaptcha")
    params = body.get("params", {})
    api_key = os.environ["CAPTCHAAI_KEY"]

    try:
        token = solve(api_key, method, params)
        return func.HttpResponse(
            json.dumps({"token": token}),
            mimetype="application/json",
        )
    except Exception as e:
        logging.error(f"Solve failed: {e}")
        return func.HttpResponse(
            json.dumps({"error": str(e)}),
            status_code=500,
            mimetype="application/json",
        )


def solve(api_key, method, params, timeout=90):
    """Solve CAPTCHA via CaptchaAI API."""
    submit_data = urllib.parse.urlencode({
        "key": api_key,
        "method": method,
        "json": 1,
        **params,
    }).encode()

    req = urllib.request.Request(
        "https://ocr.captchaai.com/in.php",
        data=submit_data,
    )
    with urllib.request.urlopen(req, timeout=30) as resp:
        result = json.loads(resp.read())

    if result.get("status") != 1:
        raise RuntimeError(f"Submit error: {result.get('request')}")

    task_id = result["request"]

    start = time.time()
    while time.time() - start < timeout:
        time.sleep(5)
        poll_url = (
            f"https://ocr.captchaai.com/res.php"
            f"?key={api_key}&action=get&id={task_id}&json=1"
        )
        with urllib.request.urlopen(poll_url, timeout=15) as resp:
            data = json.loads(resp.read())

        if data["request"] != "CAPCHA_NOT_READY":
            if data.get("status") == 1:
                return data["request"]
            raise RuntimeError(f"Solve error: {data['request']}")

    raise TimeoutError("Solve timeout")

Integrasi Gudang Kunci

Simpan kunci API di Azure Key Vault:

# Create Key Vault
az keyvault create \
  --name captchaai-vault \
  --resource-group myResourceGroup

# Store secret
az keyvault secret set \
  --vault-name captchaai-vault \
  --name CaptchaAIKey \
  --value "YOUR_API_KEY"

# Grant function access
az webapp identity assign \
  --name my-captcha-function \
  --resource-group myResourceGroup

az keyvault set-policy \
  --name captchaai-vault \
  --object-id <principal-id> \
  --secret-permissions get

Referensi dalam pengaturan aplikasi:

CAPTCHAAI_KEY=@Microsoft.KeyVault(SecretUri=https://captchaai-vault.vault.azure.net/secrets/CaptchaAIKey/)

Pemrosesan Batch yang Dipicu Antrian

Memproses tugas CAPTCHA dari Azure Queue Storage:

@app.queue_trigger(
    arg_name="msg",
    queue_name="captcha-tasks",
    connection="AzureWebJobsStorage",
)
def process_queue_task(msg: func.QueueMessage):
    """Process CAPTCHA task from queue."""
    task = json.loads(msg.get_body().decode())
    api_key = os.environ["CAPTCHAAI_KEY"]

    try:
        token = solve(api_key, task["method"], task["params"])
        logging.info(f"Task {task['id']} solved")

        # Store result in Table Storage or return queue
        _store_result(task["id"], "success", token)

    except Exception as e:
        logging.error(f"Task {task['id']} failed: {e}")
        _store_result(task["id"], "error", str(e))


def _store_result(task_id, status, value):
    """Store result (simplified — use Table Storage in production)."""
    logging.info(f"Result: {task_id} = {status}")

Struktur Proyek

captcha-function/
├── function_app.py
├── requirements.txt
├── host.json
└── local.settings.json

persyaratan.txt:

azure-functions

host.json:

{
  "version": "2.0",
  "functionTimeout": "00:02:00",
  "logging": {
    "logLevel": {
      "default": "Information"
    }
  }
}

lokal.settings.json:

{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "python",
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "CAPTCHAAI_KEY": "YOUR_API_KEY_FOR_LOCAL_DEV"
  }
}

Menyebarkan

# Create function app
az functionapp create \
  --resource-group myResourceGroup \
  --consumption-plan-location westus2 \
  --runtime python \
  --runtime-version 3.11 \
  --functions-version 4 \
  --name my-captcha-solver \
  --storage-account mystorageaccount

# Deploy
func azure functionapp publish my-captcha-solver

# Test
curl -X POST https://my-captcha-solver.azurewebsites.net/api/solve \
  -H "Content-Type: application/json" \
  -d '{
    "method": "userrecaptcha",
    "params": {
      "googlekey": "SITE_KEY",
      "pageurl": "https://example.com"
    }
  }'

Kirim Tugas ke Antrean

from azure.storage.queue import QueueClient
import json

queue = QueueClient.from_connection_string(
    conn_str="YOUR_STORAGE_CONNECTION_STRING",
    queue_name="captcha-tasks",
)

# Submit batch
for i in range(10):
    task = {
        "id": f"task-{i}",
        "method": "userrecaptcha",
        "params": {
            "googlekey": "SITE_KEY",
            "pageurl": f"https://example.com/page{i}",
        },
    }
    queue.send_message(json.dumps(task))
    print(f"Queued task-{i}")

Pemecahan Masalah

Masalah Penyebab Solusi
Fungsi timeout pada 5 menit Batas waktu default Setel functionTimeout di host.json
Referensi Key Vault mengembalikan kosong Identitas hilang atau kebijakan salah Tetapkan managed identity dan kebijakan Key Vault
Pesan antrian terus dicoba ulang Fungsi melempar exception Tangani error yang diketahui, catat dan kembalikan
Cold start > 10 detik Inisialisasi Python runtime Gunakan paket Premium atau setel FUNCTIONS_WORKER_PROCESS_COUNT

Pertanyaan Umum

Paket Konsumsi vs Premium?

Gunakan Konsumsi untuk volume rendah (< 100/day). Gunakan Premium untuk beban kerja yang konsisten – ini menjaga instance tetap hangat, menghilangkan cold start, dan mendukung integrasi VNET.

Bagaimana harga Azure Functions dibandingkan dengan AWS Lambda?

Sangat mirip untuk beban kerja CAPTCHA. Keduanya mengenakan biaya ~$0,0001 per pemanggilan pada 256MB/60s. Azure mencakup 1 juta pemanggilan gratis/month.

Bisakah saya menggunakan Fungsi Tahan Lama untuk alur kerja yang kompleks?

Ya. Fungsi Tahan Lama mendukung pola fan-out/fan-in — kirimkan 10 CAPTCHA secara paralel, lalu kumpulkan semua hasilnya. Cocok untuk pemrosesan batch.


Panduan Terkait

  • AWS Lambda + CaptchaAI
  • AWS SNS + CaptchaAI: Event-Driven CAPTCHA

Deploy di Azure – dapatkan kunci CaptchaAI Anda hari ini.

Komentar dinonaktifkan untuk artikel ini.