Skip to content
Santekno.com | Level Up Your Engineering Skills
ID
📖 0%
05 Sep 2025 · 6 mnt baca ·Artikel 67 / 125
Go

67 Menghubungkan Beberapa Service GraphQL di Go

IH
Ihsan Arif
Penulis di Santekno · Backend Engineer

67 Menghubungkan Beberapa Service GraphQL di Go

Ketika skala sistem microservices mulai meningkat, biasanya muncul kebutuhan untuk mengintegrasikan beberapa service agar mampu memberikan pengalaman API yang konsisten. Salah satu pendekatan yang sedang naik daun adalah federasi GraphQL, di mana beberapa service dengan GraphQL API masing-masing digabungkan ke dalam satu gateway terpadu. Pada artikel kali ini, saya akan membahas cara menghubungkan beberapa service GraphQL di Go, lengkap dengan contoh kode, simulasi request, dan diagram alur untuk membangun federasi sederhana.


Mengapa Federasi GraphQL?

Sebelum masuk ke implementasi, mari pahami dulu why-nya. Berikut beberapa alasan popularitas federasi GraphQL:

KeuntunganPenjelasan
Konsistensi APIKonsumen hanya perlu terhubung ke satu endpoint GraphQL.
Pengembangan TerpisahTiap team dapat membangun dan merilis schema GraphQL secara independen.
ScalabilityService bisa dipisah dan diskalakan secara mandiri.
Satu Sumber KebenaranGateway bisa menyatukan data dari berbagai sumber menjadi satu graph besar.

Landscape Library GraphQL di Go

Sampai artikel ini ditulis, library GraphQL di Go yang paling populer antara lain:

Untuk federasi, ekosistem Go belum sematang Node.js. Namun, dengan trik dan orchestrator ringan, solusi federasi tetap bisa dibangun. Pendekatan yang kita pakai di sini adalah Gateway BFF Pattern.


Studi Kasus: Menggabungkan user-service dan post-service

Bayangkan kita memiliki dua service:

  • user-service: menyajikan data user.
  • post-service: menyajikan data post, dengan referensi ke user.

Kita ingin agar di gateway satu endpoint GraphQL yang bisa mengakses data gabungan, misal: mendapatkan daftar posts beserta nama authors.

1. Struktur Arsitektur

MERMAID
flowchart TD
  subgraph Backend
    US(User Service) 
    PS(Post Service)
  end
  GQ[GraphQL Gateway] --> US
  GQ --> PS
  CLIENTS((Clients)) --> GQ

1. Membuat Schema Microservice

Mari mulai dengan mendefinisikan skema di tiap service.

user-service/schema.graphqls

graphql
 1type User {
 2  id: ID!
 3  name: String!
 4  email: String!
 5}
 6
 7type Query {
 8  user(id: ID!): User
 9  users: [User!]!
10}

post-service/schema.graphqls

graphql
 1type Post {
 2  id: ID!
 3  title: String!
 4  content: String!
 5  authorID: ID!
 6}
 7
 8type Query {
 9  post(id: ID!): Post
10  posts: [Post!]!
11}

2. Membuat Layanan GraphQL di Go (gqlgen)

Contoh implementasi sederhana untuk user-service (file hanya penting saja, ringkas demi kejelasan):

user-service/main.go

go
 1package main
 2
 3import (
 4    "log"
 5    "net/http"
 6    "github.com/99designs/gqlgen/graphql/handler"
 7    "github.com/99designs/gqlgen/graphql/playground"
 8    "user-service/graph"
 9    "user-service/graph/generated"
10)
11
12func main() {
13    srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &graph.Resolver{}}))
14
15    http.Handle("/", playground.Handler("GraphQL playground", "/query"))
16    http.Handle("/query", srv)
17
18    log.Println("connect to http://localhost:8081/ for user service playground")
19    log.Fatal(http.ListenAndServe(":8081", nil))
20}

Isi resolver bisa dengan in-memory data sederhana, begitu juga untuk post-service.


3. Membuat GraphQL Gateway (API-Orchestrator)

Inti artikel ini: menghubungkan dua (atau lebih) GraphQL service ke dalam satu orchestrator. Pada Go, kita belum punya Apollo Federation sepenuhnya, jadi kita akan menggunakan Schema Stitching ala BFF.

Skema Gateway

Kita ingin pengguna bisa melakukan query seperti berikut:

graphql
 1{
 2  posts {
 3    id
 4    title
 5    author {
 6      id
 7      name
 8    }
 9  }
10}

Artinya, kita perlu menambah field virtual “author” di graph Post pada gateway, yang resolvenya adalah remote call ke user-service.

Contoh Kode Gateway

Instalasi package pendukung:

text
1go get github.com/99designs/gqlgen
2go get github.com/machinebox/graphql

gateway/schema.graphqls

graphql
 1type User {
 2  id: ID!
 3  name: String!
 4  email: String!
 5}
 6
 7type Post {
 8  id: ID!
 9  title: String!
10  content: String!
11  author: User!
12}
13
14type Query {
15  posts: [Post!]!
16  post(id: ID!): Post
17}

gateway/resolver.go (inti pola stitch)

go
 1package graph
 2
 3import (
 4  "context"
 5  "github.com/machinebox/graphql"
 6)
 7
 8type Resolver struct{}
 9
10type Post struct {
11  ID      string
12  Title   string
13  Content string
14  AuthorID string
15}
16
17func (r *queryResolver) Posts(ctx context.Context) ([]*Post, error) {
18  // call post-service
19  client := graphql.NewClient("http://localhost:8082/query")
20  req := graphql.NewRequest(`
21    query { posts { id title content authorID } }
22  `)
23  var resp struct {
24    Posts []*Post
25  }
26  if err := client.Run(ctx, req, &resp); err != nil {
27    return nil, err
28  }
29  return resp.Posts, nil
30}
31
32func (r *postResolver) Author(ctx context.Context, obj *Post) (*User, error) {
33  // call user-service
34  client := graphql.NewClient("http://localhost:8081/query")
35  req := graphql.NewRequest(`
36    query ($id: ID!) { user(id: $id) { id name email } }
37  `)
38  req.Var("id", obj.AuthorID)
39  var resp struct {
40    User *User
41  }
42  if err := client.Run(ctx, req, &resp); err != nil {
43    return nil, err
44  }
45  return resp.User, nil
46}

Penjelasan :

  • Posts query mengambil data ke post-service secara remote.
  • Di setiap author, resolver melakukan remote GraphQL ke user-service.

4. Simulasi Request

graphql
 1query {
 2  posts {
 3    id
 4    title
 5    author {
 6      id
 7      name
 8    }
 9  }
10}

Diagram Alur

MERMAID
sequenceDiagram
    participant CLIENT
    participant GATEWAY
    participant POST_SERVICE
    participant USER_SERVICE

    CLIENT->>GATEWAY: Query posts { id title author { id name } }
    GATEWAY->>POST_SERVICE: Query posts { id title content authorID }
    POST_SERVICE-->>GATEWAY: Posts Data
    loop For each Post
      GATEWAY->>USER_SERVICE: Query user { id name email } (with authorID)
      USER_SERVICE-->>GATEWAY: User Data
    end
    GATEWAY-->>CLIENT: Daftar posts & author

5. Implikasi dan Keterbatasan

AspekPenjelasan
PerformaUntuk setiap post, ada call ke user-service. Batasi N+1, idealnya pakai batching (DataLoader).
Error HandlingError pada salah satu service harus di-handle dengan baik di orchestrator.
Schema ManagementPerubahan schema di masing-masing service harus selalu di-sync gateway.
Auth & ResilienceGateway menjadi central point untuk security dan throttle.

6. Towards Production

Langkah di atas adalah minimal viable architecture. Untuk production:

  • Gunakan DataLoader untuk menghindari N+1 remote call.
  • Perhatikan timeout dan circuit breaker.
  • Implement cache untuk kebutuhan spesifik.
  • Amati latency agregat.
  • Untuk federasi penuh (apollo federation style), pantau gqlgen feature request 980 .

Kesimpulan

Dengan sedikit schema stitching, kita bisa menghubungkan beberapa service GraphQL di Go tanpa framework federasi berat. Pola orchestrator BFF ini sangat cocok untuk team kecil hingga mid-size yang ingin kenyamanan dan konsistensi API global.

Jika kebutuhan semakin kompleks (subgraph ratusan, skema sangat dinamis), lebih baik memantau perkembangan federasi GraphQL native di Go atau, jika memungkinkan, mix dengan Node.js untuk gateway federasi.

Selamat mencoba dan semoga kode Anda lebih terorkestrasi! 🚀


Referensi

Artikel Terkait

💬 Komentar