28 Studi Kasus: Streaming Chat Sederhana
Chat menjadi salah satu fitur yang wajib ada pada banyak aplikasi modern saat ini. Entah itu website toko daring, aplikasi edukasi, atau platform komunitas—semua membutuhkan interaksi real-time agar pengguna merasa lebih terlibat. Pada artikel kali ini, saya akan membahas studi kasus sederhana: bagaimana merancang dan mengimplementasikan sistem chat streaming menggunakan teknologi gRPC Streaming yang populer di lingkungan backend modern.
Studi Kasus: Persyaratan & Arsitektur
Persyaratan Fitur
- Pengguna dapat mengirim pesan chat.
- Semua pengguna yang terhubung dapat menerima pesan chat terbaru secara real-time.
- Setiap pengguna dapat melihat histori sesi chat ketika mereka masuk.
- Sistem cukup sederhana untuk dijalankan secara lokal.
- Toleransi sederhana terhadap multiple client.
Diagram Arsitektur
flowchart TD
Client1 -->|Bidirectional Streaming| gRPCServer
Client2 -->|Bidirectional Streaming| gRPCServer
gRPCServer -->|Store Chat| DB[(Database)]
- Klien membuka koneksi bidirectional streaming dengan server gRPC.
- Ketika pesan dikirim, server menyimpannya ke database (atau memori), lalu melemparkannya ke semua klien aktif.
1. Persiapan: Stack Teknologi
- Bahasa: Go
- gRPC Framework:
google.golang.org/grpc - Protobuf Compiler:
protoc - Database: In-memory (slice/array) atau SQLite/Redis (opsional untuk persistensi)
2. Definisi Protobuf
chat.proto
1syntax = "proto3";
2
3package chat;
4
5message ChatMessage {
6 string username = 1;
7 string message = 2;
8 string timestamp = 3;
9}
10
11service ChatService {
12 rpc ChatStream(stream ChatMessage) returns (stream ChatMessage);
13}3. Implementasi Server gRPC di Go
1package main
2
3import (
4 "context"
5 "fmt"
6 "log"
7 "net"
8 "sync"
9 "time"
10
11 pb "yourmodule/chat"
12 "google.golang.org/grpc"
13)
14
15type chatServer struct {
16 pb.UnimplementedChatServiceServer
17 mu sync.Mutex
18 clients map[string]pb.ChatService_ChatStreamServer
19 msgs []pb.ChatMessage
20}
21
22func (s *chatServer) ChatStream(stream pb.ChatService_ChatStreamServer) error {
23 id := fmt.Sprintf("client-%d", time.Now().UnixNano())
24 s.mu.Lock()
25 s.clients[id] = stream
26 for _, msg := range s.msgs {
27 stream.Send(&msg)
28 }
29 s.mu.Unlock()
30
31 defer func() {
32 s.mu.Lock()
33 delete(s.clients, id)
34 s.mu.Unlock()
35 }()
36
37 for {
38 msg, err := stream.Recv()
39 if err != nil {
40 log.Printf("client %s disconnected", id)
41 return err
42 }
43
44 msg.Timestamp = time.Now().Format(time.RFC3339)
45 s.mu.Lock()
46 s.msgs = append(s.msgs, *msg)
47 for _, c := range s.clients {
48 if err := c.Send(msg); err != nil {
49 log.Println("send error:", err)
50 }
51 }
52 s.mu.Unlock()
53 }
54}
55
56func main() {
57 lis, err := net.Listen("tcp", ":50051")
58 if err != nil {
59 log.Fatalf("failed to listen: %v", err)
60 }
61 server := grpc.NewServer()
62 pb.RegisterChatServiceServer(server, &chatServer{
63 clients: make(map[string]pb.ChatService_ChatStreamServer),
64 })
65 log.Println("gRPC chat server started on :50051")
66 server.Serve(lis)
67}4. Simulasi Client gRPC
1package main
2
3import (
4 "context"
5 "fmt"
6 "log"
7 "time"
8
9 pb "yourmodule/chat"
10 "google.golang.org/grpc"
11)
12
13func main() {
14 conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
15 if err != nil {
16 log.Fatalf("fail connect: %v", err)
17 }
18 defer conn.Close()
19
20 client := pb.NewChatServiceClient(conn)
21 stream, err := client.ChatStream(context.Background())
22 if err != nil {
23 log.Fatalf("fail stream: %v", err)
24 }
25
26 // Receive stream
27 go func() {
28 for {
29 msg, err := stream.Recv()
30 if err != nil {
31 log.Fatal(err)
32 }
33 fmt.Printf("[%s] %s: %s\n", msg.Timestamp, msg.Username, msg.Message)
34 }
35 }()
36
37 // Send messages
38 for {
39 var text string
40 fmt.Print("> ")
41 fmt.Scanln(&text)
42 stream.Send(&pb.ChatMessage{
43 Username: "ihsan",
44 Message: text,
45 })
46 }
47}5. Tabel Komponen dan Fungsinya
| Komponen | Fungsi |
|---|---|
ChatService.ChatStream | Endpoint utama gRPC untuk bidirectional streaming chat |
ChatMessage | Struktur data pesan yang dikirim dan diterima |
map[string]stream | Daftar koneksi klien aktif untuk broadcast |
[]ChatMessage | Riwayat chat untuk dikirim ulang saat klien terhubung |
6. Diagram Sekuensial Proses
sequenceDiagram
participant Client as Klien
participant Server as gRPC Server
Client->>Server: Buka Stream
Server-->>Client: Kirim histori pesan
loop Chat
Client->>Server: Kirim ChatMessage
Server->>Server: Simpan pesan
Server->>Client: Broadcast ke semua klien
end
7. Kesimpulan
Dengan memanfaatkan gRPC bidirectional streaming, kita bisa membangun sistem chat real-time yang ringan, cepat, dan efisien untuk banyak klien. Pendekatan ini cocok untuk berbagai kebutuhan backend modern mulai dari fitur live support hingga aplikasi kolaborasi.
Untuk pengembangan lebih lanjut, Anda bisa menambahkan autentikasi, menyimpan pesan ke database sungguhan, atau mengintegrasikan sistem pub/sub seperti Redis agar bisa dijalankan secara horizontal.
Selamat mencoba dan semoga bermanfaat! 🚀