76. Menyambungkan gRPC Service dengan Kafka
Dalam membangun sistem terdistribusi modern, pola komunikasi antar-microservices menjadi sangat krusial. Dua teknologi populer yang sering digunakan adalah gRPC dan Apache Kafka. Kombinasi dua teknologi ini menawarkan kecepatan, kestabilan, serta skalabilitas untuk sistem enterprise. Pada artikel kali ini, saya akan membahas tentang bagaimana menyambungkan gRPC Service dengan Kafka—mulai dari arsitektur, implementasi kode, hingga simulasi pengujian.
Mengapa Perlu Integrasi gRPC dengan Kafka?
gRPC adalah sistem komunikasi Remote Procedure Call (RPC) modern berbasis HTTP/2 dan Protocol Buffers, yang efisien untuk komunikasi synchronous antar service. Sementara Kafka adalah message broker yang powerful untuk pengiriman pesan asynchronous dalam jumlah masif.
Pola tipikal yang sering digunakan:
- gRPC sebagai API service layer (front-facing service, melakukan validasi, dan proses sinkronus).
- Kafka sebagai event bus untuk komunikasi asinkron dan pengolahan data secara real-time/batch oleh downstream service.
Dengan begitu, setiap request yang diterima oleh gRPC bisa dipush sebagai event ke Kafka—membuka jalan bagi service lain untuk bereaksi terhadap event tersebut secara loose-coupled.
Studi Kasus: Order Service
Bayangkan kita membangun Order Service (gRPC) yang, setiap kali user membuat order baru, service ini akan mem-publish order event ke Kafka. System lain seperti Inventory Service, Notification Service akan mengonsumsi event ini untuk memproses lebih lanjut.
Arsitektur High Level
Mari kita lihat alur sistem ini dengan kode Mermaid Diagram:
sequenceDiagram
participant Client
participant gRPC Service
participant Kafka
participant Consumer Service
Client->>gRPC Service: gRPC call (CreateOrder)
gRPC Service->>Kafka: Publish OrderCreated event
Kafka->>Consumer Service: Consumer receives OrderCreated event
Langkah singkat:
- Client mengirim permintaan
CreateOrderke gRPC Service. - gRPC Service memvalidasi, lalu push event
OrderCreatedke Kafka topic. - Service lain menjadi consumer dari topic tersebut.
Persiapan Lingkungan
Untuk simulasi, kita akan menggunakan stack berikut:
- Go sebagai bahasa pemrograman (karena binding gRPC dan Kafka di Go sangat solid)
- protoc untuk generate stubs dari proto file
- sarama sebagai Kafka client di Go
Kode berikut relevan untuk stack selain Go, karena prinsipnya sama (publish event ke Kafka setelah menangani gRPC).
1. Definisi Protobuf
File: order.proto
syntax = "proto3";
package order;
service OrderService {
rpc CreateOrder (OrderRequest) returns (OrderResponse);
}
message OrderRequest {
string item = 1;
int32 qty = 2;
string user_id = 3;
}
message OrderResponse {
string order_id = 1;
string status = 2;
}
Generate kode Go untuk service dan message tersebut.
2. Implementasi gRPC Server dengan Kafka Publisher
File: main.go
package main
import (
"context"
"log"
"net"
pb "github.com/yourorg/orderpb"
"github.com/Shopify/sarama"
"google.golang.org/grpc"
)
type server struct {
producer sarama.SyncProducer
pb.UnimplementedOrderServiceServer
}
func (s *server) CreateOrder(ctx context.Context, req *pb.OrderRequest) (*pb.OrderResponse, error) {
orderID := generateOrderID() // fungsi random, misal UUID
event := map[string]interface{}{
"order_id": orderID,
"item": req.Item,
"qty": req.Qty,
"user_id": req.UserId,
}
// Serialize ke JSON
marshalled, err := json.Marshal(event)
if err != nil {
return nil, err
}
// Publish ke Kafka topic
message := &sarama.ProducerMessage{
Topic: "order_events",
Value: sarama.ByteEncoder(marshalled),
}
_, _, err = s.producer.SendMessage(message)
if err != nil {
return nil, err
}
return &pb.OrderResponse{
OrderId: orderID,
Status: "CREATED",
}, nil
}
func main() {
// Inisialisasi Kafka producer
config := sarama.NewConfig()
config.Producer.Return.Successes = true
producer, err := sarama.NewSyncProducer([]string{"localhost:9092"}, config)
if err != nil {
log.Fatalf("Failed to start Sarama producer: %v", err)
}
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("Failed to listen: %v", err)
}
grpcServer := grpc.NewServer()
pb.RegisterOrderServiceServer(grpcServer, &server{producer: producer})
log.Println("gRPC & Kafka server running at :50051 ...")
if err := grpcServer.Serve(lis); err != nil {
log.Fatalf("Failed to serve: %v", err)
}
}
Penjelasan Kode
- Setiap berhasil create order, event didorong ke Kafka Topic.
- gRPC tetap memberikan response synchronous ke client (“CREATED”).
- Kode mudah dikembangkan untuk juga melakukan sinkronisasi database, logging, dsb.
3. Kafka Consumer (simulasi)
Order Event dari Kafka ini bisa dikonsumsi oleh service lain seperti berikut:
consumer, err := sarama.NewConsumer([]string{"localhost:9092"}, nil)
if err != nil {
panic(err)
}
partitionConsumer, err := consumer.ConsumePartition("order_events", 0, sarama.OffsetNewest)
if err != nil {
panic(err)
}
for message := range partitionConsumer.Messages() {
var event map[string]interface{}
if err := json.Unmarshal(message.Value, &event); err == nil {
log.Printf("Order Event received: %+v\n", event)
// Lakukan hal lain: update stok, kirim email, dsb.
}
}
Simulasi Pengujian
Mari kita buat simulasi pengujian menggunakan tabel step serta sample output log.
| Step | Action | Expected Output |
|---|---|---|
| 1 | Client gRPC call CreateOrder | Response {“order_id”: “…”, “status”:“CREATED”} |
| 2 | Kafka topic receive event | Event order muncul di Kafka |
| 3 | Consumer membaca event | Log: Order Event received: … |
Contoh log output:
2024/06/12 11:00:01 gRPC & Kafka server running at :50051 ...
2024/06/12 11:00:08 Order Event received: map[item:"Coffee" order_id:"123" qty:2 user_id:"abcde"]
Manfaat Arsitektur ini
Kelebihan
- Scalability: Order event bisa diterima oleh banyak konsumen tanpa menambah beban pada gRPC API.
- Decoupling: Downstream service bisa subscribe/unsubscribe tanpa mengubah code OrderService.
- Reliability & Retries: Kafka mendukung re-delivery ketika konsumen gagal.
- Asynchronous processing: Proses berat (misal update stok, kirim email) tak memblokir request client.
Kekurangan
- Kebutuhan Infrastruktur: Perlu deploy dan mengelola Kafka cluster.
- Error Handling: Perlu monitoring/kebijakan retry jika publish ke Kafka gagal.
- Duplicate Event: Downstream service perlu idempoten (event bisa diterima lebih dari sekali).
Kesimpulan
Dengan mengombinasikan gRPC (untuk API synchronous) dan Kafka (untuk event asynchronous), kita bisa membangun microservices yang scalable dan loosely coupled. Teknik yang telah dijelaskan di atas sudah menjadi praktik terbaik di banyak perusahaan tech besar.
Berikut 📝 checklist integrasi gRPC + Kafka production ready:
- Gunakan schema registry untuk event contracts (menghindari broken consumer)
- Logging & distributed tracing di setiap step
- Monitoring publish dan delivery event
- Implementasi retry/retry policy pada publisher dan consumer
Integrasi ini cocok untuk berbagai use case — dari order management, payment, hingga notifikasi email/SMS.
Silakan coba struktur ini di proyek microservices Anda, dan nikmati kemudahannya dalam scaling layanan 🚀.
Referensi