Skip to content

Commit 6c4a3d6

Browse files
Fabian Hollerfho
authored andcommitted
fix: grpc calls block forever when service entry does not exist in consul
When no service entry in consul existed for the service that should be resolved, no result was reported to the ClientConn (UpdateState() wasn't called). This caused that the GRPC channel got stuck in CONNECTING state. When a GRPC call was done on the connection it was blocking forever because the channel was still trying to establish the connection. Calling UpdateState() with an empty set of addresses on the first try, when consul reported no addresses, transitions the channel state to TRANSIENT_FAILURE. This allows GRPC calls on the connection to fail with an UNAVAILABLE error.
1 parent d44f9b6 commit 6c4a3d6

2 files changed

Lines changed: 13 additions & 3 deletions

File tree

consul/resolver.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,12 @@ func (c *consulResolver) watcher() {
182182
// data newer then the passed opts.WaitIndex is available.
183183
// We check if the returned addrs changed to not call
184184
// cc.UpdateState() unnecessary for unchanged addresses.
185-
if (len(addrs) == 0 && len(lastReportedAddrs) == 0) ||
186-
reflect.DeepEqual(addrs, lastReportedAddrs) {
187-
185+
// If the service does not exist, an empty addrs slice
186+
// is returned. If we never reported any resolved
187+
// addresses (addrs is nil), we have to report an empty
188+
// set of resolved addresses. It informs the grpc-balancer that resolution is not
189+
// in progress anymore and grpc calls can failFast.
190+
if reflect.DeepEqual(addrs, lastReportedAddrs) {
188191
// If the consul server responds with
189192
// the same data then in the last
190193
// query in less then 50ms, we sleep a

consul/resolver_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,13 @@ func TestResolve(t *testing.T) {
118118
},
119119
},
120120

121+
{
122+
name: "emptyConsulResponseResolvestoEmptyAddrs",
123+
target: resolver.Target{Endpoint: "user-service"},
124+
consulResponse: []*consul.ServiceEntry{},
125+
resolverResult: []resolver.Address{},
126+
},
127+
121128
{
122129
name: "UseAgentAddrIfServiceAddrEmpty",
123130
target: resolver.Target{Endpoint: "user-service"},

0 commit comments

Comments
 (0)