-
Notifications
You must be signed in to change notification settings - Fork 4.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
internal/delegatingresolver: avoid proxy if networktype of target address is not tcp #8215
base: master
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #8215 +/- ##
==========================================
- Coverage 82.17% 82.16% -0.02%
==========================================
Files 410 412 +2
Lines 40236 40536 +300
==========================================
+ Hits 33065 33306 +241
- Misses 5822 5863 +41
- Partials 1349 1367 +18
🚀 New features to boost your workflow:
|
if len(curState.Endpoints) != 0 { | ||
networkType, ok = networktype.Get(curState.Endpoints[0].Addresses[0]) | ||
} else { | ||
networkType, ok = networktype.Get(curState.Addresses[0]) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we're making an assumption that the network type of the first address of the endpoint is the same the address type of all remaining addresses. This may be true for most real-world usecases, but it isn't a requirement specified in the resolver API. It should not be too difficult to avoid proxying on a per-address basis. There are two places below where we do the following, one for resolver.State.Addresses
and once for resolver.State.Endpoints
:
proxyattributes.Set(proxyAddr, proxyattributes.Options{
User: r.proxyURL.User,
ConnectAddr: targetAddr.Addr,
})
We can refactor this into a method that takes in the target address and proxy address and returns the combined address.
fn (r *delegatingResolver) combineAddresses(targetAddr, proxyAddr resolver.Address) resolver.Address {
if networktype.Get(targetAddr) != "tcp" {
return targetAddr
}
return proxyattributes.Set(proxyAddr, proxyattributes.Options{
User: r.proxyURL.User,
ConnectAddr: targetAddr.Addr,
})
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The above comment end up adding duplicate addresses in the loop on targetResolverState.Endpoints
. We will probably need to invert the loop on r.proxyAddrs
and endpt.Addresses
and break early:
for _, endpt := range (*r.targetResolverState).Endpoints {
var addrs []resolver.Address
for _, targetAddr := range endpt.Addresses {
if networktype.Get(targetAddr) != "tcp" {
addrs = append(addrs, targetAddr)
continue
}
for _, proxyAddr := range r.proxyAddrs {
addrs = append(addrs, proxyattributes.Set(proxyAddr, proxyattributes.Options{
User: r.proxyURL.User,
ConnectAddr: targetAddr.Addr,
}))
}
}
endpoints = append(endpoints, resolver.Endpoint{Addresses: addrs})
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, done ! Also added a check in beginning , if there is not address with network type TCP , we do not wait for proxy update and just update the cc state.
Please also fix the format of the release notes. |
if networkType, ok := networktype.Get(addr); !ok || networkType == "tcp" { | ||
isTCP = true | ||
break | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out here we're assuming !ok
to be the same of tcp
. However, the old code in the dialer used to parse the address string when !ok
to determine the network type, we should probably maintain the same behaviour.
grpc-go/internal/transport/http2_client.go
Lines 177 to 182 in 172fc5b
if !ok { | |
networkType, address = parseDialTarget(address) | |
} | |
if networkType == "tcp" && useProxy { | |
return proxyDial(ctx, address, grpcUA) | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
if networkType, ok := networktype.Get(addr); !ok || networkType == "tcp" || isTCP { | ||
isTCP = true | ||
break | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the code will be simpler if we refactor finding a TCP address in a helper function. The helper function can return early instead of keeping track of a isTCP
boolean and breaking out of nested loops.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right! Done!
} else { | ||
addresses = append(addresses, proxyattributes.Set(proxyAddr, proxyattributes.Options{ | ||
User: r.proxyURL.User, | ||
ConnectAddr: targetAddr.Addr, | ||
})) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: You can use continue
in the if
block to avoid indenting the else
block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
} else { | ||
for _, proxyAddr := range r.proxyAddrs { | ||
addrs = append(addrs, proxyattributes.Set(proxyAddr, proxyattributes.Options{ | ||
User: r.proxyURL.User, | ||
ConnectAddr: targetAddr.Addr, | ||
})) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: You can use continue
in the if
block to avoid indenting the else
block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
// updateClientConnStateLocked creates a list of combined addresses by | ||
// pairing each proxy address with every target address. For each pair, it | ||
// generates a new [resolver.Address] using the proxy address, and adding the | ||
// target address as the attribute along with user info. It returns nil if | ||
// either resolver has not sent update even once and returns the error from | ||
// ClientConn update once both resolvers have sent update atleast once. | ||
func (r *delegatingResolver) updateClientConnStateLocked() error { | ||
if r.targetResolverState == nil || r.proxyAddrs == nil { | ||
if r.targetResolverState == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If r.proxyAddrs == nil
is no longer in this conditional, does it mean that we can have a case where the proxy is configured, but we don't end up waiting for the resolved proxy addresses here?
return nil | ||
} | ||
|
||
curState := *r.targetResolverState | ||
|
||
// If no addresses returned by resolver have network type as tcp , do not wait for proxy update. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Please wrap comment lines at 80-cols. See: go/go-style/decisions#comment-line-length
// updateClientConnStateLocked creates a list of combined addresses by | ||
// pairing each proxy address with every target address. For each pair, it | ||
// generates a new [resolver.Address] using the proxy address, and adding the | ||
// target address as the attribute along with user info. It returns nil if | ||
// either resolver has not sent update even once and returns the error from | ||
// ClientConn update once both resolvers have sent update atleast once. | ||
func (r *delegatingResolver) updateClientConnStateLocked() error { | ||
if r.targetResolverState == nil || r.proxyAddrs == nil { | ||
if r.targetResolverState == nil { | ||
return nil | ||
} | ||
|
||
curState := *r.targetResolverState |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even though we have this local variable curState
, I see that the code (both existing and newly added) also uses r.targetResolverState
in multiple places. Can we make it consistent and use only one of them.
return r.cc.UpdateState(curState) | ||
} | ||
|
||
if r.proxyAddrs == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see that the previous check is moved here.
} | ||
|
||
// Verify that the state clientconn receives is same as updated by target resolver, | ||
// since we want to avoid proxy for any network type aprt from tcp. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: typo "aprt"
case <-time.After(defaultTestShortTimeout): | ||
t.Fatalf("Delegating resolver did not call update state") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be racy, especially on some slow GitHub action machines? We generally use defaultTestShortTimeout
for things that we expect to not happen. We do expect a state update here. So, I would rather use defaultTestTimeout
here and validate the state received on stateCh
.
} | ||
} | ||
|
||
// Tests the scenario where a proxy is configured, and the resolver returns addresses with varied |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Same here. Please wrap comments at 80-cols. Please figure out a way to configure your editor to do this for you.
const ( | ||
targetTestAddr = "test.target" | ||
resolvedTargetTestAddr1 = "1.1.1.1:8080" | ||
resolvedTargetTestAddr2 = "2.2.2.2:8080" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not used. Please delete.
resolvedProxyTestAddr1 = "11.11.11.11:7687" | ||
resolvedProxyTestAddr2 = "22.22.22.22:7687" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two are not used. Please delete.
Fixes: #8207
RELEASE NOTES: