Foto oleh Steve Johnson dari Unsplash
Tentang RPC
Pada proses pengembangan aplikasi, proses mengintegrasikan komponen-komponen seperti database maupun sistem eksternal menjadi salah satu bagian yang sulit dipisahkan. Proses integrasi ini lazimnya menggunakan API (Application Programming Interface) dari database atau sistem eksternal tertentu. Misalnya, ketika ingin mengintegrasikan database MySQL, kita perlu mengetahui perintah-perintah yang telah disediakan oleh MySQL baik lewat CLI (Command Line Interface) atau database connector dari bahasa pemrograman yang kita gunakan supaya kita bisa memanipulasi data di dalam database tersebut.
Cara lain yang lebih populer untuk mengintegrasikan aplikasi adalah menggunakan RPC atau HTTP/JSON API. RPC bisa digunakan untuk mengintegrasikan aplikasi jika performa menjadi pertimbangan, serta kita memiliki kendali penuh terhadap prosedur dari service yang kita kelola, sedangkan HTTP/JSON API digunakan jika aplikasi yang dikembangkan memperimbangkan kemudahan proses pengembangan serta aplikasi tersebut memiliki rencana untuk dikembangkan oleh orang lain di masa depan.
Tentang gRPC
gRPC merupakan RPC framework yang dikembangkan oleh Google. Seperti RPC pada umumnya, gRPC bekerja seperti memanggil fungsi atau prosedur dari suatu mesin oleh mesin lain secara remote.
gRPC menggunakan protobuf
atau protocol buffer sebagai format atau kontrak yang digunakan untuk berkomunikasi antara client/stub dengan server. Isi dari file protobuf
ini adalah service
yang merupakan method yang akan dipanggil oleh client, serta message
yang merupakan data atau parameter yang diterima oleh service
. File protobuf
ini harus di-compile ke dalam bahasa pemrograman yang ingin kita gunakan. Pada gambar di atas, dengan menggunakan file protobuf
yang sama, gRPC server yang ditulis menggunakan bahasa C++ bisa berkomunikasi dengan gRPC client yang ditulis menggunakan bahasa Java atau Ruby.
Ada beberapa daur hidup atau life cycle penggunaan gRPC yang bisa kita gunakan, diantaranya :
- Unary : Proses ini berjalan satu arah, di mana client akan memanggil method/service pada server, dan server akan mengembalikan response jika service tersebut selesai diproses.
- Server/Client Streaming : Proses ini bisa berjalan baik di sisi server atau client, dan proses ini mirip dengan unary. Hanya saja, data yang dikirim oleh server atau client dikirim secara kontinu/streaming hingga tidak ada yang bisa dikirim data dari server atau client.
- Bidirectional Streaming : Proses ini berjalan secara dua arah, di mana baik server atau client akan mengirim data hingga tidak ada data yang bisa dikirim atau salah satu dari server atau client menghentikan proses pengiriman data.
Praktik
Mengunduh Protobuf Compiler
Hal pertama yang perlu dipersiapkan adalah protobuf compiler. Compiler tersebut berguna untuk men-generate kode bahasa pemrograman dari file .proto
yang kita buat. Teman-teman bisa mengunjungi tautan ini untuk mengunduh compiler protobuf berdasarkan operating system yang teman-teman gunakan. Artikel ini menggunakan protobuf compiler untuk windows 64 bit versi 3.21.12
.
Setelah teman-teman berhasil mengunduh protobuf compiler dan mengekstrak file zip tersebut, langkah selanjutnya adalah menambahkan path folder bin
protobuf compiler yang telah diunduh ke environment variable. Folder bin
yang dimaksud adalah seperti ini.
Copy path executable file tersebut, lalu paste ke Path
pada environment. Untuk menambahkan path executable file protobuf compiler ke environment variable, silakan teman-teman bisa cari Edit the system and environment variable
di search bar windows teman-teman. Kemudian pilih Path
pada bagian User variables for admin
, tekan New
, dan paste path bin folder protobuf compiler. Langkah-langkah tersebut seperti ini.
Untuk memeriksa apakah protobuf compiler sudah terpasang dengan benar, silakan teman-teman buka cmd
dan ketik protoc
. Jika protobuf compiler sudah terpasang dengan benar, maka tampilannya akan seperti ini.
Implementasi
Silakan teman-teman buat project/folder baru dengan struktur seperti ini.
Pada file student.proto
, kita akan menuliskan message
serta service
yang akan di-generate oleh protobuf compiler. Isi file student.proto
tersebut sebagai berikut.
syntax = "proto3";
option go_package = "./../pb";
import "google/protobuf/empty.proto";
package pb;
message StudentRequest{
string name = 1;
int32 id = 2;
}
service Students{
rpc RegisterStudent(StudentRequest) returns (google.protobuf.Empty);
}
Maksud dari file proto di atas dijelaskan pada tabel di bawah.
Potongan Kode | Penjelasan |
---|---|
syntax = "proto3"; |
Menentukan versi protobuf yang digunakan. Pada contoh ini, versi yang digunakan adalah versi 3 |
option go_package = "./../pb"; |
Menentukan di mana file protobuf yang di-generate oleh protobuf compiler akan di simpan. Pada contoh ini, seluruh generated file protobuf akan disimpan di dalam folder pb yang letaknya relatif terhadap lokasi file .proto
|
import "google/protobuf/empty.proto"; |
Melakukan import file proto dari package/folder lain |
package pb; |
Menentukan nama package dari file proto yang di-generate oleh protobuf compiler |
message StudentRequest{} |
Mendefinisikan message/payload yang akan digunakan. Setelah file proto berhasil di-generate, untuk bahasa Go , protobuf compiler akan membuat struct dengan nama StudentRequest
|
service Students{} |
Mendefinisikan procedure/service yang akan dipanggil/invoke. Protobuf compiler akan men-generate interface StudentServer dan StudentClient dengan isi interface berupa method yang didefinisikan di dalam service Students{}
|
rpc RegisterStudent(StudentRequest) returns (google.protobuf.Empty); |
Mendefiniskan method/contract yang akan digunakan oleh client dan server. Protobuf compiler akan men-generate method RegisterStudent yang akan di-implement oleh StudentServer dan StudentClient
|
Untuk menghasilkan generated file, kita perlu meng-ompile file proto di atas dengan command sebagai berikut :
protoc --go_out=. --go-grpc_out=. *.proto
Perintah di atas dijalankan pada direktori di mana file proto berada. Gambar di bawah ini menunjukkan file proto yang berhasil dikompilasi.
Implementasi Dalam Golang
File proto yang telah dikompilasi kemudian bisa digunakan menggunakan bahasa pemrograman yang didukung oleh gRPC dan Protobuf (bahasa pemrograman yang didukung gRPC bisa dilihat di sini dan bahasa pemrograman yang didukung Protocol BUffer bisa dilihat di sini).
Di dalam file student_grpc.pb.go
, kita akan menemukan interface sebagai berikut :
type StudentsClient interface {
RegisterStudent(ctx context.Context, in *StudentRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
}
...
type StudentsServer interface {
RegisterStudent(context.Context, *StudentRequest) (*emptypb.Empty, error)
mustEmbedUnimplementedStudentsServer()
}
Interface StudentsServer
dan StudentsClient
merupakan service Students{}
dan method RegisterStudent
merupakan rpc RegisterStudent
yang di-generate oleh file proto yang telah kita buat. Interface tersebut harus kita implementasi baik di client atau server kita. Pada artikel ini, kita akan mengimplementasi StudentServer
. Implementasi tersebut kita tulis dalam file server/main.go
package main
import (
"context"
"go-grpc-unary/common/pb"
"log"
"net"
"os"
"os/signal"
"syscall"
"google.golang.org/grpc"
"google.golang.org/protobuf/types/known/emptypb"
)
type Server struct {
pb.UnimplementedStudentsServer
}
const PORT = ":9000"
func (s *Server) RegisterStudent(ctx context.Context, in *pb.StudentRequest) (*emptypb.Empty, error) {
log.Println(in.Name)
log.Println(in.Id)
return new(emptypb.Empty), nil
}
func initGrpcServer() {
l, err := net.Listen("tcp", PORT)
if err != nil {
log.Fatalf("unable to create tcp connection at port %v with error %v \n", PORT, err)
}
srv := grpc.NewServer()
pb.RegisterStudentsServer(srv, &Server{})
srv.Serve(l)
}
func main() {
done := make(chan os.Signal, 1)
signal.Notify(done, syscall.SIGINT, syscall.SIGTERM)
go initGrpcServer()
<-done
}
Pengujian Menggunakan Postman
Pada artikel ini, kita akan menggunakan Postman untuk menguji gRPC endpoint yang telah kita buat.
Pertama, kita perlu membuat gRPC Request
seperti pada gambar.
Kemudian, kita melakukan import file proto yang telah kita definisikan. Perhatikan bagian Import paths
yang ditandai merah. Bagian tersebut kita isi dengan path di mana kita meng-import file proto lain pada file proto yang kita tulis. Pada file proto, kita menuliskan import "google/protobuf/empty.proto";
, di mana kita meng-import file empty.proto
. File tersebut merupakan file bawaan dari protobuf yang terletak di dalam folder include/google/protobuf
(silakan kembali ke bagian Mengunduh Protocol Buffer untuk mengetahui lokasi folder tersebut).
Kemudian, pilih save without importing
untuk menyelesaikan proses import file proto.
Isikan server URL dengan localhost:9000
. Pada bagian Select a method
, kita dapat melihat gRPC contract/method yang telah kita definisikan di file proto, pada hal ini rpc RegisterStudent
. Pilih method tersebut, dan isikan data yang akan dikirim menggunakan Generate Example Message
.
Jalankan server di direktori server/main.go
menggunakan go run main.go
pada direktori tersebut, kemudian Invoke
method RegisterStudent
. Jika Status code
adalah 0, berarti data tersebut berhasil diterima oleh server. Jika kita melihat logging dari server/main.go
, kita akan melihat data yang dikirim dari Postman.
logging server/main.go
2023/01/27 11:04:43 magna
2023/01/27 11:04:43 -279401480
Rangkuman
Pada artikel ini, kita telah belajar apa itu gRPC, Protocol Buffer, cara membuat file protobuf, mengompilasi file protobuf, mengimplementasi dalam bahasa Go
, serta menguji menggunakan Postman. Banyak hal yang tidak dibahas di artikel ini. Penulis merekomendasikan teman-teman untuk membaca tentang server streaming, client streaming, bidirectional streaming, serta cara lain mendefinisikan message di file protobuf
Referensi
https://cloud.google.com/blog/products/api-management/understanding-grpc-openapi-and-rest-and-when-to-use-them
https://developers.google.com/protocol-buffers/docs/reference/overview
https://grpc.io/docs/
Top comments (1)
love you dude!