tutorial

  1. Studi Kasus: Desain API yang Konsisten untuk Microservices Multi-Bahasa dengan Protobuf


title: 110. Studi Kasus: Desain API yang Konsisten untuk Microservices Multi-Bahasa dengan Protobuf
author: Rifqi Ramadhan
date: 2024-06-10

Studi Kasus: Desain API yang Konsisten untuk Microservices Multi-Bahasa dengan Protobuf

Salah satu tantangan terbesar dalam pengembangan arsitektur microservices adalah memastikan konsistensi kontrak API antara banyak layanan yang ditulis dalam bahasa pemrograman berbeda (multi-bahasa). Dengan semakin beragamnya kebutuhan bisnis, tidak jarang sebuah sistem terdiri dari layanan berbasis Go, Java, Python, bahkan Node.js yang harus saling berkomunikasi dengan efisien, aman, dan tentunya konsisten.

Di artikel ini, saya akan membahas praktik terbaik mendesain API konsisten untuk microservices multi-bahasa menggunakan Protocol Buffers (Protobuf), dimulai dari studi kasus nyata, sample kode, hingga simulasi komunikasi, serta diagram alur implementasi-nya.


Studi Kasus: Layanan E-Commerce

Bayangkan sebuah platform e-commerce yang terdiri dari beberapa layanan utama:

  • Order Service (Go)
  • Inventory Service (Java)
  • User Service (Python)
  • Notification Service (Node.js)

Bagaimana kita bisa memastikan setiap service dapat berkomunikasi tanpa harus khawatir tentang perbedaan struktur data, konversi tipe, dan dokumentasi yang sulit dijaga?

Jawaban: DENGAN DESAIN API BERBASIS PROTOBUF.


Mengapa Protobuf?

Sebelum masuk ke teknis, mari kita bandingkan beberapa cara untuk mendesain API:

MetodeKelebihanKekurangan
REST+JSONMudah dibaca manusia, tooling luasTidak strict, rentan mismatch tipe, parsing lambat
GraphQLFleksibel query, self-docsOver-fetching, learning curve, eksekusi lambat
gRPC + ProtobufCepat, schema strict, tooling lintas bahasaKurang familiar, instalasi awal lebih rumit

Protobuf memaksa kita mendefinisikan kontrak secara eksplisit yang kemudian bisa digunakan untuk generate code client/server berbagai bahasa. For this use-case, it’s a winner!


Mendesain Kontrak Layanan Berbasis Protobuf

Contoh Kontrak: Service Order

File: order.proto

syntax = "proto3";

package ecommerce.order.v1;

message OrderRequest {
  string user_id = 1;
  repeated Item items = 2;
}

message Item {
  string sku = 1;
  int32 quantity = 2;
}

message OrderResponse {
  string order_id = 1;
  string status = 2; // PENDING, CONFIRMED, FAILED
}

service OrderService {
  rpc PlaceOrder (OrderRequest) returns (OrderResponse);
}

Penjelasan

  • Pendefinisian struktur data OrderRequest, Item, dan OrderResponse dijaga tetap sederhana, eksplisit, dan dapat digunakan lintas bahasa.
  • Service OrderService mendeskripsikan fungsi yang tersedia: misal RPC untuk memproses pemesanan.

Generate Kode untuk Bermacam Bahasa

Setelah mendefinisikan .proto, developer dapat generate kode client/server:

# Untuk Go
protoc --go_out=. --go-grpc_out=. order.proto

# Untuk Java
protoc --java_out=. --grpc-java_out=. order.proto

# Untuk Python
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. order.proto

Setiap language mempunyai library hasil generate yang 100% konsisten dengan definisi .proto.


Simulasi Interaksi Antar Microservices

Mari simulasikan Order Service (Go) yang mengakses Inventory Service (Java) memakai Protobuf.

Order Service (Go) — Memanggil Cek Stok

// inventory/v1/inventory.proto
syntax = "proto3";

package ecommerce.inventory.v1;

message StockRequest {
  string sku = 1;
}

message StockResponse {
  int32 available_quantity = 1;
}

service InventoryService {
  rpc CheckStock(StockRequest) returns (StockResponse);
}

Pemanggilan dari Order Service (Go)

conn, _ := grpc.Dial("inventory-service:50051", grpc.WithInsecure())
client := inventorypb.NewInventoryServiceClient(conn)

resp, err := client.CheckStock(context.Background(), &inventorypb.StockRequest{
  Sku: "SKU1234",
})
fmt.Printf("Stok: %d\n", resp.AvailableQuantity)

Poin Penting: Type safety dan struktur data konsisten walau berbeda implementasi.


Diagram Alur Proses Order

sequenceDiagram
    actor User
    participant OrderService (Go)
    participant InventoryService (Java)
    participant UserService (Python)
    participant NotificationService (NodeJS)

    User->>OrderService (Go): PlaceOrder(OrderRequest)
    OrderService (Go)->>InventoryService (Java): CheckStock(StockRequest)
    InventoryService (Java)-->>OrderService (Go): StockResponse
    OrderService (Go)->>UserService (Python): GetUserDetail(UserID)
    UserService (Python)-->>OrderService (Go): UserDetail
    OrderService (Go)->>NotificationService (NodeJS): SendNotif(Order)
    NotificationService (NodeJS)-->>OrderService (Go): NotifResponse
    OrderService (Go)-->>User: OrderResponse

Best Practices Desain Protobuf untuk Microservices Multi-bahasa

Berikut beberapa rekomendasi untuk menjaga konsistensi dan maintainability:

  1. Gunakan Nama Versi pada Paket

    • Contoh: package ecommerce.order.v1;
    • Memudahkan breaking change tanpa mengganggu klien lama.
  2. Komentar Isian penting

    • Lengkapi setiap field dengan komentar jelas, gunakan plugin doc/extractor bila perlu.
  3. Field Tag Tidak Pernah diubah

    • Tag (nomor di setiap field: sku = 1) tidak boleh berubah, rename field harus baru (misal tambahkan sku_code = 3 dan deprecated-kan sku = 1).
  4. Protobuf Lint

    • Gunakan linter/protobuf-lint di CI agar setiap definisi schema mengikuti gaya yang konsisten.
  5. Shared Protobuf Repo

    • Semua tim/service pointing ke repo yang sama sehingga schema selalu terbaru.

Studi Kasus: Penambahan Field Tanpa Breaking Change

Sebelum:

message OrderResponse {
  string order_id = 1;
  string status = 2;
}

Setelah (Penambahan Field):

message OrderResponse {
  string order_id = 1;
  string status = 2;
  string payment_reference = 3;
}

Semua klien lama tetap dapat memproses message! Klien baru akan memperoleh payment_reference jika disediakan.


Kelebihan untuk Bisnis dan Engineering

  • Adaptasi Bahasa Bebas: Tim dapat memilih bahasa/tools terbaik tanpa takut integrasi macet.
  • Type Safety: Developer yakin data yang masuk/keluar benar sesuai schema.
  • API-first Documentation: .proto file sekaligus dokumentasi formal API.
  • Otomatisasi & Generasi Kode: Proses update schema langsung memicu re-generasi interface client/server.

Kesimpulan

Pemilihan Protobuf untuk komunikasi microservices multi-bahasa secara signifikan mengurangi friction, meningkatkan kecepatan pengembangan, dan menjaga konsistensi kontrak antar tim developer. Studi kasus di atas membuktikan bahwa desain API yang kuat dan konsisten mampu menopang skala bisnis digital yang terus berkembang tanpa harus mengorbankan disiplin engineering.

Sudah siap mengadopsi Protobuf untuk ekosistem microservices-mu? Jangan lupa, mulailah dengan desain schema yang rapi, lintas bahasa, dan otomatis. Happy coding!


Referensi:


comments powered by Disqus