Managing Connections
1. Understanding Connection Lifecycle
| State | Meaning |
|---|---|
| IDLE | No active transport (initial with NewClient) |
| CONNECTING | Resolving + handshaking |
| READY | HTTP/2 established |
| TRANSIENT_FAILURE | Last attempt failed; backing off |
| SHUTDOWN | Closed permanently |
2. Configuring Connection Timeout
| Setting | Detail |
|---|---|
Server ConnectionTimeout | Handshake deadline |
| Client ctx deadline | Bounds first RPC including connect |
| Backoff config | Reconnect schedule |
3. Implementing Connection Pooling
Example: Round-robin pool
type Pool struct {
conns []*grpc.ClientConn
next atomic.Uint64
}
func (p *Pool) Get() *grpc.ClientConn {
i := p.next.Add(1) % uint64(len(p.conns))
return p.conns[i]
}
| Use | Detail |
|---|---|
| High throughput | >10k RPS where one conn saturates |
| Usually unnecessary | HTTP/2 multiplexing handles most loads |
4. Reusing Connections
| Rule | Detail |
|---|---|
| Singleton | One *grpc.ClientConn per upstream |
| Share stubs | Stubs are thread-safe |
| App lifetime | Close only on shutdown |
5. Handling Connection Failures
| Failure Type | Behavior |
|---|---|
| DNS failure | TRANSIENT_FAILURE; resolver retries |
| TCP refused | Exponential backoff reconnect |
| TLS error | Fail until cert/SNI fixed |
6. Detecting Connection State
Example: Read state
state := conn.GetState()
fmt.Println("state:", state) // IDLE/CONNECTING/READY/...
conn.Connect() // hint to leave IDLE
7. Waiting for Connection Ready
Example: Wait for READY
for conn.GetState() != connectivity.Ready {
if !conn.WaitForStateChange(ctx, conn.GetState()) {
return ctx.Err()
}
}
8. Closing Connections Gracefully
| Step | Detail |
|---|---|
| Stop accepting | Trigger app-level drain |
| Wait for in-flight | Bounded by timeout |
conn.Close() | Releases resources |
9. Handling Connection Leaks
| Symptom | Cause |
|---|---|
| FD exhaustion | New conn per RPC |
| Goroutine growth | Streams not closed |
| Tool | pprof goroutine + file descriptors |
10. Using Connection State Callbacks
| API | Detail |
|---|---|
conn.WaitForStateChange(ctx, current) | Blocks until state moves |
| Custom resolver/balancer | Receive subchannel state via callbacks |