Skip to content
Santekno.com | Level Up Your Engineering Skills
ID
📖 0%
12 Aug 2025 · 5 mnt baca ·Artikel 65 / 110
Go

65. gRPC Name Resolver Kustom

IH
Ihsan Arif
Penulis di Santekno · Backend Engineer

title: 65. gRPC Name Resolver Kustom: Mengoptimalkan Service Discovery dengan Gaya Sendiri
date: 2024-06-11
tags: [golang, grpc, networking, distributed systems, service discovery]

gRPC telah lama menjadi andalan developer dalam membangun microservices yang cepat, ringan, dan mudah di-maintain. Salah satu komponen krusial yang sering terlupakan adalah Name Resolver. Secara default, gRPC menghadirkan beberapa resolver seperti dns:// atau passthrough://, namun kebutuhan di lingkungan distributed modern — seperti orchestrator custom, service mesh, atau environment hybrid — kerap membutuhkan sentuhan “kustom”. Masalahnya, sangat sedikit engineer yang benar-benar memahami betapa powerful dan fleksibelnya membuat Name Resolver Kustom sendiri.

Pada artikel ini, saya akan membahas lebih dalam tentang gRPC Name Resolver Kustom — mulai dari arsitektur, alur kerja, hingga implementasi sederhana dan use case-nya di sistem nyata.


Mengapa Perlu Name Resolver Kustom?

Saat bekerja dengan microservices, cara layanan menemukan endpoint satu sama lain (service discovery) adalah life and death. Dalam konteks gRPC, target endpoint seperti dns:///service.mydomain.com akan diproses oleh name resolver. Tapi bagaimana jika source layanan datangnya dari registry unik, file lokal, atau bahkan API bespoke internal? Di sinilah Custom Name Resolver dibutuhkan.

Beberapa skenario umum:

  • Integrasi dengan registry internal (HashiCorp Consul, ETCD, dsb)
  • Dynamic microservice pada Kubernetes dengan label/filter khusus
  • Service discovery via API Gateway khusus yang tidak support DNS A/AAAA secara native

Alur Kerja Name Resolver di gRPC

Mari jabarkan diagram sederhana tentang proses name resolution di gRPC.

MERMAID
sequenceDiagram
  participant Client
  participant gRPC Library
  participant NameResolver
  participant LoadBalancer

  Client->>gRPC Library: Dial ("myres://user-service/id-1234")
  gRPC Library->>NameResolver: Build("myres")
  NameResolver->>gRPC Library: UpdateState(Resolved addresses)
  gRPC Library->>LoadBalancer: Pass endpoint list
  LoadBalancer->>Client: Ready to RPC!

Summary:

  • Client memulai koneksi dengan target khusus via proto://target
  • gRPC memilih resolver sesuai schema (proto)
  • Name Resolver mem-fetch dan mengkalkulasi endpoint dari source kustom
  • Update state ke gRPC core untuk diteruskan ke load balancer dan dial RPC

Anatomy Name Resolver pada gRPC-Go

Name resolver adalah implementasi dari interface berikut (simplified):

go
1type Builder interface {
2    Scheme() string
3    Build(target Target, cc ClientConn, opts BuildOptions) (Resolver, error)
4}
5
6type Resolver interface {
7    ResolveNow(ResolveNowOptions)
8    Close()
9}
  • Builder: Registrasi awal yang menentukan “scheme” resolver
  • Resolver: Proses backend fetching/monitoring ke source endpoint

Studi Kasus: Custom In-Memory Resolver

Katakan kita punya service discovery berbasis YAML lokal.

File: services.yaml

yaml
1user-service:
2  - 10.0.0.2:50051
3  - 10.0.0.3:50051
4order-service:
5  - 10.0.0.4:50052

Langkah 1: Definisikan Scheme Resolver

go
 1const scheme = "yamlmem"
 2
 3func init() {
 4    resolver.Register(&yamlMemBuilder{})
 5}
 6
 7type yamlMemBuilder struct{}
 8
 9func (b *yamlMemBuilder) Scheme() string { return scheme }
10
11func (b *yamlMemBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
12    // Fetch endpoints dari YAML berdasarkan target.Endpoint
13    addrs := resolveFromYaml(target.Endpoint)
14    cc.UpdateState(resolver.State{Addresses: addrs})
15    return &yamlMemResolver{cc: cc}, nil
16}

Langkah 2: Proses Resolving YAML

go
 1func resolveFromYaml(endpoint string) []resolver.Address {
 2    // 1. Load file YAML
 3    // 2. Parse endpoint
 4    // 3. Return []resolver.Address dengan format host:port
 5    // Di sini saya simplifikasi hardcoded
 6    if endpoint == "user-service" {
 7        return []resolver.Address{
 8            {Addr: "10.0.0.2:50051"},
 9            {Addr: "10.0.0.3:50051"},
10        }
11    }
12    return nil
13}
14
15type yamlMemResolver struct{ cc resolver.ClientConn }
16
17func (r *yamlMemResolver) ResolveNow(o resolver.ResolveNowOptions) {}
18func (r *yamlMemResolver) Close() {}

Langkah 3: Dial dengan Scheme Kustom

go
1conn, err := grpc.Dial("yamlmem:///user-service", grpc.WithInsecure())
2if err != nil {
3    log.Fatalf("dial failed: %v", err)
4}

Dengan pattern ini, setiap kali kita menjalankan grpc.Dial dengan scheme yamlmem://, resolver kustom akan otomatis mengambil dan memperbarui endpoint dari YAML.


Simulasi Hasil: Tabel Resolusi

Client Dial TargetgRPC Scheme ResolverEndpoints Didapatkan
yamlmem:///user-serviceyamlmem10.0.0.2:50051, 10.0.0.3:50051
yamlmem:///order-serviceyamlmem10.0.0.4:50052
dns:///api.example.orgdns

Pengembangan Lanjutan

a. Live Update

Tentu, di dunia nyata resolver akan memonitor sumber (file, registry, REST API) dan memanggil cc.UpdateState() saat ada perubahan.

go
1go func() {
2    for changes := range watchServiceChange() {
3        cc.UpdateState(resolver.State{Addresses: changes})
4    }
5}()

b. Error Handling

cc.ReportError(err) bisa dipakai saat proses resolve gagal. Ini akan mengirim feedback ke client/error balancer.

c. Advanced Use Case: Resolver untuk Service Mesh Labels

Bayangkan Anda ingin hanya service dengan label blue atau canary yang resolve-able. Custom resolver dapat melakukan filtering endpoint sebelum meng-update state.


Kapan Harus Membuat Resolver Kustom?

Use CaseHarus Kustom?Alasan
DNS biasaTidakBuilt-in resolver sudah cukup
Load dari file/registry sendiriYaDiperlukan access logic non-standar
Koneksi dengan API eksternalYaSumber data endpoints bukan lewat DNS
Filtering berdasarkan business logicYaFiltering/logic hanya di sisi aplikasi
Single static hostTidakBisa pakai passthrough://

Kesimpulan

Kemampuan menciptakan gRPC Name Resolver Kustom bisa jadi superpower bagi engineer yang ingin microservice yang lebih fleksibel, scalable, dan sesuai kebutuhan distribusi layanan modern. Baik itu registry internal, service mesh, atau hybrid environment — dengan resolver kustom, kita bisa mendefinisikan cara service discovery sendiri, tanpa harus menunggu provider atau “hack” DNS.


Referensi & Tools

Danger
Selamat bereksperimen dan eksplor gRPC lebih dalam dengan resolver kustom!
Tinggalkan komentar kalau ada ide atau pertanyaan seputar resolver unik atau integrasi service discovery di perusahaan Anda 👍

Follow saya untuk artikel selanjutnya tentang distributed systems & scalable microservices!

Artikel Terkait

💬 Komentar