tutorial

16 Penanganan Error di Server gRPC

16. Penanganan Error di Server gRPC

Pada arsitektur sistem terdistribusi modern, gRPC menjadi salah satu protokol RPC yang diandalkan untuk komunikasi antar layanan karena efisiensi, dukungan multi bahasa, dan transportasinya yang robust (HTTP/2). Namun, seperti sistem terdistribusi pada umumnya, failure pasti terjadi—mulai dari permintaan tidak valid, layanan tidak tersedia, hingga masalah autentikasi. Penanganan error yang baik di sisi server gRPC akan sangat berpengaruh pada experience klien, reliability sistem secara keseluruhan, sekaligus kemudahan troubleshooting.

Artikel ini membahas praktik penanganan error di server gRPC berbasis pengalaman nyata dan insight engineering terbaik, lengkap dengan contoh kode, simulasi kasus error, serta ilustrasi diagram alurnya.


gRPC Error Model: Menalar Arsitektur

gRPC membangun standar error berdasarkan status codes dari Google RPC dan mapping-nya pada http status. Setiap RPC dapat mengembalikan objek error dengan:

  • Kode status (codes)
  • Pesan error
  • Metadata opsional

Kode status gRPC merangkum beragam kasus umum seperti:

CodeDeskripsiHTTP Mapping
OKBerhasil200
CANCELLEDKlien membatalkan permintaan499
INVALID_ARGUMENTData input salah400
DEADLINE_EXCEEDEDTimeout504
NOT_FOUNDData tidak ditemukan404
ALREADY_EXISTSResource sudah ada409
PERMISSION_DENIEDTidak punya akses403
UNAUTHENTICATEDTidak terautentikasi401
RESOURCE_EXHAUSTEDQuota habis429
INTERNALError server500
UNAVAILABLELayanan tidak tersedia503

Lebih lengkap bisa cek gRPC Status Codes.


Contoh Implementasi Error Handling di Server gRPC (Golang)

Kita akan memakai Go karena ekosistem gRPC-nya matang dan banyak digunakan engineer backend.

Misalkan kita memiliki service UserService dengan RPC GetUser, tujuannya mengambil data user berdasarkan id.

Protobuf definition:

service UserService {
  rpc GetUser(GetUserRequest) returns (UserResponse);
}

message GetUserRequest {
  string id = 1;
}

message UserResponse {
  string id = 1;
  string name = 2;
  string email = 3;
}

Server gRPC dengan Penanganan Error

import (
    "context"
    "errors"

    pb "github.com/company/proto"
    "google.golang.org/grpc/codes"
    "google.golang.org/grpc/status"
)

type UserServiceServer struct {
    pb.UnimplementedUserServiceServer
    users map[string]*pb.UserResponse
}

func NewUserServiceServer() *UserServiceServer {
    return &UserServiceServer{
        users: map[string]*pb.UserResponse{
            "1": {Id: "1", Name: "Budi", Email: "budi@email.com"},
        },
    }
}

func (s *UserServiceServer) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.UserResponse, error) {
    if req.GetId() == "" {
        // Simulasi input invalid
        return nil, status.Error(codes.InvalidArgument, "user id tidak boleh kosong")
    }

    user, ok := s.users[req.GetId()]
    if !ok {
        // Simulasi data tidak ditemukan
        return nil, status.Error(codes.NotFound, "user tidak ditemukan")
    }

    // Simulasi error internal
    if req.GetId() == "999" {
        return nil, status.Errorf(codes.Internal, "internal error: %v", errors.New("simulasi panic"))
    }

    return user, nil
}

Catatan:

  • Error di-wrapping dengan status.Error(codes.XXXX, "pesan error").
  • Pesan error usahakan jelas (tidak hanya “error occurred”).
  • Mapping error sesuai dengan root cause, jangan asal pakai INTERNAL.

Simulasi Kasus Error

Mari kita uji 3 skenario error:

  1. Input tidak valid: id kosong.
  2. User tidak ditemukan: id tidak ada di database.
  3. Internal error: id = “999”, trigger error sistem.

Tabel Simulasi Response

RequestKode ErrorPesan ErrorHTTP
{id: ""}INVALID_ARGUMENTuser id tidak boleh kosong400
{id: "2"}NOT_FOUNDuser tidak ditemukan404
{id: "999"}INTERNALinternal error: simulasi panic500

Diagram Alur Penanganan Error gRPC di Server

Mari ilustrasikan proses penanganan error pada satu endpoint RPC:

flowchart TD
    A[Client kirim request GetUser] --> B{Validasi Input?}
    B -- No --> E[Return INVALID_ARGUMENT]
    B -- Yes --> C{User Ada?}
    C -- No --> F[Return NOT_FOUND]
    C -- Yes --> D{Terjadi Error Internal?}
    D -- Yes --> G[Return INTERNAL]
    D -- No --> H[Kirim Response Sukses]

Bagaimana Menyisipkan Metadata pada Error?

Sering kali kita ingin mengirimkan metadata tambahan pada error. Misal: error validation field mana yang salah.

gRPC mendukung penggunaan error details extension:

import "google.golang.org/genproto/googleapis/rpc/errdetails"

// Return details pada error
badRequest := &errdetails.BadRequest{
    FieldViolations: []*errdetails.BadRequest_FieldViolation{
        {
            Field:       "id",
            Description: "id tidak boleh kosong",
        },
    },
}

st := status.New(codes.InvalidArgument, "input tidak sesuai")
st, _ = st.WithDetails(badRequest)
return nil, st.Err()

Di klien, kita bisa parsing details-nya dan tampilkan error lebih informatif.


Best Practice Penanganan Error di Server gRPC

  1. Mapping yang Presisi: Gunakan kode error yang benar sesuai konteks, bukan asal INTERNAL.
  2. Pesan Human-Readable: Pesan error harus jelas, tidak menjebak, dan aman dari kebocoran data sensitif.
  3. Jangan Leak Internal Info: Untuk production, jangan expose stack trace atau query db ke klien.
  4. Gunakan Metadata/Details: Tambahkan error details bila perlu untuk kasus validasi kompleks.
  5. Standardisasi Handling: Buat middleware/interceptor error agar konsisten di semua endpoints.
  6. Log Error Internal: Selalu log error internal dengan detail untuk investigasi tanpa membocorkan ke user.
  7. Graceful Handling: Hindari panic, tangani error dalam flow yang terstruktur.
  8. Testing Error Paths: Jangan cuma test happy path, pastikan semua skenario error ter-cover.

Penutup

Error handling di server gRPC bukan sekedar return error, tapi soal komunikasi yang baik antar sistem dan engineer. Dengan mapping error yang tepat, pesan yang jelas, serta extensi metadata pada error, sistem gRPC kita menjadi lebih robust, maintainable, dan mudah diobservasi.
Ingat, error yang tidak ditangani dengan baik bisa lebih berbahaya daripada error itu sendiri.

Jangan lupa, error adalah bentuk komunikasi. Let’s make it meaningful!


Referensi:


Terima kasih sudah membaca! Share pengalaman atau tips error handling gRPC di kolom komentar. 🚀

comments powered by Disqus

Topik Terhangat

programming
171
tips-and-trick
43
tutorial
37
jaringan
28
hardware
11
linux
4
kubernetes
1