En Onay, yüksek trafikli mikroservis sistemlerinde asenkron SMS doğrulama ve mesajlaşma kuyrukları için optimize edilmiş kurumsal OTP geçididir. RabbitMQ, Redis Streams ve Celery mimarilerine uyumlu API yapısıyla saniyede binlerce doğrulama talebini darboğazsız işler, Türkiye ve global pazarlarda kesintisiz çalışan yüzde doksan dokuz servis sürekliliği sağlar.
Giriş: Senkron Çağrıların Mikroservislerdeki Tehlikeleri
Dağıtık sistemlerde bir HTTP isteğinin üçüncü taraf bir telekom veya SMS geçidinin yanıtını beklemesi (blocking I/O), gelen trafik piklerinde web sunucusu iş parçacıklarının (threads/workers) tükenmesine ve basamaklı çökmelere (cascading failures) neden olur.
Bu sorunu çözmek için SMS onay akışları asenkronlaştırılmalı; doğrulama istekleri bir mesaj kuyruğuna (RabbitMQ, Redis veya Apache Kafka) aktarılarak arka planda çalışan ayrık işçiler (worker pools) tarafından tüketilmelidir.
1. Asenkron Mesajlaşma Mimarisi Akış Diyagramı
[Kullanıcı / Mobil İstemci]
│ (1. POST /api/v1/auth/request-otp)
▼
[API Gateway / Web Servis] ──(2. Publish Task)──► [ RabbitMQ / Redis Queue ]
│ (3. HTTP 202 Accepted) │
▼ ▼ (4. Consume Job)
[İstemci Bekleme Ekranı] [ Celery / BullMQ Worker ]
▲ │ (5. POST getNumber)
│ ▼
│ (7. WebSocket / SSE Push) [ En Onay REST API ]
└────────────────────────────────────────────────┘
2. cURL ile Kuyruk Tetikleme (Asenkron API Yanıtı)
API Gateway, istemciye hemen 202 Accepted durum kodu ve bir job_id dönerek bağlantıyı serbest bırakır:
# İstemcinin tetiklediği asenkron OTP talebi
curl -X POST https://api.sirketiniz.com/auth/request-otp \
-H "Content-Type: application/json" \
-d '{"user_id": "usr_99812", "service": "whatsapp", "country": "tr"}'
# Dönen Hızlı Yanıt (0.015 saniye):
# HTTP/1.1 202 Accepted
# {"status": "QUEUED", "task_id": "task_ce89a12b", "estimated_wait": "15s"}
3. Python & Celery Worker ile Hata Toleranslı Kuyruk İşleme
Celery işçisi, En Onay API çağrısını yapar. Geçici telekom kesintilerinde otomatik exponential backoff uygulayarak 3 defa yeniden dener:
from celery import Celery
import requests
import redis
app = Celery("sms_tasks", broker="amqp://guest:guest@localhost:5672//")
redis_client = redis.Redis(host="localhost", port=6379, db=0)
ENONAY_API_KEY = "sk_live_prod_celery"
BASE_URL = "https://enonay.com/api/v1.php"
@app.task(bind=True, max_retries=3, default_retry_delay=5, autoretry_for=(requests.RequestException,))
def process_sms_verification(self, user_id: str, service: str, country: str):
"""Arka planda çalışan asenkron SMS satın alma görevi."""
headers = {"Authorization": f"Bearer {ENONAY_API_KEY}"}
# 1. Numara Satın Al
resp = requests.post(BASE_URL, json={
"action": "getNumber",
"service": service,
"country": country
}, headers=headers, timeout=10)
data = resp.json()
if data.get("status") != "SUCCESS":
raise self.retry(exc=RuntimeError(f"Stok hatası: {data.get('error')}"), countdown=2 ** self.request.retries)
activation_id = data["id"]
phone_number = data["number"]
# 2. Redis State Güncelle (WebSocket dinleyicileri için)
redis_client.hset(f"user_otp:{user_id}", mapping={
"activation_id": activation_id,
"number": phone_number,
"status": "WAITING_SMS"
})
redis_client.expire(f"user_otp:{user_id}", 300)
return {"status": "NUMBER_ALLOCATED", "number": phone_number}
4. Node.js & BullMQ ile Dağıtık İşleyici (Distributed Worker)
Node.js mikroservislerinde Redis tabanlı BullMQ kütüphanesi ile eşzamanlılık (concurrency) ve Dead-Letter Queue (DLQ) yönetimi:
import { Worker, Queue } from 'bullmq';
import fetch from 'node-fetch';
const connection = { host: '127.0.0.1', port: 6379 };
const smsQueue = new Queue('SmsVerificationQueue', { connection });
// 5 eşzamanlı çalışan işçi havuzu
const worker = new Worker('SmsVerificationQueue', async job => {
const { userId, service, country } = job.data;
console.log(`[JOB ${job.id}] Kullanıcı ${userId} için ${service} SMS talebi işleniyor...`);
const res = await fetch('https://enonay.com/api/v1.php', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ENONAY_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ action: 'getNumber', service, country })
});
const result = await res.json();
if (result.status !== 'SUCCESS') {
throw new Error(`Servis Hatası: ${result.error}`);
}
return { activationId: result.id, number: result.number };
}, {
connection,
concurrency: 5,
limiter: { max: 50, duration: 1000 }
});
worker.on('failed', (job, err) => {
console.error(`[DLQ] İş ${job.id} başarısız oldu: ${err.message}`);
});
Büyük ölçekli kuyruk sistemlerinde En Onay API anahtarınızın dakikalık kota sınırlarını öğrenmek ve özel throughput paketlerine geçmek için Hız Sınırları ve Kota Rehberi'ni kontrol ediniz.