Bidirectional Streaming RPC adalah salah satu fitur canggih dalam gRPC, framework open-source yang digagas oleh Google untuk kebutuhan komunikasi antar layanan. Dalam skenario aplikasi modern, sering kali kita butuh komunikasi dua arah yang real-time, misal dalam chat aplikasi, transfer file secara potongan, monitoring, atau bahkan collaborative editing. Di artikel ini kita akan menyelami bagaimana implementasi Bidirectional Streaming RPC di gRPC menggunakan bahasa Go—disertai contoh kode, simulasi, dan diagram alur untuk memperjelas bagaimana arsitektur ini berjalan.
Apa itu Bidirectional Streaming di gRPC?
Bidirectional streaming, atau duplex streaming, artinya baik client maupun server dapat mengirim banyak pesan secara bersamaan dan independen sepanjang sesi koneksi terbuka. Ini jelas lebih fleksibel dibandingkan dengan unary RPC (request-response 1:1), server streaming (1:N), atau client streaming (N:1).
Ilustrasi sederhana aliran data pada Bidirectional Streaming:
flowchart LR Client -- Pesan 1, 2, 3 --> Server Server -- Respon A, B, C --> Client Client -- Pesan 4 --> Server Server -- Respon D --> Client
Pada diagram di atas, tidak ada aturan mutlak siapa yang harus mengirim pesan duluan. Keduanya bisa saling bertukar data secara bersamaan.
Kapan Bidirectional Streaming RPC Dibutuhkan?
Bidirectional streaming berguna di banyak use-case, seperti:
- Chat Real-time: Client & server saling bertukar pesan secara asinkron.
- Sinkronisasi Data: Misal collaborative editing pada dokumen.
- Telemetri/Metrik Monitoring: Client stream data metrik, server bisa streaming feedback langsung.
Contoh Use-case: Sistem Chat Sederhana
Agar mudah dipahami, kita akan implementasikan sistem chat sederhana dengan gRPC Bidirectional Streaming menggunakan Go.
1. Mendefinisikan Protokol gRPC di .proto
// chat.proto
syntax = "proto3";
package chat;
service ChatService {
rpc Chat(stream ChatMessage) returns (stream ChatMessage);
}
message ChatMessage {
string user = 1;
string message = 2;
int64 timestamp = 3;
}
Di sini:
ChatService
punya metodeChat
yang bi-directional streaming.ChatMessage
mewakili format pesan chat.
2. Generate Kode gRPC
Jalankan berikut untuk generate kode Go:
protoc --go_out=. --go-grpc_out=. chat.proto
3. Implementasi Server
File server.go
:
package main
import (
"log"
"net"
"sync"
pb "yourrepo/chat"
"google.golang.org/grpc"
)
type chatServer struct {
pb.UnimplementedChatServiceServer
mu sync.Mutex
streams map[string]pb.ChatService_ChatServer
}
func newServer() *chatServer {
return &chatServer{
streams: make(map[string]pb.ChatService_ChatServer),
}
}
func (s *chatServer) Chat(stream pb.ChatService_ChatServer) error {
var user string
for {
msg, err := stream.Recv()
if err != nil {
log.Printf("user %s left: %v", user, err)
s.mu.Lock()
delete(s.streams, user)
s.mu.Unlock()
return err
}
user = msg.User
// Register stream
s.mu.Lock()
s.streams[user] = stream
s.mu.Unlock()
// Broadcast ke semua fitur (simulate group chat)
s.mu.Lock()
for u, sstr := range s.streams {
if u != user {
sstr.Send(msg)
}
}
s.mu.Unlock()
}
}
func main() {
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterChatServiceServer(s, newServer())
log.Println("Chat server running on :50051")
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
Penjelasan:
- Setiap user yang connect didaftarkan dalam map
streams
. - Ketika receive pesan, server broadcast ke setiap client lain.
- Koneksi streaming open selama client terhubung.
4. Implementasi Client
File client.go
:
package main
import (
"bufio"
"context"
"log"
"os"
"time"
pb "yourrepo/chat"
"google.golang.org/grpc"
)
func main() {
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
if err != nil { log.Fatalf("fail to dial: %v", err) }
defer conn.Close()
client := pb.NewChatServiceClient(conn)
stream, err := client.Chat(context.Background())
if err != nil { log.Fatalf("fail to open stream: %v", err) }
// Goroutine untuk menerima pesan
go func() {
for {
resp, err := stream.Recv()
if err != nil {
log.Printf("Disconnected: %v", err)
return
}
log.Printf("%s: %s", resp.User, resp.Message)
}
}()
// Kirim pesan dari stdin
reader := bufio.NewReader(os.Stdin)
user := os.Getenv("USER")
for {
text, _ := reader.ReadString('\n')
stream.Send(&pb.ChatMessage{
User: user,
Message: text,
Timestamp: time.Now().Unix(),
})
}
}
Simulasi Alur Kerja
Misal, ada dua user: Alice dan Bob.
Step | Alice (client1) | Server | Bob (client2) |
---|---|---|---|
1 | Connect & stream | Stream register | |
2 | Connect & stream | ||
3 | “Hai Bob!” | Terima, broadcast | Terima broadcast |
4 | “Hai Alice!” | ||
5 | Terima, broadcast | Terima broadcast |
Sequence Diagram
sequenceDiagram Alice->>Server: Open stream Bob->>Server: Open stream Alice->>Server: Send "Hai Bob!" Server->>Bob: Send "Hai Bob!" (broadcast) Bob->>Server: Send "Hai Alice!" Server->>Alice: Send "Hai Alice!" (broadcast)
Tabel: Tipe RPC pada gRPC
Jenis RPC | Client Request | Server Response | Kapan Dipakai |
---|---|---|---|
Unary RPC | Single | Single | CRUD, standar API |
Server Streaming | Single | Multiple (stream) | Notifikasi, Download File |
Client Streaming | Multiple | Single | Upload file potongan, batch insert |
Bidirectional Streaming | Multiple | Multiple (stream) | Chat, collaborative, telemetri |
Tantangan & Best Practices
Tantangan
- State management pada server lebih ribet, perlu mapping antara user dan stream.
- Harus handling error/koneksi mati dengan baik agar tidak memory leak.
- Sinkronisasi data jika butuh persistensi.
Best Practices
- Gunakan mutex/lock pada akses map stream untuk thread safety.
- Tutup stream ketika client disconnect untuk menghindari resource leak.
- Jangan kirim terlalu banyak pesan besar atau sangat sering tanpa flow control.
- Logging penting untuk memonitor traffic/latency.
Kesimpulan
Implementasi Bidirectional Streaming RPC di gRPC memungkinkan aplikasi yang membutuhkan komunikasi dua arah secara real-time menjadi jauh lebih mudah dikembangkan. Dengan kerangka kerja network yang sudah dioptimasi dan antarmuka deklaratif via proto file, developer ‘hanya’ perlu fokus di logika aplikasi.
Jangan lupa, fitur bi-directional streaming ini harus diimplementasikan dengan memerhatikan resource management dan concurrency agar aplikasi Anda tetap scalable dan robust.
Sudah siap membangun aplikasi dengan pengalaman interaktif yang realtime, scalable dan efisien? Saatnya eksplor lebih dalam potensi gRPC Bidirectional Streaming di proyek Anda berikutnya! 🚀
Sumber kode dan demo lengkap bisa cek di repo Github ini.
Terimakasih sudah membaca. Jika ada pertanyaan/saran, silakan kolom komentar atau DM saya di Medium!
1 Apa Itu GraphQL? Konsep Dasar dan Manfaatnya
Artikel Terhangat
47 Membuat Mutation Login dan Signup
08 Aug 2025
69. Studi Kasus: Retry dan Backoff Strategy
08 Aug 2025
46 Menambahkan Middleware Autentikasi JWT
08 Aug 2025
68. Kompresi Data (gzip) di gRPC
08 Aug 2025
67. Retry Mechanism di Client gRPC
08 Aug 2025
44 Mocking Database untuk Test Resolver
08 Aug 2025
66. Deadline dan Timeout pada gRPC
08 Aug 2025

47 Membuat Mutation Login dan Signup

69. Studi Kasus: Retry dan Backoff Strategy

46 Menambahkan Middleware Autentikasi JWT

68. Kompresi Data (gzip) di gRPC

67. Retry Mechanism di Client gRPC

44 Mocking Database untuk Test Resolver
