Protobuf & gRPC
Memahami Protobuf (Protocol Buffers) dan gRPC β serialisasi data efisien dan RPC berperforma tinggi untuk sistem terdistribusi.
Versi Bahasa Indonesia. Baca dalam Bahasa Inggris
Protobuf
Protobuf (Protocol Buffers) adalah format serialisasi data yang netral bahasa dan platform, dikembangkan oleh Google. Ini dirancang untuk komunikasi dan penyimpanan yang efisien, terutama dalam sistem terdistribusi.
- Ringkas dan Efisien: Protobuf menggunakan serialisasi biner, yang lebih kecil dan lebih cepat daripada format seperti JSON atau XML.
- Berbasis Skema: Data didefinisikan dalam file .proto menggunakan skema, yang memastikan pengetikan yang ketat dan kompatibilitas. Kurang ambigu dan lebih mudah digunakan secara programatis.
- Cross-language: Didukung di banyak bahasa seperti Go, Python, Java, dll.
gRPC
(Google Remote Procedure Calls) adalah framework RPC berperforma tinggi yang menggunakan Protobuf untuk serialisasi data. Ini memungkinkan komunikasi yang mulus antar layanan, terlepas dari bahasa pemrograman.
- Mendukung Beberapa Jenis Komunikasi:
- Unary (satu request, satu response)
- Server-streaming (satu request, banyak response)
- Client-streaming (banyak request, satu response)
- Bi-directional streaming (banyak request, banyak response)
- Code Generation Bawaan: gRPC menghasilkan stub klien dan server secara otomatis dari file
.proto. - Dukungan HTTP/2: Memungkinkan multiplexing, kompresi, dan performa yang lebih baik dibandingkan HTTP/1.1.
Contoh
Definisikan File Protobuf
user.proto
syntax = "proto3";
package user;
service UserService {
// Unary RPC: Meminta detail pengguna
rpc GetUser(GetUserRequest) returns (GetUserResponse);
}
message GetUserRequest {
string id = 1; // ID Pengguna
}
message GetUserResponse {
string id = 1;
string name = 2;
int32 age = 3;
}Generate Code
Jalankan perintah berikut untuk menghasilkan kode (contoh untuk Go):
protoc --go_out=. --go-grpc_out=. user.protoIni menghasilkan:
user.pb.go: Berisi definisi message Protobuf.user_grpc.pb.go: Berisi definisi service gRPC (interface untuk server dan client).
Langkah 3: Implementasi Server
server.go
package main
import (
"context"
"log"
"net"
"google.golang.org/grpc"
pb "path/to/generated/user" // Sesuaikan dengan path sebenarnya
)
// Server struct mengimplementasikan interface UserServiceServer yang dihasilkan
type Server struct {
pb.UnimplementedUserServiceServer
}
// Implementasi method GetUser
func (s *Server) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.GetUserResponse, error) {
log.Printf("Menerima request untuk user ID: %s", req.Id)
// Data pengguna palsu (mock)
user := &pb.GetUserResponse{
Id: req.Id,
Name: "John Doe",
Age: 30,
}
return user, nil
}
func main() {
listener, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("Gagal mendengarkan: %v", err)
}
grpcServer := grpc.NewServer()
pb.RegisterUserServiceServer(grpcServer, &Server{})
log.Println("Server berjalan di port 50051")
if err := grpcServer.Serve(listener); err != nil {
log.Fatalf("Gagal serve: %v", err)
}
}Implementasi Client
client.go
package main
import (
"context"
"log"
"time"
"google.golang.org/grpc"
pb "path/to/generated/user" // Sesuaikan dengan path sebenarnya
)
func main() {
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
if err != nil {
log.Fatalf("Gagal terhubung ke server: %v", err)
}
defer conn.Close()
client := pb.NewUserServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
// Panggil RPC GetUser
req := &pb.GetUserRequest{Id: "123"}
resp, err := client.GetUser(ctx, req)
if err != nil {
log.Fatalf("Error memanggil GetUser: %v", err)
}
log.Printf("Detail pengguna: ID=%s, Name=%s, Age=%d", resp.Id, resp.Name, resp.Age)
}Jalankan Sistem
Mulai server gRPC:
go run server.goJalankan client:
go run client.goOutput
Di server:
Menerima request untuk user ID: 123Di client:
Detail pengguna: ID=123, Name=John Doe, Age=30Last updated on