66. Deadline dan Timeout pada gRPC: Panduan Engineer Profesional
Saat kita membangun sistem terdistribusi atau microservices, salah satu aspek kritis yang sering luput dari perhatian adalah bagaimana layanan kita menangani proses permintaan yang lambat atau tak berujung (hanging). Dalam konteks gRPC, dua konsep penting yang perlu kita pahami dan gunakan secara tepat adalah Deadline dan Timeout. Keduanya berperan fundamental dalam menjaga robustness layanan dan pengalaman pengguna yang baik.
Pada artikel kali ini, saya akan membahas secara mendalam perbedaan keduanya, kapan harus menggunakannya, dampaknya pada aplikasi, serta contoh implementasinya pada gRPC menggunakan Go beserta simulasi dan diagram alur untuk memperjelas mekanismenya.
Apa itu Deadline dan Timeout di gRPC?
Sebelum membuat kode, kita perlu memahami konsep ini secara abstrak:
- Timeout adalah batas waktu maksimal untuk menjalankan sebuah operasi sebelum dianggap gagal. Timeout biasanya ditentukan oleh client saat memanggil server.
- Deadline adalah titik waktu absolut (
timestamp) kapan permintaan harus selesai. Kadang istilah Deadline dan Timeout digunakan secara bergantian, namun Deadline biasanya lebih “eksplisit”: ini adalah waktu kapan permintaan akan di-cancel.
Di gRPC, timeout akan otomatis diubah menjadi deadline di belakang layar, dan diteruskan ke setiap request hingga ke microservice paling ujung.
Tabel: Perbedaan Deadline dan Timeout
| Aspek | Timeout | Deadline |
|---|---|---|
| Tipe | Durasi relative (3s) | Waktu absolut (unix timestamp) |
| Siapa yang set | Client | Client |
| Propagasi | Propagasi ke downstream | Propagasi ke downstream |
| Cara set di Go | Context dengan Timeout | Context dengan Deadline |
| Di header gRPC | Terkirim sebagai deadline | Terkirim sebagai deadline |
Kenapa Deadline dan Timeout Penting?
1. Hindari Resources Hanging
Tanpa batas waktu, layanan kita bisa saja menggantung menangani permintaan yang tak pernah selesai. Akibatnya, resource boros dan experience memburuk.
2. Propagasi End-to-end
Sering kali, 1 permintaan dari client bisa men-trigger layanan A memanggil B, lalu B memanggil C, dst. Tanpa propagasi deadline, layanan di hilir tidak tahu kapan boleh berhenti bekerja jika upstream sudah kehabisan waktu.
3. Fail Fast
Membuat sistem yang fail fast membantu deteksi, pelaporan error, dan handling fallback lebih baik dalam aplikasi real world.
Implementasi Deadline dan Timeout di gRPC (Golang)
Mari kita simulasikan sebuah sistem sederhana:
- gRPC Client: Memanggil method “/Ping” ke server.
- gRPC Server: Menjawab Ping, namun bisa disimulasikan delay.
- Client menentukan deadline dengan context.
1. Contoh Server
// server.go
package main
import (
"context"
"fmt"
"log"
"net"
"time"
pb "your/proto/path"
"google.golang.org/grpc"
)
type server struct{
pb.UnimplementedPingerServer
}
func (s *server) Ping(ctx context.Context, req *pb.PingRequest) (*pb.PingResponse, error) {
// Simulasi proses lambat
select {
case <-time.After(2 * time.Second): // Delay 2 detik
return &pb.PingResponse{Message: "Pong"}, nil
case <-ctx.Done():
// Request dibatalkan karena deadline atau client cancel
return nil, ctx.Err()
}
}
func main() {
lis, _ := net.Listen("tcp", ":50051")
grpcServer := grpc.NewServer()
pb.RegisterPingerServer(grpcServer, &server{})
if err := grpcServer.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
2. Contoh Client dengan Deadline
// client.go
package main
import (
"context"
"log"
"time"
pb "your/proto/path"
"google.golang.org/grpc"
)
func main() {
conn, _ := grpc.Dial("localhost:50051", grpc.WithInsecure())
defer conn.Close()
client := pb.NewPingerClient(conn)
// Set deadline 1 detik dari sekarang
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
_, err := client.Ping(ctx, &pb.PingRequest{})
if err != nil {
log.Printf("Ping failed: %v", err)
}
}
Pada contoh di atas, server butuh waktu 2 detik untuk membalas, tapi client mengatur deadline 1 detik. Hasilnya, server akan menerima cancel signal dari context dan permintaan di-cancel otomatis. Ini bisa dihandle di server maupun client.
Diagram Alur Deadline Propagation
Mari kita gambarkan alurnya menggunakan diagram mermaid:
sequenceDiagram
participant Client
participant ServiceA
participant ServiceB
Client->>ServiceA: gRPC request (deadline=5s)
ServiceA->>ServiceB: gRPC request (deadline=4s)
Note right of ServiceA: Kurangi overhead processing
ServiceB-->>ServiceA: Response / Error
ServiceA-->>Client: Response / Error
Diagram di atas mengilustrasikan:
- Client kirim request dengan deadline 5 detik ke ServiceA.
- ServiceA perlu waktu untuk proses internal.
- Jika ServiceA memanggil ServiceB, ia harus menurunkan deadline, mengurangi waktu proses yang telah dipakai.
- Hal ini memastikan tidak ada request gantung di ServiceB jika waktu di ServiceA sudah habis.
Simulasi Output
Mari kita lihat output dari client jika mengatur deadline < waktu proses server:
2024/06/01 22:00:00 Ping failed: rpc error: code = DeadlineExceeded desc = context deadline exceeded
Jika deadline lebih besar dari proses server (misal, deadline 3s), respons akan berhasil. Ubah di kode client dan lihat efeknya.
Kapan Memakai Deadline dan Timeout?
- Selalu atur deadline dari sisi client. Jangan biarkan permintaan berjalan selamanya.
- Untuk internal service chaining, pastikan propagasi deadline ke downstream.
- Sesuaikan deadline sesuai SLA/millisec pendefinisian bisnis.
- Pada context Go, gunakan
WithTimeoutuntuk mudahnya.
Dampak Deadline pada Fallback dan Retry
Deadline juga fundamental untuk membangun retry logic yang baik. Jika request gagal karena timeout/deadline, aplikasi bisa mengambil langkah fallback, mencoba ke service lain, atau mengembalikan error message user-friendly ke pengguna.
Kesalahan Umum yang Mesti Dihindari
Tidak meneruskan context ke downstream
Propagasi context sangat krusial agar deadline tetap dihormati oleh seluruh stack layanan.Mengatur deadline terlalu sempit
Berpotensi memotong proses yang sebenarnya validTidak handle ctx.Err() di server
Pastikan ada handling untuk mengecek apakah context sudah done sebelum memproses request berat.
Best Practice
- Propagasi konteks context.TODO() → context.Background() → context.WithTimeout/WithDeadline()
- Cek ctx.Err() periodik di long-running worker/server.
- Logging & metric error DeadlineExceeded untuk pemantauan.
Kesimpulan
Menggunakan deadline dan timeout dengan benar adalah kunci membuat layanan gRPC yang resilient, robust, dan fail fast. Otomasi ini bukan hanya membantu resource management, tapi juga membantu user experience dan scalability aplikasi Anda.
Jadi di setiap project gRPC berikutnya, pastikan setiap call memakai deadline/timeout yang proporsional — dan selalu propagasikan context dengan benar ke downstream.
Salam,
Software Engineer Professional