tutorial

  1. gRPC Health Checking Standar

63. gRPC Health Checking Standar: Modern Approach for Microservices Reliability


Ketika membangun sistem terdistribusi berbasis microservices, memastikan setiap layanan berjalan dengan baik adalah hal krusial. Kegagalan satu service bisa berdampak ke keseluruhan sistem. Untuk itu, health check menjadi fondasi penting. Namun, bagaimana cara melakukan health check pada service berbasis gRPC, protokol RPC modern pilihan para engineer?

Di artikel ini, saya akan bahas standar gRPC Health Checking — termasuk konsep, implementasi, simulasi, contoh kode, dan best practice yang sudah banyak diadopsi industri.


Kenapa Health Check pada gRPC Penting?

Pada aplikasi tradisional HTTP/REST, health check biasanya cukup mudah: expose endpoint seperti GET /healthz yang mengembalikan status layanan (200 OK, 503 Service Unavailable, dst). Load balancer atau orchestrator seperti Kubernetes lalu menggunakan endpoint tersebut untuk memantau dan men-deploy ulang service yang gagal.

Namun, pada arsitektur gRPC, service hanya expose port binary, bukan endpoint HTTP. Tidak ada standar universal untuk health check seperti halnya pada REST API. Tanpa health check, orchestrator tidak tahu kapan harus mengganti atau memperbaiki instance service.

Di sinilah gRPC Health Checking Protocol (atau Health Checking Standard) berperan penting.


Standar gRPC Health Checking

gRPC Health Checking Protocol adalah standar terbuka untuk memeriksa status layanan gRPC. Standar ini didefinisikan sebagai sebuah service dengan nama grpc.health.v1.Health. Service ini memiliki method-method sederhana, yang memudahkan klien (load balancer, sidecar, orchestrator) untuk mengecek status service.

Definisi Protobuf

Berikut adalah definisi service health-check menurut protokol standar:

syntax = "proto3";

package grpc.health.v1;

service Health {
    // Cek status satu service
    rpc Check(HealthCheckRequest) returns (HealthCheckResponse);

    // Streaming status secara kontinu
    rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse);
}

message HealthCheckRequest {
    string service = 1;
}

message HealthCheckResponse {
    enum ServingStatus {
        UNKNOWN = 0;
        SERVING = 1;
        NOT_SERVING = 2;
        SERVICE_UNKNOWN = 3;  // status untuk service yang belum diketahui, hanya digunakan oleh Watch.
    }
    ServingStatus status = 1;
}
  1. Check: Klien mengirimkan nama service, mendapat status SERVING/NOT_SERVING.
  2. Watch: Klien bisa subscribe perubahan status secara realtime (misal, untuk load balancer/sidecar).

Tabel status:

StatusArti
UNKNOWNStatus tidak diketahui
SERVINGService dalam keadaan sehat dan siap menerima request
NOT_SERVINGService sedang bermasalah (maintenance, sedang restart, dsb)
SERVICE_UNKNOWNService dengan nama itu tidak ditemukan (khusus Watch stream)

Diagram Alur Health Checking

Mari visualisasikan proses health check dengan diagram mermaid berikut:

sequenceDiagram
    participant Orchestrator as Orchestrator / Load Balancer
    participant Service as gRPC Service
    Orchestrator->>Service: Health.Check(serviceName)
    Service-->>Orchestrator: HealthCheckResponse(SERVING / NOT_SERVING)
    Note right of Orchestrator: Decision 
Based on response

Implementasi Health Check pada Language Client & Server

Implementasi di Server Go

Pada gRPC ecosystem tersedia standard implementation untuk health checking, misal di Go (google.golang.org/grpc/health).

1. Server Setup

Misal, Anda punya service seperti di bawah ini:

package main

import (
    "context"
    "google.golang.org/grpc"
    "google.golang.org/grpc/health"
    healthpb "google.golang.org/grpc/health/grpc_health_v1"
    "net"
    "log"
)

func main() {
    lis, err := net.Listen("tcp", ":50051")
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()

    // Buat instance gRPC health check
    healthServer := health.NewServer()

    // Tandai server ini SERVING status awal
    healthServer.SetServingStatus("", healthpb.HealthCheckResponse_SERVING)
    healthpb.RegisterHealthServer(s, healthServer)

    log.Println("gRPC server with healthcheck running at :50051")
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

2. Simulasi: Ubah Status Health Check

Misalkan saat maintenance, Anda ingin men-declare layanan tidak sehat (NOT_SERVING). Anda cukup update status dengan method SetServingStatus:

// Notifikasi orchestrator dan load balancer service sedang maintenance
healthServer.SetServingStatus("", healthpb.HealthCheckResponse_NOT_SERVING)

Client: Simulasi Health Check dengan Go

Sebagai client (misal load balancer, kubernetes-probe, dsb), Anda cukup panggil method berikut:

import (
    "context"
    "google.golang.org/grpc"
    healthpb "google.golang.org/grpc/health/grpc_health_v1"
    "log"
    "time"
)

func main() {
    conn, err := grpc.Dial(":50051", grpc.WithInsecure())
    if err != nil {
        log.Fatal("fail connect:", err)
    }
    defer conn.Close()
    hc := healthpb.NewHealthClient(conn)
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()

    res, err := hc.Check(ctx, &healthpb.HealthCheckRequest{Service: ""}) // Empty = seluruh server
    if err != nil {
        log.Fatalf("could not check health: %v", err)
    }
    log.Printf("Health status: %s", res.Status)
}

Integrasi dengan Kubernetes

Di Kubernetes, probe HTTP bukan solusi ideal untuk gRPC. Namun, dengan standar gRPC health, Kubernetes >=v1.23 sudah mendukung grpc.health/v1:

livenessProbe:
  grpc:
    port: 50051
readinessProbe:
  grpc:
    port: 50051

Hasil: Kubernetes langsung tanya ke service via health protocol, tanpa HTTP endpoint tambahan.


Best Practice dan Tips

  1. Selalu Expose Health Service
    Semua gRPC service disarankan menjalankan standar health check. Banyak framework sudah menyediakan otomatisasi ini.

  2. Granular Health Checking
    Anda bisa gunakan nama service pada request untuk granularitas status (misal: database, cache).

  3. Dynamic Status
    Dinamis update status health secara periodik, misal jika gagal konek ke dependency (DB down, dsb).

  4. Gunakan Stream Watch
    Jika environment Anda support, manfaatkan Watch untuk notifikasi real-time status service.

  5. Security Concern
    Untuk keamanan, expose hanya pada internal network atau gunakan mTLS antara orchestrator dan service.


Studi Kasus: Health Check untuk Multiple Dependencies

Misal, gRPC service Anda tergantung pada beberapa database. Anda bisa buat proses checker seperti berikut (pseudo-code):

go func() {
    for {
        if db.Ping() == nil && redis.Ping() == nil {
            healthServer.SetServingStatus("", healthpb.HealthCheckResponse_SERVING)
        } else {
            healthServer.SetServingStatus("", healthpb.HealthCheckResponse_NOT_SERVING)
        }
        time.Sleep(time.Second)
    }
}()

Dengan ini, status health akan selalu update secara live.


Kesimpulan

gRPC health checking standard adalah solusi modern untuk reliability application microservices. Ia membantu load balancer, orchestrator, dan monitoring system untuk mendeteksi dini kegagalan tanpa harus menambah endpoint HTTP baru. Dengan standar ini, Anda bisa menghadirkan arsitektur yang robust, maintainable, dan future-proof.

Jangan lupa: reliability aplikasi Anda adalah hasil dari disiplin menerapkan standar seperti ini!


Referensi:


Selamat mencoba, show the world your healthy microservices! 🚀

comments powered by Disqus