Skip to content

Service Discovery

go-zero supports pluggable service discovery backends. Every RPC server registers itself automatically at startup; every RPC client watches the registry and picks healthy instances with P2C load balancing.

Add the Etcd block to the RPC server config — no code changes needed:

etc/order-rpc.yaml
Name: order.rpc
ListenOn: 0.0.0.0:8080
Etcd:
Hosts:
- 127.0.0.1:2379
Key: order.rpc # discovery key — clients use this exact string

go-zero calls etcd.Put(key, address) at startup and etcd.Delete on graceful shutdown, with a lease so stale entries expire automatically if the process crashes.

Point the client config at the same etcd cluster and key:

etc/user-api.yaml
OrderRpc:
Etcd:
Hosts:
- 127.0.0.1:2379
Key: order.rpc
Timeout: 2000
internal/svc/servicecontext.go
orderConn := zrpc.MustNewClient(c.OrderRpc)
svc.OrderRpc = order.NewOrderClient(orderConn.Conn())

For high availability use three or five nodes:

Etcd:
Hosts:
- etcd1.infra:2379
- etcd2.infra:2379
- etcd3.infra:2379
Key: order.rpc

When running inside Kubernetes, replace etcd with a headless Service DNS name:

OrderRpc:
Target: dns:///order-rpc-svc.default.svc.cluster.local:8080

Or use a list of pod endpoints directly (useful with StatefulSets):

OrderRpc:
Endpoints:
- order-rpc-0.order-rpc-svc.default:8080
- order-rpc-1.order-rpc-svc.default:8080

For local development or integration tests, skip etcd entirely:

OrderRpc:
Endpoints:
- 127.0.0.1:8080
ConventionExampleNotes
<name>.rpcorder.rpcStandard; matches the Name field
<env>/<name>.rpcprod/order.rpcMulti-environment shared etcd
<ns>.<name>.rpcpayment.order.rpcDomain namespacing

Use the same string in the server’s Etcd.Key and the client’s Etcd.Key.

go-zero RPC servers implement the gRPC health check protocol automatically. Kubernetes probes work out of the box:

k8s/order-rpc.yaml
livenessProbe:
exec:
command: ["/bin/grpc_health_probe", "-addr=:8080"]
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
exec:
command: ["/bin/grpc_health_probe", "-addr=:8080"]
initialDelaySeconds: 3
periodSeconds: 5

The client uses P2C (pick-of-two-choices) with EWMA latency by default. No configuration required — it selects the least-loaded among two randomly chosen instances on every call.

To verify which instance handled a request, enable debug logging or check the trace span’s peer.address attribute.

When a new instance starts and registers with etcd, the client discovers it within the lease TTL (default 10 s). When an instance shuts down gracefully (SIGTERM), it deregisters before accepting no new connections, ensuring zero dropped requests during rolling deploys.