Skip to content

Commit 903cce1

Browse files
authored
Merge pull request #2024 from murgatroid99/grpc-js_dns_backoff
grpc-js: Add backoff to DNS resolution attempts
2 parents bd609ce + 80f31bb commit 903cce1

File tree

2 files changed

+32
-3
lines changed

2 files changed

+32
-3
lines changed

packages/grpc-js/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@grpc/grpc-js",
3-
"version": "1.5.0",
3+
"version": "1.5.1",
44
"description": "gRPC Library for Node - pure JS implementation",
55
"homepage": "https://grpc.io/",
66
"repository": "https://github.com/grpc/grpc-node/tree/master/packages/grpc-js",

packages/grpc-js/src/resolver-dns.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { SubchannelAddress, TcpSubchannelAddress } from './subchannel-address';
3232
import { GrpcUri, uriToString, splitHostPort } from './uri-parser';
3333
import { isIPv6, isIPv4 } from 'net';
3434
import { ChannelOptions } from './channel-options';
35+
import { BackoffOptions, BackoffTimeout } from './backoff-timeout';
3536

3637
const TRACER_NAME = 'dns_resolver';
3738

@@ -85,6 +86,8 @@ class DnsResolver implements Resolver {
8586
private latestServiceConfigError: StatusObject | null = null;
8687
private percentage: number;
8788
private defaultResolutionError: StatusObject;
89+
private backoff: BackoffTimeout;
90+
private continueResolving = false;
8891
constructor(
8992
private target: GrpcUri,
9093
private listener: ResolverListener,
@@ -119,6 +122,18 @@ class DnsResolver implements Resolver {
119122
details: `Name resolution failed for target ${uriToString(this.target)}`,
120123
metadata: new Metadata(),
121124
};
125+
126+
const backoffOptions: BackoffOptions = {
127+
initialDelay: channelOptions['grpc.initial_reconnect_backoff_ms'],
128+
maxDelay: channelOptions['grpc.max_reconnect_backoff_ms'],
129+
};
130+
131+
this.backoff = new BackoffTimeout(() => {
132+
if (this.continueResolving) {
133+
this.startResolutionWithBackoff();
134+
}
135+
}, backoffOptions);
136+
this.backoff.unref();
122137
}
123138

124139
/**
@@ -140,6 +155,7 @@ class DnsResolver implements Resolver {
140155
return;
141156
}
142157
if (this.dnsHostname === null) {
158+
trace('Failed to parse DNS address ' + uriToString(this.target));
143159
setImmediate(() => {
144160
this.listener.onError({
145161
code: Status.UNAVAILABLE,
@@ -148,6 +164,7 @@ class DnsResolver implements Resolver {
148164
});
149165
});
150166
} else {
167+
trace('Looking up DNS hostname ' + this.dnsHostname);
151168
/* We clear out latestLookupResult here to ensure that it contains the
152169
* latest result since the last time we started resolving. That way, the
153170
* TXT resolution handler can use it, but only if it finishes second. We
@@ -164,6 +181,7 @@ class DnsResolver implements Resolver {
164181
this.pendingLookupPromise.then(
165182
(addressList) => {
166183
this.pendingLookupPromise = null;
184+
this.backoff.reset();
167185
const ip4Addresses: dns.LookupAddress[] = addressList.filter(
168186
(addr) => addr.family === 4
169187
);
@@ -263,10 +281,21 @@ class DnsResolver implements Resolver {
263281
}
264282
}
265283

284+
private startResolutionWithBackoff() {
285+
this.startResolution();
286+
this.backoff.runOnce();
287+
}
288+
266289
updateResolution() {
267-
trace('Resolution update requested for target ' + uriToString(this.target));
290+
/* If there is a pending lookup, just let it finish. Otherwise, if the
291+
* backoff timer is running, do another lookup when it ends, and if not,
292+
* do another lookup immeidately. */
268293
if (this.pendingLookupPromise === null) {
269-
this.startResolution();
294+
if (this.backoff.isRunning()) {
295+
this.continueResolving = true;
296+
} else {
297+
this.startResolutionWithBackoff();
298+
}
270299
}
271300
}
272301

0 commit comments

Comments
 (0)