-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
server: suppress spurious blocking query returns where multiple config entries are involved #12362
Conversation
b59362a
to
5ac56a0
Compare
agent/consul/config_endpoint.go
Outdated
for _, sid := range upstreamIDs { | ||
if _, ok := seenUpstreams[sid]; !ok { | ||
seenUpstreams[sid] = struct{}{} | ||
// Fetch all relevant config entries. We will generate a |
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 body of this blockingQuery
call was changed into two steps:
- Get all config entries we will need.
- Smoosh those config entries together to fabricate the result.
Iterations after the first one will stop after (1) and check if any of the config entries collected differ from the prior iteration. If they do it returns the new data, otherwise it signals to the RPC side that it is a not-changed
scenario.
Co-authored-by: Chris S. Kim <ckim@hashicorp.com>
🍒 If backport labels were added before merging, cherry-picking will start automatically. To retroactively trigger a backport after merging, add backport labels and re-run https://circleci.com/gh/hashicorp/consul/597518. |
…ple config entries are involved Backport of #12362 to 1.11.x Conflicts: - agent/consul/config_endpoint_test.go (imports) - go.mod (adjacencies)
…ple config entries are involved Backport of #12362 to 1.10.x Conflicts: - agent/consul/config_endpoint.go - agent/consul/discovery_chain_endpoint_test.go - agent/consul/intention_endpoint_test.go - agent/consul/internal_endpoint.go - agent/consul/internal_endpoint_test.go - agent/consul/rpc.go
…ple config entries are involved (#12459) * [1.10.x] server: suppress spurious blocking query returns where multiple config entries are involved Backport of #12362 to 1.10.x Conflicts: - agent/consul/config_endpoint.go - agent/consul/discovery_chain_endpoint_test.go - agent/consul/intention_endpoint_test.go - agent/consul/internal_endpoint.go - agent/consul/internal_endpoint_test.go - agent/consul/rpc.go * update vendor
…uery tests (#12518) Improves tests from #12362 These tests try to setup the following concurrent scenario: 1. (goroutine 1) execute read RPC with index=0 2. (goroutine 1) get response from (1) @ index=10 3. (goroutine 1) execute read RPC with index=10 and block 4. (goroutine 2) WHILE (3) is blocking, start slamming the system with stray writes that will cause the WatchSet to wakeup 5. (goroutine 2) after doing all writes, shut down the reader above 6. (goroutine 1) stops reading, double checks that it only ever woke up once (from 1)
…uery tests (#12518) Improves tests from #12362 These tests try to setup the following concurrent scenario: 1. (goroutine 1) execute read RPC with index=0 2. (goroutine 1) get response from (1) @ index=10 3. (goroutine 1) execute read RPC with index=10 and block 4. (goroutine 2) WHILE (3) is blocking, start slamming the system with stray writes that will cause the WatchSet to wakeup 5. (goroutine 2) after doing all writes, shut down the reader above 6. (goroutine 1) stops reading, double checks that it only ever woke up once (from 1)
Starting from and extending the mechanism introduced in #12110 we can specially handle the 3 main special Consul RPC endpoints that react to many config entries in a single blocking query in Connect:
DiscoveryChain.Get
ConfigEntry.ResolveServiceConfig
Intentions.Match
All of these will internally watch for many config entries, and at least one of those will likely be not found in any given query. Because these are blends of multiple reads the exact solution from #12110 isn't perfectly aligned, but we can tweak the approach slightly and regain the utility of that mechanism.
No Config Entries Found
In this case, despite looking for many config entries none may be found at all. Unlike #12110 in this scenario we do not return an empty reply to the caller, but instead synthesize a struct from default values to return. This can be handled nearly identically to #12110 with the first 1-2 replies being non-empty payloads followed by the standard spurious wakeup suppression mechanism from #12110.
No Change Since Last Wakeup
Once a blocking query loop on the server has completed and slept at least once, there is a further optimization we can make here to detect if any of the config entries that were present at specific versions for the prior execution of the loop are identical for the loop we just woke up for. In that scenario we can return a slightly different internal sentinel error and basically externally handle it similar to #12110.
This would mean that even if 20 discovery chain read RPC handling goroutines wakeup due to the creation of an unrelated config entry, the only ones that will terminate and reply with a blob of data are those that genuinely have new data to report.
Extra Endpoints
Since this pattern is pretty reusable, other key config-entry-adjacent endpoints used by
agent/proxycfg
also were updated:ConfigEntry.List
Internal.IntentionUpstreams
(tproxy)TODO:
service-intentions
would need similar treatment (YES)hashstructure
is a good alternative to use for outputs of the state store instead of theIndexSignature
structIntentions.Match
ConfigEntry.List
Internal.IntentionUpstreams