tutorial

  1. Integrasi gRPC dengan Envoy Proxy

74. Integrasi gRPC dengan Envoy Proxy


gRPC telah menjadi salah satu pilihan utama dalam membangun layanan microservices yang cepat, efisien, dan mudah dikembangkan. Namun, pada skala produksi, kebutuhan seperti load balancing, service discovery, observability, hingga mTLS sering kali menuntut adanya proxy canggih—dan di sinilah Envoy Proxy hadir sebagai solusi. Dalam artikel ini, saya akan membahas secara praktis bagaimana mengintegrasikan gRPC dengan Envoy Proxy, mulai dari konsep, benefit, hingga contoh implementasi yang bisa langsung kamu coba.

Mengapa Harus Menggunakan Envoy untuk gRPC?

Sebelum masuk ke kode dan simulasi, mari kita telaah alasan di balik keputusan untuk meletakkan Envoy di depan gRPC server:

  • gRPC memiliki protocol berbasis HTTP/2 yang tidak selalu kompatibel dengan proxy HTTP konvensional.
  • Load balancing cerdas: Envoy mendukung load balancing level aplikasi dan aware terhadap state koneksi HTTP2.
  • Observability: Integrasi logging, metrics (Prometheus), dan tracing (Jaeger, Zipkin) menjadi jauh lebih mudah.
  • Security: Envoy dapat mengenakan mTLS tanpa perlu memodifikasi aplikasi.
  • Network resilience: Dapat mengatur retry, timeouts, circuit breaking, dsb.

Komponen yang Akan Kita Bangun

Skenario sederhana yang akan kita simulasikan:

  • Service A: Client aplikasi (gRPC client)
  • Envoy Proxy: Sebagai reverse proxy dan load balancer
  • Service B: gRPC server (hello world)
  • Semua layanan berjalan secara lokal, bisa dengan Docker atau langsung run binary.

Arsitektur High-Level

flowchart LR
    subgraph Client Side
        A[gRPC Client]
    end
    subgraph Proxy
        B[Envoy Proxy]
    end
    subgraph Backend
        C[gRPC Server]
    end
    A -- gRPC/HTTP2 --> B
    B -- gRPC/HTTP2 --> C

1. Membuat gRPC Service Sederhana

Kita mulai dengan mendefinisikan service sederhana dengan Protocol Buffers:

helloworld.proto

syntax = "proto3";

package helloworld;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

Generate kode stub-nya menggunakan protoc. Untuk Go, contohnya:

protoc --go_out=. --go-grpc_out=. helloworld.proto

Implementasi sederhana untuk server (Go):

// server.go
package main

import (
    "context"
    "log"
    "net"

    pb "yourmod/helloworld"
    "google.golang.org/grpc"
)

type server struct {
    pb.UnimplementedGreeterServer
}

func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    return &pb.HelloReply{Message: "Hello, " + in.Name}, nil
}

func main() {
    lis, err := net.Listen("tcp", ":50051")
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterGreeterServer(s, &server{})
    log.Println("gRPC server listening on :50051")
    s.Serve(lis)
}

2. Konfigurasi Envoy Proxy untuk gRPC

Envoy harus diatur untuk memahami protokol HTTP/2. Kita setup sebagai reverse proxy dari port 9901 ke backend gRPC server di 50051.

envoy.yaml:

static_resources:
  listeners:
    - name: listener_0
      address:
        socket_address: { address: 0.0.0.0, port_value: 9901 }
      filter_chains:
        - filters:
            - name: envoy.filters.network.http_connection_manager
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                codec_type: AUTO
                stat_prefix: ingress_http
                route_config:
                  name: local_route
                  virtual_hosts:
                    - name: backend
                      domains: ["*"]
                      routes:
                        - match: { prefix: "/" }
                          route: { cluster: greeter_service }
                http_filters:
                  - name: envoy.filters.http.router
    # Envoy will use HTTP/2 to proxy the gRPC calls.
  clusters:
    - name: greeter_service
      connect_timeout: 0.25s
      type: logical_dns
      lb_policy: round_robin
      http2_protocol_options: {} # Enables HTTP2 for this cluster
      load_assignment:
        cluster_name: greeter_service
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: 127.0.0.1
                      port_value: 50051
admin:
  access_log_path: "/tmp/admin_access.log"
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 9900

Poin Penting:

  • http2_protocol_options: {} menginstruksikan Envoy untuk menggunakan HTTP/2 ketika berbicara ke backend cluster.
  • Pastikan cluster mengarah ke port di mana gRPC server berjalan.
  • Envoy proxy expose port 9901 (frontend).

3. Membuat Client untuk Terhubung ke Envoy

Implementasi client Go, spesifik konek ke Envoy, buka channel ke localhost:9901:

// client.go
package main

import (
    "context"
    "log"
    "time"

    pb "yourmod/helloworld"
    "google.golang.org/grpc"
)

func main() {
    conn, err := grpc.Dial("localhost:9901", grpc.WithInsecure())
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()
    c := pb.NewGreeterClient(conn)

    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()
    r, err := c.SayHello(ctx, &pb.HelloRequest{Name: "Envoy"})
    if err != nil {
        log.Fatalf("could not greet: %v", err)
    }
    log.Printf("Greeting: %s", r.Message)
}

Jalankan server, Envoy, lalu client:

go run server.go
envoy -c envoy.yaml
go run client.go

4. Simulasi Request Flow

Mari visualisasikan alur request-nya:

sequenceDiagram
    participant Client
    participant Envoy
    participant Server

    Client->>Envoy: gRPC Request (SayHello)
    Envoy->>Server: gRPC Request (forward)
    Server-->>Envoy: gRPC Response
    Envoy-->>Client: gRPC Response (relay)

Benefit-nya:

  • Client tidak perlu tahu IP/host server gRPC backend
  • Bisa scaling server gRPC dan update konfigurasi cluster Envoy secara dinamis
  • Observabilitas, circuit breaker, dll bisa langsung kita manfaatkan

5. Studi Kasus: Load Balancing dan Health Checking

Bayangkan kita menambah dua node server di belakang Envoy (misal di port 50051 dan 50052). Cukup ubah bagian load_assignment:

load_assignment:
  cluster_name: greeter_service
  endpoints:
    - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 127.0.0.1
                port_value: 50051
        - endpoint:
            address:
              socket_address:
                address: 127.0.0.1
                port_value: 50052

Kita juga bisa menambahkan health check:

health_checks:
  - timeout: 1s
    interval: 2s
    unhealthy_threshold: 2
    healthy_threshold: 2
    grpc_health_check: {} # Sesuai standard gRPC health check

Tabel ringkas fitur utama Envoy pada integrasi gRPC:

FiturDeskripsiKonfigurasi
Load BalancingRound robin, least request, dlllb_policy
ObservabilityMetrics Prometheus, tracingMetrics, Tracing config
SecuritymTLS, AuthZ, Rate Limitingtls_context, Filter HTTP
Health CheckingCek status backend, auto-remove instancehealth_checks
Retry/TimeoutMenjamin resilienceretry_policy, timeout

6. Kesimpulan, Tantangan, dan Best Practices

Dengan integrasi gRPC dan Envoy Proxy, aplikasi microservices Anda mendapatkan bonus skala, observability, dan security tanpa perlu banyak perubahan di level aplikasi. Namun, ada beberapa catatan penting:

  • Selalu menggunakan health check pada cluster backend
  • Monitor Envoy metrics untuk understanding traffic dan latency
  • Konfigurasikan rate limiting dan circuit breaking secukupnya
  • Untuk production, pastikan Envoy berjalan dengan mTLS
  • Deployment sebaiknya dilakukan via container orchestration (Kubernetes, Nomad, dsb) untuk hasil optimal

Integrasi ini bukan solusi “one size fits all”, tetapi menawarkan fondasi kokoh untuk service mesh dan scalable platform microservices Anda. Cobalah simulasi sederhana ini di lingkungan lokal Anda, dan eksplorasi lebih lanjut seluruh potensi Envoy di production!


Referensi

Selamat bereksperimen! Jangan ragu share insight dan pertanyaan di kolom komentar.

comments powered by Disqus