HN 표시: ApolloRouter보다 1.58배 빠른 Stateless Go GraphQL 페더레이션 게이트웨이

hackernews | | 🔬 연구
#federation #gateway #go #graphql #review #성능비교
원문 출처: hackernews · Genesis Park에서 요약 및 분석

요약

순수 Go로 작성된 GraphQL Federation v2 게이트웨이가 공개되었으며, @key, @requires, @provides 등 핵심 지시어를 대부분 지원하고 상태 설계(stateless)를 유지합니다. 성능 비교 결과, 기본 설정인 MaxIdleConnsPerHost를 32로 조정하여 초당 약 4,380건의 요청을 처리해 아폴로 라우터(약 2,771건)보다 약 1.58배 빠른 것으로 확인되었습니다. 반면 상태 기반 연결이 필요한 구독(Subscription)과 인증 기능은 지원하지 않아 게이트웨이 외부에서 처리해야 합니다.

본문

A stateless, high-performance GraphQL Federation v2 Gateway written purely in Go. Go GraphQL Federation Gateway is a lightweight, stateless GraphQL Federation v2 Gateway written purely in Go. While existing solutions like Apollo Router (Rust) are excellent, extending them often requires learning Rust or dealing with binary constraints. This gateway provides: - Native Go — Easy to read, debug, and extend for Go developers - Stateless design — HTTP-only (query & mutation); no WebSocket state required - Federation v2 Compliant — Core and advanced directives fully supported - Hackable — Modular Planner/Executor architecture for custom optimization - Observable — Built-in OpenTelemetry tracing support - Faster than Apollo Router — 1.58x higher throughput in benchmarks @key nested field support:@key(fields: "coordinate { lat lng }") — nested object keys are fully parsed and resolved via aKeyFieldNode tree structure- Multiple @key directives (executor fix): When an extension subgraph declares a different@key than the owner's first key, the executor now correctly uses the extension's key for_entities representations (e.g.,@key(fields: "username") in badges service when owner also has@key(fields: "id") ) @provides optimization: Entity steps are skipped when the parent service fully covers all requested child fields via@provides . Safety check ensures the optimization only applies when the entity type is declared as a fulltype definition (notextend type ) - HTTP connection pool settings via gateway.yaml :max_idle_conns_per_host (default 32),max_conns_per_host , andidle_conn_timeout are now configurable — eliminating the previous bottleneck ofMaxIdleConnsPerHost: 2 fromhttp.DefaultTransport sync.Pool request body buffering:sendRequest now uses a pool of*bytes.Buffer instances, eliminating per-requestjson.Marshal intermediate[]byte allocation andbytes.NewReader wrapper- Result: 1.58x faster than Apollo Router (4,380 req/s vs 2,771 req/s at concurrency 50) - 135+ integration tests across 8 production-like domains (EC, Fintech, SaaS, Social, Travel, nestkey, multikey, provides) - 3 new test domains demonstrating nested keys ( nestkey ), alternate key resolution (multikey ), and@provides optimization (provides ) This gateway is designed to be stateless and horizontally scalable: - HTTP-only: query and mutation operations - No persistent WebSocket connections (Subscription is intentionally out of scope) - Every request is fully self-contained - DAG-based execution: Resolves complex dependency graphs, executing independent steps in parallel @requires injection: Automatically injects required fields (e.g.,weight ) into upstream requests for computed fields (e.g.,shippingCost ). Supports chained@requires dependencies@provides optimization: Skips unnecessary_entities fetches when the parent service already provides the needed fields@shareable preference: Prefers the parent's subgraph for@shareable fields to avoid extra entity fetches- Entity step deduplication: Sibling extension fields on the same entity are merged into a single _entities call - Query plan caching: Plans are cached per query string and reused on cache hits, skipping parse/validate/plan on repeated queries - Independent subgraph steps execute in parallel via goroutines - Step dependency graph (DAG) ensures correct ordering - Returns partial data when some subgraphs fail - Failed fields are set to null with error details including path and service name - Execution continues for independent fields even when some steps fail Configurable via gateway.yaml : connection_pool: max_idle_conns_per_host: 32 # default: 32 max_conns_per_host: 0 # default: 0 (unlimited) idle_conn_timeout: "90s" # default: "90s" | Directive | Status | Notes | |---|---|---| @key | ✅ | Simple, composite, nested ("coord { lat lng }" ), multiple @key per type | @key(resolvable: false) | ✅ | Excluded from entity fetch origin selection | @external | ✅ | Correct ownership filtering, prevents stub references from being treated as owners | @requires | ✅ | Chained dependency injection in topological order | @provides | ✅ | Optimization: skips entity step when parent covers all requested fields | @shareable | ✅ | Same-subgraph preference to avoid unnecessary entity fetches | @override | ✅ | Field ownership migration between subgraphs | @inaccessible | ✅ | Type & field level; enforced at schema composition and query validation | @tag | ✅ | Type & field level metadata | @interfaceObject | ✅ | Interface types as entities; inline fragment resolution | @composeDirective | ✅ | Custom directive preservation and consistency validation | @link | ✅ | Parsed and passed through in composed schema | | Feature | Reason | |---|---| | Subscription | Requires stateful WebSocket connections; contradicts stateless design | @authenticated / @requiresScopes / @policy | Authorization layer should be handled outside the gateway | @defer / @stream | Requires long-lived streaming connections | | Federated Tracing (ftv1) | Apoll

Genesis Park 편집팀이 AI를 활용하여 작성한 분석입니다. 원문은 출처 링크를 통해 확인할 수 있습니다.

공유

관련 저널 읽기

전체 보기 →