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
2 Perbandingan Singkat: GraphQL vs REST API
07 Jul 2025
24 Implementasi Bidirectional Streaming RPC
07 Jul 2025
23 Implementasi Client-side Streaming RPC
07 Jul 2025
22 Implementasi Server-side Streaming RPC
06 Jun 2025
21 Memahami Konsep Streaming pada gRPC
06 Jun 2025
20 Menambahkan Interceptor Unary di Client
06 Jun 2025
19 Menambahkan Interceptor Unary di Server
06 Jun 2025

2 Perbandingan Singkat: GraphQL vs REST API

24 Implementasi Bidirectional Streaming RPC

23 Implementasi Client-side Streaming RPC

22 Implementasi Server-side Streaming RPC

21 Memahami Konsep Streaming pada gRPC

20 Menambahkan Interceptor Unary di Client
