Pengenalan Masalah
CodeIgniter 4 sering digunakan untuk memproses antrian pekerjaan yang masuk melalui Redis. Ketika jumlah job melonjak, worker dapat mengalami backpressure: antrean memanjang, latensi naik, dan worker mulai gagal karena sumber daya terbatas. Artikel ini langsung menjelaskan cara mengelola backpressure tersebut agar worker tetap stabil dengan menggabungkan metrik, mitigasi, dan tindakan operasional yang dapat diterapkan hari ini.
Metrik Queue Redis sebagai Indikator Backpressure
Gunakan metrik Redis seperti panjang antrean (llen) dan waktu tunggu job untuk mendeteksi tekanan awal. Di sisi CodeIgniter 4, buat layanan yang memanggil Redis secara periodik:
// app/Services/QueueMonitorService.php namespace App\Services; use CodeIgniter\Config\Redis; class QueueMonitorService { protected $redis; public function __construct() { $this->redis = Redis::connect(); } public function getMetrics(string $queue): array { $length = $this->redis->llen($queue); $latency = $this->redis->hget('queue_latency', $queue) ?? 0; return ['length' => (int)$length, 'latency' => (int)$latency]; }}Gunakan layanan ini di controller atau scheduler untuk mengirim metrik ke Prometheus atau sistem monitoring internal. Threshold tipikal: lebih dari 70% worker terpakai dan panjang antrean naik berulang kali merupakan sinyal backpressure.
Worker Resilience: Circuit Breaker dan Rate Limiter
Ketika metrik menunjukkan tekanan, worker harus menahan laju pengambilan job tanpa menghentikan sistem. Implementasikan pola circuit breaker sederhana:
- State: closed jika antrean stabil, open jika panjang > threshold selama N check berturut-turut.
- Delay: saat open, worker tidur
sleep(2)sebelum mencoba lagi. - Reset: kembali ke closed jika antrean turun di bawah safe threshold selama M check.
Tambahkan rate limiter untuk mengontrol pengambilan job per detik:
// app/Libraries/RateLimiter.php namespace App\Libraries; class RateLimiter { protected $lastRun = 0; protected $interval; public function __construct(float $qps) { $this->interval = 1 / $qps; } public function hit(): bool { $now = microtime(true); if ($now - $this->lastRun < $this->interval) { return false; } $this->lastRun = $now; return true; }}Gunakan kedua pola tersebut di worker utama sebelum memproses job. Hal ini mencegah worker memicu overload saat Redis sedang sibuk.
Sinkronisasi Metadata Job
Job di queue Redis perlu metadata agar sistem tahu job mana yang sedang diproses, gagal, atau terjadwal ulang. Simpan metadata kecil di cache (Redis Hash atau CI4 Cache) berikut:
job_status:{id}: state vs timestamp.job_attempts:{id}: jumlah percobaan.job_last_updated: untuk health check.
Setiap worker harus memperbarui metadata sebelum dan sesudah memproses job, serta membersihkan cache saat sukses atau saat job dihapus. Sinkronisasi memastikan job tidak hilang saat worker restart atau terjadi proses paralel.
Strategi Retry dengan Jitter dan Penjadwalan Ulang
Untuk job yang gagal akibat layanan downstream, hindari retry berturut-turut tanpa jeda. Terapkan retry dengan exponential backoff + jitter:
// Pseudocode per job $attempts = $metadata['attempts'] ?? 0; $delay = min(60, pow(2, $attempts)); $jitter = rand(0, 5); $delay += $jitter; $metadata['next_run'] = time() + $delay; $metadata['attempts'] = ++$attempts;Scheduler harus memindahkan job ke antrean utama hanya ketika next_run sudah lewat. Sertakan penjadwalan ulang di job handler agar worker tidak langsung mengambil job yang masih dalam cooldown.
Observabilitas dan Health Check
Logging harus mencatat:
- Perubahan status circuit breaker.
- Jumlah job yang diambil per siklus.
- Waktu pemrosesan rata-rata vs threshold.
Contoh format log overload:
[2024-XX-XXT10:00:00Z] alert queue=job_email length=185 latency=320ms status=open worker=5Pasang alert ketika log menunjukkan pengaktifan circuit breaker atau metric length melebihi limit. Health check HTTP dapat membaca metadata untuk memastikan worker aktif, misalnya:
// app/Controllers/Health.php namespace App\Controllers; use CodeIgniter\RESTful\ResourceController; class Health extends ResourceController { public function queue():
{ $data = ['queue_length' => service('queueMonitor')->getMetrics('job_email')['length']]; return $this->respond($data); }}Perintah Operasional: Drain Queue dan Reset Cache
Siapkan CLI command khusus menyelesaikan antrean dengan aman:
// app/Commands/DrainQueue.php namespace App\Commands; use CodeIgniter\CLI\BaseCommand; class DrainQueue extends BaseCommand { protected $group = 'queue'; protected $name = 'queue:drain'; protected $description = 'Kosongkan queue dan hentikan worker sementara'; public function run(array $params) { $queue = $this->getOption('queue') ?? 'default'; while (service('queue')->isNotEmpty($queue)) { service('queue')->processOnce($queue); } CLI::write("Queue $queue drained"); }}Tambahkan opsi:
--queue=nameuntuk menentukan antrean.--forceuntuk memaksa drain tanpa wait.
Saat perlu reset cache metadata job gunakan command serupa:
php spark cache:clear job_status(Command ini bisa diganti dengan script yang menghapus key pattern tertentu dari Redis, pastikan ada konfirmasi sebelum eksekusi massal.)
Format Laporan Saat Overload
Laporan harus ringkas tapi cukup rinci untuk tindakan cepat:
Timestamp: 2024-XX-XXT10:05:00Z Queue: job_email Length: 210 Latency: 420ms WorkerState: circuit-open RateLimit: 12/s Action: menurunkan worker count, memperpanjang delay monitoringSertakan tindakan yang sudah dilakukan dan langkah berikutnya: misalnya restart worker, tambah worker sementara, atau jadwalkan batch backfill di malam hari.
Ringkasan
Kunci menjaga stabilitas worker CodeIgniter 4 pada queue Redis adalah kombinasi metrik, proteksi worker, sinkronisasi metadata, dan observabilitas. Dengan menggabungkan circuit breaker, rate limiter, retry dengan jitter, dan perintah operasional yang siap pakai, Anda dapat merespons backpressure sebelum sistem gagal total.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!